Skip to content

Commit

Permalink
OnRemove and OnCreate callbacks (#130)
Browse files Browse the repository at this point in the history
* OnRemove and OnCreate callbacks

* Update world_test.go

* Adds world parameter

* Update world_test.go
  • Loading branch information
gin authored Mar 28, 2024
1 parent eaf13a5 commit d4f8606
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 0 deletions.
28 changes: 28 additions & 0 deletions world.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
Expand Down
23 changes: 23 additions & 0 deletions world_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down

0 comments on commit d4f8606

Please sign in to comment.