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  }