public void ToNextPathNode(PlayerNavigationNode currentNode)
        {
            this.currentNode = currentNode;

            this.movementTargetPathNodeIndex++;
            this.movementT -= 1f;
        }
 public void StartMovement(PlayerNavigationNode startNode)
 {
     this.currentNode = startNode;
     this.isMoving    = true;
     this.movementT   = 0f;
     this.movementTargetPathNodeIndex = 1;
 }
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                NativeArray <Translation>                    translations       = chunk.GetNativeArray(this.translationType);
                NativeArray <Rotation>                       rotations          = chunk.GetNativeArray(this.rotationType);
                NativeArray <PlayerMovementData>             playerMovements    = chunk.GetNativeArray(this.playerMovementType);
                BufferAccessor <PlayerNavigationNodeElement> nodeBufferAccessor = chunk.GetBufferAccessor(this.pathNodeBufferType);

                for (int ci = 0, cn = chunk.Count; ci < cn; ci++)
                {
                    Translation        translation    = translations[ci];
                    Rotation           rotation       = rotations[ci];
                    PlayerMovementData playerMovement = playerMovements[ci];
                    DynamicBuffer <PlayerNavigationNodeElement> pathNodeBuffer = nodeBufferAccessor[ci];

                    // Move player along path if moving
                    if (playerMovement.isMoving)
                    {
                        float3 currentPosition = translation.Value;

                        // Current/target nodes
                        PlayerNavigationNode currentNode = playerMovement.currentNode;
                        PlayerNavigationNode targetNode  = pathNodeBuffer[playerMovement.movementTargetPathNodeIndex].Value;
                        float3 fromPosition = currentNode.WorldPosition;
                        float3 toPosition   = targetNode.WorldPosition;

                        // Get velocity and move
                        float d    = math.length(toPosition - fromPosition);
                        float secs = d / playerMovement.movementVelocity;
                        playerMovement.movementT += playerMovement.movementVelocity / secs;
                        currentPosition           = math.lerp(fromPosition, toPosition, playerMovement.movementT);

                        if (playerMovement.movementT >= 1f)
                        {
                            if (playerMovement.movementTargetPathNodeIndex < pathNodeBuffer.Length - 1)
                            {
                                playerMovement.ToNextPathNode(targetNode);
                            }
                            else
                            {
                                playerMovement.FinishMovement(targetNode);
                                currentPosition = toPosition;
                            }
                        }
                        translation.Value = currentPosition;

                        // Rotate toward movement direction
                        quaternion targetRot   = quaternion.LookRotation(math.normalize(toPosition - fromPosition), math.up());
                        float3     rotationDir = math.lerp(math.forward(rotation.Value), math.normalize(toPosition - fromPosition), playerMovement.rotationSmoothFactor * deltaTime);
                        rotation.Value = UnityEngine.Quaternion.Lerp(rotation.Value, targetRot, playerMovement.rotationSmoothFactor * deltaTime);

                        // Apply changes
                        translations[ci]    = translation;
                        rotations[ci]       = rotation;
                        playerMovements[ci] = playerMovement;
                    }
                }
            }
 public void FinishMovement(PlayerNavigationNode endNode)
 {
     this.currentNode = endNode;
     this.isMoving    = false;
 }
        protected override void OnUpdate()
        {
            // TEMPORARY for testing

            bool gatherBlocks = Input.GetKeyDown(KeyCode.F);

            if (gatherBlocks)
            {
                NativeArray <Entity>             currentBlocks   = this.blocksQuery.ToEntityArray(Allocator.TempJob);
                NativeArray <Translation>        translations    = new NativeArray <Translation>(currentBlocks.Length, Allocator.TempJob);
                NativeArray <Rotation>           rotations       = new NativeArray <Rotation>(currentBlocks.Length, Allocator.TempJob);
                NativeArray <BlockTraversalData> blockTraversals = new NativeArray <BlockTraversalData>(currentBlocks.Length, Allocator.TempJob);
                NativeArray <BlockGridNodeData>  blockGridNodes  = new NativeArray <BlockGridNodeData>(currentBlocks.Length, Allocator.TempJob);

                Translation          playerStartTranslation = new Translation();
                Rotation             playerStartRotation    = new Rotation();
                PlayerNavigationNode playerStartNode        = new PlayerNavigationNode();

                for (int i = 0, n = currentBlocks.Length; i < n; i++)
                {
                    translations[i]    = this.EntityManager.GetComponentData <Translation>(currentBlocks[i]);
                    rotations[i]       = this.EntityManager.GetComponentData <Rotation>(currentBlocks[i]);
                    blockTraversals[i] = this.EntityManager.GetComponentData <BlockTraversalData>(currentBlocks[i]);
                    blockGridNodes[i]  = this.EntityManager.GetComponentData <BlockGridNodeData>(currentBlocks[i]);
                }

                Entities.WithAll <Tag_NavigationGrid>().WithoutBurst().ForEach(
                    (int entityInQueryIndex, DynamicBuffer <AStarNodeElement> nodeBuf, ref NavigationGridData navigationGrid) => {
                    nodeBuf.Clear();

                    float minX, maxX;
                    minX = maxX = translations[0].Value.x;
                    float minZ, maxZ;
                    minZ = maxZ = translations[0].Value.z;
                    for (int ti = 0, tn = translations.Length; ti < tn; ti++)
                    {
                        if (minX > translations[ti].Value.x)
                        {
                            minX = translations[ti].Value.x;
                        }
                        if (maxX < translations[ti].Value.x)
                        {
                            maxX = translations[ti].Value.x;
                        }
                        if (minZ > translations[ti].Value.z)
                        {
                            minZ = translations[ti].Value.z;
                        }
                        if (maxZ < translations[ti].Value.z)
                        {
                            maxZ = translations[ti].Value.z;
                        }
                    }
                    int lengthX = (int)(math.abs(maxX - minX) / GridConstants.BLOCK_SIZE) + 1;
                    int lengthY = (int)(math.abs(maxZ - minZ) / GridConstants.BLOCK_SIZE) + 1;

                    navigationGrid.worldBoundsMin = new float2(minX, minZ);
                    navigationGrid.worldBoundsMax = new float2(maxX, maxZ);
                    navigationGrid.lengthX        = lengthX;
                    navigationGrid.lengthY        = lengthY;

                    for (int ti = 0, tn = translations.Length; ti < tn; ti++)
                    {
                        int x, y;
                        navigationGrid.WorldToGridPosition(translations[ti].Value, out x, out y);
                        int i          = (y * lengthX) + x;
                        AStarNode node = new AStarNode(x, y, i, true);
                        nodeBuf.Add(node);

                        BlockGridNodeData gridNode = new BlockGridNodeData()
                        {
                            XCoord = x,
                            YCoord = y,
                            Index  = i,
                        };
                        this.EntityManager.SetComponentData <BlockGridNodeData>(currentBlocks[ti], gridNode);

                        if (blockTraversals[ti].blockType == BlockType.Start)
                        {
                            playerStartTranslation = translations[ti];
                            playerStartRotation    = rotations[ti];
                            playerStartNode        = new PlayerNavigationNode(x, y, i, translations[ti].Value);
                        }
                    }
                    ;
                })
                .Run();

                translations.Dispose();
                rotations.Dispose();
                blockTraversals.Dispose();
                blockGridNodes.Dispose();


                currentBlocks.Dispose();

                EntityCommandBuffer.Concurrent ecb = this.endSimulationEntitySystem.CreateCommandBuffer().ToConcurrent();

                BufferFromEntity <Child> childrenBuffer = GetBufferFromEntity <Child>(true);
                //Entities.WithAll<Tag_Block>().ForEach(
                //	(int entityInQueryIndex, Entity entity) => {
                //		EntityUtils.EnableEntityHierarchy(ref ecb, entityInQueryIndex, entity, childrenBuffer);
                //	})
                //.Schedule();

                Entities.WithAll <Tag_BlockGroup>().ForEach(
                    (int entityInQueryIndex, ref DynamicBuffer <EntityElement> entityBuff) => {
                    for (int i = 0, n = entityBuff.Length; i < n; i++)
                    {
                        EntityUtils.DisableEntityHierarchy(ref ecb, entityInQueryIndex, entityBuff[i], childrenBuffer);
                    }
                })
                .Schedule();

                this.endSimulationEntitySystem.AddJobHandleForProducer(this.Dependency);

                //ecb = this.endSimulationEntitySystem.CreateCommandBuffer().ToConcurrent();

                //Entities.WithAll<Tag_Block>().ForEach(
                //	(int entityInQueryIndex, ref BlockSwitchData blockSwitch) => {
                //		blockSwitch.Reset();
                //		blockSwitch.RefreshView(ref ecb, entityInQueryIndex);
                //	})
                //.Schedule();

                //this.endSimulationEntitySystem.AddJobHandleForProducer(this.Dependency);

                Entities.WithAll <Tag_Player>().WithoutBurst().ForEach(
                    (ref PlayerMovementData playerMovement, ref Translation translation, ref Rotation rotation) => {
                    translation = playerStartTranslation;
                    rotation    = playerStartRotation;
                    playerMovement.currentNode = playerStartNode;
                })
                .Run();
            }

            /*
             * bool generateBlocks = Input.GetKeyDown(KeyCode.Space);
             *
             * if (!generateBlocks) {
             *      return;
             * }
             *
             * EntityCommandBuffer.Concurrent ecb = this.endSimulationEntitySystem.CreateCommandBuffer().ToConcurrent();
             *
             * Entity prefab = BlockManager.Instance.BlockPrefabEntity;
             *
             * NativeArray<Entity> currentBlocks = this.blocksQuery.ToEntityArray(Allocator.TempJob);
             *
             * Entities.WithAll<Tag_NavigationGrid>().WithoutBurst().ForEach(
             *      (int entityInQueryIndex, DynamicBuffer<AStarNodeElement> nodeBuf, ref NavigationGridData navigationGrid) =>
             * {
             *      for (int i = 0, n = currentBlocks.Length; i < n; i++) {
             *              ecb.DestroyEntity(entityInQueryIndex, currentBlocks[i]);
             *      }
             *
             *      Unity.Mathematics.Random random = new Unity.Mathematics.Random((uint)System.DateTime.Now.Millisecond);
             *      int rand = 0;
             *
             *      bool pathFound = false;
             *
             *      NativeArray<AStarNode> nodes = new NativeArray<AStarNode>(navigationGrid.LinearLength, Allocator.Temp);
             *
             *      while (!pathFound) {
             *
             *              for (int y = 0; y < navigationGrid.lengthY; y++) {
             *                      for (int x = 0; x < navigationGrid.lengthX; x++) {
             *                              int i = (y * navigationGrid.lengthX) + x;
             *                              AStarNode node;
             *                              bool forceWalkable = (x == 0 && y == 0) || (x == navigationGrid.lengthX - 1 && y == navigationGrid.lengthY - 1);
             *                              if (!forceWalkable && random.NextInt(0, navigationGrid.emptyRandFactor) < ++rand) {
             *                                      rand = 0;
             *                                      node = new AStarNode(x, y, i, false);
             *
             *                              } else {
             *                                      node = new AStarNode(x, y, i, true);
             *                              }
             *
             *                              nodes[i] = node;
             *                      }
             *              }
             *
             *              // Create temp grid
             *              AStarGrid aStarGrid = new AStarGrid(navigationGrid.lengthX, navigationGrid.lengthY, nodes);
             *
             *              // Start/end nodes
             *              AStarNode start = nodes[0];
             *              AStarNode end = nodes[nodes.Length - 1];
             *
             *              // Solve path
             *              NativeList<AStarNode> pathNodeList = new NativeList<AStarNode>(Allocator.Temp);
             *              pathFound = AStarSolver.SolvePath(aStarGrid, start, end, ref pathNodeList);
             *
             *              pathNodeList.Dispose();
             *              aStarGrid.Dispose();
             *      }
             *
             *      nodeBuf.Clear();
             *
             *      for (int i = 0, n = nodes.Length; i < n; i++) {
             *              if (nodes[i].IsTraverseable) {
             *                      float3 position = new float3(nodes[i].XCoord * GridConstants.BLOCK_SIZE, 0, nodes[i].YCoord * GridConstants.BLOCK_SIZE);
             *
             *                      Entity block = ecb.Instantiate(entityInQueryIndex, prefab);
             *
             *                      Translation translation = new Translation();
             *                      translation.Value = position;
             *                      ecb.SetComponent<Translation>(entityInQueryIndex, block, translation);
             *              }
             *
             *              nodeBuf.Add(nodes[i]);
             *      }
             *
             *      navigationGrid.pathRequested = true;
             *      navigationGrid.pathStart = nodeBuf[0];
             *      navigationGrid.pathEnd = nodeBuf[nodeBuf.Length - 1];
             *
             * }).WithDeallocateOnJobCompletion(currentBlocks).ScheduleParallel();
             *
             * this.endSimulationEntitySystem.AddJobHandleForProducer(this.Dependency);
             */
        }