hellcat-nardo-felidal/Assets/_PoiyomiShaders/Scripts/ThryEditor/Editor/DecalTool.cs
2023-09-09 21:16:23 -07:00

177 lines
8.3 KiB
C#
Executable file

using UnityEditor;
using UnityEngine;
namespace Thry
{
public class DecalTool : EditorWindow
{
const string GUID_GIZMO_SHADER = "94a63a84353e517488db284dc8fab0ca";
private MaterialProperty _propPosition;
private MaterialProperty _propRotation;
private MaterialProperty _propScale;
private MaterialProperty _propOffset;
private MaterialProperty _propUVChannel;
private Material _material;
private Material _gizmoMaterial;
public static DecalTool OpenDecalTool(Material m)
{
var window = EditorWindow.GetWindow<DecalTool>("Decal Tool");
window._material = m;
window._gizmoMaterial = new Material(AssetDatabase.LoadAssetAtPath<Shader>(AssetDatabase.GUIDToAssetPath(GUID_GIZMO_SHADER)));
window._gizmoMaterial.color = Color.white;
return window;
}
public void SetMaterialProperties(MaterialProperty decalProp, MaterialProperty uvProp, MaterialProperty positionProp, MaterialProperty rotationProp, MaterialProperty scaleProp, MaterialProperty offsetProp)
{
_propPosition = positionProp;
_propRotation = rotationProp;
_propScale = scaleProp;
_propOffset = offsetProp;
_propUVChannel = uvProp;
_gizmoMaterial.SetTexture("_DecalTex", decalProp.textureValue);
this.Repaint();
}
private void OnGUI()
{
if(_propPosition == null)
{
return;
}
HandleInput();
// EditorGUI.DrawPreviewTexture(new Rect(0, 0, position.width, position.height), _material.mainTexture, _material);
EditorGUI.DrawTextureTransparent(new Rect(0, 0, position.width, position.height), _material.mainTexture, ScaleMode.StretchToFill);
_gizmoMaterial.SetVector("_Position", _propPosition.vectorValue);
_gizmoMaterial.SetVector("_Scale", _propScale.vectorValue);
_gizmoMaterial.SetFloat("_Rotation", _propRotation.floatValue);
_gizmoMaterial.SetVector("_Offset", _propOffset.vectorValue);
_gizmoMaterial.SetFloat("_UVChannel", _propUVChannel.floatValue);
EditorGUI.DrawPreviewTexture(new Rect(0, 0, position.width, position.height), Texture2D.whiteTexture, _gizmoMaterial);
}
private Vector2 _lastMousePosition;
private Vector2 _initialMousePosition;
private Vector4 _initalScale;
private float _initialRotation;
private bool _isInsideAction;
private bool _isOutsideAction;
private Vector2 _grabbedSnappoint;
private Vector2 _lastDecalMouseUV;
private Vector2 _initalDecalMouseUV;
private Vector2 _initalMouseUV;
private void HandleInput()
{
Vector2 pivot = _propPosition.vectorValue * position.size;
Vector2 pivotUV = pivot / position.size;
Vector2 mouseUV = Event.current.mousePosition / position.size;
mouseUV.y = 1 - mouseUV.y;
Vector2 decalMouseUV = DecalUV(mouseUV, _propPosition.vectorValue, _propRotation.floatValue, _propScale.vectorValue, _propOffset.vectorValue);
Event e = Event.current;
bool isMouseDrag = e.type == EventType.MouseDrag;
Vector2 delta = e.mousePosition - _lastMousePosition;
Vector2 deltaDecalUV = decalMouseUV - _lastDecalMouseUV;
if(isMouseDrag)
{
_lastMousePosition = e.mousePosition;
}
if (e.type == EventType.MouseDown && e.button == 0)
{
_initialMousePosition = e.mousePosition;
_lastMousePosition = e.mousePosition;
_initalMouseUV = mouseUV;
_initalDecalMouseUV = decalMouseUV;
_lastDecalMouseUV = decalMouseUV;
_initalScale = _propScale.vectorValue;
_initialRotation = _propRotation.floatValue;
_isInsideAction = decalMouseUV.x >= 0.1f && decalMouseUV.x <= 0.9f && decalMouseUV.y >= 0.1f && decalMouseUV.y <= 0.9f;
_isOutsideAction = decalMouseUV.x < -0.1f || decalMouseUV.x > 1.1f || decalMouseUV.y < -0.1f || decalMouseUV.y > 1.1f;
_grabbedSnappoint = new Vector2(Mathf.Round(decalMouseUV.x * 2), Mathf.Round(decalMouseUV.y * 2)) / 2;
}
// Translate
if (_isInsideAction && isMouseDrag && !e.alt)
{
delta = delta / position.size;
Vector2 pos = _propPosition.vectorValue;
pos.x += delta.x;
pos.y -= delta.y;
_propPosition.vectorValue = pos;
this.Repaint();
}
// Rotate
else if(_isOutsideAction && isMouseDrag && !e.alt)
{
Vector2 vecInital = _initalMouseUV - pivotUV;
Vector2 vecLast = mouseUV - pivotUV;
float angle = Vector2.SignedAngle(vecInital, vecLast);
SetClampedRotation(_propRotation, _initialRotation - angle);
this.Repaint();
}
// Scale
else if(isMouseDrag && e.alt)
{
Vector2 vecInital = _initalMouseUV - pivotUV;
Vector2 vecLast = mouseUV - pivotUV;
float vecLastIntoInitalDir = Vector2.Dot(vecLast, vecInital.normalized);
float uniform = vecInital.magnitude / vecLastIntoInitalDir;
_propScale.vectorValue = _initalScale / uniform;
this.Repaint();
}
// Offset
else if(isMouseDrag && !_isInsideAction && !_isOutsideAction)
{
Vector4 offset = _propOffset.vectorValue;
if(_grabbedSnappoint.x == 0)
offset.x = Mathf.Max(-_propScale.vectorValue.x / 2, offset.x - deltaDecalUV.x * _propScale.vectorValue.y);
if(_grabbedSnappoint.x == 1)
offset.y = Mathf.Max(-_propScale.vectorValue.x / 2, offset.y + deltaDecalUV.x * _propScale.vectorValue.y);
if(_grabbedSnappoint.y == 0)
offset.z = Mathf.Max(-_propScale.vectorValue.y / 2, offset.z - deltaDecalUV.y * _propScale.vectorValue.y);
if(_grabbedSnappoint.y == 1)
offset.w = Mathf.Max(-_propScale.vectorValue.y / 2, offset.w + deltaDecalUV.y * _propScale.vectorValue.y);
_propOffset.vectorValue = offset;
this.Repaint();
}
if(isMouseDrag)
{
_lastDecalMouseUV = DecalUV(mouseUV, _propPosition.vectorValue, _propRotation.floatValue, _propScale.vectorValue, _propOffset.vectorValue);
}
}
static Vector2 Remap(Vector2 x, Vector2 minOld, Vector2 maxOld, Vector2 minNew, Vector2 maxNew)
{
return minNew + (x - minOld) * (maxNew - minNew) / (maxOld - minOld);
}
static Vector2 DecalUV(Vector2 uv, Vector2 position, float rotation, Vector2 scale, Vector4 scaleOffset)
{
scaleOffset = new Vector4(-scaleOffset.x, scaleOffset.y, -scaleOffset.z, scaleOffset.w);
Vector2 centerOffset = new Vector2((scaleOffset.x + scaleOffset.y)/2, (scaleOffset.z + scaleOffset.w)/2);
Vector2 decalCenter = position + centerOffset;
float theta = Mathf.Deg2Rad * rotation;
float cs = Mathf.Cos(theta);
float sn = Mathf.Sin(theta);
uv = new Vector2((uv.x - decalCenter.x) * cs - (uv.y - decalCenter.y) * sn + decalCenter.x, (uv.x - decalCenter.x) * sn + (uv.y - decalCenter.y) * cs + decalCenter.y);
uv = Remap(uv, new Vector2(0, 0) - scale / 2 + position + new Vector2(scaleOffset.x, scaleOffset.z), scale / 2 + position + new Vector2(scaleOffset.y,scaleOffset.w), Vector2.zero, Vector2.one);
return uv;
}
public static void SetClampedRotation(MaterialProperty property, float value)
{
Vector2 limits = property.rangeLimits;
value = Helper.Mod(value - limits.x, limits.y - limits.x) + limits.x;
property.floatValue = value;
}
}
}