|
@@ -23,6 +23,8 @@ function DynamicAppleSpawner:OnActivate()
|
|
|
self.lastPos = Vector3(0,0,0)
|
|
|
self.update = false
|
|
|
self.closestAppleTrees = {}
|
|
|
+ self.numPrefabsToSpawn = 0 -- don't spawn prefabs until a follow target exists
|
|
|
+ self.spawningPrefabs = false
|
|
|
|
|
|
self.appleTreeTag = Crc32(self.Properties.DestAppleTreeTag)
|
|
|
|
|
@@ -39,197 +41,221 @@ function DynamicAppleSpawner:OnActivate()
|
|
|
end
|
|
|
|
|
|
function DynamicAppleSpawner:OnSpawn(spawnTicket, entityList)
|
|
|
-
|
|
|
-
|
|
|
-- first entity should be the root
|
|
|
table.insert(self.freeAppleGroups, entityList[1])
|
|
|
+ self:SetPhysicsEnabled(entityList[1], false)
|
|
|
+ local entityName = GameEntityContextRequestBus.Broadcast.GetEntityName(entityList[1])
|
|
|
+ Debug.Log("$5 Spawned " .. tostring(entityName))
|
|
|
+
|
|
|
+ if self.numPrefabsSpawned >= self.numPrefabsToSpawn then
|
|
|
+ self.spawningPrefabs = false
|
|
|
+ end
|
|
|
+
|
|
|
+ local children = TransformBus.Event.GetChildren(entityList[1])
|
|
|
+ for i=1,#children do
|
|
|
+ local childId = children[i]
|
|
|
+ local pos = TransformBus.Event.GetLocalTranslation(childId)
|
|
|
+ Debug.Log("("..tostring(pos.x)..","..tostring(pos.y)..","..tostring(pos.z).."),")
|
|
|
+ end
|
|
|
+
|
|
|
+ -- mark all follow targets to update in case they are waiting on groups
|
|
|
+ for k,followTarget in pairs(self.followTargets) do
|
|
|
+ followTarget.update = true
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
function DynamicAppleSpawner.DestTagHandler:OnEntityTagAdded(entityId)
|
|
|
table.insert(self.component.appleTrees, entityId)
|
|
|
end
|
|
|
|
|
|
-function DynamicAppleSpawner.FollowTagHandler:OnEntityTagAdded(entityId)
|
|
|
- if self.component.followTargets == nil then
|
|
|
- self.component.followTargets = {}
|
|
|
+function DynamicAppleSpawner:AddFollowTarget(entityId)
|
|
|
+ if self.followTargets == nil then
|
|
|
+ self.followTargets = {}
|
|
|
end
|
|
|
- table.insert(self.component.followTargets, entityId)
|
|
|
+
|
|
|
+ self.followTargets[entityId] = {
|
|
|
+ position=Vector3(0,0,0),
|
|
|
+ update=false,
|
|
|
+ handler = nil,
|
|
|
+ OnTransformChanged = function(followTarget, localTM, worldTM)
|
|
|
+ local translation = worldTM:GetTranslation()
|
|
|
+ translation.z = self.Properties.GroundHeight
|
|
|
+
|
|
|
+ -- only set this target to update if we moved over the threshold
|
|
|
+ if followTarget.update == false and followTarget.position:GetDistanceSq(translation) > self.Properties.TranslationThreshold then
|
|
|
+ followTarget.update = true
|
|
|
+ followTarget.position = translation
|
|
|
+ followTarget.position.z = self.Properties.GroundHeight
|
|
|
+ end
|
|
|
+ end
|
|
|
+ }
|
|
|
+
|
|
|
+ self.followTargets[entityId].handler = TransformNotificationBus.Connect(self.followTargets[entityId], entityId)
|
|
|
+
|
|
|
+ self.numPrefabsToSpawn = self.numPrefabsToSpawn + self.Properties.NumPrefabsToSpawn
|
|
|
+
|
|
|
local entityName = GameEntityContextRequestBus.Broadcast.GetEntityName(entityId)
|
|
|
- Debug.Log("$5 Follow target entity: " .. tostring(entityName))
|
|
|
+ Debug.Log("$5 Follow target added " .. tostring(entityName))
|
|
|
end
|
|
|
|
|
|
-function DynamicAppleSpawner:OnTransformChanged(localTM, worldTM)
|
|
|
- local translation = worldTM:GetTranslation()
|
|
|
- translation.z = self.Properties.GroundHeight
|
|
|
-
|
|
|
- if self.Properties.DebugColliders then
|
|
|
- local pos = worldTM:GetTranslation() + worldTM:GetBasisY() *3.0
|
|
|
- local tm = Transform.CreateTranslation(pos)
|
|
|
- local overlapRequest = CreateSphereOverlapRequest( 0.5, tm)
|
|
|
- local physicsSystem = GetPhysicsSystem()
|
|
|
- local sceneHandle = physicsSystem:GetSceneHandle(DefaultPhysicsSceneName)
|
|
|
- local scene = physicsSystem:GetScene(sceneHandle)
|
|
|
- hits = scene:QueryScene(overlapRequest)
|
|
|
-
|
|
|
- DebugDrawRequestBus.Broadcast.DrawSphereAtLocation(pos, 0.5, Color(0.0,0.0,1.0), 0.2)
|
|
|
-
|
|
|
- if #hits.HitArray > 1 then
|
|
|
- Debug.Log("NumSphereHits " ..tostring(#hits.HitArray))
|
|
|
+function DynamicAppleSpawner.FollowTagHandler:OnEntityTagAdded(entityId)
|
|
|
+ self.component:AddFollowTarget(entityId)
|
|
|
+end
|
|
|
+
|
|
|
+function DynamicAppleSpawner:SetPhysicsEnabled(entityId, enabled)
|
|
|
+ -- change the physics settings on all descendents
|
|
|
+ local descendants = TransformBus.Event.GetAllDescendants(entityId)
|
|
|
+ if enabled then
|
|
|
+ for i=1,#descendants do
|
|
|
+ local descendantEntityId = descendants[i]
|
|
|
+ SimulatedBodyComponentRequestBus.Event.DisablePhysics(descendantEntityId)
|
|
|
+ end
|
|
|
+ else
|
|
|
+ for i=1,#descendants do
|
|
|
+ local descendantEntityId = descendants[i]
|
|
|
+ SimulatedBodyComponentRequestBus.Event.EnablePhysics(descendantEntityId)
|
|
|
end
|
|
|
end
|
|
|
-
|
|
|
- if self.update == false and self.lastPos:GetDistanceSq(translation) > self.Properties.TranslationThreshold then
|
|
|
- self.update = true
|
|
|
- self.lastPos = translation
|
|
|
+end
|
|
|
|
|
|
- self.lastPos.z = self.Properties.GroundHeight
|
|
|
+ function getAppleTreeIndex(appleTrees, entityId)
|
|
|
+ for k,tree in ipairs(appleTrees) do
|
|
|
+ if tree.entityId == entityId then
|
|
|
+ return k
|
|
|
+ end
|
|
|
end
|
|
|
+ return -1
|
|
|
+end
|
|
|
+
|
|
|
+function hitEntityId(hitArray, entityId)
|
|
|
+ for i=1,#hitArray do
|
|
|
+ if hitArray[i].EntityId == entityId then
|
|
|
+ return true
|
|
|
+ end
|
|
|
+ end
|
|
|
+ return false
|
|
|
end
|
|
|
|
|
|
function DynamicAppleSpawner:OnTick(delaTime, scriptTime)
|
|
|
+ local physicsSystem = GetPhysicsSystem()
|
|
|
+ local sceneHandle = physicsSystem:GetSceneHandle(DefaultPhysicsSceneName)
|
|
|
+ local scene = physicsSystem:GetScene(sceneHandle)
|
|
|
+ local needMorePrefabs = false
|
|
|
+
|
|
|
+ for k,followTarget in pairs(self.followTargets) do
|
|
|
+ if followTarget.update then
|
|
|
+ followTarget.update = false
|
|
|
+ local tm = Transform.CreateTranslation(followTarget.position)
|
|
|
+ -- use a small height to avoid intersecting apples if possible
|
|
|
+ -- otherwise need to filter
|
|
|
+ local dimensions = Vector3(self.Properties.DetectionRadius, self.Properties.DetectionRadius, 0.1)
|
|
|
+ local overlapRequest = CreateBoxOverlapRequest(dimensions, tm)
|
|
|
+ local hits = scene:QueryScene(overlapRequest)
|
|
|
|
|
|
- if self.update then
|
|
|
- self.update = false
|
|
|
- local tm = Transform.CreateTranslation(self.lastPos)
|
|
|
- -- use a small height to avoid intersecting apples if possible
|
|
|
- -- otherwise need to filter
|
|
|
- local dimensions = Vector3(self.Properties.DetectionRadius, self.Properties.DetectionRadius, 0.1)
|
|
|
- local overlapRequest = CreateBoxOverlapRequest(dimensions, tm)
|
|
|
-
|
|
|
- local physicsSystem = GetPhysicsSystem()
|
|
|
- local sceneHandle = physicsSystem:GetSceneHandle(DefaultPhysicsSceneName)
|
|
|
- local scene = physicsSystem:GetScene(sceneHandle)
|
|
|
- hits = scene:QueryScene(overlapRequest)
|
|
|
- local treesToRemove = {}
|
|
|
- local treesToAdd = {}
|
|
|
- local closestTrees = {}
|
|
|
-
|
|
|
- function getAppleTreeIndex(appleTrees, entityId)
|
|
|
- for k,tree in ipairs(appleTrees) do
|
|
|
- if tree.entityId == entityId then
|
|
|
- return k
|
|
|
- end
|
|
|
- end
|
|
|
- return -1
|
|
|
- end
|
|
|
-
|
|
|
- function hitEntityId(hitArray, entityId)
|
|
|
- for i=1,#hitArray do
|
|
|
- if hitArray[i].EntityId == entityId then
|
|
|
- return true
|
|
|
- end
|
|
|
- end
|
|
|
- return false
|
|
|
- end
|
|
|
-
|
|
|
- if hits.HitArray :Size()> 0 then
|
|
|
-
|
|
|
- if self.Properties.Debug then
|
|
|
- local aabb = Aabb.CreateCenterHalfExtents(self.lastPos, dimensions * 0.5)
|
|
|
- DebugDrawRequestBus.Broadcast.DrawAabb(aabb, Color(1.0,1.0,0.0), 1.0)
|
|
|
- Debug.Log("hit " .. tostring(hits.HitArray:Size()) .. " objects")
|
|
|
- end
|
|
|
+ local treesToRemove = {}
|
|
|
+ local treesToAdd = {}
|
|
|
+ local closestTrees = {}
|
|
|
|
|
|
- for k,tree in ipairs(self.closestAppleTrees) do
|
|
|
- if hitEntityId(hits.HitArray, tree.entityId) == false then
|
|
|
- if self.Properties.Debug then
|
|
|
- Debug.Log("Removing apple group entity " ..tostring(tree.applesEntityId))
|
|
|
- end
|
|
|
- -- remove this tree and free the apple group
|
|
|
- if tree.applesEntityId ~= -1 then
|
|
|
- table.insert(self.freeAppleGroups, tree.applesEntityId)
|
|
|
- TransformBus.Event.SetWorldTranslation(tree.applesEntityId, Vector3(0,0,-100))
|
|
|
+ if hits.HitArray :Size()> 0 then
|
|
|
+ if self.Properties.Debug then
|
|
|
+ local aabb = Aabb.CreateCenterHalfExtents(followTarget.position, dimensions * 0.5)
|
|
|
+ DebugDrawRequestBus.Broadcast.DrawAabb(aabb, Color(1.0,1.0,0.0), 1.0)
|
|
|
+ Debug.Log("hit " .. tostring(hits.HitArray:Size()) .. " objects")
|
|
|
+ end
|
|
|
+
|
|
|
+ for k,tree in ipairs(self.closestAppleTrees) do
|
|
|
+ if hitEntityId(hits.HitArray, tree.entityId) == false then
|
|
|
+ if self.Properties.Debug then
|
|
|
+ Debug.Log("Removing apple group entity " ..tostring(tree.applesEntityId))
|
|
|
+ end
|
|
|
+ RenderMeshComponentRequestBus.Event.SetVisibility(tree.entityId, true)
|
|
|
+
|
|
|
+ -- remove this tree and free the apple group
|
|
|
+ if tree.applesEntityId ~= -1 then
|
|
|
+ table.insert(self.freeAppleGroups, tree.applesEntityId)
|
|
|
+ self:SetPhysicsEnabled(tree.applesEntityId, false)
|
|
|
+ TransformBus.Event.SetWorldTranslation(tree.applesEntityId, Vector3(0,0,1))
|
|
|
+ end
|
|
|
+ table.insert(treesToRemove, tree.entityId)
|
|
|
end
|
|
|
- table.insert(treesToRemove, tree.entityId)
|
|
|
end
|
|
|
- end
|
|
|
-
|
|
|
-
|
|
|
- for i=1,#hits.HitArray do
|
|
|
- local entityId = hits.HitArray[i].EntityId
|
|
|
- local index = getAppleTreeIndex(self.closestAppleTrees, entityId)
|
|
|
|
|
|
- if index ~= -1 then
|
|
|
- table.insert(closestTrees, self.closestAppleTrees[index])
|
|
|
- elseif TagComponentRequestBus.Event.HasTag(entityId, self.appleTreeTag) then
|
|
|
- local applesEntityId = -1
|
|
|
- if #self.freeAppleGroups > 0 then
|
|
|
- applesEntityId = self.freeAppleGroups[#self.freeAppleGroups]
|
|
|
- if applesEntityId == nil or type(applesEntityId) == "number" then
|
|
|
- Debug.Log("Non EntityId found in freeAppleGroups " ..tostring(applesEntityId) .. " contains " ..#self.freeAppleGroups.." items")
|
|
|
- else
|
|
|
+ for i=1,#hits.HitArray do
|
|
|
+ local entityId = hits.HitArray[i].EntityId
|
|
|
+ local index = getAppleTreeIndex(self.closestAppleTrees, entityId)
|
|
|
+
|
|
|
+ if index ~= -1 and self.closestAppleTrees[index].applesEntityId ~= -1 then
|
|
|
+ table.insert(closestTrees, self.closestAppleTrees[index])
|
|
|
+ elseif TagComponentRequestBus.Event.HasTag(entityId, self.appleTreeTag) then
|
|
|
+ local applesEntityId = -1
|
|
|
+ if #self.freeAppleGroups > 0 then
|
|
|
+ applesEntityId = self.freeAppleGroups[#self.freeAppleGroups]
|
|
|
+ if applesEntityId == nil or type(applesEntityId) == "number" then
|
|
|
+ Debug.Log("Non EntityId found in freeAppleGroups " ..tostring(applesEntityId) .. " contains " ..#self.freeAppleGroups.." items")
|
|
|
+ followTarget.update = true
|
|
|
+ needMorePrefabs = true
|
|
|
+ else
|
|
|
+ if self.Properties.Debug then
|
|
|
+ Debug.Log("Claiming apple group " ..tostring(applesEntityId))
|
|
|
+ end
|
|
|
+ local treeTM = TransformBus.Event.GetWorldTM(entityId)
|
|
|
+ self:SetPhysicsEnabled(applesEntityId, false)
|
|
|
+ TransformBus.Event.SetWorldTM(applesEntityId, treeTM)
|
|
|
+ self:SetPhysicsEnabled(applesEntityId, true)
|
|
|
+
|
|
|
+ -- hide the render meshes
|
|
|
+ RenderMeshComponentRequestBus.Event.SetVisibility(entityId, false)
|
|
|
+ table.remove(self.freeAppleGroups)
|
|
|
+ table.insert(closestTrees, {entityId=entityId, applesEntityId=applesEntityId})
|
|
|
+ table.insert(treesToAdd, entityId)
|
|
|
+ end
|
|
|
+ else
|
|
|
if self.Properties.Debug then
|
|
|
- Debug.Log("Claiming apple group " ..tostring(applesEntityId))
|
|
|
+ Debug.Log("$4 Couldn't find free apple tree group in free pool of size" .. tostring(#self.freeAppleGroups))
|
|
|
end
|
|
|
- local treeTM = TransformBus.Event.GetWorldTM(entityId)
|
|
|
- TransformBus.Event.SetWorldTM(applesEntityId, treeTM)
|
|
|
- table.remove(self.freeAppleGroups)
|
|
|
+ needMorePrefabs = true
|
|
|
+ followTarget.update = true
|
|
|
end
|
|
|
- elseif self.Properties.Debug then
|
|
|
- Debug.Log("$4 Couldn't find free apple tree group containing" .. tostring(#self.freeAppleGroups) .. " elements")
|
|
|
end
|
|
|
- table.insert(closestTrees, {entityId=entityId, applesEntityId=applesEntityId})
|
|
|
- table.insert(treesToAdd, entityId)
|
|
|
+ end
|
|
|
+ else
|
|
|
+ for k,tree in ipairs(self.closestAppleTrees) do
|
|
|
+ table.insert(treesToRemove, tree.entityId)
|
|
|
end
|
|
|
end
|
|
|
- else
|
|
|
- for k,tree in ipairs(self.closestAppleTrees) do
|
|
|
- table.insert(treesToRemove, tree.entityId)
|
|
|
- end
|
|
|
- end
|
|
|
-
|
|
|
-
|
|
|
- if self.Properties.Debug then
|
|
|
- for k,tree in ipairs(closestTrees) do
|
|
|
- DebugDrawRequestBus.Broadcast.DrawSphereOnEntity(tree.entityId, 0.5, Color(1.0,0.0,0.0), 1.0)
|
|
|
- end
|
|
|
- end
|
|
|
- self.closestAppleTrees = closestTrees
|
|
|
- end
|
|
|
-
|
|
|
- if self.followTargets ~= nil then
|
|
|
- self.transformHandler = TransformNotificationBus.Connect(self, self.followTargets[1])
|
|
|
- end
|
|
|
-
|
|
|
- -- get apple tree positions
|
|
|
- if self.appleTreePositions == nil and false then
|
|
|
- local positions = {}
|
|
|
- self.appleTreePositions = {}
|
|
|
- for k,entityId in ipairs(self.appleTrees) do
|
|
|
- local tm = TransformBus.Event.GetWorldTM(entityId)
|
|
|
- local position = tm:GetTranslation()
|
|
|
- table.insert(positions, {entityId=entityId, transform=tm, position2D=Vector2(position.x, position.y)})
|
|
|
-
|
|
|
- self.appleTreePositions[entityId] = {transform=tm, closest={}}
|
|
|
- --table.insert(self.appleTreePositions, {EntityId=entityId, Transform=tm, Closest={}})
|
|
|
- end
|
|
|
-
|
|
|
- local numClosest = 16
|
|
|
- -- do a one time distance analysis (slow, but better than runtime check)
|
|
|
- for k,appleTree in ipairs(appleTreePositions) do
|
|
|
- local translation = appleTree.tm:GetTranslation()
|
|
|
- local position2D = Vector2(translation.x, translation.y)
|
|
|
|
|
|
- table.sort(positions, function (a,b) return position2D:GetDistanceSq(a.position2D) < position2D:GetDistanceSq(b.position2D) end)
|
|
|
|
|
|
- for j,otherPosition in ipairs(positions) do
|
|
|
- table.insert(appleTree.closest, otherPosition.entityId)
|
|
|
+ if self.Properties.Debug then
|
|
|
+ for k,tree in ipairs(closestTrees) do
|
|
|
+ DebugDrawRequestBus.Broadcast.DrawSphereOnEntity(tree.entityId, 0.5, Color(1.0,0.0,0.0), 1.0)
|
|
|
+ end
|
|
|
end
|
|
|
+ self.closestAppleTrees = closestTrees
|
|
|
end
|
|
|
end
|
|
|
+
|
|
|
+ if needMorePrefabs and self.spawningPrefabs == false then
|
|
|
+ self.numPrefabsToSpawn = self.numPrefabsToSpawn + 1
|
|
|
+ end
|
|
|
|
|
|
-
|
|
|
- -- spawn apples in pool
|
|
|
- if self.numPrefabsSpawned < self.Properties.NumPrefabsToSpawn then
|
|
|
- self.numPrefabsSpawned = self.numPrefabsSpawned + 1
|
|
|
- Debug.Log("$7 Spawning apple group " .. tostring(self.numPrefabsSpawned ))
|
|
|
- local tm = TransformBus.Event.GetWorldTM(self.entityId)
|
|
|
- local translation = tm:GetTranslation()
|
|
|
- local rotation = tm:GetRotation():GetEulerRadians()
|
|
|
- self.spawnableMediator:SpawnAndParentAndTransform(self.ticket, self.entityId, translation, rotation, 1.0)
|
|
|
+ -- spawn one apple group per frame for now
|
|
|
+ if self.numPrefabsSpawned < self.numPrefabsToSpawn then
|
|
|
+ self:SpawnAppleGroup()
|
|
|
end
|
|
|
end
|
|
|
|
|
|
+function DynamicAppleSpawner:SpawnAppleGroup()
|
|
|
+ self.numPrefabsSpawned = self.numPrefabsSpawned + 1
|
|
|
+
|
|
|
+ local tm = TransformBus.Event.GetWorldTM(self.entityId)
|
|
|
+ local translation = tm:GetTranslation()
|
|
|
+ local rotation = tm:GetRotation():GetEulerRadians()
|
|
|
+
|
|
|
+ Debug.Log("$7 Spawning apple group " .. tostring(self.numPrefabsSpawned ))
|
|
|
+ self.spawningPrefabs = true
|
|
|
+ self.spawnableMediator:SpawnAndParentAndTransform(self.ticket, self.entityId, translation, rotation, 1.0)
|
|
|
+end
|
|
|
+
|
|
|
function DynamicAppleSpawner:OnDeactivate()
|
|
|
if self.tickHandler ~= nil then
|
|
|
self.tickHandler:Disconnect()
|
|
@@ -243,6 +269,10 @@ function DynamicAppleSpawner:OnDeactivate()
|
|
|
self.DestTagHandler.handler = nil
|
|
|
self.FollowTagHandler.handler:Disconnect()
|
|
|
self.FollowTagHandler.handler = nil
|
|
|
+
|
|
|
+ for k,followTarget in pairs(self.followTargets) do
|
|
|
+ followTarget.handler:Disconnect()
|
|
|
+ end
|
|
|
end
|
|
|
|
|
|
return DynamicAppleSpawner
|