Notifications
Clear all

[Closed] Scripted Geometry – reference problem

Hello everyone,

I am trying to create a scripted geometry which mirrors a selected geometry. I use weak reference because when i just use the node instead, when translating the source-node it behaves awkardly (it translates jagged, very fast, away from mouse). The problem that arises with weak reference is that when i change the source-geometry the mesh does not update. I have to select the object and use the on rollout open event to do so (even then i have to re-evaluate the mirrorBool value [line:27] or else it does not re-builds the mesh). p.s.(it also does not store in memory the pickbutton text)
Is there a way to create a reference to the mesh property of the source-node so as when the source-geometry changes so does the mesh of the plug-in?


plugin simpleObject MirrorObject
name:"Mirror Object"
classID:#(0x14c6b999, 0x6c060ea1)
category:"har1sf0x"
(
   parameters mainP rollout:mainR
   (
      valid type:#boolean default:false
      mirrorBool type:#boolean default:true ui:chk_mirror
      obj type:#maxObject
      on obj set val do this.rebuildMesh()
      on mirrorBool set val do this.rebuildMesh()
   )
   rollout mainR "Parameters"
   (
      pickbutton pck_obj "Pick mesh" autodisplay:true
      checkbox chk_mirror "Mirror" checked:true
      on pck_obj picked o do
      (
         if isValidnode o and superclassof o == GeometryClass do
         (
            obj = (nodeTransformMonitor node:o forwardTransformChangeMsgs:false)
            pck_obj.text = o.name
            valid = true
         )
      )
      on mainR open do (if valid and isValidNode obj.node do (pck_obj.text = obj.node.name);mirrorBool = chk_mirror.checked)
   )
   on buildmesh do this.rebuildMesh()
   
   fn rebuildMesh =
   (
      proxy = trimesh()
      setMesh proxy length:10 width:10
      if valid and isValidNode obj.node do
      (
         proxy = obj.node.mesh
         if mirrorBool do proxy = this.mirrorMesh proxy
      )
      mesh = proxy
   )
   fn mirrorMesh msh =
   (
      for f =1 to msh.numFaces do
      (
         verts = getFace msh f
         local tmp = verts.x
         verts.x = verts.z
         verts.z = tmp
         setFace msh f verts
      )
      for v = 1 to msh.numVerts do
      (
         setVert msh v ((getVert msh v)*[-1,1,1])
      )
      update msh
      msh
   )
   
   tool create
   (
      on mousePoint click do
      (
         case click of
         (
            1: nodeTM.translation = gridPoint
            2: #stop
         )
      )
   )
)

Best regards,
har1sf0x

14 Replies

first of all i don’t think that simpleObject is the right type of plugin for this task… more likely it should be a modifier … the simpleMeshMod

but of course we can organize true monitoring of any mesh with simpleObject plugin…

1 Reply
(@har1sf0x)
Joined: 11 months ago

Posts: 0

How? Any reference to check?

Hello again,

I did it with the modifier (i also did it with function -> reference copy and mirror modifier) but you have to do one or more clicks (that is one of the reasons i went to the geometry, the other is learning references). I finaly made it work but without the weak reference. I would be very interested and much appreciated if someone could give some ideas about how to get notification from a weak referenced node about its mesh changes.
Here is the code of the updated version (the pickbutton .text still is not being stored, even though i used a parameter):


plugin simpleObject MirrorObject
name:"Mirror Object"
classID:#(0x14c6b999, 0x6c060ea1)
category:"har1sf0x"
(
   parameters mainP rollout:mainR
   (
      valid type:#boolean default:false
      mirrorBool type:#boolean default:true ui:chk_mirror
      obj type:#node--#maxObject
      txt type:#string
--       on obj set val do this.rebuildMesh()
--       on mirrorBool set val do this.rebuildMesh()
   )
   rollout mainR "Parameters"
   (
      pickbutton pck_obj "Pick mesh" autodisplay:true
      checkbox chk_mirror "Mirror" checked:true
      on pck_obj picked o do
      (
         if isValidnode o and superclassof o == GeometryClass do
         (
            obj = o--(nodeTransformMonitor node:o forwardTransformChangeMsgs:false)
            txt = o.name
            pck_obj.text = txt
            valid = true
         )
      )
--       on mainR open do (if valid and isValidNode obj do (pck_obj.text = obj.name))--;mirrorBool = chk_mirror.checked)
   )
   
   on buildmesh do this.rebuildMesh()
   
   fn rebuildMesh =
   (
      proxy = trimesh()
      setMesh proxy length:10 width:10
      if valid and isValidNode obj do--.node do
      (
         proxy = obj.mesh--.node.mesh
         if mirrorBool do proxy = this.mirrorMesh proxy
      )
      setMesh mesh proxy
   )
   fn mirrorMesh msh =
   (
      for f =1 to msh.numFaces do
      (
         verts = getFace msh f
         local tmp = verts.x
         verts.x = verts.z
         verts.z = tmp
         setFace msh f verts
      )
      for v = 1 to msh.numVerts do
      (
         setVert msh v ((getVert msh v)*[-1,1,1])
      )
      update msh
      msh
   )
   
   tool create
   (
      on mousePoint click do
      (
         case click of
         (
            1: nodeTM.translation = gridPoint
            2: #stop
         )
      )
   )
)

Best regards,
har1sf0x

You just have to change two lines in your code:


.
.
      txt type:#string default:"Pick mesh"
.
.
      pickbutton pck_obj txt autodisplay:true
.
.

But, in fact, I can’t understand how your plugin works (and it works fine). I mean, why the MirrorObject changes when you change the referenced node. I can’t see any handler for this.

1 Reply
(@har1sf0x)
Joined: 11 months ago

Posts: 0

Thnx, worked like a charm. Any ideas about the weak reference?

What is your goal? I mean, what are you missing in your plugin?

1 Reply
(@har1sf0x)
Joined: 11 months ago

Posts: 0

It’s a study. Suppose i want to link the referenced mesh to the scripted object. Without the weak reference this is impossible.

#1 try to use nodemonitor instead of nodetransformmonitor
#2 look at referencetargetcontainer

1 Reply
(@har1sf0x)
Joined: 11 months ago

Posts: 0

Hello,

I’ve tried both (NodeMonitor, RefTargContainer), even RefTargMonitor. It either has a dependency loop problem or it does not update live. Never both problems are absent:


plugin simpleObject MirrorObject
name:"Mirror Object"
classID:#(0x14c6b999, 0x6c060ea1)
category:"har1sf0x"
(
--    local objCont --with this i can link either way but it does not update live
   parameters mainP rollout:mainR
   (
      valid type:#boolean default:false
      mirrorBool type:#boolean default:true ui:chk_mirror
      objCont type:#maxObject --with this it does update live but i can link only one way
      size type:#float default:20
      type type:#integer default:1 ui:rdb_type
      txt type:#string default:"Pick mesh" ui:pck_obj
      on mirrorBool set val do this.rebuildMesh()
   )
   rollout mainR "Parameters"
   (
      pickbutton pck_obj txt autodisplay:true
      checkbox chk_mirror "Mirror" checked:true
      group "Mirror Axis"
      (
         radiobuttons rdb_type labels:#("X","Y","Z","XY","XZ","YZ","XYZ") columns:3
      )
      on pck_obj picked o do
      (
         if isValidnode o and superclassof o == GeometryClass do
         (
            objCont.SetItem 1 o
            txt = o.name
            valid = true
         )
      )
   )
   
   on postCreate do objCont = RefTargContainer holdAsWeakReferences:true
   
   on buildmesh do this.rebuildMesh()
   
   fn rebuildMesh =
   (
      mesh = trimesh()
      if valid and isValidNode (this.objCont.GetItem 1) then
      (
         mesh = (objCont.GetItem 1).mesh
         if mirrorBool do mesh = this.mirrorMesh mesh
      ) else (setMesh mesh length:size width:size lengthsegs:1 widthsegs:1)
   )
   fn mirrorMesh msh =
   (
      scaleVec = #([-1,1,1],[1,-1,1],[1,1,-1],[-1,-1,1],[-1,1,-1],[1,-1,-1],[-1,-1,-1])[type]
      for f = 1 to msh.numFaces while type < 4 or type == 7 do
      (
         local bl = false
         if (getEdgeVis msh f 1) and (getEdgeVis msh f 2) and (getEdgeVis msh f 3) do bl = true
         blList = #()
         for i = 1 to 3 do append blList (getEdgeVis msh f i)
         verts = getFace msh f
         local tmp = verts.x
         verts.x = verts.z
         verts.z = tmp
         setFace msh f verts
         if bl then for i = 1 to 3 do setEdgeVis msh f i true
            else
         (
            if not blList[1] and (mod f 2) == 1 do
            (
               setEdgeVis msh f 1 false
               setEdgeVis msh f 2 false
               setEdgeVis msh f 3 true
            )
            if blList[1] and (mod f 2) == 0 do
            (
               setEdgeVis msh f 1 true
               setEdgeVis msh f 2 true
               setEdgeVis msh f 3 false
            )
         )
      )
      for v = 1 to msh.numVerts do
      (
         setVert msh v ((getVert msh v)*scaleVec)
      )
      update msh
      msh
   )
   
   tool create
   (
      on mousePoint click do
      (
         case click of
         (
            1: nodeTM.translation = gridPoint
            2: #stop
         )
      )
      on mouseMove click do
      (
         case click of
         (
            2:
            (
               size = abs(amax #(gridDist.x,gridDist.y))
            )
            3: (#stop)
         )
      )
   )
)

see this example that i’ve showed here and on area…


plugin simpleObject Cloner
   name:"Cloner"
   classID:#(0x00001967, 0x0af62091)
   category:"Scripted Primitives"
   silentErrors:off
   version:1
(
   fn validGeometry node = (iskindof node GeometryClass) 
--   local mesh
   parameters main rollout:main 
   (
      meshTarget type:#node subanim:on ui:pickobject_bt
      meshObject type:#MaxObject
   )
   parameters params rollout:main 
   (
      count type:#integer ui:ui_count
      radius type:#worldunits ui:ui_radius
      tilt type:#worldunits ui:ui_tilt
   )
   rollout main "Parameters"
   (
      group "Mesh Object: "
      (
         pickbutton pickobject_bt "Pick Mesh Object" autoDisplay:on filter:validGeometry width:144 align:#right offset:[4,0] 
      )
      on pickobject_bt picked obj do
      (
         meshObject = createinstance Editable_mesh
         meshObject.mesh = obj.mesh
      )
      
      group "Spacing: "
      (
         spinner ui_count "Count: " range:[1,512,1] type:#integer fieldwidth:60 align:#right offset:[4,0] 
         spinner ui_radius "Radius: " range:[0,1e9,0] type:#worldunits fieldwidth:60 align:#right offset:[4,0] 
         spinner ui_tilt "Tilt: " range:[0,1e9,0] type:#float fieldwidth:60 align:#right offset:[4,0] 
      )
   )
   fn _transformMesh mesh tm = 
   (
      list = for v=1 to mesh.numverts collect ((getVert mesh v)*tm)
      setmesh mesh vertices:list
   )
   fn _attachMeshes meshes = 
   (
      n = meshes.count
      while (num = n/2) > 0 do for k=1 to num do 
      (
         meshop.attach meshes[k] meshes[n]
         n -= 1
      )
      meshes[1]
   )
   on buildMesh do
   (
      setMesh mesh numverts:0 numfaces:0
      if meshObject != undefined do
      (
         m = if isvalidnode meshTarget then (copy meshTarget.mesh) else (copy meshObject.mesh)
         tm = transmatrix [radius,0,0]
         cc = for k=1 to count collect
         (
            c = copy m
            _transformMesh c tm
            tm = prerotateY tm (tilt/count)
            tm = rotateZ tm (360.0/count)
            c
         )
         setMesh mesh (_attachMeshes cc)
         
         free m
      )
   )
   tool create
   (
      on mousePoint click do case click of
      (
         1: 
         (
            nodeTM.translation = gridPoint
            #stop
         )
      )
      on mouseMove click do case click of
      (
      )
   )
)

you can use NodeTransformMonitor instead of node…
also there is another way of to store mesh (using reftargcontainer). you can find posts about it on this forum

Hello and thank you for your concern.

I’ve read your post in the autodesk forum and just tested but it also creates a dependency loop becauce of the meshTarget. That is what makes the mesh update live. If you comment the

ui:pickobject_bt

in line 12 the object will not give a dependency loop but it will also not update live.
I tend to believe that it is not possible to create a ‘live’ reference to an other object without creating a dependency loop. I even tried to create and test an indirect reference (ref.setIndirectReference() getting error all over the place) but as i saw in the help files it cannot be done via maxscript.

p.s. have in mind that your script was crashing in my computer probably because of count=0 on initialization even thougn in the ui was saying 1 (because of the range) and the cc was an empty array. i gave a default to count and worked like a charm.

p.s.1 as i said i tested the other suggestions. i do not want to store the mesh. i want to reference it so as to update live

p.s.2 when you create a reference copy of an object it does not create a dependency loop and updates the mesh live. that is what i am looking for to replicate in my plugin.

yes … my example crashes if the number of cloned instances equals 0. but believe me i don’t care. usually my example codes are very far from my commercial versions. but they show enough…

going to your issue…

i see a fundamental misunderstanding of how the notification system works. because of the difference there are special ways (plugin types) to achieve what you want.

1 Reply
(@har1sf0x)
Joined: 11 months ago

Posts: 0

Hello,

you are definitely right, i am totally confused as it seems. From your reply i understand that i am using the wrong plugin type and that it is not possible achieving such behaviour with this plugin type, right? Is there a way to learn more about the notification-reference system of max besides the maxscript manual?

Thanks,
har1sf0x

p.s. i hope you did not misunderstood my comment about your example code. it was just a note in case someone would like to try it and got into the error. I am obliged to you and to all about your concern and the time you spend sharing your experience with me and off-course honestly thankful having the opportunity to take advice from all of you.