mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-02 19:38:24 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
523 lines
16 KiB
C#
523 lines
16 KiB
C#
using Sandbox.ModelEditor.Internal;
|
|
using System;
|
|
using System.Text;
|
|
|
|
namespace Sandbox.ModelEditor.Internal
|
|
{
|
|
public class BaseModelDocAttribute : Editor.MetaDataAttribute
|
|
{
|
|
internal string HelperName = "";
|
|
|
|
public BaseModelDocAttribute( string name )
|
|
{
|
|
HelperName = name;
|
|
}
|
|
|
|
public override void AddHelpers( List<Tuple<string, string[]>> helpers )
|
|
{
|
|
StringBuilder sb = new();
|
|
sb.AppendLine( "{" );
|
|
|
|
AddTransform( sb );
|
|
|
|
Dictionary<string, object> KVs = new();
|
|
AddKeys( KVs );
|
|
foreach ( var pair in KVs )
|
|
{
|
|
// Skip empty strings
|
|
if ( pair.Value == null || pair.Value is string && string.IsNullOrEmpty( (string)pair.Value ) ) continue;
|
|
|
|
sb.AppendLine( $"\t{pair.Key.QuoteSafe()} = {(pair.Value is string @string ? @string.QuoteSafe() : pair.Value.ToString().ToLower())}" );
|
|
}
|
|
sb.AppendLine( "}" );
|
|
|
|
helpers.Add( Tuple.Create( HelperName, new string[] { sb.ToString() } ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Internal, used to add multi level key-values.
|
|
/// </summary>
|
|
protected virtual void AddTransform( StringBuilder sb )
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add generic key-values to the helper.
|
|
/// </summary>
|
|
protected virtual void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
}
|
|
}
|
|
|
|
public class BaseTransformAttribute : BaseModelDocAttribute
|
|
{
|
|
/// <summary>
|
|
/// Internal name of the key that dictates which bone to use as parent for position/angles.
|
|
/// </summary>
|
|
public string Bone { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key that dictates which attachment to use as parent for position/angles.
|
|
/// </summary>
|
|
public string Attachment { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key to store position in, if set, allows the helper to be moved.
|
|
/// </summary>
|
|
public string Origin { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key to store angles in, allows the helper to be rotated.
|
|
/// </summary>
|
|
public string Angles { get; set; }
|
|
|
|
// These are present in the helper but do unknown things, unsed by default nodes
|
|
//public bool transform_chain { get; set; }
|
|
//public bool true_worldspace { get; set; }
|
|
//public string translation_only_key { get; set; }
|
|
|
|
public BaseTransformAttribute( string name ) : base( name )
|
|
{
|
|
}
|
|
|
|
protected override void AddTransform( StringBuilder sb )
|
|
{
|
|
var transformKeys = "";
|
|
if ( !string.IsNullOrEmpty( Origin ) ) transformKeys += $"\t\torigin_key = {Origin.QuoteSafe()}\r\n";
|
|
if ( !string.IsNullOrEmpty( Angles ) ) transformKeys += $"\t\tangles_key = {Angles.QuoteSafe()}\r\n";
|
|
if ( !string.IsNullOrEmpty( Attachment ) ) transformKeys += $"\t\tattachment_key = {Attachment.QuoteSafe()}\r\n";
|
|
if ( !string.IsNullOrEmpty( Bone ) ) transformKeys += $"\t\tbone_key = {Bone.QuoteSafe()}\r\n";
|
|
|
|
if ( !string.IsNullOrEmpty( transformKeys ) )
|
|
{
|
|
sb.AppendLine( $"\ttransform =\r\n\t{{\r\n{transformKeys}\t}}" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace Sandbox.ModelEditor
|
|
{
|
|
/// <summary>
|
|
/// Indicates that this class/struct should be available as GenericGameData node in ModelDoc
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct )]
|
|
public class GameDataAttribute : LibraryAttribute
|
|
{
|
|
internal string ListName { get; private set; }
|
|
|
|
/// <summary>
|
|
/// Indicates that this type compiles as list, rather than a single entry in the model.
|
|
/// This will also affect how you retrieve this data via Model.GetData().
|
|
/// </summary>
|
|
public bool AllowMultiple { get; set; } = false;
|
|
|
|
public GameDataAttribute( string name ) : base( name )
|
|
{
|
|
// For the pre existing list names we gotta do this.
|
|
if ( name == "particle" ) ListName = "particles_list";
|
|
else if ( name == "break_list_piece" ) ListName = "break_list";
|
|
else if ( name == "eye" ) ListName = "eye_data_list";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws 3 line axis visualization, which can set up to be manipulated via gizmos. You can have multiple of these.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true )]
|
|
public class AxisAttribute : BaseTransformAttribute
|
|
{
|
|
/// <summary>
|
|
/// Internal name of a boolean key that dictates whether this helper should draw or not. If unset, will draw always.
|
|
/// </summary>
|
|
public string Enabled { get; set; }
|
|
|
|
/// <summary>
|
|
/// If set to true, when the node is selected a line will be drawn from the helper to the parent attachment/bone.
|
|
/// </summary>
|
|
public bool ParentLine { get; set; }
|
|
|
|
public AxisAttribute() : base( "locator_axis" )
|
|
{
|
|
}
|
|
|
|
protected override void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
dict.Add( "enabled_key", Enabled );
|
|
if ( ParentLine ) dict.Add( "draw_parent", true );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws a box, which can be manipulated via gizmos. You can have multiple of these.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true )]
|
|
public class BoxAttribute : BaseTransformAttribute
|
|
{
|
|
internal string Dimensions { get; set; }
|
|
internal string Mins { get; set; }
|
|
internal string Maxs { get; set; }
|
|
|
|
/// <summary>
|
|
/// If set, the semi-transparent box "walls" will not be drawn.
|
|
/// </summary>
|
|
public bool HideSurface { get; set; }
|
|
|
|
/// <summary>
|
|
/// If set, gizmos will be shown in transform mode to quickly move/scale the box.
|
|
/// For "dimensions" box Origin/Angles must be set.
|
|
/// </summary>
|
|
public bool ShowGizmos { get; set; }
|
|
|
|
/// <summary>
|
|
/// Store the box's dimensions in a single key, acting as (maxs-mins) which assumes the box's center is at the models origin.
|
|
/// The box's center can be set up to be movable via "Origin" property and rotatable via "Angles" property.
|
|
/// </summary>
|
|
/// <param name="dimensionsKey">Internal name of a key on the node that will store the dimensions of the box.</param>
|
|
public BoxAttribute( string dimensionsKey ) : base( "box" )
|
|
{
|
|
Dimensions = dimensionsKey;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Store the box's dimensions in 2 keys as Mins and Maxs. This type cannot be rotated.
|
|
/// </summary>
|
|
/// <param name="minsKey">Internal name of a key on the node that will store the mins of the box.</param>
|
|
/// <param name="maxsKey">Internal name of a key on the node that will store the maxs of the box.</param>
|
|
public BoxAttribute( string minsKey, string maxsKey ) : base( "box" )
|
|
{
|
|
Mins = minsKey;
|
|
Maxs = maxsKey;
|
|
}
|
|
|
|
protected override void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
dict.Add( "dimensions_key", Dimensions );
|
|
dict.Add( "min_key", Mins );
|
|
dict.Add( "max_key", Maxs );
|
|
//dict.Add( "draw_bone_name", Enabled ); // Draws the name of the Bone when selected and hovered, is that useful?
|
|
if ( ShowGizmos ) dict.Add( "transform_gizmo", true );
|
|
if ( HideSurface ) dict.Add( "draw_surface", false );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws a sphere, which can be manipulated via gizmos. You can have multiple of these.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true )]
|
|
public class SphereAttribute : BaseTransformAttribute
|
|
{
|
|
internal string Radius { get; set; }
|
|
internal string Center { get; set; }
|
|
|
|
/// <summary>
|
|
/// If set, the semi-transparent sphere "wall"/surface will not be drawn.
|
|
/// </summary>
|
|
public bool HideSurface { get; set; }
|
|
|
|
public SphereAttribute( string radiusKey, string centerKey = "" ) : base( "sphere" )
|
|
{
|
|
Radius = radiusKey;
|
|
Center = centerKey;
|
|
}
|
|
|
|
protected override void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
dict.Add( "radius_key", Radius );
|
|
dict.Add( "center_key", Center );
|
|
if ( HideSurface ) dict.Add( "draw_surface", false );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws a capsule, which can be manipulated via gizmos. You can have multiple of these.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true )]
|
|
public class CapsuleAttribute : BaseTransformAttribute
|
|
{
|
|
internal string Point1 { get; set; }
|
|
internal string Point2 { get; set; }
|
|
internal string Radius1 { get; set; }
|
|
internal string Radius2 { get; set; }
|
|
|
|
/// <summary>
|
|
/// This variation has 1 radius for both points.
|
|
/// </summary>
|
|
public CapsuleAttribute( string point1Key, string point2key, string radiusKey ) : base( "capsule" )
|
|
{
|
|
Point1 = point1Key;
|
|
Point2 = point2key;
|
|
Radius1 = radiusKey;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This variation has independent radius for each point.
|
|
/// </summary>
|
|
public CapsuleAttribute( string point1Key, string point2key, string radius1Key, string radius2Key ) : base( "capsule" )
|
|
{
|
|
Point1 = point1Key;
|
|
Point2 = point2key;
|
|
Radius1 = radius1Key;
|
|
Radius2 = radius2Key;
|
|
}
|
|
|
|
protected override void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
dict.Add( "point0_key", Point1 );
|
|
dict.Add( "point1_key", Point2 );
|
|
|
|
if ( string.IsNullOrEmpty( Radius2 ) )
|
|
{
|
|
dict.Add( "radius_key", Radius1 );
|
|
return;
|
|
}
|
|
|
|
dict.Add( "independent_radii", true );
|
|
dict.Add( "radius0_key", Radius1 );
|
|
dict.Add( "radius1_key", Radius2 );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws a cylinder, which can be manipulated via gizmos. You can have multiple of these.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true )]
|
|
public class CylinderAttribute : CapsuleAttribute
|
|
{
|
|
/// <summary>
|
|
/// This variation has 1 radius for both points.
|
|
/// </summary>
|
|
public CylinderAttribute( string point1Key, string point2key, string radiusKey ) : base( point1Key, point2key, radiusKey )
|
|
{
|
|
HelperName = "cylinder";
|
|
}
|
|
|
|
/// <summary>
|
|
/// This variation has independent radius for each point.
|
|
/// </summary>
|
|
public CylinderAttribute( string point1Key, string point2key, string radius1Key, string radius2Key ) : base( point1Key, point2key, radius1Key, radius2Key )
|
|
{
|
|
HelperName = "cylinder";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A helper that draws axis of rotation and angle limit of a hinge joint.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true )]
|
|
public class HingeJointAttribute : BaseTransformAttribute
|
|
{
|
|
/// <summary>
|
|
/// Key name that dictates whether the hinge limit is enabled or not.
|
|
/// </summary>
|
|
public string EnableLimit { get; set; }
|
|
|
|
/// <summary>
|
|
/// Key name that stores the minimum angle value for the revolute joint.
|
|
/// </summary>
|
|
public string MinAngle { get; set; }
|
|
|
|
/// <summary>
|
|
/// Key name that stores the maximum angle value for the revolute joint.
|
|
/// </summary>
|
|
public string MaxAngle { get; set; }
|
|
|
|
public HingeJointAttribute() : base( "physicsjoint_hinge" )
|
|
{
|
|
}
|
|
|
|
protected override void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
dict.Add( "min_angle", MinAngle );
|
|
dict.Add( "max_angle", MaxAngle );
|
|
dict.Add( "enable_limit", EnableLimit );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a custom editor widget to the game data node.
|
|
/// Currently only 1 option is available - "HandPosePairEditor"
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct )]
|
|
public class EditorWidgetAttribute : Editor.MetaDataAttribute
|
|
{
|
|
internal string Editor;
|
|
|
|
public EditorWidgetAttribute( string editor )
|
|
{
|
|
Editor = editor;
|
|
}
|
|
|
|
public override void AddHelpers( List<Tuple<string, string[]>> helpers )
|
|
{
|
|
helpers.Add( Tuple.Create( "custom_editor_widget", new string[] { Editor } ) );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A helper used for VR hand purposes.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true )]
|
|
public class HandPoseAttribute : BaseModelDocAttribute
|
|
{
|
|
/// <summary>
|
|
/// Internal name of the key to store position in.
|
|
/// </summary>
|
|
internal string Origin { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key to store angles in.
|
|
/// </summary>
|
|
internal string Angles { get; set; }
|
|
|
|
/// <summary>
|
|
/// Path to a model to use.
|
|
/// </summary>
|
|
internal string Model { get; set; }
|
|
|
|
/// <summary>
|
|
/// Whether this helper represents the right hand or not.
|
|
/// This decides the names of the bones the helper will try to use.
|
|
/// </summary>
|
|
internal bool IsRightHand { get; set; }
|
|
|
|
/// <summary>
|
|
/// Text label this helper will have when hovered/selected.
|
|
/// </summary>
|
|
public string Label { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key that controls whether this helper is visible or not.
|
|
/// </summary>
|
|
public string Enabled { get; set; }
|
|
|
|
/// <param name="originKey">Internal name of the key to store position in.</param>
|
|
/// <param name="anglesKey">Internal name of the key to store angles in.</param>
|
|
/// <param name="model">Path to a model to use.</param>
|
|
/// <param name="isRightHand">Whether this helper represents the right hand or not. This decides the names of the bones the helper will try to use.</param>
|
|
public HandPoseAttribute( string originKey, string anglesKey, string model, bool isRightHand ) : base( "hand_pose" )
|
|
{
|
|
Origin = originKey;
|
|
Angles = anglesKey;
|
|
Model = model;
|
|
IsRightHand = isRightHand;
|
|
}
|
|
|
|
protected override void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
dict.Add( "enabled_key", Enabled );
|
|
dict.Add( "origin_key", Origin );
|
|
dict.Add( "angles_key", Angles );
|
|
dict.Add( "label", Label );
|
|
dict.Add( "model", Model );
|
|
if ( IsRightHand ) dict.Add( "is_right_hand", true );
|
|
}
|
|
}
|
|
|
|
public class LineAttribute : BaseModelDocAttribute
|
|
{
|
|
/// <summary>
|
|
/// Internal name of the key that dictates which bone to use as parent for start position.
|
|
/// </summary>
|
|
public string BoneFrom { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key that dictates which attachment to use as parent for start position.
|
|
/// </summary>
|
|
public string AttachmentFrom { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key to read line start position from.
|
|
/// </summary>
|
|
public string OriginFrom { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key that dictates which bone to use as parent for end position.
|
|
/// </summary>
|
|
public string BoneTo { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key that dictates which attachment to use as parent for end position.
|
|
/// </summary>
|
|
public string AttachmentTo { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key to read line end position from.
|
|
/// </summary>
|
|
public string OriginTo { get; set; }
|
|
|
|
/// <summary>
|
|
/// Internal name of the key that controls whether this helper is visible or not.
|
|
/// </summary>
|
|
public string Enabled { get; set; }
|
|
|
|
/// <summary>
|
|
/// A string formatted color for this helper. Format is "255 255 255"
|
|
/// </summary>
|
|
public string Color { get; set; }
|
|
|
|
/// <summary>
|
|
/// The width of the line helper
|
|
/// </summary>
|
|
public float Width { get; set; }
|
|
|
|
public LineAttribute() : base( "line" )
|
|
{
|
|
}
|
|
|
|
protected override void AddTransform( StringBuilder sb )
|
|
{
|
|
var transformFromKeys = "";
|
|
if ( !string.IsNullOrEmpty( OriginFrom ) ) transformFromKeys += $"\t\torigin_key = {OriginFrom.QuoteSafe()}\r\n";
|
|
if ( !string.IsNullOrEmpty( AttachmentFrom ) ) transformFromKeys += $"\t\tattachment_key = {AttachmentFrom.QuoteSafe()}\r\n";
|
|
if ( !string.IsNullOrEmpty( BoneFrom ) ) transformFromKeys += $"\t\tbone_key = {BoneFrom.QuoteSafe()}\r\n";
|
|
|
|
if ( !string.IsNullOrEmpty( transformFromKeys ) )
|
|
{
|
|
sb.AppendLine( $"\tfrom =\r\n\t{{\r\n{transformFromKeys}\t}}" );
|
|
}
|
|
|
|
var transformToKeys = "";
|
|
if ( !string.IsNullOrEmpty( OriginTo ) ) transformToKeys += $"\t\torigin_key = {OriginTo.QuoteSafe()}\r\n";
|
|
if ( !string.IsNullOrEmpty( AttachmentTo ) ) transformToKeys += $"\t\tattachment_key = {AttachmentTo.QuoteSafe()}\r\n";
|
|
if ( !string.IsNullOrEmpty( BoneTo ) ) transformToKeys += $"\t\tbone_key = {BoneTo.QuoteSafe()}\r\n";
|
|
|
|
if ( !string.IsNullOrEmpty( transformToKeys ) )
|
|
{
|
|
sb.AppendLine( $"\tto =\r\n\t{{\r\n{transformToKeys}\t}}" );
|
|
}
|
|
}
|
|
|
|
protected override void AddKeys( Dictionary<string, object> dict )
|
|
{
|
|
dict.Add( "enabled_key", Enabled );
|
|
dict.Add( "color", Color );
|
|
if ( Width > 0 ) dict.Add( "width", Width );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scales the vector with the "ScaleAndMirror" node, relative to associated bone.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Property )]
|
|
public class ScaleBoneRelativeAttribute : Editor.FieldMetaDataAttribute
|
|
{
|
|
public override void AddMetaData( Dictionary<string, string> meta_data )
|
|
{
|
|
meta_data["scale_bone_relative"] = "true";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Scales the vector with the "ScaleAndMirror" node.
|
|
/// </summary>
|
|
[AttributeUsage( AttributeTargets.Property )]
|
|
public class ScaleWorldAttribute : Editor.FieldMetaDataAttribute
|
|
{
|
|
public override void AddMetaData( Dictionary<string, string> meta_data )
|
|
{
|
|
meta_data["scale_world"] = "true";
|
|
}
|
|
}
|
|
}
|