[Closed] Save and Load transforms to a File
Hey Everybody,
i need a script where i can store Object Positions and Rotations to a file.
i work with freezed Positions so i only need to store the “pos.controller[2]” and “rotation.controller[2]” value. no problem there…
this is what the script writes in my txt file:
Teapot002
pos = [-115.054,-14.0734,0]
Rotation = (quat 0 0 0 1)
Teapot001
pos = [-40.8722,89.8317,-43.1387]
Rotation = (quat 0.742904 0.133543 0.552876 -0.352971)
…
But now i need to load the stored data and apply it to my objects…this is where i got some trouble
i learned a lot from other scripts…but not enaugh to finish it
here is the unfinished script:
rollout PS "Save/Load freezed Position" width:223 height:329
(
button svb "Save Position" pos:[66,71] width:90 height:30
button ldb "Load Position" pos:[66,227] width:90 height:30
on svb pressed do -- the save pos button
(
MyLog = getSaveFileName types:"PoseFiles (*.txt)|*.txt"
ini_file = createFile MyLog
ToMyLog = openFile MyLog mode:"at"
for a in selection do
(
if selection.count !=0 then
(
format "%
" a.name to:ToMyLog
format "%
" (" pos = " + a.pos.controller[2].value as string ) to:ToMyLog
format "%
" (" Rotation = " + a.rotation.controller[2].value as string)to:ToMyLog
)
else (messageBox "Nothing selected !
Please select something" title:"3ds Max")
)
close ToMyLog
)
on ldb pressed do -- the load pose button
(
fload= getOpenFileName types:"PoseFiles (*.txt)|*.txt" -- asks for the saved file
ff=openfile fload --opens the saved file
---rng=readvalue ff
for i=1 to selection.count do --takes every selected object and...
(
o=selection[i]
seek ff 0 --goes to begining of the saved file
skiptostring ff (o.name+ " ")
skiptostring ff "pos = " --goes to saved position controller line --begining of reading position controller
)
)
)
createdialog PS
if anybody got an idea how i can load the file back…let me know
cheers
Tommy
You would be better off doing the formatting to one line…
format "\"%\",%,%
" a.name a.pos.controller[2].value a.rotation.controller[2].value to:ToMyLog
Then you can read one line at a time and split it to values and use ReadValue, notice how I made the name a string literal in the stringstream too by putting the quotes in there.
Are your objects in a hierarchy? Just applying their world rotation back onto them could become an issue if they are parented as you may apply a position and rotation in world space, but later load on the pos or rot of a parent which will then change all of its children.
I always save AND load my positions and rotations in parent space and always apply the rotations first.
I’ve been fighting something kind of related to this recently and it can sometimes get to be a real pain!
Hey guys
thanks dave for your tip!
i am not a technical artist with coding background but i want to understand the maxscript syntax as good as possible.
lets say i have an rig where all my animation Controller are linked to a master object. After linking i freezed all the transform and rotations to get zero values.
now i am able to reset my controllers to there zero position or rotation while animating.
i created a script that works with selection sets or simple object selection for faster “resetting”
all you need is a “resest object” with a custom attribute modifier
here is the code :
ca=attributes ResestControls (
parameters ResetP rollout:transform_reset (
)
rollout transform_reset "Reset Controls"
(
button BTN_selectset "Open Reset Center" width:140 height:40 pos:[10,10]
on BTN_selectset pressed do
(
rollout transform_reset "Reset Controls"
(
listbox MyList items: (for ss in SelectionSets collect ss.name) pos:[10,20]
button BTN_selectset "Select Controlset" width:140 height:40 pos:[10,170]
button BTN_resetset "Reset selected Controller" width:140 height:40 pos:[10,210]
groupBox group1 "Selection Sets" pos:[5,5] width:150 height:160
on BTN_selectset pressed do
(
select selectionSets[MyList.selected]
)
on BTN_resetset pressed do
(
macros.run "Animation Tools" "TransformToZero"
macros.run "Animation Tools" "RotationToZero"
)
)
createdialog transform_reset pos:[1280,720]
)
)
)
custAttributes.add $.modifiers[1] ca
my next idea was to expand the script so that i can save my controller data (pos and rot) to a txt file. writing the data was not that big trouble but reading my txt file the right way and applying the data back to my controllers is a bit pain for me.
this is where i end…
rollout PS "Save/Load freezed Position" width:223 height:329
(
button svb "Save Position" pos:[66,71] width:90 height:30
button ldb "Load Position" pos:[66,227] width:90 height:30
on svb pressed do -- the save pos button
(
MyLog = getSaveFileName types:"PoseFiles (*.txt)|*.txt"
ini_file = createFile MyLog
ToMyLog = openFile MyLog mode:"at"
for o in selection do
(
if selection.count !=0 then
(
format "\"%\",%,%
" o.name o.pos.controller[2].value o.rotation.controller[2].value to:ToMyLog ---o.rotation.controller[2].value
)
else (messageBox "Nothing selected !
Please select something" title:"3ds Max")
)
close ToMyLog
)
on ldb pressed do -- the load pose button
(
fload= getOpenFileName types:"PoseFiles (*.txt)|*.txt" -- asks for the saved file
ff=openfile fload --opens the saved file
---rng=readvalue ff
for i=1 to selection.count do --takes every selected object and...
(
o=selection[i]
---acc = o.pos.controller[2].value
seek ff 0 --goes to begining of the saved file
skiptostring ff (o.name)
if (eof ff) == false then
(
ss = readLine ff ---as stringStream
print ss
)
)
close ff
)
)
createdialog PS
this is the end of my coding skills i will spent some more time in reading the maxhelp asap.
greetz tommy
I add the missing part for reading the values back.
I don’t know if that’s what you”re looking for.
rollout PS "Save/Load freezed Position" width:223 height:329
(
button svb "Save Position" pos:[66,71] width:90 height:30
button ldb "Load Position" pos:[66,227] width:90 height:30
on svb pressed do -- the save pos button
(
MyLog = getSaveFileName types:"PoseFiles (*.txt)|*.txt"
ini_file = createFile MyLog
ToMyLog = openFile MyLog mode:"at"
for o in selection do
(
if selection.count !=0 then
(
format "\"%\",%,%
" o.name o.pos.controller[2].value o.rotation.controller[2].value to:ToMyLog ---o.rotation.controller[2].value
)
else (messageBox "Nothing selected !
Please select something" title:"3ds Max")
)
close ToMyLog
)
on ldb pressed do -- the load pose button
(
fload= getOpenFileName types:"PoseFiles (*.txt)|*.txt" -- asks for the saved file
ff=openfile fload --opens the saved file
---rng=readvalue ff
for i=1 to selection.count do --takes every selected object and...
(
o=selection[i]
---acc = o.pos.controller[2].value
seek ff 0 --goes to begining of the saved file
skiptostring ff (o.name)
if (eof ff) == false then
(
ss = readLine ff ---as stringStream
values = substring ss 3 ss.count
fltValues = filterstring values ","
o.pos.controller[2].value = execute fltValues[1]
o.rotation.controller[2].value = execute fltValues[2]
format "%
" fltValues
)
)
close ff
)
)
createdialog PS
—- I add the missing part for reading the values back.
awesome! many thanks for your help…
i only made a little change in your lines so that it work the way i want…
fltValues = filterstring values ",[]"
o.pos.controller[2].value = [(fltValues[1] as integer),(fltValues[2] as integer),(fltValues[3]) as integer]
o.rotation.controller[2].value = execute fltValues[4]
thanks again everybody!
Tommy
Have you seen this thread?
http://forums.cgsociety.org/showthread.php?f=98&t=748348&highlight=xml+transform
Cheers.
I’m not sure it’s necessary to separate the position and rotation values. The times I’ve needed to do this, I just print out all the transforms to a script. Then I can just run the generated script to apply the transforms.
TextFile = newScript()
for obj in selection do
(
format "$'%'.transform = %
" obj.name obj.transform to:TextFile
)
It will generate a script like this…
$'Ctrl BoneRoot'.transform = (matrix3 [1,0,0] [0,1,0] [0,0,1] [0,0,0])
$'Ctrl BonePelvis'.transform = (matrix3 [-0.99554,-4.27239e-006,-0.0943403] [3.85593e-006,-1,4.59678e-006] [-0.0943403,4.21251e-006,0.99554] [-6.50494,-4.02452e-006,48.566])
$'Ctrl Bone L Leg'.transform = (matrix3 [-0.955077,-1.88037e-006,0.296357] [-3.05384e-006,1,-3.49675e-006] [-0.296357,-4.2447e-006,-0.955077] [-29.8531,-3.28637e-005,61.8583])
$'Ctrl Bone L Calf'.transform = (matrix3 [-0.543345,2.00843e-006,0.839509] [3.87101e-006,-1,4.89777e-006] [0.839509,5.91093e-006,0.543345] [-63.4048,-9.91251e-005,72.2693])
$'Ctrl Bone L Foot'.transform = (matrix3 [-0.83747,-5.65305e-007,0.546483] [4.51399e-006,-1,5.88311e-006] [0.546483,7.39375e-006,0.83747] [-75.9225,-5.15904e-005,91.6101])
$'Ctrl Bone R Leg'.transform = (matrix3 [-0.704645,-5.61233e-006,-0.70956] [-3.27408e-006,1,-4.6582e-006] [0.70956,-9.59218e-007,-0.704645] [-29.0673,-0.000145967,33.3782])
$'Ctrl Bone R Calf'.transform = (matrix3 [-0.869514,-5.14758e-006,-0.493908] [2.72847e-006,-1,5.61872e-006] [-0.493908,3.53794e-006,0.869514] [-51.3719,-0.000331845,8.8686])
$'Ctrl Bone R Foot'.transform = (matrix3 [-0.556834,-5.17697e-006,-0.830624] [8.09834e-007,-1,5.68974e-006] [-0.830624,2.49557e-006,0.556834] [-71.1575,-0.000480602,-9.86764])
$'Ctrl BoneSpine'.transform = (matrix3 [0.999678,3.17062e-006,0.0253867] [-3.00841e-006,1,-6.42779e-006] [-0.0253867,6.34935e-006,0.999678] [-6.50589,-4.31785e-006,48.566])
You might want to print the transforms relative to the parent.
I didn’t think using something like ‘in coordsys parent $.transform’ would work – I thought they always came out in world space?