[Closed] Custom attribute help in maxscript
Hey, im getting stuck on this, im trying to create (through a UI, using a button) to place cust atribute to an object and have the atribute perform actions. it works great but what im finding is, when i use it twice its only effecting the newly made object and the first object does nothing.
I want to get it so it can be used over and over with out closing the UI. I’ve read it has somthing to do with #nodes but im getting lost. any help would be great.
Heres the test script im trying to get to work:
(
local a
local b
local c
struct myRiggingTools
(
fn Adding_Atribute item =
(
IKFK_Switch = EmptyModifier()
addmodifier item IKFK_Switch
),
fn CustAttirbute_IKFK item =
(
IKFK_Switch = item
IKFK_SwitchCA= attributes IKFK_Switch
(
parameters params_IK_FK rollout:rollout_IK_FK
(
IK_FK_Match type:#float ui:(matchIKtoFK,matchFKtoIK)
)
rollout rollout_IK_FK "es"
(
group "Blend"
(
button matchIKtoFK "C --> B" across:2
button matchFKtoIK "C --> A"
on matchIKtoFK pressed do
(
c.transform = b.transform
)
on matchFKtoIK pressed do
(
c.transform = a.transform
)
)
)
)
custAttributes.add item.modifiers[1] IKFK_SwitchCA
)
)
myRiggingTools=myRiggingTools
–End Of Struct
global riggingT
try destroyDialog riggingT catch()
rollout riggingT "Rigging Tools UI" width:250 height:600
(
fn test =
(
a = box()
b = box()
c = box()
a.height = 10
a.width = 10
a.length = 10
a.pos = [50,0,0]
b.height = 10
b.width = 10
b.length = 10
b.pos = [-50,0,0]
myRiggingTools.Adding_Atribute c
myRiggingTools.CustAttirbute_IKFK c
)
group "Create"
(
button createIKFK "Create"
on createIKFK pressed do
(
test()
)
)
)
createDialog riggingT 250 150
)
Please use the [ code ] and [ /code ] tags and indentation, that will make your code a lot easier to read.
From what I can see the problem you’re having comes from the fact that in your CA you reference local variables outside of the CA definition. Instead, you should store the nodes you want to use as a parameter on the CA itself.
thanks for the reply and defo will do for the future.
I tried placing, a type:#node b type:#node c type:#node, in the parameter block but the listener window is kicking with the error >> MAXScript Rollout Handler Exception:
– Unknown property: “transform” in undefined <<
ill keep trying
Well you’ll then have to set these parameters on the CA of course. Currently you’re assigning your local a, b and c. To preserve the references, you should set the CA properties after adding the CA to the modifier.
” To preserve the references, you should set the CA properties after adding the CA to the modifier.”
argh im really trying to understand im just getting a mental block, im unsure how to set it after adding it…
There are two ways of going about this: either you access the CA’s property through the object it is applied on:
custAttributes.add item.modifiers[1] IKFK_SwitchCA
item.modifiers[1].a = something
or you access it through the CA instance:
local ca = custAttributes.add item.modifiers[1] IKFK_SwitchCA
ca.a = something
I have to add a note here that the add method might not return a CA instance, I don’t exactly remember and don’t have the documentation in front of me. If it doesn’t, then you have to get the ca using custattributes.get.
Just got back on my computer today
Thanks for the help Pjanssen but i'm still unable to get this to work.
Anychance if u can tell me if i'm in the general ballpark?
(
local a
local b
local c
struct myRiggingTools
(
fn Adding_Atribute item =
(
IKFK_Switch = EmptyModifier()
addmodifier item IKFK_Switch
),
fn CustAttirbute_Node item =
(
NodeS = item
NodeS = attributes NodeStore
(
parameters NStoreP
(
a type:#node
b type:#node
c type:#node
)
)
custAttributes.add item.modifiers[1] NodeS
),
fn CustAttirbute_IKFK item =
(
IKFK_Switch = item
IKFK_SwitchCA= attributes IKFK_Switch
(
parameters params_IK_FK rollout:rollout_IK_FK
(
IK_FK_Match type:#float ui:(matchIKtoFK,matchFKtoIK)
)
rollout rollout_IK_FK "es"
(
group "Blend"
(
button matchIKtoFK "C --> B" across:2
button matchFKtoIK "C --> A"
on matchIKtoFK pressed do
(
$.modifiers[1].NodeStore.c.transform = $.modifiers[1].NodeStore.b.transform
)
on matchFKtoIK pressed do
(
$.modifiers[1].NodeStore.c.transform = $.modifiers[1].NodeStore.a.transform
)
)
)
)
custAttributes.add item.modifiers[1] IKFK_SwitchCA
item.modifiers[1].a = test01
item.modifiers[1].b = test02
item.modifiers[1].c = test03
)
)
myRiggingTools=myRiggingTools
--End Of Struct
global riggingT
try destroyDialog riggingT catch()
rollout riggingT "Rigging Tools UI" width:250 height:600
(
fn test =
(
a = box()
b = box()
c = box()
a.height = 10
a.width = 10
a.length = 10
a.pos = [50,0,0]
b.height = 10
b.width = 10
b.length = 10
b.pos = [-50,0,0]
myRiggingTools.Adding_Atribute c
myRiggingTools.CustAttirbute_Node c
myRiggingTools.CustAttirbute_IKFK c
myRiggingTools.test01
myRiggingTools.test02
myRiggingTools.test03
)
group "Create"
(
button createIKFK "Create"
on createIKFK pressed do
(
test()
)
)
)
createDialog riggingT 250 150
)
Thanks again
sometimes i feel myself kinda confused looking on max scripts like this… the script utilizes structures and custom attributes. but the owner of the script has very… abstract knowledge about both these things.
is it not simpler to figure out first how these things work, before trying to mix them together?
there is another sample: http://forums.cgsociety.org/showpost.php?p=7170150&postcount=1
yeah…thats fair enough comment. I just thought the best way to learn by myself was to create a script, which would be useful for production. I think its worked great for the one script I’ve done so far. I am aware that I have missed a lot, in between what I’m learning.
Here is your script in a working format. I’ve removed the struct, and had to drop a few functions, but it does what (I think) you want it to do:
(
local a, b, c
fn CustAttribute_Node item nodesArray =
(
str = "attributes objectData
(
rollout paramsRollout \"Parameters\"
(
dropdownlist nodesDd items:%
)
)
"
ss = stringstream ""
format str (with printallelements on nodesArray as string) to:ss
objectData = execute (ss as string)
free ss
custAttributes.add item objectData baseobject:on
select item
max modify mode
)
fn CustAttribute_IKFK item =
(
IKFK_Switch = item
IKFK_SwitchCA = attributes IKFK_SwitchData
(
rollout rollout_IK_FK "es"
(
group "Blend"
(
button matchIKtoFK "C --> B" across:2
button matchFKtoIK "C --> A"
on matchIKtoFK pressed do
(
arr = $.objectData.paramsRollout.nodesDd.items --collect the custom attributes array
--get nodes by their name
local aa = getnodebyname (arr[1] as string) exact:true
local bb = getnodebyname (arr[2] as string) exact:true
local cc = getnodebyname (arr[3] as string) exact:true
--set c's transform to b's transform
local tm = bb.transform
local pos = bb.pos
local new_TM = matrix3 tm.row1 tm.row2 tm.row3 pos
cc.transform = new_TM
)
on matchFKtoIK pressed do
(
arr = $.objectData.paramsRollout.nodesDd.items --collect the custom attributes array
--get nodes by their name
local aa = getnodebyname (arr[1] as string) exact:true
local bb = getnodebyname (arr[2] as string) exact:true
local cc = getnodebyname (arr[3] as string) exact:true
--set c's transform to b's transform
local tm = aa.transform
local pos = aa.pos
local new_TM = matrix3 tm.row1 tm.row2 tm.row3 pos
cc.transform = new_TM
)
)
)
)
custAttributes.add item IKFK_SwitchCA
)
global riggingT
try destroyDialog riggingT catch()
rollout riggingT "Rigging Tools UI" width:250 height:600
(
fn test =
(
a = box()
b = box()
c = box()
a.height = 10
a.width = 10
a.length = 10
a.pos = [50,0,0]
b.height = 10
b.width = 10
b.length = 10
b.pos = [-50,0,0]
CustAttribute_node c #(a.name, b.name, c.name)
CustAttribute_IKFK c
)
group "Create"
(
button createIKFK "Create"
on createIKFK pressed do test()
)
)
createDialog riggingT 250 150
)
Let’s go over some things, so you can have a deeper understanding of maxscript:
#1. You’re code didn’t call for a custom data structure, so I removed the struct. You can do what you want to do with just functions.
#2. Adding an empty modifier to hold attributes is not the best way to go about doing certain things, like storing references to scene nodes. I prefer to store CAs on the node itself.
#3. (A) I’m 99% sure you can’t directly store a reference to a scene node on a custom attribute (like you were doing with: “NodeStore” and “a type:Node” ). (B) I’m 100% sure you can’t store an array data type on a custom attribute.
#4. The script was failing when you tried to get a node’s transform from NodeStore because of #3(A).
#5. In my code example, I’m using a snippet written by denisT to add an array to a dropdown list on a custom attribute. Then I retrieve the array from the dropdown list, get the node in the scene by the name stored in the array, and finally affect the transforms to match c to b, or c to a. This is the only way that I know of storing an array of scene nodes on another node.
but the owner of the script has very… abstract knowledge about both these things.
is it not simpler to figure out first how these things work, before trying to mix them together?
I think what denisT means is that you should first start with basic examples of structs to get a feel for how they work, and then begin to include structs (appropriately) in more complex scripts.
If you want to learn more about maxscript, then the maxscript help is your best friend. Use the search field to locate topics that you would like to learn more about, there are also many code examples in the help file. If you can’t find what you’re looking for, try searching through CGtalk’s forums, which house a metric ton of code examples from brilliant scripter’s like bobo, denisT, loneRobot, biddle, etc… You can also google for ‘Allan McKay maxscript tutorial” – he gives a great introduction to working with maxscript on his website, including working with the help file and listener to understand errors when they occur. I would also suggest using lots of print statements to check the states of variables as your code executes. For example, one of the first things I did when refactoring your code was to “print NodeStore”, which didn’t print at all and led to me to realize that the custom attributes were being stored incorrectly.
Hope this helps.