[Closed] SDK how return struct to maxscript?
I’m trying the sdk for the first time, as a learning experience i’m porting certain functions to the sdk as function publishing.
I have successfully been able to port a function and return a Point3 position from it.
Now i want to port another functions. but i require to return more then one parameter type. Is there a way to return a struct in which i have for example and array of points, a few int values and a boolean?
I have been looking at the samples to see if i can find something similar but i haven’t found anything.
i was looking at several examples that use four_value_locals or five_typed_value_locals_tls …
But i’m not sure if that’s the way to do it.
Anyone has any tips?
Thanks
Guillermo Leal
Guess you can pass variables by reference and assign them directly without the need to return anything.
def_visible_primitive(AssignByRef, "AssignByRef");
Value* AssignByRef_cf(Value** arg_list, int count)
{
check_arg_count_with_keys(AssignByRef, 3, count);
Thunk *var1 = arg_list[0]->to_thunk();
Thunk *var2 = arg_list[1]->to_thunk();
Thunk *var3 = arg_list[2]->to_thunk();
var1->assign(new String(_T("Victory!!!")));
var2->assign(new Point3Value(1, 2, 3));
var3->assign(new BitArrayValue(666));
return &true_value;
}
Then in mxs
AssignByRef &a &b &c
a
b
c.count
– true
– “Victory!!!”
– [1,2,3]
– 666
you could probably create and return one but I don’t think mxs would “understand” what it was getting. the generally accepted method is to return an array of values which in turn can be arrays or point3values etc here my implementation of polyop.intersectrayex as an example
def_struct_primitive(polyop_intersectRayEx, polyop, "intersectRayEx");
Value* polyop_intersectRayEx_cf(Value** arg_list, int count)
{
check_arg_count(intersectRayEx, 2, count);
MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, intersectRayEx);
Ray ray = arg_list[1]->to_ray();
// get the node transforms
INode* node = get_valid_node(arg_list[0], intersectRayEx);
Matrix3 tm = node->GetObjectTM(MAXScript_time());
Matrix3 itm = Inverse(tm);
// convert the ray in to local space
Ray os_ray;
os_ray.p = itm * ray.p;
os_ray.dir = VectorTransform(itm, ray.dir);
float t;
Point3 normal;
int fi;
Tab<float> bary;
if(!pmesh->IntersectRay(os_ray,t,normal,fi,bary))
return &undefined;
// convert bary table into array value
Array* barray = new Array(bary.Count());
for(int i = 0; i < bary.Count(); ++i)
barray->append(Float::intern(bary[i]));
// Return the array containing the intersection details
one_typed_value_local(Array* result);
vl.result = new Array(3);
vl.result->append(new RayValue((os_ray.p + os_ray.dir * t) * tm, Normalize(VectorTransform(tm, normal))));
vl.result->append(Integer::intern (fi+1));
vl.result->append(barray);
return_value (vl.result);
}
with the result looking something like in mxs
#((ray [-22.0326,43.1826,28.3888] [-0.617795,0.767651,-0.170415]), 6, #(0.212238, 0.0, 0.593346, 0.194416))
Thanks to both of you.
I end up doing something similar to what you just said, I created arrays inside arrays with all the information then in maxscript i convert them back to a struct. I just wasn’t sure it was the correct way. I was just doing it that way because i saw some samples written that way.
Another couple of questions about one_typed_value_local.
how does it work When i first saw that there were different defines one_typed_value_local, two_typed_value_local , three_typed_value_local, etc. I thought i could put all the values in there and then by returning the result it would bring everything into maxscript. but of course it didn’t work. Then what are they for?
Also whats the difference between one_typed_value_local and one_typed_value_local_tls that i see in lots of the sample code.
Thanks,
Guillermo
have a look at
Value*
get_max_file_asset_metadata_cf(Value** arg_list, int count)
in avg_DLX.cpp
looks like it returns an array of structs
Thanks Klvnk,
I still haven’t figure it out how to use that code, but i will keep looking into.
Klvnk,
I have another completely different question.
in maxscript i have the following code to draw some viewport lines and points while the code is generating the positions.
fn DisplayDrawing =
(
local nodePoint
gw.setTransform(Matrix3 1)
for r = 1 to points.count do
(
if points[r].nodes.count > 2 then
(
thePoints = #()
for n = 1 to points[r].nodes.count do
(
nodePoint = points[r].nodes[n].pos
append thePoints nodePoint
gw.setColor #line green
gw.Polyline thePoints false
gw.updateScreen()
redrawViews()
)
)
)
)
fn doStuff =
(
--- for loop generating the points
for t = 1 to lots.count do
(
-- stuff here
-- call the gw draw function
DisplayDrawing()
)
)
on chk_displayDrawing changed state do
(
unRegisterRedrawViewsCallback DisplayDrawing
if state then
registerRedrawViewsCallback DisplayDrawing
completeRedraw()
)
I’m trying to do that on the sdk but i can’t find a solution.
The complete plugin is based on the FunctionPublishing sample in the howto solution.
I already have the function correctly generating a std::vector with all the positions i want to draw on the viewport.
but i can’t find how to implement it. I saw the post [SDK] issues drawing polyline in viewport
but i still can’t figure it out. I tried to use the code in the polycnt.cpp to register a callback but it didn’t work and crashed the plugin.
can you give me some guidelines? or perhaps you have done something similar in the past?
Thanks
Guillermo
have a look at the source for the function you are using in the script in the file
C:\Program Files\Autodesk\3ds Max **** SDK\maxsdk\samples\maxscript\mxsagni\GraphicsWindow.cpp
and go from there.