Not sure if this works (or something similar):
public static unsafe void Test (IMatrix3 matrix, INode node)
{
ISetXFormPacket setXFormPacket = globalInterface.SetXFormPacket.Create(matrix, globalInterface.Matrix3.Create());
void* nativePtr = setXFormPacket.Handle.ToPointer();
IntPtr* ptr = (IntPtr*)nativePtr;
node.TMController.SetValue(coreInterface.Time, *ptr, true, GetSetMethod.Absolute);
}
At least, it compiles.
INode is not defined, so I used IINode instead.
.Handle is not property of setXFormPacket. so I used .NativePointer instead
Yes, it will be compiled this way, But it will crash the Max again.
private readonly static IGlobal globalInterface = GlobalInterface.Instance;
private readonly static IInterface coreInterface = globalInterface.COREInterface;
public static unsafe void Test(IMatrix3 matrix, IINode node)
{
int time = coreInterface.Time;
ISetXFormPacket setXFormPacket = globalInterface.SetXFormPacket.Create(matrix, globalInterface.Matrix3.Create());
void* nativePtr = setXFormPacket.NativePointer.ToPointer();
IntPtr* ptr = (IntPtr*)nativePtr;
node.TMController.SetValue(coreInterface.Time, *ptr, true, GetSetMethod.Absolute);
globalInterface.COREInterface.RedrawViews(time, RedrawFlags.Normal, null);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
IINode selNode = coreInterface.GetSelNode(0);
if (selNode == null) MessageBox.Show("Selection empty.");
else
{
IMatrix3 matrix = globalInterface.Matrix3.Create(true);
Test(matrix, selNode);
}
}
Maybe we can use that hack : ManagedServices.MaxscriptSDK.ExecuteStringMaxscriptQuery
any idea how we can send transform controller handler value?
what’s that?
if it is an animatable then simply use getHandleByAnim on mxs side and Animatable.GetAnimByHandle on c# side
Alternatively you can pass maxscript values to c# methods directly, but you’ll have to use some c# argument naming rules for it to work. Check MaxPlusArgNameParsingConstants in …\maxsdk\samples\maxscript\mxsdotNet\utils.h
for example if you want to pass point3 value to the c# method its signature should be like that
… MyMethod( IntPtr point3_pointer )
Class Animatable
OK, I ended up with this, but super slow!
private static string MatrixToString(IMatrix3 matrix)
{
string ss = "";
for (int i = 0; i < 4; i++)
{
IPoint3 point3 = matrix.GetRow(i);
ss += "[" + point3.X.ToString() + ", " + point3.Y.ToString() + ", " + point3.Z.ToString() + "] ";
}
return "matrix3 " + ss;
}
private IMatrix3 GetTMControllerValue(IControl tMController)
{
string mxsCode = "(getanimbyhandle "+ globalInterface.Animatable.GetHandleByAnim(tMController) +").value";
IFPValue fPValue = globalInterface.FPValue.Create();
globalInterface.ExecuteMAXScriptScript(mxsCode, true, fPValue, false);
return fPValue.M;
}
private void SetTMControllerValue(IControl tMController, IMatrix3 matrix)
{
string mxsCode = "(getanimbyhandle " + globalInterface.Animatable.GetHandleByAnim(tMController) + ").value = " + MatrixToString(matrix);
globalInterface.ExecuteMAXScriptScript(mxsCode, true, null, false);
}
Actually this is very bad that C# SetValue doesn’t work and nobody can solve it.
I bet there’s an easier way to get IMatrix3 from the controller, without messing with the script execution
btw you can copy matrix3 values like this
static public string Matrix3ToString( IMatrix3 tm )
{
var values = new float[12];
Marshal.Copy(tm.Handle, values, 0, 12);
return $"Matrix3 [{values[0]},{values[1]},{values[2]}] [{values[3]},{values[4]},{values[5]}] [{values[6]},{values[7]},{values[8]}] [{values[9]},{values[10]},{values[11]}]";
}
This code works for the getter, except that the values I get don’t seem very right.
private static IMatrix3 GetTMControllerValue(IControl tMController)
{
IMatrix3 mat = global.Matrix3.Create();
object matobj = (object)mat;
IInterval interval = global.Interval.Create();
interval.SetInfinite();
tMController.GetValue(ip.Time, ref matobj, interval, GetSetMethod.Relative);
mat = matobj as IMatrix3;
return mat;
}
Perhaps I’m missing something. It’s been for three or four years I don’t work with 3dsMax.
And same for the set:
private static void SetTMControllerValue(IControl tMController, IMatrix3 matrix)
{
object matobj = (object)matrix;
tMController.SetValue(ip.Time, matobj, true, GetSetMethod.Relative);
}