S&box Wiki

Revision Difference


<cat>Code.Misc</cat> <title>Custom Asset Types</title> Custom assets are things you can define yourself. They give you a nice inspector window and they're hotloaded in-game, which means you can whip things up pretty quickly if you're using them. # Creating a custom asset type You can find plenty of examples of assets throughout s&box, here's a snippet from the clothing asset: Let's say you wanted your own custom weapon asset type. Here's how you'd do that. ## Creating the FGD Make a folder in your addon's root directory, call it `config`. Make a file in there called `weapon.asset`. The file name you choose here will be the name for the base class and the extension for any files of this type. Writing the FGD here is similar to [how you'd write an FGD normally](https://developer.valvesoftware.com/wiki/FGD). ``` @BaseClass = weapon : "A weapon" [ [Library( "clothing" ), AutoGenerate] public partial class Clothing : Asset Name(string) : "Name" : "Weapon Name" Description(string) : "Description" : "This is my weapon." Damage(float) : "Damage" : "5" ] ``` When writing these, give your fields some sane default values to make it easier on yourself. You can obviously do a lot more than this - you could define all of the possible parameters here - but we'll keep things simple for now. ## Mirroring it in code You then need to mirror this class in code. Make sure you specify the same defaults that you specify in the FGD. ``` [Library( "weapon" )] public class WeaponData : Asset { // Data from weapon.asset public string Name { get; set; } = "Weapon Name"; public string Description { get; set; } = "This is my weapon."; public float Damage { get; set; } = 5.0f; [Property] public string Title { get; set; } [Property, ResourceType( "vmdl" )] public string Model { get; set; } // ... } ``` <warning> If you don't specify defaults in code, then they won't be assigned to at all - regardless of whether these are set up in the FGD. </warning> ## Using the inspector * `[Library( "clothing" )]` specifies the file extension our assets use will be .clothing * Because we specified `[AutoGenerate]` on our asset class a .asset file will automatically generate for us. * Properties that should be editable via the inspector in your asset should be marked with `[Property]` ## Using the inspector Now that you have everything set up, you can use the inspector tool to edit your first weapon. 1. Click the "Inspector" icon in the asset browser. <upload src="44a6e/8d941a81d2276f1.png" size="36799" name="image.png" /> 2. Pick your asset type. <upload src="44a6e/8d941a921ee5812.png" size="15315" name="image.png" /> 3. Set up your weapon however you want. <upload src="44a6e/8d941a8a3d0efee.png" size="9916" name="image.png" /> 4. Save your asset into your addon's config directory - call it "MyWeapon.weapon" ## Loading the asset type Loading an asset type is super easy. ## Accessing assets All assets are loaded when you first start the game, there are several ways you can access them: ### FromPath When assets are loaded they are stored in a dictionary with their path, you can access these with `Resource.FromPath<T>`. ``` // Property allows for hot-loading public WeaponData WeaponData { get; set; } public Clothing Clothing { get; set; } // ... // Load the weapon data from a path WeaponData = Resource.FromPath<WeaponData>( "config/MyWeapon.weapon" ); Clothing = Resource.FromPath<Clothing>( "config/tshirt.clothing" ); ``` Congrats, you can now get your weapon's data using the WeaponData object you just created. For example: ``` Log.Info( WeaponData.Name ); Log.Info( WeaponData.Description ); Log.Info( WeaponData.Damage ); // Output: // Cool Weapon // This is my cool gun // 69 ### PostLoad When assets are loaded they call their PostLoad method, you can use this to store a list of your assets for later use. ```csharp public partial class Clothing : Asset { // Access these statically with Clothing.All public static IReadOnlyList<Clothing> All => _all; internal static List<Clothing> _all = new(); protected override void PostLoad() { base.PostLoad(); if ( !_all.Contains( this ) ) _all.Add( this ); } } ``` You can edit these values in the inspector and they'll apply in-game as soon as you hit save with no extra work required.