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();
}