You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
10 KiB
C#
286 lines
10 KiB
C#
// #define Z_DEBUG
|
|
|
|
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Polybrush;
|
|
using UnityEditor.SettingsManagement;
|
|
|
|
namespace UnityEditor.Polybrush
|
|
{
|
|
/// <summary>
|
|
/// Base class for brush modes.
|
|
/// </summary>
|
|
[System.Serializable]
|
|
internal abstract class BrushMode : ScriptableObject
|
|
{
|
|
static readonly string k_DefaultBrushColorGradient = "RGBA(0.227, 1.000, 0.227, 255.000)&0.000|RGBA(1.000, 1.000, 1.000, 255.000)&1.000|\n1.0000&0.000|0.2588&1.000|";
|
|
static readonly Color k_DefaultBrushColor = new Color(0f, .8f, 1f, 1f);
|
|
|
|
[UserSetting("General Settings", "Hide Wireframe", "Hides the object wireframe when a brush is hovering.")]
|
|
internal static Pref<bool> s_HideWireframe = new Pref<bool>("Brush.HideWireframe", true, SettingsScope.Project);
|
|
|
|
[UserSetting("General Settings", "Inner Brush Color", "Vertices inside the brush's Inner Radius will be highlighted with this color")]
|
|
internal static Pref<Color> s_FullStrengthColor = new Pref<Color>("Brush.BrushColor", k_DefaultBrushColor, SettingsScope.Project);
|
|
|
|
[UserSetting("General Settings", "Brush Gradient", "Vertices outside the Inner Radius will be highlighted with this gradient, matching the brush's Falloff curve")]
|
|
internal static Pref<Gradient> s_BrushGradientColor = new Pref<Gradient>("Brush.BrushColorGradient", GradientSerializer.Deserialize(k_DefaultBrushColorGradient), SettingsScope.Project);
|
|
|
|
// The message that will accompany Undo commands for this brush. Undo/Redo is handled by PolyEditor.
|
|
internal virtual string UndoMessage { get { return "Apply Brush"; } }
|
|
|
|
// A temporary component attached to the currently editing object. Use this to (by default) override the
|
|
// scene zoom functionality, or optionally extend (see OverlayRenderer).
|
|
[SerializeField] protected ZoomOverride tempComponent;
|
|
|
|
// The title to be displayed in the settings header.
|
|
protected abstract string ModeSettingsHeader { get; }
|
|
|
|
// The link to the documentation page for this mode.
|
|
protected abstract string DocsLink { get; }
|
|
|
|
protected Color innerColor, outerColor;
|
|
|
|
/// <summary>
|
|
/// Create the temporary component
|
|
/// </summary>
|
|
/// <param name="target">The object to attach the temporary component on</param>
|
|
protected virtual void CreateTempComponent(EditableObject target)
|
|
{
|
|
if(!Util.IsValid(target))
|
|
return;
|
|
|
|
if(tempComponent == null)
|
|
tempComponent = target.gameObjectAttached.AddComponent<ZoomOverride>();
|
|
|
|
tempComponent.hideFlags = HideFlags.HideAndDontSave;
|
|
tempComponent.SetWeights(null, 0f);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Update the temporary component with new weigths and strengh
|
|
/// </summary>
|
|
/// <param name="target">Target object containing the temporary component</param>
|
|
/// <param name="settings">Current brush settings</param>
|
|
protected virtual void UpdateTempComponent(BrushTarget target, BrushSettings settings)
|
|
{
|
|
if(!Util.IsValid(target))
|
|
return;
|
|
|
|
tempComponent.SetWeights(target.GetAllWeights(), settings.strength);
|
|
}
|
|
|
|
protected virtual void DestroyTempComponent()
|
|
{
|
|
if(tempComponent != null)
|
|
GameObject.DestroyImmediate(tempComponent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called on instantiation. Base implementation sets HideFlags.
|
|
/// </summary>
|
|
internal virtual void OnEnable()
|
|
{
|
|
this.hideFlags = HideFlags.HideAndDontSave;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when mode is disabled.
|
|
/// </summary>
|
|
internal virtual void OnDisable()
|
|
{
|
|
DestroyTempComponent();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Will be called by the unit test to ensure that all the settings are reset to default values, with basic settings or palettes
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal virtual bool SetDefaultSettings()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called by PolyEditor when brush settings have been modified.
|
|
/// Updates the temporary component
|
|
/// </summary>
|
|
/// <param name="target">Target object containing the temporary component</param>
|
|
/// <param name="settings">Modified brush settings</param>
|
|
internal virtual void OnBrushSettingsChanged(BrushTarget target, BrushSettings settings)
|
|
{
|
|
UpdateTempComponent(target, settings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inspector GUI shown in the Editor window.
|
|
/// </summary>
|
|
/// <param name="brushSettings"></param>
|
|
internal virtual void DrawGUI(BrushSettings brushSettings)
|
|
{
|
|
if( PolyGUILayout.HeaderWithDocsLink( PolyGUI.TempContent(ModeSettingsHeader, "")) )
|
|
Application.OpenURL(DocsLink);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse begins hovering an editable object.
|
|
/// </summary>
|
|
/// <param name="target">Object being hovered</param>
|
|
/// <param name="settings">Current brush settings</param>
|
|
internal virtual void OnBrushEnter(EditableObject target, BrushSettings settings)
|
|
{
|
|
if(s_HideWireframe.value && target.renderer != null)
|
|
{
|
|
// disable wirefame
|
|
PolyEditorUtility.SetSelectionRenderState(target.renderer, PolyEditorUtility.GetSelectionRenderState() & SelectionRenderState.Outline);
|
|
}
|
|
|
|
CreateTempComponent(target);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called whenever the brush is moved. Note that @target may have a null editableObject.
|
|
/// </summary>
|
|
/// <param name="target">Current target of the brush</param>
|
|
/// <param name="settings">Current brush settings</param>
|
|
internal virtual void OnBrushMove(BrushTarget target, BrushSettings settings)
|
|
{
|
|
UpdateTempComponent(target, settings);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse exits hovering an editable object.
|
|
/// </summary>
|
|
/// <param name="target">Previously hovered object</param>
|
|
internal virtual void OnBrushExit(EditableObject target)
|
|
{
|
|
if(target.renderer != null)
|
|
PolyEditorUtility.SetSelectionRenderState(target.renderer, PolyEditorUtility.GetSelectionRenderState());
|
|
|
|
DestroyTempComponent();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when the mouse begins a drag across a valid target.
|
|
/// </summary>
|
|
/// <param name="target"> The object the mouse is dragging on</param>
|
|
/// <param name="settings">Current brush settings</param>
|
|
internal virtual void OnBrushBeginApply(BrushTarget target, BrushSettings settings) {}
|
|
|
|
/// <summary>
|
|
/// Called every time the brush should apply itself to a valid target. Default is on mouse move.
|
|
/// </summary>
|
|
/// <param name="target">Object on which to apply the brush</param>
|
|
/// <param name="settings">Current brush settings</param>
|
|
internal abstract void OnBrushApply(BrushTarget target, BrushSettings settings);
|
|
|
|
|
|
/// <summary>
|
|
/// Called when a brush application has finished. Use this to clean up temporary resources or apply
|
|
/// deferred actions to a mesh (rebuild UV2, tangents, whatever).
|
|
/// </summary>
|
|
/// <param name="target">The Object the brush was being applied on</param>
|
|
/// <param name="settings">Current brush settings</param>
|
|
internal virtual void OnBrushFinishApply(BrushTarget target, BrushSettings settings)
|
|
{
|
|
DestroyTempComponent();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Update gizmos drawing color based on settings.
|
|
/// </summary>
|
|
internal void UpdateBrushGizmosColor()
|
|
{
|
|
innerColor = s_FullStrengthColor;
|
|
outerColor = s_BrushGradientColor.value.Evaluate(1f);
|
|
|
|
innerColor.a = .9f;
|
|
outerColor.a = .35f;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draw scene gizmos. Base implementation draws the brush preview.
|
|
/// </summary>
|
|
/// <param name="target">Current target Object</param>
|
|
/// <param name="settings">Current brush settings</param>
|
|
internal virtual void DrawGizmos(BrushTarget target, BrushSettings settings)
|
|
{
|
|
UpdateBrushGizmosColor();
|
|
foreach (PolyRaycastHit hit in target.raycastHits)
|
|
PolyHandles.DrawBrush(hit.position, hit.normal, settings, target.localToWorldMatrix, innerColor, outerColor);
|
|
|
|
#if Z_DEBUG
|
|
|
|
#if Z_DRAW_WEIGHTS || DRAW_PER_VERTEX_ATTRIBUTES
|
|
float[] w = target.GetAllWeights();
|
|
#endif
|
|
|
|
#if Z_DRAW_WEIGHTS
|
|
Mesh m = target.mesh;
|
|
Vector3[] v = m.vertices;
|
|
GUIContent content = new GUIContent("","");
|
|
|
|
Handles.BeginGUI();
|
|
for(int i = 0; i < v.Length; i++)
|
|
{
|
|
if(w[i] < .0001f)
|
|
continue;
|
|
|
|
content.text = w[i].ToString("F2");
|
|
GUI.Label(HandleUtility.WorldPointToSizedRect(target.transform.TransformPoint(v[i]), content, EditorStyles.label), content);
|
|
}
|
|
Handles.EndGUI();
|
|
#endif
|
|
|
|
#if DRAW_PER_VERTEX_ATTRIBUTES
|
|
|
|
Mesh m = target.editableObject.editMesh;
|
|
Color32[] colors = m.colors;
|
|
Vector4[] tangents = m.tangents;
|
|
List<Vector4> uv0 = m.uv0;
|
|
List<Vector4> uv1 = m.uv1;
|
|
List<Vector4> uv2 = m.uv2;
|
|
List<Vector4> uv3 = m.uv3;
|
|
|
|
int vertexCount = m.vertexCount;
|
|
|
|
Vector3[] verts = m.vertices;
|
|
GUIContent gc = new GUIContent("");
|
|
|
|
List<List<int>> common = MeshUtility.GetCommonVertices(m);
|
|
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
|
|
|
Handles.BeginGUI();
|
|
foreach(List<int> l in common)
|
|
{
|
|
if( w[l[0]] < .001 )
|
|
continue;
|
|
|
|
Vector3 v = target.transform.TransformPoint(verts[l[0]]);
|
|
|
|
if(colors != null) sb.AppendLine("color: " + colors[l[0]].ToString("F2"));
|
|
if(tangents != null) sb.AppendLine("tangent: " + tangents[l[0]].ToString("F2"));
|
|
if(uv0 != null && uv0.Count == vertexCount) sb.AppendLine("uv0: " + uv0[l[0]].ToString("F2"));
|
|
if(uv1 != null && uv1.Count == vertexCount) sb.AppendLine("uv1: " + uv1[l[0]].ToString("F2"));
|
|
if(uv2 != null && uv2.Count == vertexCount) sb.AppendLine("uv2: " + uv2[l[0]].ToString("F2"));
|
|
if(uv3 != null && uv3.Count == vertexCount) sb.AppendLine("uv3: " + uv3[l[0]].ToString("F2"));
|
|
|
|
gc.text = sb.ToString();
|
|
sb.Remove(0, sb.Length); // @todo .NET 4.0
|
|
GUI.Label(HandleUtility.WorldPointToSizedRect(v, gc, EditorStyles.label), gc);
|
|
}
|
|
Handles.EndGUI();
|
|
#endif
|
|
|
|
#endif
|
|
}
|
|
|
|
internal abstract void RegisterUndo(BrushTarget brushTarget);
|
|
|
|
internal virtual void UndoRedoPerformed(List<GameObject> modified)
|
|
{
|
|
DestroyTempComponent();
|
|
}
|
|
}
|
|
}
|