mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-01-05 04:48:19 -05:00
This commit imports the C# engine code and game files, excluding C++ source code. [Source-Commit: ceb3d758046e50faa6258bc3b658a30c97743268]
270 lines
7.5 KiB
C#
270 lines
7.5 KiB
C#
using NativeEngine;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Sandbox;
|
|
|
|
/// <summary>
|
|
/// A model scene object that supports animations and can be rendered within a <see cref="SceneWorld"/>.
|
|
/// </summary>
|
|
[Expose]
|
|
public sealed partial class SceneModel : SceneObject
|
|
{
|
|
internal CSceneAnimatableObject animNative;
|
|
|
|
DelegateFunctionPointer animGraphChangedCallback;
|
|
|
|
[UnmanagedFunctionPointer( CallingConvention.StdCall )]
|
|
internal delegate void AnimGraphChangedCallback( IntPtr p );
|
|
|
|
internal SceneModel() { }
|
|
internal SceneModel( HandleCreationData _ ) { }
|
|
|
|
public SceneModel( SceneWorld sceneWorld, string model, Transform transform ) : this( sceneWorld, Model.Load( model ), transform ) { }
|
|
|
|
public SceneModel( SceneWorld sceneWorld, Model model, Transform transform )
|
|
{
|
|
Assert.IsValid( sceneWorld );
|
|
Assert.NotNull( model );
|
|
|
|
if ( !model.HasRenderMeshes() ) model = Model.Error;
|
|
|
|
using ( var h = IHandle.MakeNextHandle( this ) )
|
|
{
|
|
var flags = Rendering.SceneObjectFlags.CastShadows | Rendering.SceneObjectFlags.IsLoaded;
|
|
var typeFlags = ESceneObjectTypeFlags.NONE;
|
|
|
|
MeshSystem.CreateSceneObject( model.native, transform, "AnimatableSceneObjectDesc", flags, typeFlags, sceneWorld, 0x1 );
|
|
|
|
if ( !animNative.IsValid )
|
|
{
|
|
Log.Warning( "SceneModel: Didn't get a valid native pointer" );
|
|
throw new System.ArgumentException( "Error creating AnimSceneObject - possible invalid model?" );
|
|
}
|
|
|
|
Transform = transform;
|
|
|
|
if ( animGraphChangedCallback == DelegateFunctionPointer.Null )
|
|
{
|
|
animGraphChangedCallback = DelegateFunctionPointer.Get<AnimGraphChangedCallback>( OnAnimGraphChanged );
|
|
}
|
|
|
|
// TODO
|
|
animNative.InitAnimGraph( animGraphChangedCallback );
|
|
}
|
|
}
|
|
|
|
private void OnAnimGraphChanged( IntPtr p )
|
|
{
|
|
_animationGraph = AnimationGraph.FromNative( animNative.GetAnimGraph() );
|
|
}
|
|
|
|
internal override void OnNativeInit( CSceneObject ptr )
|
|
{
|
|
base.OnNativeInit( ptr );
|
|
|
|
animNative = (NativeEngine.CSceneAnimatableObject)ptr;
|
|
}
|
|
|
|
internal override void OnNativeDestroy()
|
|
{
|
|
animNative = default;
|
|
base.OnNativeDestroy();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override the anim graph this scene model uses
|
|
/// </summary>
|
|
[System.Obsolete( "Can use AnimationGraph directly" )]
|
|
public void SetAnimGraph( string name )
|
|
{
|
|
animNative.SetAnimGraph( name );
|
|
}
|
|
|
|
private AnimationGraph _animationGraph;
|
|
|
|
public AnimationGraph AnimationGraph
|
|
{
|
|
get => _animationGraph;
|
|
set
|
|
{
|
|
animNative.SetAnimGraph( value?.native ?? default );
|
|
}
|
|
}
|
|
|
|
public float PlaybackRate
|
|
{
|
|
get => animNative.GetPlaybackRate();
|
|
set => animNative.SetPlaybackRate( value );
|
|
}
|
|
|
|
internal override void OnModelChanged()
|
|
{
|
|
base.OnModelChanged();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the world space bone transform of a bone by its index.
|
|
/// </summary>
|
|
/// <param name="boneIndex">Bone index to set transform of.</param>
|
|
/// <param name="transform"></param>
|
|
public void SetBoneWorldTransform( int boneIndex, Transform transform )
|
|
{
|
|
// TODO: Throw on index OOB
|
|
animNative.SetWorldSpaceRenderBoneTransform( boneIndex, transform );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the world space transform of a bone by its index.
|
|
/// </summary>
|
|
/// <param name="boneIndex">Index of the bone to calculate transform of.</param>
|
|
/// <returns>The world space transform, or an identity transform on failure.</returns>
|
|
public Transform GetBoneWorldTransform( int boneIndex )
|
|
{
|
|
// TODO: Throw on index OOB
|
|
// TODO: Returns nullable to match GetAttachment()?
|
|
return animNative.GetWorldSpaceRenderBoneTransform( boneIndex );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the world space transform of a bone by its name.
|
|
/// </summary>
|
|
/// <param name="boneName">Name of the bone to calculate transform of.</param>
|
|
/// <returns>The world space transform, or an identity transform on failure.</returns>
|
|
public Transform GetBoneWorldTransform( string boneName )
|
|
{
|
|
// TODO: Returns nullable to match GetAttachment()?
|
|
return animNative.GetWorldSpaceRenderBoneTransform( boneName );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the local space transform of a bone by its index.
|
|
/// </summary>
|
|
/// <param name="boneIndex">Index of the bone to calculate transform of.</param>
|
|
/// <returns>The local space transform, or an identity transform on failure.</returns>
|
|
public Transform GetBoneLocalTransform( int boneIndex )
|
|
{
|
|
// TODO: Throw on index OOB
|
|
// TODO: Returns nullable to match GetAttachment()?
|
|
return animNative.GetLocalSpaceRenderBoneTransform( boneIndex );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the local space transform of a bone by its name.
|
|
/// </summary>
|
|
/// <param name="boneName">Name of the bone to calculate transform of.</param>
|
|
/// <returns>The local space transform, or an identity transform on failure.</returns>
|
|
public Transform GetBoneLocalTransform( string boneName )
|
|
{
|
|
// TODO: Returns nullable to match GetAttachment()?
|
|
return animNative.GetLocalSpaceRenderBoneTransform( boneName );
|
|
}
|
|
|
|
internal Transform GetWorldSpaceAnimationTransform( int boneIndex )
|
|
{
|
|
return animNative.GetWorldSpaceAnimationTransform( boneIndex );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set material group to replace materials of the model as set up in ModelDoc.
|
|
/// </summary>
|
|
public new void SetMaterialGroup( string name ) // TODO - REMOVE ME
|
|
{
|
|
base.SetMaterialGroup( name );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set which body group to use.
|
|
/// </summary>
|
|
public void SetBodyGroup( string name, int value )
|
|
{
|
|
animNative.SetBodyGroup( name, value );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get attachment transform by name.
|
|
/// </summary>
|
|
/// <param name="name">Name of the attachment to calculate transform of.</param>
|
|
/// <param name="worldspace">Whether the transform should be in world space (relative to the scene world), or local space (relative to the scene object)</param>
|
|
/// <returns></returns>
|
|
public Transform? GetAttachment( string name, bool worldspace = true )
|
|
{
|
|
if ( animNative.SBox_GetAttachment( name, worldspace, out var tx ) )
|
|
return tx;
|
|
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Allows the scene model to not use the anim graph so it can play sequences directly
|
|
/// </summary>
|
|
public bool UseAnimGraph
|
|
{
|
|
get => animNative.GetShouldUseAnimGraph();
|
|
set
|
|
{
|
|
if ( UseAnimGraph == value ) return;
|
|
|
|
animNative.SetShouldUseAnimGraph( value );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the calculated motion from animgraph since last frame
|
|
/// </summary>
|
|
public Transform RootMotion
|
|
{
|
|
get => animNative.GetRootMotion();
|
|
}
|
|
|
|
SceneObjectAnimationSequence _currentSequence;
|
|
|
|
/// <summary>
|
|
/// Allows playback of sequences directly, rather than using an animation graph.
|
|
/// Requires <see cref="UseAnimGraph"/> disabled if the scene model has one.
|
|
/// </summary>
|
|
public AnimationSequence CurrentSequence
|
|
{
|
|
get
|
|
{
|
|
// Create on first access
|
|
_currentSequence ??= new SceneObjectAnimationSequence( this );
|
|
|
|
return _currentSequence;
|
|
}
|
|
}
|
|
|
|
SceneObjectMorphCollection _morphs;
|
|
|
|
/// <summary>
|
|
/// Access this sceneobject's morph collection. Morphs are generally used in the model to control
|
|
/// the face, for things like emotions and lip sync.
|
|
/// </summary>
|
|
public MorphCollection Morphs
|
|
{
|
|
get
|
|
{
|
|
// Create on first access
|
|
_morphs ??= new SceneObjectMorphCollection( this );
|
|
|
|
return _morphs;
|
|
}
|
|
}
|
|
|
|
SceneObjectDirectPlayback _directPlayback;
|
|
|
|
/// <summary>
|
|
/// Access this sceneobject's direct playback. Direct playback is used to control the direct playback node in an animgraph
|
|
/// to play sequences directly in code
|
|
/// </summary>
|
|
public AnimGraphDirectPlayback DirectPlayback
|
|
{
|
|
get
|
|
{
|
|
// Create on first access
|
|
_directPlayback ??= new SceneObjectDirectPlayback( this );
|
|
|
|
return _directPlayback;
|
|
}
|
|
}
|
|
}
|