Ejemplo n.º 1
0
        /// <summary>
        /// Initialize the wizard.
        /// </summary>
        /// <param name="meshBrush">The linked MeshBrush instance (the one whose range limits are being edited).</param>
        public void Initialize(MeshBrush meshBrush)
        {
            meshBrushInstance = new SerializedObject(meshBrush);
            {
                groupName        = meshBrushInstance.FindProperty("groupName");
                maxQuantityLimit = meshBrushInstance.FindProperty("maxQuantityLimit");
                maxDelayLimit    = meshBrushInstance.FindProperty("maxDelayLimit");
                maxDensityLimit  = meshBrushInstance.FindProperty("maxDensityLimit");
                minOffsetLimit   = meshBrushInstance.FindProperty("minOffsetLimit");
                maxOffsetLimit   = meshBrushInstance.FindProperty("maxOffsetLimit");
                maxMinimumAbsoluteDistanceLimit = meshBrushInstance.FindProperty("maxMinimumAbsoluteDistanceLimit");
                maxRandomScaleLimit             = meshBrushInstance.FindProperty("maxRandomScaleLimit");
                maxAdditiveScaleLimit           = meshBrushInstance.FindProperty("maxAdditiveScaleLimit");
            }

            helpString = "Edit the range limits of your MeshBrush instance here:";
            minSize    = maxSize = new Vector2(450.0f, 250.0f);

            Initialized = true;
        }
Ejemplo n.º 2
0
        // Save the settings of a specific MeshBrush instance
        // (global or inspector) to a MeshBrush template file.
        public static void SaveTemplate(MeshBrush instance)
        {
            // Abort the procedure in case the instance parameter is null.
            if (instance == null)
            {
                Debug.LogError("MeshBrush instance parameter is null!");
                return;
            }

            // Create the serializer.
            if (xml_templateSerializer == null)
            {
                xml_templateSerializer = new XmlSerializer(typeof(TemplateData));
            }

            // Ask the user via a file saving panel for the path where the MeshBrush template shall be stored.
            string templatePath = EditorUtility.SaveFilePanelInProject("Save MeshBrush template", "<template_name>", "meshbrush", "Save your favorite MeshBrush settings to disk for later reusage, so you don't have to set up the brushes again everytime.", "Assets/MeshBrush/Saved Templates");
            if (templatePath.Length != 0 && xml_templateSerializer != null)
            {
                // Create an instance of the TemplateData class (it holds the data we want to store).
                TemplateData data = new TemplateData(instance);

                // Initialize the xml file via the FileStream.
                using (xml_templateFile = new FileStream(templatePath, FileMode.Create))
                {
                    // Serialize the data to the xml file 
                    // (this is where the data actually gets written into the file).
                    xml_templateSerializer.Serialize(xml_templateFile, data);
                }
            }

            // Refresh Unity's AssetDatabase.
            // If we don't do this, the newly 
            // created xml file might not immediately show up in the project panel.
            AssetDatabase.Refresh();
        }
Ejemplo n.º 3
0
        // Method used to load up a template into a  
        // specific MeshBrush instance (global painting  
        // instance or traditional MeshBrush instance).
        public static bool LoadTemplate(MeshBrush instance)
        {
            if (instance == null)
            {
                Debug.LogError("MeshBrush instance parameter is null!");
                return false;
            }

            if (xml_templateSerializer == null)
            {
                xml_templateSerializer = new XmlSerializer(typeof(TemplateData));
            }

            string templatePath = EditorUtility.OpenFilePanel("Load MeshBrush Template", "Assets/MeshBrush/Saved Templates", "meshbrush");
            if (templatePath != null && templatePath.Length > 0 && xml_templateSerializer != null)
            {
                try
                {
                    // Deserialize the template into our transitory data holder class.
                    TemplateData data;
                    using (xml_templateFile = File.Open(templatePath, FileMode.Open))
                        data = (TemplateData)xml_templateSerializer.Deserialize(xml_templateFile);

                    // If the deserialization was successful, start 
                    // loading up the template data into the instance variables.
                    if (data != null)
                    {
                        instance.isActive = data.active;
                        instance.groupName = data.groupName;

                        if (data.setOfMeshesToPaint != null && data.setOfMeshesToPaint.Length != 0)
                        {
                            instance.setOfMeshesToPaint = new List<GameObject>(data.setOfMeshesToPaint.Length);
                            for (int i = 0; i < data.setOfMeshesToPaint.Length; i++)
                            {
                                instance.setOfMeshesToPaint.Add(string.CompareOrdinal(data.setOfMeshesToPaint[i], "null") == 0 ? null : (GameObject)AssetDatabase.LoadAssetAtPath(data.setOfMeshesToPaint[i], typeof(GameObject)));
                            }
                        }

                        if (data.globalPaintingLayers != null && data.globalPaintingLayers.Length != 0)
                        {
                            instance.globalPaintingLayers = null;
                            instance.globalPaintingLayers = new bool[32];
                            for (int i = 0; i < data.globalPaintingLayers.Length; i++)
                                instance.globalPaintingLayers[i] = data.globalPaintingLayers[i];
                        }

                        instance.paintKey = data.paintKey;
                        instance.deleteKey = data.deleteKey;
                        instance.combineAreaKey = data.combineAreaKey;
                        instance.increaseRadiusKey = data.increaseRadiusKey;
                        instance.decreaseRadiusKey = data.decreaseRadiusKey;

                        instance.hRadius = data.brushRadius;
                        instance.hColor = data.brushColor;

                        instance.meshCount = data.numberOfMeshesToPaint;
                        instance.useRandomMeshCount = data.useRandomNumberOfMeshesToPaint;
                        instance.minNrOfMeshes = data.minNrOfMeshes;
                        instance.maxNrOfMeshes = data.maxNrOfMeshes;
                        instance.delay = data.delay;
                        instance.meshOffset = data.verticalOffset;
                        instance.slopeInfluence = data.slopeInfluence;

                        instance.activeSlopeFilter = data.useSlopeFilter;
                        instance.maxSlopeFilterAngle = data.maxSlopeFilterAngle;
                        instance.inverseSlopeFilter = data.inverseSlopeFilter;
                        instance.manualRefVecSampling = data.manualReferenceVectorSampling;
                        instance.showRefVecInSceneGUI = data.showReferenceVectorInSceneGUI;

                        instance.slopeRefVec = data.slopeReferenceVector;
                        instance.slopeRefVec_HandleLocation = data.slopeReferenceVector_HandleLocation;

                        instance.useOverlapFilter = data.useOverlapFilter;
                        instance.absoluteMinDist = data.absoluteMinDist;
                        instance.useRandomAbsMinDist = data.useRandomAbsMinDist;
                        instance.randomAbsMinDist = data.randomAbsMinDist;

                        instance.yAxisIsTangent = data.yAxisIsTangent;
                        instance.invertY = data.invertY;
                        instance.scattering = data.scattering;
                        instance.autoStatic = data.autoStatic;
                        instance.uniformScale = data.uniformScale;
                        instance.constUniformScale = data.constantUniformScale;
                        instance.rWithinRange = data.randomWithinRange;

                        instance.rScaleW = data.randomScaleWidth;
                        instance.rScaleH = data.randomScaleHidth;
                        instance.rScale = data.randomScale;
                        instance.rUniformRange = data.randomUniformRange;
                        instance.rNonUniformRange = data.randomNonUniformRange;

                        instance.cScale = data.constantAdditiveScale;
                        instance.cScaleXYZ = data.constantScaleXYZ;

                        instance.rRot = data.randomRotation;

                        instance.autoSelectOnCombine = data.autoSelectOnCombine;
                    }

                    return true;
                }
                catch
                {
                    if (!EditorUtility.DisplayDialog("Template deserialization failed!", "MeshBrush Template deserialization failed!\nDid you mess with that template file?", "Yeah, sorry :/", "No..."))
                    {
                        if (EditorUtility.DisplayDialog("Hm...", "Are you sure?", "Yes", "No, lol"))
                            EditorUtility.DisplayDialog("Bug detected", "Sorry for the inconvenience! Please report this bug (including the involved template file) on MeshBrush's main Unity forum thread.\n\nLink:   http://tinyurl.com/MeshBrush", "Okay");
                        else EditorUtility.DisplayDialog("Warning", "Modifying a template file the wrong way can break it. Only modify the file directly if you know what you're doing. A simple change in the file's structure can already make the deserialization process fail.", "Okay");
                    }
                    else EditorUtility.DisplayDialog("Warning", "Modifying a template file the wrong way can break it. Only modify the file directly if you know what you're doing. A simple change in the file's structure can already make the deserialization process fail.", "Okay");

                    // If we have an exception and the deserialization fails, 
                    // we manually close the used xml file and dispose of its resources.
                    xml_templateFile.Close();

                    return false;
                }
            }
            return false;
        }
Ejemplo n.º 4
0
        public TemplateData(MeshBrush instance)
        {
            active = instance.isActive;
            groupName = instance.groupName;

            setOfMeshesToPaint = new string[instance.setOfMeshesToPaint.Count];
            for (int i = 0; i < instance.setOfMeshesToPaint.Count; i++)
                setOfMeshesToPaint[i] = instance.setOfMeshesToPaint[i] != null ? AssetDatabase.GetAssetPath(instance.setOfMeshesToPaint[i]) : "null";

            globalPaintingLayers = new bool[instance.globalPaintingLayers.Length];
            for (int i = 0; i < instance.globalPaintingLayers.Length; i++)
                globalPaintingLayers[i] = instance.globalPaintingLayers[i];

            paintKey = instance.paintKey;
            deleteKey = instance.deleteKey;
            combineAreaKey = instance.combineAreaKey;
            increaseRadiusKey = instance.increaseRadiusKey;
            decreaseRadiusKey = instance.decreaseRadiusKey;

            brushRadius = instance.hRadius;
            brushColor = instance.hColor;

            numberOfMeshesToPaint = instance.meshCount;
            useRandomNumberOfMeshesToPaint = instance.useRandomMeshCount;
            minNrOfMeshes = instance.minNrOfMeshes;
            maxNrOfMeshes = instance.maxNrOfMeshes;
            delay = instance.delay;
            verticalOffset = instance.meshOffset;
            slopeInfluence = instance.slopeInfluence;

            useSlopeFilter = instance.activeSlopeFilter;
            maxSlopeFilterAngle = instance.maxSlopeFilterAngle;
            inverseSlopeFilter = instance.inverseSlopeFilter;
            manualReferenceVectorSampling = instance.manualRefVecSampling;
            showReferenceVectorInSceneGUI = instance.showRefVecInSceneGUI;

            slopeReferenceVector = instance.slopeRefVec;
            slopeReferenceVector_HandleLocation = instance.slopeRefVec_HandleLocation;

            useOverlapFilter = instance.useOverlapFilter;
            absoluteMinDist = instance.absoluteMinDist;
            useRandomAbsMinDist = instance.useRandomAbsMinDist;
            randomAbsMinDist = instance.randomAbsMinDist;

            yAxisIsTangent = instance.yAxisIsTangent;
            invertY = instance.invertY;
            scattering = instance.scattering;
            autoStatic = instance.autoStatic;
            uniformScale = instance.uniformScale;
            constantUniformScale = instance.constUniformScale;
            randomWithinRange = instance.rWithinRange;

            randomScaleWidth = instance.rScaleW;
            randomScaleHidth = instance.rScaleH;
            randomScale = instance.rScale;
            randomUniformRange = instance.rUniformRange;
            randomNonUniformRange = instance.rNonUniformRange;

            constantAdditiveScale = instance.cScale;
            constantScaleXYZ = instance.cScaleXYZ;

            randomRotation = instance.rRot;

            autoSelectOnCombine = instance.autoSelectOnCombine;
        }
Ejemplo n.º 5
0
        void OnEnable()
        {
            // Reference to the script we are overriding.
            _mp = (MeshBrush)target;

            // Initialize the brushmode delegate. This is EXTREMELY important, since the call of a null delegate function could break everything spitting out horrible errors, if not even crash the program.
            activeBrushMode = BrushMode_MeshPaint;

            thisTransform = _mp.transform;
            thisCollider = _mp.GetComponent<Collider>();

            if (!thisCollider)
            {
                Debug.LogError("This GameObject has no collider attached to it. MeshBrush needs a collider in order to work properly though; fix please!");
            }

            // This sets up a holder object for our painted meshes
            // (in case we don't already have one we create one).
            MeshBrushParent[] holders = _mp.GetComponentsInChildren<MeshBrushParent>();
            if (holders.Length > 0)
            {
                _mp.holderObj = null;
                foreach(MeshBrushParent holder in holders)
                {
                    if (holder)
                    {
                        if (string.CompareOrdinal(holder.name, _mp.groupName) == 0)
                        {
                            _mp.holderObj = holder.transform;
                        }
                    }
                    else continue;
                }

                if (!_mp.holderObj)
                    CreateHolder();
            }
            else CreateHolder();

            // Create a brush object if we don't have one already. This is needed for multiple mesh painting.
            if (_mp.holderObj.FindChild("Brush") != null)
            {
                _mp.brush = _mp.holderObj.FindChild("Brush").gameObject;
                _mp.brushTransform = _mp.brush.transform;
            }
            else
            {
                _mp.brush = new GameObject("Brush");
                _mp.brushTransform = _mp.brush.transform; // Initialize the brush's transform variable.
                _mp.brushTransform.position = thisTransform.position;
                _mp.brushTransform.parent = _mp.holderObj;
            }

            // The GUI elements of the custom inspector, with their corresponding tooltips:

            toolTipColor = new GUIContent("Color:", "Color of the circle brush.");

            toolTipRadius = new GUIContent("Radius [m]:", "Radius of the circle brush.");

            toolTipFreq = new GUIContent("Delay [s]:", "If you press and hold down the paint button, this value will define the delay (in seconds) between paint strokes; thus, the higher you set this value, the slower you'll be painting meshes.");

            toolTipOffset = new GUIContent("Offset amount [cm]:", "Offsets all the painted meshes away from their underlying surface.\n\nThis is useful if your meshes are stuck inside your GameObject's geometry, or floating above it.\nGenerally, if you place your pivot points carefully, you won't need this.");

            toolTipSlopeInfluence = new GUIContent("Slope influence [%]:", "Defines how much influence slopes have on the rotation of the painted meshes.\n\nA value of 100% for example would adapt the painted meshes to be perfectly perpendicular to the surface beneath them, whereas a value of 0% would keep them upright at all times.");

            toolTipSlopeFilter = new GUIContent("Slope filter max. angle [°]:", "Avoids the placement of meshes on slopes and hills whose angles exceed this value.\nA low value of 20° for example would restrain the painting of meshes onto very flat surfaces, while the maximum value of 180° would deactivate the slope filter completely.");

            toolTipInvSlope = new GUIContent("Inverse slope filter", "Inverts the slope filter's functionality; low values of the filter would therefore focus the placement of meshes onto slopes instead of avoiding it.");

            toolTipManualRefVecS = new GUIContent("Manual reference vector sampling", "You can choose to manually sample a reference slope vector, whose direction will then be used by the slope filter instead of the world's Y-Up axis, to further help you paint meshes with the slope filter applied onto arbitrary geometry (like for instance painting onto huge round planet-meshes, concave topologies like caves etc...).\n\nTo sample one, enter the reference vector sampling mode by clicking the 'Sample reference vector' button below.");

            toolTipRefVecSample = new GUIContent("Sample reference vector", "Activates the reference vector sampling mode, which allows you to pick a normal vector of your mesh to use as a reference by the slope filter.\n\nPress " + _mp.paint + " to sample a vector.\nPress Esc to cancel the sampling and return to the regular mesh painting mode.\n(Deselecting and reselecting this object will also exit the sampling mode)");

            toolTipTangentY = new GUIContent("Y-Axis tangent to surface", "As you decrease the slope influence value, you can choose whether you want your painted meshes to be kept upright along the Y-Axis, or tangent to their underlying surface.");

            toolTipInvertY = new GUIContent("Invert Y-Axis", "Flips all painted meshes on their Y-Axis.\nUseful if you are painting upside down and still want your painted meshes to be kept upright (but pointing downwards) on sloped ceiling surfaces for instance.");

            toolTipInset = new GUIContent("Scattering [%]:", "Percentage of how much the meshes are scattered away from the center of the circle brush.\n\n(Default is 60%)");

            toolTipNR = new GUIContent("Nr. of meshes to paint:", "Maximum number of meshes you are going to paint inside the circle brush area at once.");

            toolTipUniformly = new GUIContent("Scale uniformly", "Applies the scale uniformly along all three XYZ axes.");

            toolTipUniformlyRange = new GUIContent("Scale within this random range [Min/Max(XYZ)]:", "Randomly scales the painted meshes between these two minimum/maximum scale values.\n\nX stands for the minimum scale and Y for the maximum scale applied.");

            toolTipWithinRange = new GUIContent("Scale within range", "Randomly scales the meshes based on custom defined random range parameters.");

            toolTipRot = new GUIContent("Random Y rotation amount [%]:", "Applies a random rotation around the local Y-axis of the painted meshes.");

            toolTipV4 = new GUIContent("[Min/Max Width (X/Y); Min/Max Height (Z/W)]", "Randomly scales meshes based on custom defined random ranges.\n\nThe X and Y values stand for the minimum and maximum width (it picks a random value between them); " +
                "the Z and W values are for the minimum and maximum height.");

            toolTipReset = new GUIContent("Reset all randomizers", "Resets all the randomize parameters back to zero.");

            toolTipAddScale = new GUIContent("Apply additive scale", "Applies a constant, fixed amount of 'additive' scale after the meshes have been placed.");

            toolTipFlagS = new GUIContent("Flag all painted\nmeshes as static", "Flags all the meshes you've painted so far as static in the editor.\nCheck out the Unity documentation about drawcall batching if you don't know what this is good for.");

            toolTipCombine = new GUIContent("Combine painted meshes", "Once you're done painting meshes, you can click here to combine them. This will combine all the meshes you've painted into one single mesh (one per material).\n\nVery useful for performance optimization.\nCannot be undone.");

            toolTipDelete = new GUIContent("Delete all painted meshes", "Are you sure? This will delete all the meshes you've painted onto this GameObject's surface so far (except already combined meshes).");

            for (int i = 0 ; i < _mp.paintBuffer.Count ; i++)
            {
                if (!_mp.paintBuffer[i])
                {
                    ClearPaintBuffer();
                }
            }
        }