Пример #1
0
        private static void WeldDraftToMain(TerrainTile reference, TerrainTile welded, Coord weldDir)
        /// Lowers edges on welding to main tile
        {
            if (welded.draft.edges.heightEdges.IsEmpty)
            {
                welded.draft.edges.heightEdges.ReadFloats2D(welded.draft.terrain.terrainData.GetHeights(0, 0, welded.draft.terrain.terrainData.heightmapResolution, welded.draft.terrain.terrainData.heightmapResolution));
            }
            //for an unknown reason ready chunks in scene do not have their edges (generated or saved). Leads to "Empty weld array" error. Forcing to read from terrain.

            EdgesSet refEdges  = reference.main.edges;
            EdgesSet weldEdges = welded.draft.edges;

            //loading saved edges big array
            float[] refArr = refEdges.heightEdges.GetArr(weldDir);

            //duplicating neig saved edges short array
            float[] weldArr     = weldEdges.heightEdges.GetArr(-weldDir);
            float[] weldArrCopy = new float[weldArr.Length];
            //Array.Copy(weldArr, weldArrCopy, weldArr.Length); //will be re-filled anyways

            //welding and apply to terrain
            Weld.WeldArrays(refArr, weldArrCopy, lowerOnMismatch: true);

            Weld.ApplyToTerrain(welded.draft.terrain.terrainData, weldArrCopy, -weldDir);
        }
Пример #2
0
        private static void RestoreDraftWeld(TerrainTile welded, Coord weldDir)
        /// Restoring height edges if they were lowered by welding with main
        {
            EdgesSet edges = welded.draft.edges;

            float[] arr = edges.heightEdges.GetArr(weldDir);
            Weld.ApplyToTerrain(welded.draft.terrain.terrainData, arr, weldDir);
        }
Пример #3
0
        public static void WeldEdgesInThread(EdgesSet thisEdges, TerrainTileManager tileManager, Coord coord, bool isDraft = false)
        /// Welds edges (does not affect data)
        {
            if (tileManager == null)
            {
                return;
            }

            for (int d = 0; d < weldDirections.Length; d++)
            {
                TerrainTile neigTile = tileManager[coord + weldDirections[d]];
                if (neigTile == null ||
                    (isDraft && neigTile.draft == null) || (isDraft && !neigTile.draft.generateReady) ||
                    (!isDraft && neigTile.main == null) || (!isDraft && !neigTile.main.generateReady))
                {
                    continue;
                }
                //if null or not generate-ready

                EdgesSet neigEdges = isDraft ? neigTile.draft?.edges : neigTile.main?.edges;
                if (neigEdges == null || !neigEdges.ready)
                {
                    continue;
                }

                //height
                if (neigEdges.heightEdges != null && neigEdges.heightEdges.SizeX == thisEdges.heightEdges.SizeX)
                {
                    Weld.WeldEdges(neigEdges.heightEdges, neigTile.coord, thisEdges.heightEdges, coord);
                }

                //splats
                if (neigEdges.splatEdges != null && thisEdges.splatEdges != null && thisEdges.splatEdges.Length == neigEdges.splatEdges.Length)
                {
                    for (int i = 0; i < thisEdges.splatEdges.Length; i++)
                    {
                        if (thisEdges.splatEdges[i].SizeX == neigEdges.splatEdges[i].SizeX)
                        {
                            Weld.WeldEdges(neigEdges.splatEdges[i], neigTile.coord, thisEdges.splatEdges[i], coord);
                        }
                    }
                }

                //textures
                if (neigEdges.controlEdges != null && thisEdges.controlEdges != null && thisEdges.controlEdges.Length == neigEdges.controlEdges.Length)
                {
                    for (int i = 0; i < thisEdges.controlEdges.Length; i++)
                    {
                        if (thisEdges.controlEdges[i].SizeX == neigEdges.controlEdges[i].SizeX)
                        {
                            Weld.WeldEdges(neigEdges.controlEdges[i], neigTile.coord, thisEdges.controlEdges[i], coord);
                        }
                    }
                }
            }
        }
Пример #4
0
        private void Generate(Graph graph, TerrainTile tile, DetailLevel det, StopToken stop)
        /// Note that referencing det.task is illegal since task could be changed
        {
            OnBeforeTileGenerate?.Invoke(tile, det.data, stop);

            //do not return (for draft) until the end (apply)
//				if (!stop.stop) graph.CheckClear(det.data, stop);
            if (!stop.stop)
            {
                graph.Generate(det.data, stop);
            }
            if (!stop.stop)
            {
                graph.Finalize(det.data, stop);
            }

            //finalize event
            OnTileFinalized?.Invoke(tile, det.data, stop);

            //flushing products for playmode (all except apply)
            if (MapMagicObject.isPlaying)
            {
                det.data.Clear(clearApply: false);
            }

            //welding (before apply since apply will flush 2d array)
            if (!stop.stop)
            {
                Weld.ReadEdges(det.data, det.edges);
            }
            if (!stop.stop)
            {
                Weld.WeldEdgesInThread(det.edges, tile.mapMagic.tiles, tile.coord, det.data.isDraft);
            }
            if (!stop.stop)
            {
                Weld.WriteEdges(det.data, det.edges);
            }

            //enqueue apply
            //was: while the playmode is applied on SwitchLod to avoid unnecessary lags for main

            if (det.data.isDraft)
            {
                det.coroutine = CoroutineManager.Enqueue(() => ApplyNow(det, stop), Priority + 1000, "ApplyNow " + coord);
            }

            else                     //main
            {
                IEnumerator coroutine = ApplyRoutine(det, stop);
                det.coroutine = CoroutineManager.Enqueue(coroutine, Priority, "ApplyRoutine " + coord);
            }

            det.generateReady = true;
        }
Пример #5
0
        private static void WeldDraftToMain(TerrainTile reference, TerrainTile welded, Coord weldDir)
        /// Lowers edges on welding to main tile
        {
            EdgesSet refEdges  = reference.main.edges;
            EdgesSet weldEdges = welded.draft.edges;

            //loading saved edges big array
            float[] refArr = refEdges.heightEdges.GetArr(weldDir);

            //duplicating neig saved edges short array
            float[] weldArr     = weldEdges.heightEdges.GetArr(-weldDir);
            float[] weldArrCopy = new float[weldArr.Length];
            //Array.Copy(weldArr, weldArrCopy, weldArr.Length); //will be re-filled anyways

            //welding and apply to terrain
            Weld.WeldArrays(refArr, weldArrCopy, lowerOnMismatch: true);

            Weld.ApplyToTerrain(welded.draft.terrain.terrainData, weldArrCopy, -weldDir);
        }
Пример #6
0
        public void SwitchLod()
        /// Changes detail level based on main and draft avaialability and readyness
        {
            if (this == null)
            {
                return;                           //happens after scene switch
            }
            Profiler.BeginSample("Switch Lod");

            bool useMain  = main != null;
            bool useDraft = draft != null;

            //if both using main
            //if none disabling terrain

            //in editor
                        #if UNITY_EDITOR
            if (!MapMagicObject.isPlaying)
            {
                //if both detail levels are used - choosing the one should be displayed
                if (useMain && useDraft)
                {
                    //if generating Draft in DraftData - switching to draft
                    if (draft.data != null && mapMagic?.graph != null && !mapMagic.graph.AllOutputsReady(OutputLevel.Draft, draft.data))
                    {
                        useMain = false;
                    }

                    //if generating Both in MainData - switching to draft too
                    if (main.data != null && mapMagic?.graph != null && !mapMagic.graph.AllOutputsReady(OutputLevel.Draft | OutputLevel.Main, main.data))
                    {
                        useMain = false;
                    }

                    //if dragging graph dragfield - do not switch from draft back to main
                    if (mapMagic.guiDraggingField && ActiveTerrain == draft.terrain)
                    {
                        useMain = false;
                    }
                }
            }
            else
                        #endif

            //if playmode
            {
                //default case with drafts
                if (mapMagic.draftsInPlaymode)
                {
                    if ((int)distance > mapMagic.draftSwitchRange)
                    {
                        useMain = false;
                    }
                    if ((int)distance > mapMagic.tiles.generateRange && mapMagic.hideFarTerrains)
                    {
                        useDraft = false;
                    }
                    if (!draft.applyReady)
                    {
                        useDraft = false;                                        //hiding just moved terrains
                    }
                }

                //case no drafts at all
                else
                {
                    useDraft = false;
                    if ((int)distance > mapMagic.tiles.generateRange && mapMagic.hideFarTerrains)
                    {
                        useMain = false;
                    }
                }

                //starting apply if main is not fully applied yet
                if (useMain && !main.applyReady && main.generateReady && main.data.apply.Count != 0)
                {
                    IEnumerator coroutine = ApplyRoutine(main, null);
                    main.coroutine = CoroutineManager.Enqueue(coroutine, (int)(-distance * 100), "ApplyRoutinePlaymode " + coord);
                }

                //if main is not ready and using drafts
                if (useMain && useDraft && !main.applyReady)
                {
                    useMain = false;
                }
            }

            //debugging
            //string was = ActiveTerrain==main.terrain ? "main" : (ActiveTerrain==draft.terrain ? "draft" : "null");
            //string replaced = useMain ? "main" : (useDraft ? "draft" : "null");
            //Debug.Log("Switching lod. Was " + was + ", replaced with " + replaced);
            //if (was == "draft" && replaced == "main")
            //	Debug.Log("Test");

            //finding if lod switch is for real and switching active terrain
            Terrain newActiveTerrain;
            if (useMain)
            {
                newActiveTerrain = main.terrain;
            }
            else if (useDraft)
            {
                newActiveTerrain = draft.terrain;
            }
            else
            {
                newActiveTerrain = null;
            }

            bool lodSwitched = false;
            if (ActiveTerrain != newActiveTerrain)
            {
                lodSwitched   = true;
                ActiveTerrain = newActiveTerrain;
            }

            //disabling objects
            bool objsEnabled        = useMain;      // || (useDraft && mapMagic.draftsIfObjectsChanged);
            bool currentObjsEnabled = objectsPool.isActiveAndEnabled;
            if (!objsEnabled && currentObjsEnabled)
            {
                objectsPool.gameObject.SetActive(false);
            }
            if (objsEnabled && !currentObjsEnabled)
            {
                objectsPool.gameObject.SetActive(true);
            }


            //welding
            //TODO: check active terrain to know if the switch is for real
            if (lodSwitched &&
                mapMagic.tiles.Contains(coord))                  //otherwise error on SwitchLod called from Generate (when tile has been moved)
            {
                if (useMain)
                {
                    Weld.WeldSurroundingDraftsToThisMain(mapMagic.tiles, coord);
                    Weld.WeldCorners(mapMagic.tiles, coord);

                    //Weld.SetNeighbors(mapMagic.tiles, coord);
                    //Unity calls Terrain.SetConnectivityDirty on each terrain enable or disable that resets neighbors
                    //using autoConnect instead. AutoConnect is a crap but neighbors are broken
                }
                else if (useDraft && draft.applyReady)
                {
                    Weld.WeldThisDraftWithSurroundings(mapMagic.tiles, coord);
                }
            }

            if (lodSwitched)
            {
                OnLodSwitched?.Invoke(this, useMain, useDraft);
            }

            //CoroutineManager.Enqueue( ()=>Weld.SetNeighbors(mapMagic.tiles, coord) );
            //CoroutineManager.Enqueue( mapMagic.Tmp );
            //mapMagic.Tmp();

            Profiler.EndSample();
        }