using NativeEngine; using Sandbox.Engine; using Sandbox.Engine.Utility.RayTrace; namespace Sandbox; /// /// A model. /// public sealed partial class Model : Resource { internal IModel native; internal bool procedural; public override bool IsValid => native.IsValid; /// /// Private constructor, use /// private Model( IModel native, string name, bool procedural ) { if ( native.IsNull ) throw new Exception( "Model pointer cannot be null!" ); this.native = native; this.Name = name; this.procedural = procedural; SetIdFromResourcePath( Name ); } ~Model() { var n = native; native = default; MainThread.Queue( () => n.DestroyStrongHandle() ); } /// /// Called when the resource is reloaded. We should clear any cached values. /// internal override void OnReloaded() { _data?.Dispose(); _data = null; _physics?.Dispose(); _physics = default; _morphs?.Dispose(); _morphs = null; _attachments?.Dispose(); _attachments = default; _animationNames?.Clear(); _animationNames = default; _sequenceNames?.Clear(); _sequenceNames = default; _materials = default; _bones = default; _hitboxset = default; _parts?.Dispose(); _parts = default; DataCache?.Clear(); IToolsDll.Current?.RunEvent( "model.reload", this ); foreach ( var scene in Scene.All ) { using var scope = scene.Push(); var components = scene.GetAllComponents(); foreach ( var c in components ) { if ( c.Model != this ) continue; c.OnModelReloaded(); } } } /// /// Whether this model is an error model or invalid or not. /// public bool IsError => native.IsNull || !native.IsStrongHandleValid() || native.IsError(); /// /// Name of the model, usually being its file path. /// public string Name { get; internal set; } /// /// Whether this model is procedural, i.e. it was created at runtime via . /// public bool IsProcedural => procedural; /// /// Total number of meshes this model is made out of. /// public int MeshCount => native.GetNumMeshes(); /// /// Trace against the triangles in this mesh /// public MeshTraceRequest Trace => new() { targetModel = this }; } internal interface IHasModel { /// /// The associated with this object. /// Model Model { get; } /// /// Called by the engine when the associated is reloaded. /// Implementing classes should clear or update any cached data that depends on the model. /// void OnModelReloaded(); }