[Closed] [SDK] Make modifier dependent of node's TM
Hi, here’s the example:
delete objects
t1 = Teapot wirecolor:gray
t2 = copy t1 pos:(t1.pos + [0,50,0]) wirecolor:(gray * 0.5)
b1 = Box width:30 height:40 length:30 boxmode:on wirecolor:yellow
b2 = copy b1 pos:(b1.pos + [0,50,0]) wirecolor:white boxmode:on
animate on
(
at time 0f
(
t1.pos = [0,0,0]
b2.pos = [0,50,0]
)
at time 100f
(
t1.pos = [50,0,0]
b2.pos = [50,50,0]
)
)
addModifier t1 (VolumeSelect level:1 volume:3 node:b1)
addModifier t2 (VolumeSelect level:1 volume:3 node:b2)
select #( t1, t2 )
playAnimation()
As you can see there’s no difference what node to move. The node where modifier is applied to or the target node, both somehow invalidate the state of volumeselect modifier and it fires ModifyObject again…
from SDK\samples\modifiers\selmod.cpp_
class SelMod : public Modifier, public EditSSCB {
public:SelModValidatorClass validator;
IParamBlock2 *pblock2,*pblock2_afr;
Control *tmControl; <– these two looks suspicious as their validityinterval is being checked in GetValidity. Although it may be gizmo related controls
Control *posControl;
DWORD flags;
Can someone more experienced explain to me how does it work?
How does modifier gets notified when its self node is animated or just moved around.
Strictly speaking, a modifier should not react in any way to the transformation of its context object. It is inherent in its essence. Otherwise it creates a dependency loop. But you can take its transform controller as a weak reference into one of paramblock parameters. This way the modifier can get a signal that this parameter is changing. But ‘dependency loop’ possibility you have to control yourself.
That’s what I found so far…
It uses ITrackViewNode to add a controller of node’s TM.
Are you aware of any less convoluted example of how to achieve that? I mean in my example it is too much needs to be to implemented just to test if it really works and related to my task at all…
but it doesn’t make it any better for me
this is how it works in MXS:
plugin simpleMeshMod simpleMeshTest
name:"simpleMesh"
classID:#(0x193aa23b, 0x01010101)
category:"Tests"
(
local test
parameters params
(
node_transform type:#maxObject subanim:on
)
on modifyMesh do
(
format "changed: %\n" (timestamp())
mesh
)
on attachedtonode node do
(
node_transform = node.controller
)
)
/************************
-- set node_transform to undefined:
<this modifier>.node_transform = undefined
************************/
i don’t have time right now to make a API example. but the idea is clear.
And forget what I said above about “weak reference”. We don’t need it. We can directly use ReferenceTarget (transform controller or dependent subanim)
Thanks. I will check it out. In mxs I used NodeTransformMonitor interface only once long long time ago…
btw, I found a class called MaxSDK::SingleWeakRefMaker so I’m half-way there… PART_TM messages are captured nicely, what’s left is to invalidate modifier so it will update.
here is the clearer example … see the difference:
plugin simpleMeshMod simpleMesh
name:"simpleMesh"
classID:#(0x193aa23b, 0x01010100)
category:"Tests"
(
on modifyMesh do
(
format "% >> changed: %\n" this (timestamp())
mesh
)
)
plugin simpleMeshMod simpleMeshTM
name:"simpleMeshTM"
classID:#(0x193aa23b, 0x01010103)
category:"Tests"
(
parameters params
(
node_transform type:#maxObject subanim:on
)
on modifyMesh do
(
format "% >> changed: %\n" this (timestamp())
mesh
)
on attachedtonode node do
(
node_transform = node.controller
)
)
delete objects
b0 = box name:#b0 pos:[-20,0,0] wirecolor:green
addmodifier b0 (simpleMesh())
b1 = box name:#b1 pos:[20,0,0] wirecolor:orange
addmodifier b1 (simpleMeshTM())
as i said, we don’t need week reference. Use the transform control itself (or any of its parts(position, rotation, scale controls))
it’s better to use transform SubAnim instead of control (in case that the control can be replaced with another one).
added
it seems like we can’t do it with MXS but with API there is a difference between subanim and actual control. But i have to think about it a little more…
I see your point. simpleMeshTM does exactly what I need. Thanks.
The only question remains what will happen if modifier that is applied to several nodes and that one self-node that we selected as the MaxObject gets deleted by user. We’ll have a dangling pointer then?
No!!!
I was right about Weak Reference. It has to be:
plugin simpleMeshMod simpleMeshWeak
name:"simpleMeshWeak"
classID:#(0x193aa23b, 0x01010104)
category:"Tests"
(
parameters params
(
node_transform type:#maxObject subanim:on
)
on modifyMesh do
(
format "% >> changed: %\n" this (timestamp())
mesh
)
on attachedtonode node do
(
node_transform = NodeTransformMonitor node:node --node.controller
)
)
delete objects
b0 = box name:#b0 pos:[-20,0,0] wirecolor:green
addmodifier b0 (simpleMesh())
b1 = box name:#b1 pos:[20,0,0] wirecolor:orange
addmodifier b1 (simpleMeshTM())
b2 = box name:#b2 pos:[60,0,0] wirecolor:yellow
addmodifier b2 (simpleMeshWeak())
now you can change node’s controller and still keep reference to it’s transformation. With simpleMeshTM you loose this dependency.
see the difference:
b1.controller = createinstance prs
b2.controller = createinstance prs
do you want to apply one instance of your modifier to multiple objects? hmm… in this case you have to use tab array parameter probably and put there all nodes transforms (node monitors). you have messages if anything happened with controlled nodes. You have to handle all related events (node deleted, node added, etc.) yourself in this case.
You will get transform messages from all nodes, but the tab array can tell you exactly which node sent it. After that your own logic has to decide what to do. I did it some time ago. It’s doable.
I’m not so optimictic when it comes to cpp anything :)) But c++ sdk advantages outweight c# usability and development speed.
These dependencies need to be not only handled but even loaded and saved with the modifer. For the first time in my life