Files
2025-05-07 15:07:44 +08:00

202 lines
6.2 KiB
C#

using System;
using UnityEditor;
using UnityEditor.IMGUI.Controls;
using UnityEngine;
// Shapes © Freya Holmér - https://twitter.com/FreyaHolmer/
// Website & Documentation - https://acegikmo.com/shapes/
namespace Shapes {
public class SceneDiscEditor : SceneEditGizmos {
static bool isEditing;
ArcHandle arcHandleEnd = ShapesHandles.InitAngularHandle();
ArcHandle arcHandleStart = ShapesHandles.InitAngularHandle();
ArcHandle arcHandleRadius = ShapesHandles.InitRadialHandle();
ArcHandle arcHandleThicknessOuter = ShapesHandles.InitRadialHandle();
ArcHandle arcHandleThicknessInner = ShapesHandles.InitRadialHandle();
public SceneDiscEditor( Editor parentEditor ) => this.parentEditor = parentEditor;
protected override bool IsEditing {
get => isEditing;
set => isEditing = value;
}
Color GetAvgDiscColor( Disc disc ) {
switch( disc.ColorMode ) {
case Disc.DiscColorMode.Single: return disc.Color;
case Disc.DiscColorMode.Radial: return ( disc.ColorOuter + disc.ColorInner ) / 2f;
case Disc.DiscColorMode.Angular: return ( disc.ColorStart + disc.ColorEnd ) / 2f;
case Disc.DiscColorMode.Bilinear: return ( disc.ColorInnerStart + disc.ColorInnerEnd + disc.ColorOuterStart + disc.ColorOuterEnd ) / 2f;
default: throw new ArgumentOutOfRangeException();
}
}
Color GetHandleColor( ShapeRenderer shape ) {
if( shape is Disc disc )
return ShapesHandles.GetHandleColor( GetAvgDiscColor( disc ) );
return shape.Color;
}
static ShapeRenderer currentSceneShape;
static ThicknessSpace RadiusSpace {
get {
switch( currentSceneShape ) {
case Disc d: return d.RadiusSpace;
case RegularPolygon rp: return rp.RadiusSpace;
default: return default;
}
}
}
static ThicknessSpace ThicknessSpace {
get {
switch( currentSceneShape ) {
case Disc d: return d.ThicknessSpace;
case RegularPolygon rp: return rp.ThicknessSpace;
default: return default;
}
}
}
static bool HasThickness {
get {
switch( currentSceneShape ) {
case Disc d: return d.HasThickness;
case RegularPolygon rp: return rp.Border;
default: return default;
}
}
}
static float Thickness {
get {
switch( currentSceneShape ) {
case Disc d: return d.Thickness;
case RegularPolygon rp: return rp.Thickness;
default: return default;
}
}
set {
if( currentSceneShape is Disc d ) d.Thickness = value;
else if( currentSceneShape is RegularPolygon rp ) rp.Thickness = value;
}
}
static float Radius {
get {
switch( currentSceneShape ) {
case Disc d: return d.Radius;
case RegularPolygon rp: return rp.Radius;
default: return default;
}
}
set {
if( currentSceneShape is Disc d ) d.Radius = value;
else if( currentSceneShape is RegularPolygon rp ) rp.Radius = value;
}
}
public bool DoSceneHandles( ShapeRenderer shape ) {
if( IsEditing == false )
return false;
currentSceneShape = shape;
if( RadiusSpace != ThicknessSpace.Meters )
return false;
bool holdingShift = ( Event.current.modifiers & EventModifiers.Shift ) != 0;
bool editInnerOuterRadius = holdingShift;
// set up matrix
Vector3 rootDir = shape.transform.right;
Vector3 discNormal = shape.transform.forward;
Quaternion rot = Quaternion.LookRotation( rootDir, discNormal );
Matrix4x4 mtx = Matrix4x4.TRS( shape.transform.position, rot, Vector3.one ); // todo: scale?
using( new Handles.DrawingScope( GetHandleColor( shape ), mtx ) ) {
// thickness handles
if( HasThickness && ThicknessSpace == ThicknessSpace.Meters ) {
using( var chchk = new EditorGUI.ChangeCheckScope() ) {
arcHandleThicknessOuter.radius = Radius + Thickness * 0.5f;
arcHandleThicknessOuter.DrawHandle();
if( chchk.changed ) {
Undo.RecordObject( shape, "edit disc" );
if( editInnerOuterRadius ) {
float prevInnerRadius = Radius - Thickness * 0.5f;
float newOuterRadius = arcHandleThicknessOuter.radius;
Radius = ( prevInnerRadius + newOuterRadius ) / 2;
Thickness = newOuterRadius - prevInnerRadius;
} else {
Thickness = ( arcHandleThicknessOuter.radius - Radius ) * 2;
}
}
}
// inner radius
if( editInnerOuterRadius ) {
using( var chchk = new EditorGUI.ChangeCheckScope() ) {
arcHandleThicknessInner.radius = Radius - Thickness * 0.5f;
arcHandleThicknessInner.DrawHandle();
if( chchk.changed ) {
Undo.RecordObject( shape, "edit disc" );
float prevOuterRadius = Radius + Thickness * 0.5f;
float newInnerRadius = arcHandleThicknessInner.radius;
Radius = ( newInnerRadius + prevOuterRadius ) / 2;
Thickness = prevOuterRadius - newInnerRadius;
}
}
}
}
// radius handle
using( var chchk = new EditorGUI.ChangeCheckScope() ) {
arcHandleRadius.radius = Radius;
arcHandleRadius.DrawHandle();
if( chchk.changed ) {
Undo.RecordObject( shape, "edit disc radius" );
Radius = arcHandleRadius.radius;
}
}
// angle handles
if( shape is Disc disc ) {
if( disc.HasSector && editInnerOuterRadius == false ) {
arcHandleEnd.angle = disc.AngRadiansEnd * Mathf.Rad2Deg;
arcHandleStart.angle = disc.AngRadiansStart * Mathf.Rad2Deg;
foreach( ArcHandle arcHandle in new[] { arcHandleStart, arcHandleEnd } ) {
float radius = Radius;
if( ThicknessSpace == ThicknessSpace.Meters && HasThickness )
radius += Thickness / 2f;
arcHandle.radius = radius;
arcHandle.wireframeColor = Color.clear;
arcHandle.radiusHandleSizeFunction = pos => 0f; // no radius handle
using( var chchk = new EditorGUI.ChangeCheckScope() ) {
arcHandle.DrawHandle();
if( chchk.changed ) {
Undo.RecordObject( shape, "edit disc angle" );
//disc.Radius = arcHandle.radius;
if( arcHandle == arcHandleEnd )
disc.AngRadiansEnd = arcHandle.angle * Mathf.Deg2Rad;
else
disc.AngRadiansStart = arcHandle.angle * Mathf.Deg2Rad;
}
}
}
}
}
}
return false;
}
}
}