S&box Wiki

Revision Difference

custom_modeldoc_nodes#548094

<cat>Model.Nodes</cat><title>Custom ModelDoc nodes</title> ⤶ You can make a custom ModelDoc node. This is useful for any gamemode-specific data you want to attach to specific models. These nodes are defined in C# code, and the FGD for these is automatically generated for you. ⤶ This page describes how you can create custom ModelDoc nodes. This is useful for any gamemode-specific data you may want to attach to specific models. ⤶ There are currently 2 types of custom ModelDoc nodes you can create: Generic Game Data and Break Commands. # Generic Game Data ⤶ Generic Game Data nodes are just that - a node that can carry arbitrary data on the model and then retrieved in code when needed.⤶ ⤶ Here's the process for registering and using a custom game data node:⤶ 1. Define a struct or class. Add the `ModelDoc.GameData` attribute. ``` /// <summary> /// Spawn a particle when the model is used on an entity. Support for this depends on the entity. /// </summary> [ModelDoc.GameData( "particle", AllowMultiple = true )] public class ModelParticle { [DisplayName( "Particle" ), ResourceType( "vpcf") ] public string Name { get; set; } [JsonPropertyName( "attachment_point" ), FGDType( "model_attachment" )] public string AttachmentPoint { get; set; } [JsonPropertyName( "attachment_type" )] public ParticleAttachment AttachmentType { get; set; } = ParticleAttachment.AttachmentFollow; [JsonPropertyName( "attachment_offset" )] public Vector3 AttachmentOffset { get; set; } } ``` 2. Let the gamemode (re)compile. This will make the new nodes appear in ModelDoc. 3. Assign the node in ModelDoc to the `GameDataList` parent node, or use the node wizard if the node is not present. If you wish to know more, you can read <page text="this guide on importing a model">Importing_a_new_model</page>. <upload src="70c/8dac70f747e77f7.png" size="12354" name="image.png" /> 4. Compile the model. 5. Now you can use this data in code like so. ``` // Get the custom data on the a model. Will return null if it not present on the model ModelParticle[] modelParticles = Model.GetData<ModelParticle[]>(); // Or like so if ( Model.TryGetData( out ModelParticle[] modelParticles ) { // Data exists on this model, use it.. } ``` # Break Commands Break commands are a more specific alternative to GenericGameData which allows code to be ran when an entity with a model that has a given node breaks via the [Breakables](https://asset.party/api/Sandbox.Breakables) class, such as doors, physics props and others. They work identically to GenericGameData but the class markup looks a little different: ``` /// <summary> /// Spawn a particle system when this model breaks. /// </summary> [Library( "break_create_particle" )] public class ModelBreakParticle : IModelBreakCommand { /// <summary> /// The particle to spawn when the model breaks. /// </summary> [JsonPropertyName( "name" ), ResourceType( "vpcf" )] public string Particle { get; set; } // ... public void OnBreak( Sandbox.Breakables.Result res ) { if ( !(res.Source is ModelEntity ent) ) return; var part = Particles.Create( Particle, ent.Position ); // ... } } ``` The `OnBreak` callback will be called automatically when an entity breaks and has a model with (in this case) `break_create_particle` break command. # Other things you can do with this There are multiple attributes that you can use in order to make your own custom designers/helpers:⤶ There are multiple attributes that you can use in order to make your own custom designers/helpers for your custom nodes:⤶ - `ModelDoc.Axis` - `ModelDoc.Box` - `ModelDoc.Sphere` - `ModelDoc.Capsule` - `ModelDoc.Cylinder` - `ModelDoc.Line` - `ModelDoc.HandPose` - `ModelDoc.EditorWidget`