[Closed] my copy/paste poses in skinmorph tool
Hello!
Thanks to Rivendale i could finish this script With it you can quickly copy/paste “poses” between skinmorphtargets. For example if you work on a shoulder and want the base to stay the same unregarding the skintransformation (and not using an external morph). Especially if there are lots of targets its easier to get a coherent result.
how to use:
save it into macroscripts folder and it should appear in a sebstools section
after its run, select the object to work on and in the dropdown the bone.
now just select source and target and it will copy the vertexselection between those.
If just the object is selected (and no verts) it will copy the whole morph the the target.
this is my first i think is good enough to show so take it easy on me
-- skin morph tools V1.0
/*
Script to copy a "pose" from one morph to another. This is useful when working on for
example on several shoulder corrective morphs where the base should stay the same - basically
getting rid of the inital skintransformation.
*/
--there are dead morphs that i cant delete for some reason so i need to get them by name
fn FindSkinMorphByName smorph boneId name =
(
local numMorphs = smorph.boneGetNumberOfMorphs smorph.bones[boneId]
for i = 1 to numMorphs do (
if (smorph.boneGetMorphIsDead smorph.bones[boneID] i) do continue --dead morph!
mname = smorph.boneGetMorphName smorph.bones[boneID] i
if name == mname do return i
)
return undefined
)
--find the "local" vertex ids for a mesh vertex ids - they are different across morphs
fn FindSkinMorphId smorph morphID boneID vertexIDs =
(
local returnIds = #()
local vertexIds = makeobjarray vertexIds
for v in vertexIds do (
local numVerts = smorph.boneGetMorphNumPoints smorph.bones[boneID] morphId
found = false
for i = 1 to numVerts do (
if (smorph.boneGetMorphVertID smorph.bones[boneID] morphId i) == v do
(
append returnIds i --found
found = true
break;
)
)
if not found do append returnIds -1 --bad!
)
if returnIds.count > 1 then return returnIds else return returnIds[1]
)
fn PasteSkinMorphVertices smorph mSource mTarget boneID vertices:undefined =
(
--need the targets transform also (to get the right vector)
local mTargetMatrix = smorph.boneGetMorphTM smorph.bones[boneID] mTarget
format "Source Morph: %
"(smorph.boneGetMorphName smorph.bones[boneID] mSource )
format "Target Morph: %
"(smorph.boneGetMorphName smorph.bones[boneID] mTarget)
if (smorph.boneGetMorphIsDead smorph.bones[boneID] mTarget) do (
print "This morph is dead"
return false
)
--to get the vertex selection we need to get the object
local obj
deps = refs.dependents smorph
for d in deps do if (superclassof d == geometryclass ) do (
obj = d
break
)
if obj == undefined do (
format "Couldnt get %'s baseobject.." smorph
return false
)
local numVerts = smorph.boneGetMorphNumPoints smorph.bones[boneID] mSource
local skinobj = modpanel.getcurrentobject()
local copyAll = false -- instead of the current vertselection
if classof skinobj != skin_morph do (
copyAll = Querybox "No vertices in skinmorph selected. Copy whole morph?"
if copyAll == false then return false
else modpanel.setCurrentObject smorph --getting an exception otherwise
)
for i = 1 to numVerts do (
local id = smorph.boneGetMorphVertID smorph.bones[boneID] mSource i
local doit = false
if copyAll then doit = true else if skinobj.isSelectedVertex obj id do doit = true
if doit do (
local vecSource = smorph.boneGetMorphVecInParentSpace smorph.bones[boneID] mSource i
local baseSource = smorph.boneGetMorphBasePoint smorph.bones[boneID] mSource i
-- ok so the index is per morph. i need to find the matching id on the other morph
idTarget = FindSkinMorphId smorph mTarget boneID id
if idTarget == -1 do ( --the vert is actually not in the other morph (or not moved)
print "Couldnt find vertex in targetmorph. skipping."
continue
)
local baseTarget = smorph.boneGetMorphBasePoint smorph.bones[boneID] mTarget idTarget
local posSource = (baseSource+vecSource) --position in parentspace
local vecTargetBefore = smorph.boneGetMorphVecInParentSpace smorph.bones[boneID] mTarget idTarget
local vecTarget = posSource - baseTarget -- that should be the new vector
format "i:% iTarget:% Vec target:% Before:%
" i idTarget vecTarget vecTargetBefore
smorph.boneSetMorphVecInParentSpace smorph.bones[boneID] mTarget idTarget vecTarget
)
)
smorph.update()
)
--for making the dropdown entries. get all morphnames that are not dead
fn GetValidSkinmorphs smorph boneId=
(
local names = #()
local numMorphs = smorph.boneGetNumberOfMorphs smorph.bones[boneId]
for i = 1 to numMorphs do (
if (smorph.boneGetMorphIsDead smorph.bones[boneID] i) do continue --dead morph!
append names (smorph.boneGetMorphName smorph.bones[boneID] i)
)
return names
)
rollout uiCopyMorph "Copy Morph from ..." width:128 height:296
(
listbox lbxMorphs "copy morph from.." pos:[8,56] width:112 height:10
button btnUpdate "update" pos:[8,264] width:48 height:24
button btnFetchMorph "copy" pos:[56,264] width:64 height:24
local smorph = undefined
dropdownList ddlBones "Bones" pos:[8,8] width:112 height:40
dropdownList ddlTargetMorph "copy morph to..." pos:[8,216] width:112 height:40
fn clearUI = (
lbxMorphs.items = #()
ddlTargetMorph.items =#()
ddlBones.items = #()
smorph = undefined
)
fn updateUI =
(
local obj = selection[1]
try (smorph = obj.modifiers[#skin_morph]; if smorph == undefined do (ClearUI();return false))
catch (
ClearUI()
return false
)
--get bones in skinmod
local names = for b in smorph.bones collect b.name
ddlBones.items = names
--get morphs for that bone
local morphs = GetValidSkinmorphs smorph ddlBones.selection
if morphs != undefined do (
lbxMorphs.items = morphs
ddlTargetMorph.items = morphs
)
)
on uiCopyMorph open do
(
--make some callbacks to update the ui
callbacks.addScript #selectionSetChanged "uiCopyMorph.updateUi()" id:#SkinMorphToolsCallbacks
callbacks.addScript #modPanelObjPostChange "uiCopyMorph.updateUi()" id:#SkinMorphToolsCallbacks
updateUI()
)
on uiCopyMorph close do
(
--remove callbacks
callbacks.removeScripts id:#SkinMorphToolsCallbacks
)
on btnUpdate pressed do
(
updateUI()
)
on btnFetchMorph pressed do
(
if smorph == undefined do (
MessageBox "Skin morph invalid"
return false
)
--get the selections from dropdowns
if lbxMorphs.selection == ddlTargetMorph.selection then (
MessageBox "Cant copy onto itself. blast!"
)
else (
local boneID = ddlBones.selection
source = FindSkinMorphByName smorph boneID lbxMorphs.items[lbxMorphs.selection]
target = FindSkinMorphByName smorph boneID ddlTargetMorph.items[ddlTargetMorph.selection]
with undo on
PasteSkinMorphVertices smorph source target boneID
)
)
on ddlBones selected sel do
(
local morphs = GetValidSkinmorphs smorph ddlBones.selection
if morphs != undefined do
lbxMorphs.items = morphs
)
)
macroscript msCopyMorph category:"Sebstools"
(
CreateDialog uiCopyMorph
)
please let me know if there are “style errors” and if you think its useful! Next thing im going to is something to copy a skinmorph properly to another object!
thanks, seb
:wip: