github.com/15mga/kiwi@v0.0.2-0.20240324021231-b95d5c3ac751/ecs/scene.go (about) 1 package ecs 2 3 import ( 4 "github.com/15mga/kiwi/ds" 5 "github.com/15mga/kiwi/util" 6 ) 7 8 func NewScene(id string, typ TScene) *Scene { 9 return &Scene{ 10 id: id, 11 typ: typ, 12 data: util.M{}, 13 idToEntity: ds.NewKSet[string, *Entity](512, 14 func(entity *Entity) string { 15 return entity.Id() 16 }), 17 tagToComponents: ds.NewSet[string, IComponent](16), 18 componentTags: make(map[IComponent]map[string]struct{}, 32), 19 onBeforeAddEntityLink: ds.NewFnErrLink1[*Entity](), 20 onAfterAddEntityLink: ds.NewFnLink1[*Entity](), 21 onBeforeDisposeEntityLink: ds.NewFnErrLink1[*Entity](), 22 onAfterDisposeEntityLink: ds.NewFnLink1[*Entity](), 23 } 24 } 25 26 type Scene struct { 27 id string 28 typ TScene 29 data util.M 30 idToEntity *ds.KSet[string, *Entity] 31 tagToComponents *ds.KSet[string, *ds.SetItem[string, IComponent]] 32 componentTags map[IComponent]map[string]struct{} //key换成entityId_TComponent试试 33 onBeforeAddEntityLink *ds.FnErrLink1[*Entity] 34 onAfterAddEntityLink *ds.FnLink1[*Entity] 35 onBeforeDisposeEntityLink *ds.FnErrLink1[*Entity] 36 onAfterDisposeEntityLink *ds.FnLink1[*Entity] 37 } 38 39 func (s *Scene) Id() string { 40 return s.id 41 } 42 43 func (s *Scene) Type() TScene { 44 return s.typ 45 } 46 47 func (s *Scene) Data() util.M { 48 return s.data 49 } 50 51 func (s *Scene) AddEntity(e *Entity) *util.Err { 52 id := e.Id() 53 err := s.onBeforeAddEntityLink.Invoke(e) 54 if err != nil { 55 return err 56 } 57 58 if _, ok := s.idToEntity.Get(id); ok { 59 return util.NewErr(util.EcExist, util.M{ 60 "id": id, 61 }) 62 } 63 64 _ = s.idToEntity.Add(e) 65 e.setScene(s) 66 e.start() 67 for _, component := range e.Components() { 68 s.TagComponent(component, string(component.Type())) 69 } 70 s.onAfterAddEntityLink.Invoke(e) 71 return nil 72 } 73 74 func (s *Scene) DelEntity(id string) *util.Err { 75 e, ok := s.idToEntity.Get(id) 76 if !ok { 77 return util.NewErr(util.EcNotExist, util.M{ 78 "entity id": id, 79 }) 80 } 81 err := s.onBeforeDisposeEntityLink.Invoke(e) 82 if err != nil { 83 return err 84 } 85 for _, component := range e.Components() { 86 if a, ok := s.componentTags[component]; ok { 87 for tag := range a { 88 set, ok := s.tagToComponents.Get(tag) 89 if !ok { 90 continue 91 } 92 set.Del(component.Entity().Id()) 93 if set.Count() == 0 { 94 s.tagToComponents.Del(tag) 95 } 96 } 97 } 98 delete(s.componentTags, component) 99 } 100 s.idToEntity.Del(id) 101 s.onAfterDisposeEntityLink.Invoke(e) 102 e.Dispose() 103 return nil 104 } 105 106 func (s *Scene) GetEntity(id string) (*Entity, bool) { 107 a, ok := s.idToEntity.Get(id) 108 return a, ok 109 } 110 111 func (s *Scene) IterEntities(fn FnEntity) { 112 s.idToEntity.Iter(fn) 113 } 114 115 func (s *Scene) Entities() []*Entity { 116 return s.idToEntity.Values() 117 } 118 119 func (s *Scene) EntityCount() int { 120 return s.idToEntity.Count() 121 } 122 123 func (s *Scene) EntityIds(ids *[]string) { 124 s.idToEntity.CopyKeys(ids) 125 } 126 127 func (s *Scene) IsEmpty() bool { 128 return s.idToEntity.Count() == 0 129 } 130 131 func (s *Scene) HasTagComponent(component IComponent, tag string) bool { 132 a, ok := s.componentTags[component] 133 if !ok { 134 return false 135 } 136 _, ok = a[tag] 137 return ok 138 } 139 140 func (s *Scene) TagComponent(component IComponent, tags ...string) { 141 a, ok := s.componentTags[component] 142 if !ok { 143 a = make(map[string]struct{}, 4) 144 s.componentTags[component] = a 145 } 146 for _, tag := range tags { 147 if _, ok := a[tag]; ok { 148 continue 149 } 150 a[tag] = struct{}{} 151 set, ok := s.tagToComponents.Get(tag) 152 if !ok { 153 set = ds.NewSetItem[string, IComponent](32, tag, func(component IComponent) string { 154 return component.Entity().Id() 155 }) 156 _ = s.tagToComponents.AddNX(set) 157 } 158 _ = set.AddNX(component) 159 } 160 } 161 162 func (s *Scene) TagComponents(tag string, components []IComponent) { 163 set, ok := s.tagToComponents.Get(tag) 164 if !ok { 165 set = ds.NewSetItem[string, IComponent](32, tag, func(component IComponent) string { 166 return component.Entity().Id() 167 }) 168 _ = s.tagToComponents.AddNX(set) 169 } 170 set.AddRange(components) 171 for _, component := range components { 172 a, ok := s.componentTags[component] 173 if !ok { 174 a = make(map[string]struct{}, 4) 175 s.componentTags[component] = a 176 } 177 a[tag] = struct{}{} 178 } 179 } 180 181 func (s *Scene) TagEntityComponent(entityId string, t TComponent, tags ...string) { 182 e, ok := s.idToEntity.Get(entityId) 183 if !ok { 184 return 185 } 186 component, ok := e.GetComponent(t) 187 if !ok { 188 return 189 } 190 s.TagComponent(component, tags...) 191 } 192 193 func (s *Scene) UntagComponent(component IComponent, tags ...string) { 194 ca, ok := s.componentTags[component] 195 if !ok { 196 return 197 } 198 for _, tag := range tags { 199 delete(ca, tag) 200 a, ok := s.tagToComponents.Get(tag) 201 if !ok { 202 continue 203 } 204 a.Del(component.Entity().Id()) 205 if a.Count() == 0 { 206 s.tagToComponents.Del(tag) 207 } 208 } 209 if len(ca) == 0 { 210 delete(s.componentTags, component) 211 } 212 } 213 214 func (s *Scene) UntagComponents(tag string, components []IComponent) { 215 set, ok := s.tagToComponents.Get(tag) 216 if !ok { 217 return 218 } 219 for _, component := range components { 220 set.Del(component.Entity().Id()) 221 ca, _ := s.componentTags[component] 222 delete(ca, tag) 223 if len(ca) == 0 { 224 delete(s.componentTags, component) 225 } 226 } 227 if set.Count() == 0 { 228 s.tagToComponents.Del(tag) 229 } 230 } 231 232 func (s *Scene) GetTagComponents(tag string) ([]IComponent, bool) { 233 a, ok := s.tagToComponents.Get(tag) 234 if !ok { 235 return nil, false 236 } 237 return a.Values(), true 238 } 239 240 func (s *Scene) GetTagComponentsSet(tag string) (*ds.SetItem[string, IComponent], bool) { 241 a, ok := s.tagToComponents.Get(tag) 242 if !ok { 243 return nil, false 244 } 245 return a, true 246 } 247 248 func (s *Scene) ClearComponentTags(component IComponent) { 249 a, ok := s.componentTags[component] 250 if !ok { 251 return 252 } 253 delete(s.componentTags, component) 254 for tag := range a { 255 set, ok := s.tagToComponents.Get(tag) 256 if !ok { 257 continue 258 } 259 set.Del(component.Entity().Id()) 260 if set.Count() == 0 { 261 s.tagToComponents.Del(tag) 262 } 263 } 264 } 265 266 func (s *Scene) ClearTag(tag string) bool { 267 a, ok := s.tagToComponents.Del(tag) 268 if !ok { 269 return false 270 } 271 for _, c := range a.Values() { 272 delete(s.componentTags[c], tag) 273 if len(s.componentTags[c]) == 0 { 274 delete(s.componentTags, c) 275 } 276 } 277 return true 278 } 279 280 func (s *Scene) ClearTags(tags ...string) { 281 for _, tag := range tags { 282 a, ok := s.tagToComponents.Del(tag) 283 if !ok { 284 continue 285 } 286 for _, c := range a.Values() { 287 delete(s.componentTags[c], tag) 288 if len(s.componentTags[c]) == 0 { 289 delete(s.componentTags, c) 290 } 291 } 292 } 293 } 294 295 func (s *Scene) TransferComponentTag(target string, origin string) { 296 a, ok := s.tagToComponents.Del(origin) 297 if !ok { 298 return 299 } 300 a.ResetKey(target) 301 _ = s.tagToComponents.Add(a) 302 for _, component := range a.Values() { 303 ca := s.componentTags[component] 304 delete(ca, origin) 305 ca[target] = struct{}{} 306 } 307 } 308 309 func (s *Scene) BindBeforeAddEntity(fn EntityToErr) { 310 s.onBeforeAddEntityLink.Push(fn) 311 } 312 313 func (s *Scene) BindAfterAddEntity(fn FnEntity) { 314 s.onAfterAddEntityLink.Push(fn) 315 } 316 317 func (s *Scene) BindBeforeDisposeEntity(fn EntityToErr) { 318 s.onBeforeDisposeEntityLink.Push(fn) 319 } 320 321 func (s *Scene) BindAfterDisposeEntity(fn FnEntity) { 322 s.onAfterDisposeEntityLink.Push(fn) 323 } 324 325 func (s *Scene) Dispose() { 326 for _, entity := range s.idToEntity.Values() { 327 entity.Dispose() 328 } 329 s.idToEntity = nil 330 s.componentTags = nil 331 s.tagToComponents = nil 332 }