[Closed] persistent global structs
I’d like to discuss (again) the ways to keep structs between sessions.
“global” works with structs, but:
“persistant global” doesn’t keep the struct content between sessions.
custom attributes? don’t work with structs…
appData? only stores strings.
Same with filestreams/INI/XML.
One neat way (if it worked) would be converting the struct into a string and executing it after restoring the string.
But that only works with numbers, strings, boolean, etc, not with nodes, and other classes:
“$Box001” becomes: “$Box:Box001 @ [184.403152,-87.286911,0.000000]” when converted to string.
The only way to store/restore a struct with all kinds of (mixed) data would be:
looping through it, storing the name, value and class in some XML tree.
then putting the string stream into a CA, appdata, or external textfile.
later restoring all values into a new struct.
This is a very tedious way. Anyone got an idea for a more simple solution?
You need to store a single struct or an array of structs?
Custom attributes allow you to store a whole range of objects, you could use stringTab + maxobjectTab and use their array attributes to parallel store different types of data, which you can then parse back into structs. I’m using something similar to store poses, loads of data can be “serialized” to strings ($.transform as string) you can even store arrays of transforms ((for o in selection collect o.transform) as string) etc. Objects can be stored via either maxObjectTab with a nodetransform monitor of directly in a nodetab. etc. But it’s true that it would be nice to store structs.
Hope this is of any help,
-Johan
Well, I’m working on this script, where I pick different source objects and target objects in listviews. Every picked object has different settings, edited from rollouts.
The best way to store pre-defined properties for a variable count of picked sceneobjects seemed to me an array of structs, with all rollout-settings etc. stored inside.
the struced for a picked object looks like this:
struct_sourceObject node:$Teapot:Teapot001 @ [136.665131,-87.597031,0.000000] name:"Teapot001" checked:true Properties:#(1, 0.0, 0.0, 0.0, false, 1, false, "Teapot001_", (color 145 28 177), false, 1, 1) mutationsList:#() linkedSourceObjectsList:#($Editable_Mesh:Plane001 @ [18.430813,-96.929871,0.009262], $Sphere:Sphere001 @ [-118.707733,-102.855934,-0.001023])
So I need to store/restore all that stuff somehow...
Looping through every child/subchild and checking the classes to store everything properly is a nightmare…
the only one way to store and restore all information about max scene (nodes, controllers, materials, ca, modifiers, dependencies, etc.) is to save the data in max format file and merge it. When you merge the file it brings the persistence globals with it. Actually MAX overrides the persistence globals in your scene after the merging. So you have to make unique names for globals and have a mechanics to identify the merged globals by merged max file filename. I’m using CRC32 to make the persistence globals (structures) which are supposed to be read by other file unique.
Hi Denis,
I played with your suggestion to merge max files, with mixed results.
It did work, when the structs and globals were declared before merging the file.
I found out that it also worked with normal file/open that way.
struct global_struct(node, name, checked, properties)
persistent global test
So as long as I run this code before loading the max file with the persistent globals, it works! Everything is in place.
So what I’m doing now is putting this init code into an autostart script file.
This is clearly not elegant, because it will create empty variables in every new scene file, regardless if used for the script or not, but why not?
If I look at your struct I see 2 node declarations and some properties. All the properties can be parsed back and forth to a string, the nodes could be stored in a maxObject tab with a weak reference. A CA would work on those properties, but obviously not everything can be stored. Is there more value types you are using, because with what you have now I’d probably use a CA.
(
struct sourceObject
(
node,
name,
checked,
Properties = #(),
mutationsList = #(),
linkedSourceObjectsList = #()
)
ca = attributes ca
(
parameters store
(
node type:#maxObject
name type:#string
checked type:#boolean
properties type:#string
mutationsList type:#string
linkedSourceObjectsList type:#maxObjectTab tabSize:0 tabSizeVariable:true
)
)
b = box name:"CA_Holder"
append b.children (box name:"Child1" pos:[25,0,0])
append b.children (box name:"Child2" pos:[0,25,0])
custAttributes.add b ca
-- Save data to CA
b.ca.node = NodeTransformMonitor node:b forwardTransformChangeMsgs:false
b.ca.name = b.name
b.ca.checked = true
b.ca.properties = #(1, 0.0, 0.0, 0.0, false, 1, false, "Teapot001_", (color 145 28 177), false, 1, 1) as string
b.ca.mutationsList = #() as string
b.ca.linkedSourceObjectsList = for c in b.children collect NodeTransformMonitor node:c forwardTransformChangeMsgs:false
-- Parse back to struct
mySource = sourceObject node:b.ca.node.node \
name:b.ca.name \
checked:b.ca.checked \
properties:(execute b.ca.properties) \
mutationsList:(execute b.ca.mutationsList) \
linkedSourceObjectsList:(for n in b.ca.linkedSourceObjectsList collect n.node)
print mySource
ok
)
-Johan
That’s cool, thanks for the code…I never used CA´s but I will read into it.
struct global_struct(node, name, checked, properties)
After further testing I found out that it’s enough to define the struct before loading the scene, then the persistent global structs are restored pefectly.
That’s amazing, why did no one ever mention that?
I put the struct definitions into a startup script and everything is remembered.