Problem understanding structures

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

 
Thread Tools Display Modes
  1 Week Ago
Problem understanding structures

Hi!
I'm currently trying to get deeper into maxscript, having done only small snippets before here and there. And I'm having trouble understanding some concepts on maxscript. Mainly structures, the order of things, and how to get values from for example spinners updated on other functions.
I'm trying to create a script based on Paul Neales facial bone rig script .
I'd like to have a dialog with a size spinner on it and later ticking of the hierarchy depending how many parents you need, but first I'd just like it to work again

This is the script I have now:

try(DestroyDialog surfaceHelpers)catch()
struct surfaceHelpersStructure
(
   targetNode=$,
   controlSize=1,
   
   fn dialog=
   (
   
rollout surfaceHelpers "Surface Helpers" width:200 height:150
(
   spinner 'spn1' "" pos:[100,37] width:75 height:16 range:[1,100,1] type:#float scale:0.1 align:#left
   label 'lbl1' "Remember to select surface object" pos:[25,5] width:150 height:25 align:#left
   label 'lbl2' "Control size" pos:[25,38] width:75 height:15 align:#left
   button 'btn1' "Start Creation" pos:[25,70] width:150 height:70 align:#left
   on spn1 changed val do
   (
      
   )
   on btn1 pressed  do
(
   surfaceHelpersStructure.runTool()
   )
)
),
   
   fn makeControl hit=
   (
      if hit!=undefined do
      (
         print hit.pos
         print hit.dir
         
         pt=point box:true cross:false axisTripod:true centerMarker:false size:(controlSize/2.0) wireColor:red name:(uniqueName "PT_ControlRoot")
         Zv=hit.dir
         Yv=[0,0,1]
         Xv=normalize (cross yV Zv)
         Yv=normalize (cross Zv Xv)
         pt.transform=matrix3 Xv Yv Zv hit.pos
         
         pt2=point box:true cross:false axisTripod:true centerMarker:false size:(controlSize) wireColor:green name:(uniqueName "PT_ControlPos")
         pt2.transform=pt.transform
         pt2.parent=pt
         
         cnt=circle radius:(controlSize) wirecolor:blue name:(uniqueName "CNT_Face")
         cnt.transform=pt.transform
         cnt.parent=pt2
         
         xf=xForm()
         addModifier cnt xf
         xf.gizmo.pos.z=controlSize
         convertToSplineShape cnt
      )
   ),
   
   fn runTool=
   (
      tool mouseHit
      (
         on mousePoint clickNo do
         (
            if clickNo>1 do
            (
               r=(mapScreenToWorldRay mouse.pos)
               hit=intersectRay targetNode r
               makeControl hit
               
               if queryBox "Do you want to make a mirror control" title:"Well!" do
               (
                  hit=intersectRay targetNode (ray (r.pos*[-1,1,1])(r.dir*[-1,1,1]))
                  makeControl hit
               )
            )
         )
      )
      startTool mouseHit
   ),
   
)
if $ == undefined then   messagebox "Select surface object"
else createDialog surfaceHelpers pos:[1000,300] style:#(#style_titlebar, #style_border, #style_sysmenu, #style_minimizebox)

at this point the script does not work at all. The error I get is:


Syntax error: at ), expected member name or local function: 
--  In line: );

on line 79 on the forum code point I believe, so near the end.
I had it working somewhat on max 2019, got the dialog open and could create helpers, but the size spinner did not work as it should, I was not able to update the spinner value correctly.
Then I tried it on max 2016 and trying to fix it there seem to have broken it completely.
The controlSize is back to just 1 instead of surfaceHelpers.spn1.value, because it wasn't working correctly with only that.

I'm quite aware I'm probably doing things in a weird order with the dialog and such? But trying to search the help and online I'm not finding any good help on how these things should be done.
If anyone could help with this, I hope I could learn how these things should work
Any help is greatly appreciated!
 
  1 Week Ago
I haven't seen the purpose of your script, just tryed to make it work.
Really too many mistakes. Is all this code from you?
You can make it work by:
- Deleting the last coma ',' in your last function
- to use your struct, you have to create an instance of it (for example, myStructInstance = surfaceHelpersStructure())
- to use any element of your struct (data or function) outside your struct, you have to use the 'dot' property method (for example, myStructInstance.dialog())
- all the calls/uses of struct elements (data or functions) inside plugin clauses (as 'on mousePoint clickNo do') won't be understood as members of the struct. So you have to call/use them as your instance members (dot property method, see above) and, probably, your instance should be created as global (or creating a local variable pointing to the struct).
__________________
Andrés FC.
P3D_PathScripts
Proin3D YouTube Channel
 
  1 Week Ago
Thank you very much for the help!
The purpose of the script is to create helpers on the surface of objects oriented correctly along the surface normal.
All the functions, except those concerning the dialog are from Paul Neales video I linked on the first post.
It's just me messing things up with my dialog things
But I got it working thanks to your help.

struct surfaceHelpersStructure
(
   targetNode=undefined,
   
   fn makedialog=
   (
   
      rollout surfaceHelpers "Surface Helpers" width:200 height:150
      (
         spinner 'spn1' "" pos:[100,37] width:75 height:16 range:[1,100,1] type:#float scale:0.1 align:#left
         label 'lbl1' "Remember to select surface object" pos:[25,5] width:150 height:25 align:#left
         label 'lbl2' "Control size" pos:[25,38] width:75 height:15 align:#left
         button 'btn1' "Start Creation" pos:[25,70] width:150 height:70 align:#left
         on spn1 changed val do
         (
            
         )
         on btn1 pressed  do
      (
         controlSize=surfaceHelpers.spn1.value
         shInstance.runTool()
         )
      )
   ),
   fn usedialog=
   (
      try(DestroyDialog surfaceHelpers)catch()
      surfaceHelpers=makedialog()
      if $ == undefined then   messagebox "Select surface object"
      else createDialog surfaceHelpers pos:[1000,300] style:#(#style_titlebar, #style_border, #style_sysmenu, #style_minimizebox)
   ),
   
   fn makeControl hit=
   (
      if hit!=undefined do
      (
         print hit.pos
         print hit.dir
         
         pt=point box:true cross:false axisTripod:true centerMarker:false size:(controlSize/2.0) wireColor:red name:(uniqueName "PT_ControlRoot")
         Zv=hit.dir
         Yv=[0,0,1]
         Xv=normalize (cross yV Zv)
         Yv=normalize (cross Zv Xv)
         pt.transform=matrix3 Xv Yv Zv hit.pos
         
         pt2=point box:true cross:false axisTripod:true centerMarker:false size:(controlSize) wireColor:green name:(uniqueName "PT_ControlPos")
         pt2.transform=pt.transform
         pt2.parent=pt
         
         cnt=circle radius:(controlSize) wirecolor:blue name:(uniqueName "CNT_Face")
         cnt.transform=pt.transform
         cnt.parent=pt2
         
         xf=xForm()
         addModifier cnt xf
         xf.gizmo.pos.z=controlSize
         convertToSplineShape cnt
      )
   ),
   
   fn runTool=
   (
      tool mouseHit
      (
         on mousePoint clickNo do
         (
            if clickNo>1 do
            (
               r=(mapScreenToWorldRay mouse.pos)
               hit=intersectRay targetNode r
               makeControl hit
               
               if queryBox "Do you want to make a mirror control" title:"Well!" do
               (
                  hit=intersectRay targetNode (ray (r.pos*[-1,1,1])(r.dir*[-1,1,1]))
                  makeControl hit
               )
            )
         )
      )
      startTool mouseHit
   )
   
)
shInstance=surfaceHelpersStructure()
shInstance.targetNode=$
shInstance.usedialog()

I moved the controlSize variable to the button press so I got it updating correctly. Not sure if it's the best way, but seems to be working
Still a few things I'd like to add to it, but I believe I can manage them now. Thank you again!
 
  1 Week Ago
I'm glad I was helpful but... your code still doesn't work. Try it restarting 3dsMax: it will throw errors.
You have problems with variables visibility due to their scope.
Edit: I'll try to give you a working version with some explanations.
__________________
Andrés FC.
P3D_PathScripts
Proin3D YouTube Channel

Last edited by aaandres : 1 Week Ago at 07:47 AM.
 
  1 Week Ago
Yes, I noticed after trying on another version of max.
So still gotta do some changes
That controlSize with the spinner was the biggest problem for me anyway, so the fight continues.
Is it possible to define a variable for the whole structure that pulls a value from inside one of the functions? The controlSize variable in this case getting the value from the dialog spinner.
Or should I pull the value inside functions that need it? And how could I do that?

Not sure what is the best practice for this, or functional.
 
  1 Week Ago
Here's a code with three different methods of accessing the 'controlSize' value.
If you have any doubt, just ask.

--   Example with three methods of accesing the 'controlSize':
   --   In method 1, we use directly the spinner value
   --    In method 2, we use the struct parameter 'controlSize'
   --   In method 3, we use the local rollout variable 'controlSize'
(
   struct surfaceHelpersStructure
   (
      targetNode,
      --controlSize,   -- uncomment to use method 2
      
      -- Define the rollout as data instead of function. This way, it will be more accesible.
      surfaceHelpers = rollout surfaceHelpers "Surface Helpers" width:200 height:150
      (
         local owner = if owner != undefined do owner         --   That's just a check that 'owner' is initialized. See the 'showDialog' function
                                                               --   'owner' will hold a reference to the created instance of the struct
         --local controlSize   -- uncomment to use as method 3
         
         spinner spn_controlSize "" pos:[100,37] width:75 height:16 range:[1,100,1] type:#float scale:0.1 align:#left
         label 'lbl1' "Remember to select surface object" pos:[25,5] width:150 height:25 align:#left
         label 'lbl2' "Control size" pos:[25,38] width:75 height:15 align:#left
         button 'btn1' "Start Creation" pos:[25,70] width:150 height:70 align:#left
         
         on spn_controlSize changed val do
         (
            --owner.controlSize = spn_controlSize.value   -- uncomment to use as method 2
            --controlSize = spn_controlSize.value         -- uncomment to use as method 3
         )
         on btn1 pressed  do
         (
            owner.runTool()   
         )
         on surfaceHelpers open do
         (
            --owner.controlSize = spn_controlSize.value   -- uncomment to use as method 2
            --controlSize = spn_controlSize.value         -- uncomment to use as method 3
         )
      ),
      
      fn showDialog=
      (
         try(DestroyDialog surfaceHelpers) catch()
         surfaceHelpers.owner = this   --   Initialize the rollout local 'owner' to the created instance of the struct
         
         if targetNode == undefined or not isKindOf targetNode GeometryClass then messagebox "Select surface object"      --   Avoid the use of '$' inside the struct and check for GeometryClass.
         else createDialog surfaceHelpers pos:[1000,300] style:#(#style_titlebar, #style_border, #style_sysmenu, #style_minimizebox)
      ),
      
      fn makeControl hit=
      (
         if hit!=undefined do
         (
            print hit.pos
            print hit.dir
            pt=point box:true cross:false axisTripod:true centerMarker:false size:(surfaceHelpers.spn_controlSize.value/2.0) wireColor:red name:(uniqueName "PT_ControlRoot")
            --pt=point box:true cross:false axisTripod:true centerMarker:false size:(controlSize/2.0) wireColor:red name:(uniqueName "PT_ControlRoot")                  -- uncomment to use as method 2
            --pt=point box:true cross:false axisTripod:true centerMarker:false size:(surfaceHelpers.controlSize/2.0) wireColor:red name:(uniqueName "PT_ControlRoot")      -- uncomment to use as method 3
            Zv=hit.dir
            Yv=[0,0,1]
            Xv=normalize (cross yV Zv)
            Yv=normalize (cross Zv Xv)
            pt.transform=matrix3 Xv Yv Zv hit.pos
            pt2=point box:true cross:false axisTripod:true centerMarker:false size:(surfaceHelpers.spn_controlSize.value) wireColor:green name:(uniqueName "PT_ControlPos")
            --pt2=point box:true cross:false axisTripod:true centerMarker:false size:(controlSize) wireColor:green name:(uniqueName "PT_ControlPos")                     -- uncomment to use as method 2
            --pt2=point box:true cross:false axisTripod:true centerMarker:false size:(surfaceHelpers.controlSize) wireColor:green name:(uniqueName "PT_ControlPos")      -- uncomment to use as method 3
            pt2.transform=pt.transform
            pt2.parent=pt
            cnt=circle radius:(surfaceHelpers.spn_controlSize.value) wirecolor:blue name:(uniqueName "CNT_Face")
            --cnt=circle radius:(controlSize) wirecolor:blue name:(uniqueName "CNT_Face")                  -- uncomment to use as method 2
            --cnt=circle radius:(surfaceHelpers.controlSize) wirecolor:blue name:(uniqueName "CNT_Face")      -- uncomment to use as method 3
            cnt.transform=pt.transform
            cnt.parent=pt2
            xf=xForm()
            addModifier cnt xf
            xf.gizmo.pos.z = surfaceHelpers.spn_controlSize.value
            --xf.gizmo.pos.z=controlSize                     -- uncomment to use as method 2
            --xf.gizmo.pos.z=surfaceHelpers.controlSize      -- uncomment to use as method 3
            convertToSplineShape cnt
         )
      ),
      fn runTool=
      (
         tool mouseHit
         (
            on mousePoint clickNo do
            (
               if clickNo>1 do
               (
                  r=(mapScreenToWorldRay mouse.pos)
                  hit=intersectRay targetNode r
                  makeControl hit
                  if queryBox "Do you want to make a mirror control" title:"Well!" do
                  (
                     hit=intersectRay targetNode (ray (r.pos*[-1,1,1])(r.dir*[-1,1,1]))
                     makeControl hit
                  )
               )
            )
         )
         startTool mouseHit
      ),
      
         
      on create do 
      (
         -- targetNode = selection[1]      --   Uncomment to assign the 'targetNode' on creation
      )
   )
   ::shInstance = surfaceHelpersStructure selection[1]   --   Assign the targetNode on instance creation and limit it to the first node.
                                                         --   You can do this in the 'on create' event and here just do: ::shInstance = surfaceHelpersStructure()
   -- We assign the instance as a global. This way everytime you call the '::shInstance.showDialog()' function, it will work and the old dialog will be closed. 
   -- You can call this function from the listener or create a macro that just calls this function (of course you have to run once the script(and only once)).
)
   ::shInstance.showDialog()
__________________
Andrés FC.
P3D_PathScripts
Proin3D YouTube Channel
 
  1 Week Ago
Thank you very much for this! Truly appreciate all of this
Really helps to understand how these things work.
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright ©2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 08:22 AM.


Powered by vBulletin
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.