Exemplo n.º 1
0
        private void PoolMeshInstances()
        {
            if (FoliageCore_MainManager.instance == null)
            {
                return;
            }

            _meshInstances = FoliageCore_MainManager.GetPrototypeMeshInstances(foliageAreaResolution);
        }
Exemplo n.º 2
0
        protected override void OnEnable()
        {
            base.OnEnable();

            _instance = this;

            if (sector == null)
            {
            }                       // call this to force the sector to be created if not available.

            FoliagePrototype.OnFoliageEnabledStateChangedEvent += OnFoliagePrototypeChanged;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Create a prototype.
        /// </summary>
        /// <param name="texture"></param>
        /// <param name="prefab"></param>
        /// <param name="minSize"></param>
        /// <param name="maxSize"></param>
        /// <param name="spread"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public static FoliagePrototype CreatePrototype(Texture2D texture, GameObject prefab, float minWidth, float minHeight, float maxWidth, float maxHeight, float spread, int layer, int id, Color healthyColor, Color dryColor)
        {
            FoliagePrototype prototype = new FoliagePrototype(texture, prefab, minWidth, minHeight, maxWidth, maxHeight, spread, layer, id);

            FoliageDB.instance.RegisterNewPrototype(prototype);

            prototype.GenerateInstantiatedMesh(healthyColor, dryColor);

            prototype.instancedEuler       = prototype.FoliageInstancedMeshData.eulerAngles;
            prototype.maxFoliageCapability = prototype.CalculateMaxFoliageCapability();
            prototype.UpdateManagerInformation();

            FoliageCore_MainManager.UpdateGrassMap();

            return(prototype);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Remove an existing Foliage prototype.
        /// </summary>
        public void RemovePrototype(FoliagePrototype prototype)
        {
            _prototypes.Remove(prototype);
            sortedPrototypes.Remove(prototype.id);

            FoliageCore_MainManager.DestroyMeshInstance(prototype.id);
            FoliageCore_MainManager.RemoveGrassMap(prototype);

            #if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                UnityEditor.EditorUtility.SetDirty(this);
            }
            #endif

            FoliageChunk.OnPrototypeDeleted(prototype.id);

            System.GC.SuppressFinalize(prototype);
        }
Exemplo n.º 5
0
        /// <summary>
        /// Add a new Foliage prototype.
        /// </summary>
        public void AddPrototype(Texture2D texture, GameObject prefab, float minWidth, float minHeight, float maxWidth, float maxHeight, float spread, int layer, Color healthyColor, Color dryColor)
        {
            int id = lastID;

            FoliagePrototype.CreatePrototype(texture, prefab, minWidth, minHeight, maxWidth, maxHeight, spread, layer, id, healthyColor, dryColor);

            FoliageCore_MainManager.GenerateFoliageMeshInstances(id);

            FoliageChunk.OnPrototypeCreated(id);

            #if UNITY_EDITOR
            if (!Application.isPlaying)
            {
                UnityEditor.EditorUtility.SetDirty(this);
            }
            #endif

            lastID++;
        }
Exemplo n.º 6
0
        protected virtual void ApplyScaleChange()
        {
            if (FoliageCore_MainManager.instance == null)
            {
                return;
            }

            FoliageCore_MainManager mInstance = FoliageCore_MainManager.instance;

            float scaleX = worldScale.x * transform.localScale.x;
            float scaleZ = worldScale.z * transform.localScale.z;

            mInstance.UpdateHeights(Mathf.FloorToInt(transform.position.x), Mathf.FloorToInt(transform.position.z), Mathf.CeilToInt(scaleX), Mathf.CeilToInt(scaleZ));

            scaleX = worldScale.x * lastReadScale.x;
            scaleZ = worldScale.z * lastReadScale.z;

            //revert old scale
            mInstance.UpdateHeights(Mathf.FloorToInt(transform.position.x), Mathf.FloorToInt(transform.position.z), Mathf.CeilToInt(scaleX), Mathf.CeilToInt(scaleZ));

            lastReadScale = transform.localScale;

            FoliageCore_MainManager.SaveDelayedMaps();
        }
Exemplo n.º 7
0
        /// <summary>
        /// Set detail layer in world cords
        /// </summary>
        /// <param name="baseX">WORLD CORDS!!</param>
        /// <param name="baseZ">WORLD CORDS!!</param>
        /// <param name="sizeX">WORLD CORDS!!</param>
        /// <param name="sizeZ">WORLD CORDS!!</param>
        /// <param name="prototypeIndex">prototype.id</param>
        /// <param name="densities">the density in bytes from 0 -> 15</param>
        public void SetDetailLayer(int baseX, int baseZ, int sizeX, int sizeZ, int prototypeIndex, byte[,] densities)
        {
            if (sector == null)
            {
                return;
            }

            if (densities.GetLength(0) != sizeX || densities.GetLength(1) != sizeZ)
            {
                Debug.LogError("uNature: Densities out of range!!");

                return;
            }

            Vector3 pos = transform.position;

            int startX = baseX;
            int startZ = baseZ;

            int endX = startX + sizeX;
            int endZ = startZ + sizeZ;

            int interpolatedX;
            int interpolatedZ;

            int mChunkID;
            FoliageCore_Chunk      mChunk;
            FoliageManagerInstance mInstance;

            FoliagePrototype prototype;
            FoliageGrassMap  grassMap;

            for (int x = startX; x < endX; x++)
            {
                for (int z = startZ; z < endZ; z++)
                {
                    mChunkID = GetChunkID(x - pos.x, z - pos.z);

                    if (!CheckChunkInBounds(mChunkID))
                    {
                        continue;                                // if position is out of bounds continue to the next position [very rare]
                    }
                    mChunk = _sector.foliageChunks[mChunkID];

                    if (!mChunk.isFoliageInstanceAttached)
                    {
                        continue;                                    // if this chunk doesnt have an manager instance attached then there's no need to modify it.
                    }
                    mInstance = mChunk.GetOrCreateFoliageManagerInstance();

                    interpolatedX = mInstance.TransformCord(x, mInstance.transform.position.x);
                    interpolatedZ = mInstance.TransformCord(z, mInstance.transform.position.z);

                    prototype = FoliageDB.sortedPrototypes[prototypeIndex];

                    grassMap = mInstance.grassMaps[prototype];

                    grassMap.mapPixels[interpolatedX + interpolatedZ * grassMap.mapWidth].b = densities[x - startX, z - startZ];
                    grassMap.SetPixels32Delayed();
                    grassMap.dirty = true;
                }
            }

            FoliageCore_MainManager.SaveDelayedMaps();
        }
Exemplo n.º 8
0
        public void OnGUI()
        {
            if (FoliageCore_MainManager.instance == null)
            {
                GUILayout.BeginVertical();
                GUILayout.Label("Foliage Manager Not Found!!");

                if (GUILayout.Button("Create Foliage Manager"))
                {
                    FoliageCore_MainManager.InitializeAndCreateIfNotFound();
                }
                GUILayout.EndVertical();

                return;
            }

            globalScrollPos = EditorGUILayout.BeginScrollView(globalScrollPos);

            ctrlPressed = Event.current == null ? false : Event.current.control;

            if (Event.current != null && Event.current.keyCode == KeyCode.Escape) // try to disable brush on GUI window
            {
                chosenBrushes.Clear();

                EditorUtility.SetDirty(FoliageDB.instance);
                EditorUtility.SetDirty(FoliageCore_MainManager.instance);
            }

            if (invisibleButtonStyle == null)
            {
                invisibleButtonStyle = new GUIStyle("Box");

                invisibleButtonStyle.normal.background  = null;
                invisibleButtonStyle.focused.background = null;
                invisibleButtonStyle.hover.background   = null;
                invisibleButtonStyle.active.background  = null;
            }

            FoliageCore_MainManager.instance.enabled = UNEditorUtility.DrawHelpBox(string.Format("Foliage Manager: (GUID : {0})", FoliageCore_MainManager.instance.guid), "Here you can manage and paint \nFoliage all over your scene!", true, FoliageCore_MainManager.instance.enabled); // add variable to edit.

            GUI.enabled = FoliageCore_MainManager.instance.enabled;

            DrawPaintWindow();

            GUILayout.Space(5);

            DrawPrototypesWindow();

            prototypesEditDataPos = EditorGUILayout.BeginScrollView(prototypesEditDataPos);

            GUILayout.Space(2);

            DrawPrototypesEditUI();

            GUILayout.Space(5);

            DrawGlobalSettingsUI();

            GUILayout.Space(5);

            DrawFoliageInstancesEditingUI();

            EditorGUILayout.EndScrollView();

            if (GUI.changed)
            {
                EditorUtility.SetDirty(FoliageDB.instance);
                EditorUtility.SetDirty(FoliageCore_MainManager.instance);
            }

            EditorGUILayout.EndScrollView();

            GUI.enabled = true;
        }
Exemplo n.º 9
0
        void PaintBrush(bool isErase, Vector2 position, PaintBrush brush)
        {
            FoliageCore_MainManager mManager = FoliageCore_MainManager.instance;

            int chunkID;
            FoliageManagerInstance mInstance;

            brush.TryToResize(paintBrushSize);

            Texture2D texture = brush.instancedTexture;

            int textureWidth  = texture.width;
            int textureHeight = texture.height;

            Color32 pixel;

            Color32[] grassMapPixels;
            int       mapWidth;

            int posX;
            int posZ;

            int transformedCordX;
            int transformedCordZ;

            FoliagePrototype prototype;
            FoliageGrassMap  grassMap;

            int radius = textureWidth / 2;

            byte density;

            for (int prototypeIndex = 0; prototypeIndex < chosenPrototypes.Count; prototypeIndex++)
            {
                prototype = chosenPrototypes[prototypeIndex];

                for (int x = 0; x < textureWidth; x++)
                {
                    for (int y = 0; y < textureHeight; y++)
                    {
                        pixel = brush.pixels[x, y];

                        if (pixel.r == 255 && pixel.g == 255 && pixel.b == 255)
                        {
                            posX = x - radius + (int)position.x - (int)mManager.transform.position.x;
                            posZ = y - radius + (int)position.y - (int)mManager.transform.position.z;

                            chunkID = mManager.GetChunkID(posX, posZ);

                            mInstance = mManager.sector.foliageChunks[chunkID].GetOrCreateFoliageManagerInstance();

                            transformedCordX = mInstance.TransformCord(posX, mInstance.attachedTo.transform.localPosition.x);
                            transformedCordZ = mInstance.TransformCord(posZ, mInstance.attachedTo.transform.localPosition.z);

                            grassMap = mInstance.grassMaps[prototype];

                            grassMapPixels = grassMap.mapPixels;
                            mapWidth       = grassMap.mapWidth;

                            density = grassMapPixels[transformedCordX + transformedCordZ * mapWidth].b;

                            if (paintDensity > density || (isErase && (instaRemove || paintDensity < density)))
                            {
                                grassMap.mapPixels[transformedCordX + transformedCordZ * mapWidth].b = isErase && instaRemove ? (byte)0 : paintDensity;

                                grassMap.dirty = true;
                                grassMap.SetPixels32Delayed();
                            }
                        }
                    }
                }

                FoliageCore_MainManager.SaveDelayedMaps();
                FoliageCore_MainManager.CallInstancesChunksUpdate();
            }
        }
Exemplo n.º 10
0
        void DrawPrototypesWindow()
        {
            GUILayout.BeginVertical("Box", GUILayout.Width(450));

            GUILayout.BeginHorizontal();
            GUILayout.Label("Prototypes Management:", EditorStyles.boldLabel);

            GUILayout.FlexibleSpace();

            if (chosenPrototypes.Count > 0)
            {
                if (GUILayout.Button("-", GUILayout.Width(15), GUILayout.Width(15)))
                {
                    if (EditorUtility.DisplayDialog("uNature", "Are you sure you want to delete this prototype ? \nThis cannot be undone!", "Yes", "No"))
                    {
                        for (int i = 0; i < chosenPrototypes.Count; i++)
                        {
                            FoliageDB.instance.RemovePrototype(chosenPrototypes[i]);
                        }
                        chosenPrototypes.Clear();

                        return;
                    }
                }
                if (GUILayout.Button(new GUIContent("R", "Remove the prototype density from this foliage manager.")))
                {
                    if (EditorUtility.DisplayDialog("uNature", "Are you sure you want to remove this prototype's density ? \nThis cannot be undone!", "Yes", "No"))
                    {
                        for (int i = 0; i < chosenPrototypes.Count; i++)
                        {
                            FoliageCore_MainManager.ResetGrassMap(chosenPrototypes);
                        }
                    }
                }

                if (GUILayout.Button(new GUIContent("L", "Locate the material instance of this prototype")))
                {
                    UnityEngine.Object[] selectionTargets = new UnityEngine.Object[chosenPrototypes.Count];

                    for (int i = 0; i < selectionTargets.Length; i++)
                    {
                        selectionTargets[i] = chosenPrototypes[i].FoliageInstancedMeshData.mat;
                    }

                    Selection.objects = selectionTargets;
                }
            }

            GUILayout.EndHorizontal();

            chosenPrototypes = UNEditorUtility.DrawPrototypesSelector(FoliageDB.unSortedPrototypes, chosenPrototypes, ctrlPressed, 440, ref prototypesScrollPos);

            #region Drag and drop
            DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
            if (Event.current.type == EventType.DragExited)
            {
                GameObject         targetFoliagePrefab;
                Texture2D          targetFoliageTexture;
                UnityEngine.Object targetGeneric;

                bool exists = false;

                for (int i = 0; i < DragAndDrop.objectReferences.Length; i++)
                {
                    targetFoliagePrefab  = DragAndDrop.objectReferences[i] as GameObject;
                    targetFoliageTexture = DragAndDrop.objectReferences[i] as Texture2D;

                    targetGeneric = targetFoliagePrefab == null ? (UnityEngine.Object)targetFoliageTexture : targetFoliagePrefab;

                    if (targetGeneric != null)
                    {
                        for (int b = 0; b < FoliageDB.unSortedPrototypes.Count; b++)
                        {
                            if ((targetFoliagePrefab != null && targetFoliagePrefab == FoliageDB.unSortedPrototypes[b].FoliageMesh) || (targetFoliageTexture != null && targetFoliageTexture == FoliageDB.unSortedPrototypes[b].FoliageTexture))
                            {
                                Debug.LogWarning("Foliage : " + targetGeneric.name + " Already exists! Ignored!");
                                exists = true;
                                break;
                            }
                        }
                    }

                    if (exists)
                    {
                        continue;
                    }

                    if (targetFoliagePrefab != null)
                    {
                        FoliageDB.instance.AddPrototype(targetFoliagePrefab);
                    }
                    else if (targetFoliageTexture != null)
                    {
                        FoliageDB.instance.AddPrototype(targetFoliageTexture);
                    }
                }
            }
            #endregion

            GUILayout.EndVertical();
        }
Exemplo n.º 11
0
        public void OnDrawCamera(Camera camera)
        {
            if (!FoliageCore_MainManager.instance.enabled || prototypeMeshInstances == null)
            {
                return;
            }

            bool            runCameraCheck = true;
            FoliageReceiver receiver       = null;

            #if UNITY_EDITOR
            runCameraCheck = !UnityEditor.SceneView.GetAllSceneCameras().Contains(camera);
            #endif

            if (runCameraCheck)
            {
                if (FoliageReceiver.FReceivers.Count == 0)
                {
                    return;
                }

                for (int i = 0; i < FoliageReceiver.FReceivers.Count; i++)
                {
                    if (camera == FoliageReceiver.FReceivers[i].playerCamera)
                    {
                        receiver = FoliageReceiver.FReceivers[i];

                        break;
                    }
                    if (i == FoliageReceiver.FReceivers.Count - 1)
                    {
                        return;
                    }
                }
            }

            if (receiver != null && !receiver.isGrassReceiver)
            {
                return;
            }

            int areaSizeIntegral = FoliageCore_MainManager.FOLIAGE_INSTANCE_AREA_SIZE;

            FoliageCore_Chunk[] targetedChunks = null;
            FoliageCore_Chunk   currentMChunk;

            if (receiver == null)
            {
                targetedChunks     = UNStandaloneUtility.GetFoliageChunksNeighbors(camera.transform.position - transform.position, targetedChunks);
                latestManagerChunk = targetedChunks[4];
            }
            else
            {
                targetedChunks     = receiver.neighbors;
                latestManagerChunk = receiver.middleFoliageChunkFromNeighbors;
            }

            Vector3 normalizedCameraPosition;

            FoliageManagerInstance mInstance;
            FoliageSector          sector;
            FoliageChunk           chunk;

            float density             = FoliageCore_MainManager.instance.density;
            int   instancesResolution = FoliageCore_MainManager.instance.instancesSectorResolution;

            #region PER_INSTANCE
            GPUMesh gpuInstance = null;

            FoliageChunk currentInstanceChunk;

            Vector3  pos;
            Material mat;

            int chunkIndex;

            FoliageMeshInstancesGroup meshGroup;
            FoliagePrototype          prototype;
            int maxDensity;

            FoliageMeshInstance meshInstance;

            Vector3 chunkPos;

            int gpuMeshIndex = -1;

            Camera renderCamera = Application.isPlaying ? camera : null;

            List <FoliageChunk> chunks;

            Mesh targetMesh;
            Dictionary <int, GPUMesh> prototypeInstances;

            bool  useQualitySettingsShadows = FoliageCore_MainManager.instance.useQualitySettingsShadowDistance;
            float shadowsDistance           = FoliageCore_MainManager.instance.foliageShadowDistance;
            #endregion

            propertyBlock.SetVector("_StreamingAdjuster", UNStandaloneUtility.GetStreamingAdjuster());

            if (receiver != null)
            {
                propertyBlock.SetFloat("_InteractionResolution", receiver.interactionMapResolutionIntegral);
            }

            for (int i = 0; i < targetedChunks.Length; i++)
            {
                currentMChunk = targetedChunks[i];

                if (currentMChunk == null)
                {
                    continue;
                }

                normalizedCameraPosition = camera.transform.position;

                if (!currentMChunk.InBounds(normalizedCameraPosition, 100) || !currentMChunk.isFoliageInstanceAttached)
                {
                    continue;
                }

                mInstance = currentMChunk.GetOrCreateFoliageManagerInstance();

                normalizedCameraPosition -= mInstance.transform.position;

                normalizedCameraPosition.x = Mathf.Clamp(normalizedCameraPosition.x, 0, areaSizeIntegral - 1);
                normalizedCameraPosition.z = Mathf.Clamp(normalizedCameraPosition.z, 0, areaSizeIntegral - 1);

                sector = mInstance.sector;
                chunks = sector.FoliageChunks;

                prototypeInstances = mInstance.meshInstances;

                chunk = sector.getChunk(normalizedCameraPosition) as FoliageChunk;

                if (chunk == null)
                {
                    continue;
                }

                if (receiver != null)
                {
                    propertyBlock.SetVector(PROPERTY_ID_FOLIAGE_INTERACTION_POSITION, chunk.position3D);
                }

                DEBUG_ResetValues();

                mInstance.UpdateMaterialBlock(propertyBlock);

                for (int prototypeIndex = 0; prototypeIndex < FoliageDB.unSortedPrototypes.Count; prototypeIndex++)
                {
                    prototype = FoliageDB.unSortedPrototypes[prototypeIndex];

                    if (!prototype.enabled)
                    {
                        continue;
                    }

                    int chunkOffset = FoliageMeshInstance.GENERATION_RANGE_OFFSET(prototype);

                    int prototypeRadius = (int)prototype.FoliageGenerationRadius;

                    propertyBlock.SetTexture(PROPERTY_ID_GRASSMAP, mInstance.grassMaps[prototype].map);

                    //DEBUG
                    _lastRenderedPrototypes++;

                    try
                    {
                        gpuInstance = prototypeInstances[prototype.id];
                    }
                    catch (System.Exception ex)
                    {
                        Debug.LogError(ex.ToString());

                        return;
                    }

                    try
                    {
                        mat = prototype.FoliageInstancedMeshData.mat;
                    }
                    catch
                    {
                        // if Foliage db was deleted/ a detail was removed...

                        FoliageCore_MainManager.DestroyMeshInstance(prototype.id);

                        OnDrawCamera(camera);
                        return;
                    }

                    int xIndex;
                    int zIndex;

                    for (int x = 0; x < prototypeRadius; x++)
                    {
                        for (int z = 0; z < prototypeRadius; z++)
                        {
                            xIndex = chunk.x + (x - chunkOffset);
                            zIndex = chunk.z + (z - chunkOffset);

                            if (xIndex < 0 || zIndex < 0)
                            {
                                continue;
                            }

                            chunkIndex = xIndex + (zIndex * instancesResolution);

                            if (chunkIndex >= chunks.Count)
                            {
                                continue;
                            }

                            currentInstanceChunk = chunks[chunkIndex];

                            if (currentInstanceChunk != null)
                            {
                                chunkPos = currentInstanceChunk.position3D;

                                maxDensity   = (int)(currentInstanceChunk.GetMaxDensityOnArea(prototype.id) * density);
                                gpuMeshIndex = gpuInstance.GetMesh(maxDensity);

                                if (gpuMeshIndex != -1)
                                {
                                    //meshGroup = gpuInstance.LODMeshInstances[x, z, gpuMeshIndex];
                                    meshGroup = gpuInstance.LODMeshInstances[gpuMeshIndex];

                                    targetMesh = gpuInstance.meshes[gpuMeshIndex].mesh;

                                    for (int j = 0; j < meshGroup.Count; j++)
                                    {
                                        meshInstance = meshGroup[j];

                                        pos = meshInstance.GetPosition(chunkPos);

                                        if (pos.x < 0 || pos.z < 0 || pos.x >= areaSizeIntegral || pos.z >= areaSizeIntegral)
                                        {
                                            continue;
                                        }

                                        propertyBlock.SetVector(PROPERTY_ID_WORLDPOSITION, pos);

                                        //DEBUG
                                        _lastRenderedVertices += targetMesh.vertexCount;

                                        //DEBUG
                                        _lastRenderedDrawCalls++;

                                        meshInstance.DrawAndUpdate(pos, targetMesh, mat, renderCamera, normalizedCameraPosition, prototype, propertyBlock, useQualitySettingsShadows, shadowsDistance);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }