diff --git a/world.go b/world.go index 5d879a6..bf1bf9e 100644 --- a/world.go +++ b/world.go @@ -32,6 +32,13 @@ type World interface { StorageAccessor() StorageAccessor // ArcheTypes returns the archetypes in the world. Archetypes() []*storage.Archetype + + // OnCreate registers a callback function that gets triggered when an entity is created. + OnCreate(callback func(world World, entity Entity)) + + // OnRemove registers a callback function that gets triggered when an entity is removed. + // Note that it is called before the entity is removed from the ECS. + OnRemove(callback func(world World, entity Entity)) } // StorageAccessor is an accessor for the world's storage. @@ -55,6 +62,9 @@ type world struct { destroyed []Entity entries []*Entry nextEntityId storage.EntityId + + removeCallbacks []func(world World, entity Entity) + createCallbacks []func(world World, entity Entity) } var nextWorldId WorldId = 0 @@ -111,6 +121,11 @@ func (w *world) createEntity(archetypeIndex storage.ArchetypeIndex) Entity { w.entities.Insert(entity.Id(), archetypeIndex, componentIndex) archetype.PushEntity(entity) w.createEntry(entity) + + for _, callback := range w.createCallbacks { + callback(w, entity) + } + return entity } @@ -158,6 +173,11 @@ func (w *world) Len() int { func (w *world) Remove(ent Entity) { if w.Valid(ent) { + // Called before any operations so that user code can access all the data it might need + for _, callback := range w.removeCallbacks { + callback(w, ent) + } + loc := w.entities.LocationMap[ent.Id()] w.entities.Remove(ent.Id()) w.removeAtLocation(ent, loc) @@ -226,6 +246,14 @@ func (w *world) StorageAccessor() StorageAccessor { } } +func (w *world) OnCreate(callback func(world World, entity Entity)) { + w.createCallbacks = append(w.createCallbacks, callback) +} + +func (w *world) OnRemove(callback func(world World, entity Entity)) { + w.removeCallbacks = append(w.removeCallbacks, callback) +} + func (w *world) Archetypes() []*storage.Archetype { return w.archetypes } diff --git a/world_test.go b/world_test.go index 985c088..ca988ec 100644 --- a/world_test.go +++ b/world_test.go @@ -214,9 +214,32 @@ func TestArchetypeStorageExpands(t *testing.T) { func TestRemoveAndCreateEntity(t *testing.T) { world := donburi.NewWorld() + var calledCreate, calledRemove bool + + if calledCreate || calledRemove { + t.Fatalf("OnCreate/OnRemove event should not have been called at this point") + } + + world.OnCreate(func(world donburi.World, entity donburi.Entity) { + calledCreate = true + }) + + world.OnRemove(func(world donburi.World, entity donburi.Entity) { + calledRemove = true + }) + entityA := world.Create(tagA) + if !calledCreate { + t.Fatalf("OnCreate event must have been called at this point") + } + world.Remove(entityA) + + if !calledRemove { + t.Fatalf("OnCreate event must have been called at this point") + } + if world.Valid(entityA) { t.Errorf("Entity should be invalid") }