swb_shared/util/ModelUtil.cs
/*
* Utility class for handling models
*/
namespace SWB.Shared;
public class ModelUtil
{
public static void ParentToBone( GameObject gameObject, SkinnedModelRenderer target, string bone, int tries = 0, bool deleteOnFail = true, System.Action<GameObject> onFail = null )
{
if ( !gameObject.IsValid() ) return;
void Fail( string message )
{
Log.Warning( message );
onFail?.Invoke( gameObject );
if ( deleteOnFail && gameObject.IsValid() )
gameObject.Destroy();
}
if ( !target.IsValid() )
{
Fail( $"Could not parent {gameObject} to bone '{bone}' because target renderer is invalid" );
return;
}
var holdBoneGO = target.GetBoneObject( bone );
if ( !holdBoneGO.IsValid() || holdBoneGO.Scene is null )
{
// Try again 1 frame later, viewmodel edge case
async void retry()
{
await GameTask.Delay( 1 );
ParentToBone( gameObject, target, bone, tries + 1, deleteOnFail, onFail );
}
if ( tries < 10 )
retry();
else
Fail( $"Could not get bone object from '{bone}' on {target}" );
return;
}
try
{
gameObject.SetParent( holdBoneGO );
}
catch
{
//Log.Info( target.Model.ResourcePath );
//Log.Info( holdBoneGO.Scene );
//Log.Info( holdBoneGO.Scene == null );
Fail( $"Could not parent {gameObject} to {holdBoneGO}" );
return;
}
if ( !gameObject.IsValid() ) return;
gameObject.WorldPosition = holdBoneGO.WorldPosition;
gameObject.WorldRotation = holdBoneGO.WorldRotation;
gameObject.Transform.ClearInterpolation();
}
}