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

185 lines
8.0 KiB
C#

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Shapes;
using UnityEditor;
public static class CodegenInterfaces {
static CodeWriter code;
public static void Generate() {
// find all component-based Shapes with interfaces
Assembly asm = Assembly.Load( "ShapesRuntime" );
var allShapes = asm.DefinedTypes.Where(
type => type.IsAbstract == false && ( type.BaseType == typeof(ShapeRenderer) || type.BaseType?.BaseType == typeof(ShapeRenderer) )
).OrderBy( type => type.FullName );
var shapesWithInterfaces = allShapes.Where( sh => sh.ImplementedInterfaces.Contains( typeof(IDashable) ) || sh.ImplementedInterfaces.Contains( typeof(IFillable) ) );
// generate code
code = new CodeWriter();
using( code.MainScope( typeof(CodegenInterfaces), "UnityEngine" ) ) {
foreach( var shape in shapesWithInterfaces ) {
code.Spacer();
using( code.Scope( $"public partial class {shape.Name}" ) ) {
if( shape.ImplementedInterfaces.Contains( typeof(IDashable) ) )
AppendDashLines( shape );
if( shape.ImplementedInterfaces.Contains( typeof(IFillable) ) )
AppendFillLines();
}
}
}
// write to file
string path = ShapesIO.RootFolder + "/Scripts/Runtime/Interfaces/GeneratedInterfaceImplementations.cs";
code.WriteTo( path );
}
static void Append( string s ) => code.Append( s );
const string DD_LINE = nameof(DashStyle) + "." + nameof(DashStyle.defaultDashStyleLine);
const string DD_RING = nameof(DashStyle) + "." + nameof(DashStyle.defaultDashStyleRing);
static string GetDefaultDashStyle( TypeInfo type ) => type.AsType() == typeof(Line) ? DD_LINE : DD_RING;
static string GetDashTypeCondition( TypeInfo type ) => type.AsType() == typeof(Line) ? "Geometry != LineGeometry.Volumetric3D" : "setType: true";
static void AppendDashLines( TypeInfo type ) {
Append( "[SerializeField] bool matchDashSpacingToSize = true;" );
Append( "public bool MatchDashSpacingToSize {" );
Append( "\tget => matchDashSpacingToSize;" );
Append( "\tset {" );
Append( "\t\tmatchDashSpacingToSize = value;" );
Append( "\t\tSetAllDashValues( now: true );" );
Append( "\t}" );
Append( "}" );
Append( "[SerializeField] bool dashed = false;" );
Append( "public bool Dashed {" );
Append( "\tget => dashed;" );
Append( "\tset {" );
Append( "\t\tdashed = value;" );
Append( "\t\tSetAllDashValues( now: true );" );
Append( "\t}" );
Append( "}" );
Append( $"[SerializeField] DashStyle dashStyle = {GetDefaultDashStyle( type )};" );
Append( "public float DashSize {" );
Append( "\tget => dashStyle.size;" );
Append( "\tset {" );
Append( "\t\tdashStyle.size = value;" );
Append( "\t\tfloat netDashSize = dashStyle.GetNetAbsoluteSize( dashed, thickness );" );
Append( "\t\tif( matchDashSpacingToSize )" );
Append( "\t\t\tSetFloat( ShapesMaterialUtils.propDashSpacing, GetNetDashSpacing() );" );
Append( "\t\tSetFloatNow( ShapesMaterialUtils.propDashSize, netDashSize );" );
Append( "\t}" );
Append( "}" );
Append( "public float DashSpacing {" );
Append( "\tget => matchDashSpacingToSize ? dashStyle.size : dashStyle.spacing;" );
Append( "\tset {" );
Append( "\t\tdashStyle.spacing = value;" );
Append( "\t\tSetFloatNow( ShapesMaterialUtils.propDashSpacing, GetNetDashSpacing() );" );
Append( "\t}" );
Append( "}" );
Append( "public float DashOffset {" );
Append( "\tget => dashStyle.offset;" );
Append( "\tset => SetFloatNow( ShapesMaterialUtils.propDashOffset, dashStyle.offset = value );" );
Append( "}" );
Append( "public DashSpace DashSpace {" );
Append( "\tget => dashStyle.space;" );
Append( "\tset {" );
Append( "\t\tSetInt( ShapesMaterialUtils.propDashSpace, (int)( dashStyle.space = value ) );" );
Append( "\t\tSetFloatNow( ShapesMaterialUtils.propDashSize, dashStyle.GetNetAbsoluteSize( dashed, thickness ) );" );
Append( "\t}" );
Append( "}" );
Append( "public DashSnapping DashSnap {" );
Append( "\tget => dashStyle.snap;" );
Append( "\tset => SetIntNow( ShapesMaterialUtils.propDashSnap, (int)( dashStyle.snap = value ) );" );
Append( "}" );
Append( "public DashType DashType {" );
Append( "\tget => dashStyle.type;" );
Append( "\tset => SetIntNow( ShapesMaterialUtils.propDashType, (int)( dashStyle.type = value ) );" );
Append( "}" );
Append( "public float DashShapeModifier {" );
Append( "\tget => dashStyle.shapeModifier;" );
Append( "\tset => SetFloatNow( ShapesMaterialUtils.propDashShapeModifier, dashStyle.shapeModifier = value );" );
Append( "}" );
Append( $"void SetAllDashValues( bool now ) => SetAllDashValues( dashStyle, Dashed, matchDashSpacingToSize, thickness, {GetDashTypeCondition( type )}, now );" );
Append( "float GetNetDashSpacing() => GetNetDashSpacing( dashStyle, dashed, matchDashSpacingToSize, thickness );" );
}
static void AppendFillLines() {
Append( "[SerializeField] private protected GradientFill fill = GradientFill.defaultFill;" );
Append( "[SerializeField] private protected bool useFill;" );
Append( "public GradientFill Fill {" );
Append( "\tget => fill;" );
Append( "\tset {" );
Append( "\t\tfill = value;" );
Append( "\t\tSetFillProperties();" );
Append( "\t}" );
Append( "}" );
Append( "public bool UseFill {" );
Append( "\tget => useFill;" );
Append( "\tset {" );
Append( "\t\tuseFill = value;" );
Append( "\t\tSetIntNow( ShapesMaterialUtils.propFillType, fill.GetShaderFillTypeInt( useFill ) );" );
Append( "\t}" );
Append( "}" );
Append( "public FillType FillType {" );
Append( "\tget => fill.type;" );
Append( "\tset {" );
Append( "\t\tfill.type = value;" );
Append( "\t\tSetIntNow( ShapesMaterialUtils.propFillType, fill.GetShaderFillTypeInt( useFill ) );" );
Append( "\t}" );
Append( "}" );
Append( "public FillSpace FillSpace {" );
Append( "\tget => fill.space;" );
Append( "\tset => SetIntNow( ShapesMaterialUtils.propFillSpace, (int)( fill.space = value ) );" );
Append( "}" );
Append( "public Vector3 FillRadialOrigin {" );
Append( "\tget => fill.radialOrigin;" );
Append( "\tset {" );
Append( "\t\tfill.radialOrigin = value;" );
Append( "\t\tSetVector4Now( ShapesMaterialUtils.propFillStart, fill.GetShaderStartVector() );" );
Append( "\t}" );
Append( "}" );
Append( "public float FillRadialRadius {" );
Append( "\tget => fill.radialRadius;" );
Append( "\tset {" );
Append( "\t\tfill.radialRadius = value;" );
Append( "\t\tSetVector4Now( ShapesMaterialUtils.propFillStart, fill.GetShaderStartVector() );" );
Append( "\t}" );
Append( "}" );
Append( "public Vector3 FillLinearStart {" );
Append( "\tget => fill.linearStart;" );
Append( "\tset {" );
Append( "\t\tfill.linearStart = value;" );
Append( "\t\tSetVector4Now( ShapesMaterialUtils.propFillStart, fill.GetShaderStartVector() );" );
Append( "\t}" );
Append( "}" );
Append( "public Vector3 FillLinearEnd {" );
Append( "\tget => fill.linearEnd;" );
Append( "\tset => SetVector3Now( ShapesMaterialUtils.propFillEnd, fill.linearEnd = value );" );
Append( "}" );
Append( "public Color FillColorStart {" );
Append( "\tget => fill.colorStart;" );
Append( "\tset => SetColorNow( ShapesMaterialUtils.propColor, fill.colorStart = value );" );
Append( "}" );
Append( "public Color FillColorEnd {" );
Append( "\tget => fill.colorEnd;" );
Append( "\tset => SetColorNow( ShapesMaterialUtils.propColorEnd, fill.colorEnd = value );" );
Append( "}" );
Append( "" );
Append( "private void SetFillProperties() {" );
Append( "\tif( useFill ) {" );
Append( "\t\tSetInt( ShapesMaterialUtils.propFillSpace, (int)fill.space );" );
Append( "\t\tSetVector4( ShapesMaterialUtils.propFillStart, fill.GetShaderStartVector() );" );
Append( "\t\tSetVector3( ShapesMaterialUtils.propFillEnd, fill.linearEnd );" );
Append( "\t\tSetColor( ShapesMaterialUtils.propColor, fill.colorStart );" );
Append( "\t\tSetColor( ShapesMaterialUtils.propColorEnd, fill.colorEnd );" );
Append( "\t}" );
Append( "" );
Append( "\tSetInt( ShapesMaterialUtils.propFillType, fill.GetShaderFillTypeInt( useFill ) );" );
Append( "}" );
}
}