Exemplo n.º 1
0
        // http://docs.unity3d.com/Documentation/ScriptReference/Editor.OnSceneGUI.html
        void OnSceneGUI()
        {
            if (_mp.isActive && thisCollider) // Only enable the meshbrush when the user sets the specific instance to enabled (through the toggle in the inspector).
            {
                Handles.color = _mp.hColor;

                Time2Die = EditorApplication.timeSinceStartup;

                canPaint = (_t > Time2Die) ? false : true;

                activeBrushMode(); // Call the delegate method.

                // Assign the various brushmode methods to the delegate based on the current value of the brushmode enum.
                // This is very comfortable, because now I can just change the enum's value to swap the brushmodes with ease.
                switch (brushMode)
                {
                    case BrushMode.MeshPaint:
                        activeBrushMode = BrushMode_MeshPaint;
                        break;
                    case BrushMode.Sample:
                        activeBrushMode = BrushMode_SampleReferenceVector;
                        break;

                    default:
                        activeBrushMode = BrushMode_MeshPaint;
                        break;
                }

                switch (Event.current.type)
                {
                    // Increase/decrease the radius with the keyboard buttons I and O
                    case EventType.KeyDown:
                        if (Event.current.keyCode == _mp.increaseRadius)
                            _mp.hRadius += 0.05f;
                        else if (Event.current.keyCode == _mp.decreaseRadius && _mp.hRadius > 0)
                            _mp.hRadius -= 0.05f;
                        break;
                }

                // Draw the custom sampled reference slope vector in the scene view (given that the user wants it to appear and he is actually using the slope filter at all)...
                if (_mp.showRefVecInSceneGUI == true && _mp.manualRefVecSampling == true && _mp.activeSlopeFilter == true)
                    Handles.ArrowCap(0, _mp.slopeRefVec_HandleLocation, Quaternion.LookRotation(_mp.slopeRefVec), 0.9f);
            }

            // Smoothly clear the deletion buffer lobby
            // instead of deleting all meshes inside the brush area at once.
            // See more infos about that in the script MeshBrush.cs @ line 36.
            if (_mp.deletionBuffer.Count > 0)
            {
                if (nextDeletion < Time2Die || nextDeletion == 0d)
                {
                    nextDeletion = Time2Die + 0.25d;

                    for (int i = 0 ; i < _mp.deletionBuffer.Count ; i++)
                    {
                        DestroyImmediate(_mp.deletionBuffer[i]);
                    }
                    _mp.deletionBuffer.Clear();
                }
            }

            // Constantly fill up the paint buffer (with short delays between strokes, the buffer
            // can get drained out pretty quickly, so we wanna avoid that by filling it up regularly).
            int bufferSize = (_mp.useRandomMeshCount ? _mp.maxNrOfMeshes : _mp.meshCount) * 2;
            if (_mp.paintBuffer.Count < bufferSize)
            {
                if (nextBufferRefill < Time2Die || nextBufferRefill == 0d)
                {
                    nextBufferRefill = Time2Die + 0.1d;

                    for (int i = 0 ; i < bufferSize / 6 ; i++)
                    {
                        int r = Random.Range(0, _mp.setOfMeshesToPaint.Length);
                        GameObject bufferedObj = Instantiate(_mp.setOfMeshesToPaint[r]);

                        bufferedObj.name = _mp.setOfMeshesToPaint[r].name;
                        bufferedObj.hideFlags = HideFlags.HideInHierarchy;
                        bufferedObj.SetActive(false);

                        _mp.paintBuffer.Add(bufferedObj);
                    }
                }
            }
        }
Exemplo n.º 2
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();
                }
            }
        }