Exemple #1
0
        public void Reset()
        {
            EditorSceneManager.NewScene(NewSceneSetup.EmptyScene);
            mockMesher           = new MockMesher(mockGetComponent);
            mockMesher.CullFaces = true;//by default mesher is dependent on neighbour, as only the naive mesher is not
            mockProvider         = new MockProvider();
            mockComponentStorage = new Dictionary <Vector3Int, MockChunkComponent>();
            mockPlayChunkID      = Vector3Int.zero;
            mockLightManager     = Substitute.For <ILightManager>();
            mockLightManager.CreateGenerationJob(Arg.Any <Vector3Int>())
            .Returns(args =>
            {
                return(new BasicFunctionJob <LightmapGenerationJobResult>(() => new LightmapGenerationJobResult()));
            });

            mockManager = Substitute.For <IChunkManager>();
            mockManager.GetChunkComponent(Arg.Any <Vector3Int>())
            .Returns(args =>
            {
                var chunkId = (Vector3Int)args[0];
                return(mockGetComponent(chunkId));
            });
            mockManager.GetManhattanDistanceFromPlayer(Arg.Any <Vector3Int>())
            .Returns(args => {
                var chunkId = (Vector3Int)args[0];
                return(MockGetPriorityOfChunk(chunkId));
            });
            worldLimits = new WorldSizeLimits(false, 0);
            worldLimits.Initalise();
            mockManager.WorldLimits.Returns(worldLimits);
        }
Exemple #2
0
        public void SetTargetOfOutOfBoundsChunk()
        {
            worldLimits = new WorldSizeLimits(true, 8);
            worldLimits.Initalise();
            mockManager.WorldLimits.Returns(worldLimits);
            MakePipeline(1000, 1, 1, true, includeLighting: true);

            var testChunkID = new Vector3Int(0, 8, 0);//This chunk is outside the vertical limits

            mockComponentStorage.Add(testChunkID, new MockChunkComponent()
            {
                ChunkID = testChunkID, Data = Substitute.For <IChunkData>()
            });
            pipeline.AddWithData(testChunkID, pipeline.FullyGeneratedStage);

            AssertChunkStages(testChunkID, pipeline.FullyGeneratedStage);

            pipeline.SetTarget(testChunkID, pipeline.OwnStructuresStage);

            pipeline.Update();

            //Nothing should have been downgraded, as the chunk is outside the vertical limits
            AssertChunkStages(testChunkID, pipeline.FullyGeneratedStage);
        }
Exemple #3
0
        private void SetupMocks(Vector3Int chunkDimensions, WorldSizeLimits worldSizeLimits = null, bool generateStructures = true)
        {
            if (worldSizeLimits == null)
            {
                worldSizeLimits = new WorldSizeLimits(false, 0);
                worldSizeLimits.Initalise();
            }


            mockManager = Substitute.For <IChunkManager>();
            mockManager.GenerateStructures.Returns(generateStructures);
            mockManager.WorldToChunkPosition(Arg.Any <Vector3>()).Returns(args => WorldToChunkPos((Vector3)args[0], chunkDimensions));

            mockManager.WorldLimits.Returns(worldSizeLimits);
            mockManager.GetAllLoadedChunkIds().Returns((_) => statusMap.Keys.ToArray());

            mockPipeline = Substitute.For <IChunkPipeline>();
            mockPipeline.TerrainDataStage.Returns(0);
            mockPipeline.OwnStructuresStage.Returns(1);
            mockPipeline.FullyGeneratedStage.Returns(2);
            mockPipeline.RenderedStage.Returns(3);
            mockPipeline.CompleteStage.Returns(4);

            statusMap = new Dictionary <Vector3Int, int>();

            //Mock set target to write to the status map instead
            mockManager
            .When(_ => _.SetTargetStageOfChunk(Arg.Any <Vector3Int>(), Arg.Any <int>(), Arg.Any <TargetUpdateMode>()))
            .Do(args =>
            {
                Vector3Int pos = (Vector3Int)args[0];
                int newStatus  = (int)args[1];
                var mode       = (TargetUpdateMode)args[2];

                if (statusMap.TryGetValue(pos, out var currentStatus))
                {    //If the pos exists, ensure update modes are respected
                    if (newStatus > currentStatus && mode.allowsUpgrade())
                    {
                        statusMap[pos] = newStatus;
                    }
                    else if (newStatus < currentStatus && mode.allowsDowngrade())
                    {
                        statusMap[pos] = newStatus;
                    }
                }
                else
                {    //Otherwise, add the new pos and status
                    statusMap[pos] = newStatus;
                }
            });

            //Mock deactivate to remove from the status map
            mockManager
            .When(_ => _.TryDeactivateChunk(Arg.Any <Vector3Int>()))
            .Do(args =>
            {
                Vector3Int pos = (Vector3Int)args[0];
                statusMap.Remove(pos);
            });

            player          = Substitute.For <IVoxelPlayer>();
            player.Position = Vector3.zero;
        }
        public void Reset()
        {
            maxIntensity    = LightValue.MaxIntensity;
            heightMapYValue = 0;
            chunkDimensions = new Vector3Int(16, 16, 16);
            chunkStorage    = new Dictionary <Vector3Int, IChunkData>();

            lampId           = (VoxelTypeID)1;
            blockerId        = (VoxelTypeID)2;
            voxelTypeManager = Substitute.For <IVoxelTypeManager>();
            voxelTypeManager.LastVoxelID.Returns(blockerId);
            voxelTypeManager.GetLightProperties(Arg.Any <VoxelTypeID>())
            .Returns((args) =>
            {
                var typeId = (VoxelTypeID)args[0];
                if (typeId.Equals(lampId))
                {
                    return(maxIntensity, maxIntensity);
                }
                else if (typeId.Equals(blockerId))
                {
                    return(0, maxIntensity);
                }
                return(0, 1);
            });

            fullyGenerated = new HashSet <Vector3Int>();
            chunkManager   = Substitute.For <IChunkManager>();
            chunkManager.IsChunkFullyGenerated(Arg.Any <Vector3Int>())
            .Returns((args) =>
            {
                var id = (Vector3Int)args[0];
                return(fullyGenerated.Contains(id));
            });

            var worldLimits = new WorldSizeLimits(false, 0);

            worldLimits.Initalise();
            chunkManager.WorldLimits.Returns(worldLimits);

            chunkManager.ChunkToWorldPosition(Arg.Any <Vector3Int>())
            .Returns((args) =>
            {
                var chunkId = (Vector3Int)args[0];
                return(chunkId * chunkDimensions);
            });

            chunkManager.GetReadOnlyChunkData(Arg.Any <Vector3Int>())
            .Returns((args) =>
            {
                var chunkId = (Vector3Int)args[0];
                return(new RestrictedChunkData(GetMockChunkData(chunkId)));
            });

            chunkManager.GetChunkData(Arg.Any <Vector3Int>())
            .Returns((args) =>
            {
                var chunkId = (Vector3Int)args[0];
                return(GetMockChunkData(chunkId));
            });

            chunkManager.ChunkDimensions.Returns(chunkDimensions);

            IHeightMapProvider heightMapProvider = Substitute.For <IHeightMapProvider>();

            heightMapProvider.GetHeightMapForColumn(Arg.Any <Vector2Int>())
            .Returns((args) =>
            {
                return(getFlatHeightMap(heightMapYValue));
            });

            lightManager = new LightManager();
            lightManager.Initialise(voxelTypeManager, chunkManager, heightMapProvider);
        }
Exemple #5
0
        public ChunkPipelineManager(IChunkProvider chunkProvider,
                                    IChunkMesher chunkMesher,
                                    IChunkManager chunkManager,
                                    int maxDataPerUpdate,
                                    int maxMeshPerUpdate,
                                    int maxCollisionPerUpdate,
                                    bool structureGen          = false,
                                    int maxStructurePerUpdate  = 200,
                                    ILightManager lightManager = null)
        {
            getChunkComponent  = chunkManager.GetChunkComponent;
            this.chunkProvider = chunkProvider;
            this.chunkMesher   = chunkMesher;
            GenerateStructures = structureGen;
            worldLimits        = chunkManager.WorldLimits;

            bool lighting = lightManager != null;

            bool meshDependentOnNeighbours = chunkMesher.CullFaces || lighting;

            Func <Vector3Int, float> priorityFunc = chunkManager.GetManhattanDistanceFromPlayer;

            int i = 0;

            var ScheduledForData = new PrioritizedBufferStage("ScheduledForData", i++,
                                                              this, chunkManager.GetManhattanDistanceFromPlayer);

            stages.Add(ScheduledForData);

            var GeneratingData = new GenerateTerrainStage(
                "GeneratingTerrain", i++, this, maxDataPerUpdate);

            stages.Add(GeneratingData);

            TerrainDataStage   = i;
            OwnStructuresStage = i;

            if (structureGen)
            {
                ///Wait until all neighbours including diagonal ones have their terrain data
                var waitForNeighbourTerrain = new WaitForNeighboursStage(
                    "WaitForNeighbourTerrain", i++, this, true);
                stages.Add(waitForNeighbourTerrain);

                var scheduledForStructures = new PrioritizedBufferStage(
                    "ScheduledForStructures", i++, this, priorityFunc);
                stages.Add(scheduledForStructures);

                var generatingStructures = new GenerateStructuresStage(
                    "GeneratingStructures", i++, this, maxStructurePerUpdate);
                stages.Add(generatingStructures);

                ///At this point the chunk has generated all of its own structures.
                OwnStructuresStage = i;
                if (lighting)
                {
                    PreLightGenWaitStage = i;//This is the wait stage before lighting
                }
                var waitingForAllNeighboursToHaveStructures = new WaitForNeighboursStage(
                    "WaitForNeighbourStructures", i++, this, true);

                stages.Add(waitingForAllNeighboursToHaveStructures);
            }


            if (lighting)
            {
                if (!structureGen)
                {
                    PreLightGenWaitStage = i;
                    ///If structures are not generated, need a separate wait for neighbours.
                    ///Otherwise, the wait at the end of the structure generation is sufficient.
                    var waitingForNeighboursForLighting = new WaitForNeighboursStage(
                        "WaitForNeighboursPreLights", i++, this, false
                        );
                    stages.Add(waitingForNeighboursForLighting);
                }

                var scheduledForLighting = new PrioritizedBufferStage(
                    "ScheduledForLights", i++, this, priorityFunc);
                stages.Add(scheduledForLighting);

                var generatingLights = new GenerateLightsStage("GeneratingLights",
                                                               i++, this, lightManager.MaxChunksGeneratedPerUpdate, lightManager);
                stages.Add(generatingLights);
            }

            ///Passthrough stage to set chunkdata fully generated flag
            var preFullyGeneratedStage = new PassThroughApplyFunctionStage("PreFullGenerated", i++, this,
                                                                           (chunkId) =>
            {
                var chunkData = getChunkComponent(chunkId).Data;
                if (chunkData.FullyGenerated)
                {
                    var stageData = chunkStageMap.TryGetValue(chunkId, out var tmp) ? tmp : null;
                    Debug.LogError($"Chunk data for {chunkId} was listed as fully generated before reaching the fully generated stage!");
                }
                //The chunk is now fully generated, after having received both voxels and lighting.
                chunkData.FullyGenerated = true;
            });

            stages.Add(preFullyGeneratedStage);

            FullyGeneratedStage = i;

            if (meshDependentOnNeighbours)
            {
                /// If mesh is dependent on neighbour chunks, add a waiting stage
                /// to wait until the neighbours of a chunk have their data before
                /// moving that chunk onwards through the pipeline. Diagonals are included
                /// in the neighbourhood if structureGen is on.
                stages.Add(new WaitForNeighboursStage("WaitForNeighboursPreMesh", i++,
                                                      this, includeDiagonals: structureGen));
            }
            else
            {
                ///Otherwise, the chunk can move onwards freely
                stages.Add(new PassThroughStage("GotAllData", i++, this));
            }


            var ScheduledForMesh = new PrioritizedBufferStage("ScheduledForMesh", i++,
                                                              this, priorityFunc);

            stages.Add(ScheduledForMesh);

            var GeneratingMesh = new GenerateMeshStage("GeneratingMesh", i++,
                                                       this, maxMeshPerUpdate);

            stages.Add(GeneratingMesh);


            RenderedStage = i;
            stages.Add(new PassThroughStage("GotMesh", i++, this));

            var ScheduledForCollisionMesh = new PrioritizedBufferStage(
                "ScheduledForCollisionMesh", i++, this, priorityFunc);

            stages.Add(ScheduledForCollisionMesh);

            var ApplyingCollisionMesh = new ApplyCollisionMeshStage(
                "ApplyingCollisionMesh", i++, this, maxCollisionPerUpdate);

            stages.Add(ApplyingCollisionMesh);

            //Final stage
            CompleteStage = i;
            stages.Add(new PassThroughStage("Complete", i++, this));


            foreach (var stage in stages)
            {
                stage.Initialise();
            }
        }