I managed to make all the changes I wanted but I still have a piece of code to correct.
Currently if you select a bone in the viewport, the popup Skintools don't follow. You have to select the bone in Skintool's list to change the weight of a vertex.
I'm looking since yesterday, but I feel that it's beyond my capacity with MAXScript/Dotnet ...
Someone have an idea?
Here the code
--*****************************************************************************
--* Skin Helper Tweak&Rename => SkinTools_v3 by zOffTy, May 11 2009 => http://zoffty.free.fr
--* by Ofer Zelichover (c) 11/2008
--* Last update: 11:30 AM Tuesday, November 11, 2008
--* http://www.oferz.com ; maxscripts@oferz.com
--* http://scriptspot.com/3ds-max/skin-helper
--*****************************************************************************
try(cui.UnRegisterDialogBar ro_SkinTools)catch()
try(destroyDialog ro_SkinTools)catch()
rollout ro_SkinTools "Skin Tools v3"
(
-- Local Struct Declerations
-----------------------------------------------
struct s_UndoRedoAction (
_skinMod = undefined,
_vertices = #{},
_oldWeights = #(),
_boneNodes = #(),
_selectionOnly = false,
_description = "",
fn getSelectedSkinVerts =
(
for v = 1 to skinOps.GetNumberVertices _skinMod where skinOps.IsVertexSelected _skinMod v == 1 collect v
),
fn getBoneNodes =
(
local numBones = skinOps.getNumberBones _skinMod
for boneID = 1 to numBones collect
getNodeByName (skinOps.GetBoneName _skinMod boneID 1)
),
fn getBoneWeights =
(
local numBones = skinOps.getNumberBones _skinMod
for v in _vertices collect (
local weightsCount = skinOps.GetVertexWeightCount _skinMod v
local weightBoneIDs = for i = 1 to weightsCount collect skinOps.GetVertexWeightBoneID _skinMod v i
for boneID = 1 to numBones collect (
local n = findItem weightBoneIDs boneID
if n > 0 then
skinOps.GetVertexWeight _skinMod v n
else
undefined
)
)
),
-- Checks if the
fn isValidAction =
(
if not _selectionOnly then (
local currentBones = getBoneNodes()
local validAction = (currentBones.count == _boneNodes.count)
for i = 1 to _boneNodes.count where validAction and _boneNodes[i] != currentBones[i] do
validAction = false
validAction
) else
true
),
fn store skinMod vertices selectionOnly:false description: =
(
_skinMod = skinMod
if isKindOf vertices array then
_vertices = vertices
else
_vertices = getSelectedSkinVerts()
if not selectionOnly then (
_boneNodes = getBoneNodes()
_oldWeights = getBoneWeights()
)
_selectionOnly = selectionOnly
if isKindOf description string then
_description = description
true
),
fn restore =
(
if isValidAction() then (
if not _selectionOnly then (
local verts = _vertices as array
for v = 1 to verts.count do (
local vert = verts[v]
local currentWeights = getBoneWeights()
local oldWeights = _oldWeights[v]
local boneIDs = #()
local weights = #()
for i = 1 to oldWeights.count do (
if oldWeights[i] != undefined or currentWeights[i] != undefined then (
append boneIDs i
if oldWeights[i] != undefined then
append weights oldWeights[i]
else
append weights 0.0
)
)
skinOps.unNormalizeVertex _skinMod vert true
skinOps.SetVertexWeights _skinMod vert boneIDs weights
skinOps.unNormalizeVertex _skinMod vert false
)
)
if modPanel.getCurrentObject() != _skinMod then (
max modify mode
modPanel.setCurrentObject _skinMod
subObjectLevel = 1
)
skinOps.SelectVertices _skinMod _vertices
#(_skinMod, _vertices)
) else
undefined
)
) -- End of s_UndoRedoAction struct
struct s_UndoRedoSystem (
undoLevels = 100,
suspend = false,
undoStack = #(),
redoStack = #(),
fn storeUndoState skinMod verts selectionOnly:false description: clearRedo:true =
(
if suspend then return()
local newUndoAction = s_UndoRedoAction()
newUndoAction.store skinMod verts selectionOnly:selectionOnly description:description
append undoStack newUndoAction
if undoStack.count > undoLevels then
deleteItem undoStack 1
if clearRedo then
redoStack = #()
),
fn storeRedoState skinMod verts selectionOnly:false description: =
(
if suspend then return()
local newUndoAction = s_UndoRedoAction()
newUndoAction.store skinMod verts selectionOnly:selectionOnly description:description
append redoStack newUndoAction
if redoStack.count > undoLevels then
deleteItem redoStack 1
),
fn canUndo =
(
undoStack.count > 0 and undoStack[undoStack.count].isValidAction()
),
fn canRedo =
(
redoStack.count > 0 and redoStack[redoStack.count].isValidAction()
),
fn performUndo =
(
if canUndo() then (
local undoItem = undoStack[undoStack.count]
storeRedoState undoItem._skinMod #selection selectionOnly:undoItem._selectionOnly description:undoItem._description
local values = undoItem.restore()
deleteItem undoStack undoStack.count
values
) else
undefined
),
fn performRedo =
(
if canRedo() then (
local redoItem = redoStack[redoStack.count]
storeUndoState redoItem._skinMod #selection selectionOnly:redoItem._selectionOnly clearRedo:false description:redoItem._description
local values = redoItem.restore()
deleteItem redoStack redoStack.count
values
) else
undefined
),
fn getNextUndoDecription =
(
local txt = "Undo"
if canUndo() then (
local undoItem = undoStack[undoStack.count]
if undoItem._description != "" then
txt += " " + undoItem._description
)
txt
),
fn getNextRedoDecription =
(
local txt = "Redo"
if canRedo() then (
local redoItem = redoStack[redoStack.count]
if redoItem._description != "" then
txt += " " + redoItem._description
)
txt
)
) -- End of s_UndoRedoSystem struct
-- Local Functions Forward Declerations
-----------------------------------------------
local inverseImage
local updateUI, updateUndoButtonsState
local dncWeightsListContextMenu_ItemClicked
-- Local Variable Declerations
-----------------------------------------------
local workingVerts
local workingSkinMod
local HideUnusedBones = true
local undoSystem = s_UndoRedoSystem()
local suspendVertSelectionChangeUpdate = false
local weightPrecision = 3
-- User Interface
-----------------------------------------------
button bnGrow "Grow" width:50 height:30 align:#left pos:[5,5]
button bnShrink "Shrink" width:50 height:30 align:#left pos:[56,5]
button bnRing "Ring" width:50 height:30 align:#left pos:[107,5]
button bnLoop "Loop" width:50 height:30 align:#left pos:[158,5]
button bnPresetValue0_0 "0.0" width:28 height:20 align:#left pos:[5,40]
button bnPresetValue0_1 "0.1" width:28 height:20 align:#left pos:[34,40]
button bnPresetValue0_25 "0.25" width:28 height:20 align:#left pos:[63,40]
button bnPresetValue0_5 "0.5" width:28 height:20 align:#left pos:[92,40]
button bnPresetValue0_75 "0.75" width:28 height:20 align:#left pos:[121,40]
button bnPresetValue0_9 "0.9" width:28 height:20 align:#left pos:[150,40]
button bnPresetValue1_0 "1.0" width:28 height:20 align:#left pos:[179,40]
spinner spValue "" fieldWidth:40 type:#float range:[0.0, 10, 0.1] scale:0.01 align:#left pos:[5, 72]
checkButton cbValueSet "=" width:25 height:20 align:#left pos:[407,65]
button bnValueAdd "+" width:40 height:30 align:#left pos:[60,65]
button bnValueSubtract "-" width:40 height:30 align:#left pos:[105,65]
--button bnValueMult "*" width:25 height:20 align:#left pos: [134,65]
--button bnValueDivide "/" width:25 height:20 align:#left pos:[159,65]
button bnCopy "Copy" width:50 height:20 align:#left pos:[5,100]
button bnPaste "Paste" width:50 height:20 align:#left pos:[56,100]
button bnBlend "Blend" width:50 height:20 align:#left pos:[107,100]
button bnExclude "Exclude" width:50 height:20 align:#left pos:[158,100]
checkbox SelectElement "SelectElement" checked: false width:150 height:25 pos:[5,125]
label lblSelectedVerts "No vertices selected." pos:[7,150]
button bnAllbones "All Bones" width:54 height:20 pos:[150,148]
button bnUndo "U" width:18 height:18 pos:[545,155] tooltip:"Undo" images:#("Maintoolbar_16i.bmp", undefined, 100, 1, 1, 2, 2)
button bnRedo "R" width:18 height:18 pos:[565,155] tooltip:"Redo" images:#("Maintoolbar_16i.bmp", undefined, 100, 3, 3, 4, 4)
--checkButton cbDockState "D" width:18 height:18 pos:[27,0] tooltip:"Make window dockable."
dotNetControl dncWeightsList "System.Windows.Forms.ListView" height:150 pos:[5,170] width:200
local dncWeightsListContextMenu
button RemoveZeroWeights "Remove Zero Weights" width:120 height:25 pos:[5,325]
spinner spRemoveZeroWeights "" fieldWidth:50 type:#float range:[0, 1, 0.03] scale:0.01 pos:[135, 329]
checkbox AlwaysDeform "Always Deform" checked: true width:150 height:25 pos:[5,355]
checkbox ShowNoEnvelopes "Show No Envelopes" checked: true width:150 height:25 pos:[5,376]
spinner spBonesLimit "Bones Affect Limit: " fieldWidth:40 type:#integer range:[1, 10, 3] scale:1 pos:[5, 405]
button RefreshMe "Refresh" width:57 height:25 pos:[150,400]
timer tmUpdateDelay interval:1000 --active:on
-- Functions
------------------------------------------------
fn inverseImage bm =
(
for y = 0 to (bm.height - 1) do (
local colors = getPixels bm [0,y] bm.width
for i = 1 to colors.count do (
local a = colors[i].a
colors[i] = white - colors[i]
colors[i].a = a
)
setPixels bm [0,y] colors
)
bm
)
fn roundNumber num precision:weightPrecision =
(
local multiplier = 10 ^ precision
( floor ( (num * multiplier) + 0.5) ) / multiplier
)
fn getFormattedWeight weights =
(
weights = makeUniqueArray weights
if weights.count > 1 then (
local n = findItem weights undefined
if weights.count == 2 and n > 0 then (
--"0.0/- - -"
n = if n == 1 then 2 else 1
formattedPrint weights[n] format:("0." + weightPrecision as string + "f") + "/- - -"
) else
"Mixed"
) else if weights[1] == undefined then
"- - -"
else
formattedPrint weights[1] format:("0." + weightPrecision as string + "f")
)
fn getSelectedSkinVerts skinMod =
(
for v = 1 to skinOps.GetNumberVertices skinMod where skinOps.IsVertexSelected skinMod v == 1 collect v
)
fn getLockedItems =
(
local items = dncWeightsList.checkedItems
local locks = for i = 0 to (items.count - 1) collect items.Item[i].Tag
locks as bitArray
)
fn getSelectedListItem =
(
local selectedItems = dncWeightsList.selectedIndices
if selectedItems.count > 0 then
dncWeightsList.Items.Item[selectedItems.Item[0]]
else
undefined
)
fn getSelectedListItemWeight =
(
local selectedItem = getSelectedListItem()
if selectedItem != undefined then (
local weight = selectedItem.SubItems.Item[1].Text
if weight as float != undefined then
weight as float
else
weight
) else
undefined
)
fn getVertexWeightBoneIDs skinMod vert =
(
local weightsCount = skinOps.GetVertexWeightCount skinMod vert
for i = 1 to weightsCount collect
skinOps.GetVertexWeightBoneID skinMod vert i
)
fn getCurrentWeights skinMod vert =
(
local numBones = skinOps.getNumberBones skinMod
local vertBones = getVertexWeightBoneIDs skinMod vert
for boneID = 1 to numBones collect (
local n = findItem vertBones boneID
if n > 0 then
roundNumber (skinOps.GetVertexWeight skinMod vert n) precision:weightPrecision
else
undefined
)
)
fn calculateNormalizedValues skinMod vert valueID newVal locks =
(
if locks[valueID] then (
messageBox "Can not set value of a locked bone."
return()
)
-- Get the currnet weights
local weights = getCurrentWeights skinMod vert
-- Check if the valueID is of a bone with no weight, if so, initialize it's weight to 0
if weights[valueID] == undefined then
weights[valueID] = 0
-- Calculate the total of the weights
local totalWeight = 0
for i = 1 to weights.count where not locks[i] and i != valueID and weights[i] != undefined do
totalWeight += weights[i]
-- Calculate the weight percentages
local percentages = for w in weights collect if w != undefined and totalWeight > 0 then (w / totalWeight) else undefined
-- Make sure the sum of the new value and the locked values don't go over 1.0
local totalLockedWeights = 0
for i = 1 to weights.count where weights[i] != undefined and locks[i] and i != valueID do
totalLockedWeights += weights[i]
newVal = amax (amin newVal (1.0 - totalLockedWeights)) 0.0
-- Sanity check
local totalPercentages = 0
for i = 1 to percentages.count where percentages[i] != undefined and not locks[i] and i != valueID do
totalPercentages += percentages[i]
if totalPercentages <= 1 then (
-- Calculate new values
local valueDiff = weights[valueID] - newVal
for i = 1 to weights.count where percentages[i] != undefined and not locks[i] and i != valueID do
weights[i] += valueDiff * percentages[i]
weights[valueID] = newVal
)
weights
)
fn setWeights skinMod vert newValues =
(
local boneIDs = for i = 1 to newValues.count where newValues[i] != undefined collect i
newValues = for v in newValues where v != undefined collect v
skinOps.unNormalizeVertex skinMod vert true
skinOps.SetVertexWeights skinMod vert boneIDs newValues
skinOps.unNormalizeVertex skinMod vert false
)
fn updateValuesInList skinMod verts =
(
local vertWeights = for v in verts collect (getCurrentWeights skinMod v)
local numBones = skinOps.getNumberBones skinMod
for i = 0 to (dncWeightsList.Items.Count - 1) do (
local item = dncWeightsList.Items.Item[i]
local boneID = item.Tag
local weights = for w in vertWeights collect w[boneID]
item.SubItems.Item[1].Text = getFormattedWeight weights
)
updateUndoButtonsState()
)
fn setNewWeights newValues =
(
suspendVertSelectionChangeUpdate = true
local locks = getLockedItems()
local selectedItem = getSelectedListItem()
if selectedItem != undefined then (
local breakLoop = false
local boneID = selectedItem.Tag
undo "Change skin weights" on (
-- Create undo state
undoSystem.storeUndoState workingSkinMod workingVerts description:"set weights."
for i = 1 to workingVerts.count where not breakLoop do (
local newWeights = calculateNormalizedValues workingSkinMod workingVerts[i] boneID newValues[i] locks
if newWeights != undefined then (
setWeights workingSkinMod workingVerts[i] newWeights
) else
breakLoop = true
)
)
if not breakLoop then
updateValuesInList workingSkinMod workingVerts
)
suspendVertSelectionChangeUpdate = false
)
fn setNewFixedValue newVal =
(
if workingVerts != undefined then (
local newValues = for i = 1 to workingVerts.count collect newVal
setNewWeights newValues
)
)
fn populateWeightList skinMod verts =
(
dncWeightsList.BeginUpdate()
dncWeightsList.Items.Clear()
if isKindOf skinMod skin and verts != undefined then (
local vertWeights = for v in verts collect (getCurrentWeights skinMod v)
local numBones = skinOps.getNumberBones skinMod
for boneID = 1 to numBones do(
local weights = for w in vertWeights collect w[boneID]
local weight = (getFormattedWeight weights)
if not HideUnusedBones or weight != "- - -" then (
local lvi = dotNetObject "System.Windows.Forms.listViewItem"
lvi.Text = skinOps.GetBoneName skinMod boneID 1
lvi.Tag = boneID
lvi.SubItems.Add weight
dncWeightsList.Items.Add lvi
)
)
)
dncWeightsList.EndUpdate()
)
fn selectBoneVerts threshold below:false above:true addSubtract: =
(
local selectedItem = getSelectedListItem()
if workingSkinMod != undefined and selectedItem != undefined then (
local boneID = selectedItem.Tag
local boneVets = #{}
local numVerts = skinOps.GetNumberVertices workingSkinMod
for v = 1 to numVerts do (
local vertBones = getVertexWeightBoneIDs workingSkinMod v
local n = findItem vertBones boneID
if n > 0 then (
local weight = roundNumber (skinOps.GetVertexWeight workingSkinMod v n) precision:weightPrecision
if (above and weight >= threshold) or (below and weight <= threshold) then
append boneVets v
)
)
local currentVertSelection = (getSelectedSkinVerts workingSkinMod) as bitArray
case addSubtract of (
#Subtract: boneVets = currentVertSelection - boneVets
#Add: boneVets = currentVertSelection + boneVets
)
skinOps.SelectVertices workingSkinMod boneVets
updateUI()
)
)
fn initWeightsListView =
(
-- Create right-click menu
dncWeightsListContextMenu = dotNetObject "System.Windows.Forms.ContextMenuStrip"
dncWeightsListContextMenu.Items.Add "Hide un-used bones."
for i = 0 to (dncWeightsListContextMenu.Items.count - 1) do
dncWeightsListContextMenu.Items.Item[i].Tag = i
dncWeightsListContextMenu.ShowImageMargin = false
dncWeightsListContextMenu.ShowCheckMargin = true
dotNet.addEventHandler dncWeightsListContextMenu #ItemClicked dncWeightsListContextMenu_ItemClicked
dncWeightsList.View = dncWeightsList.View.Details
dncWeightsList.FullRowSelect = true
--dncWeightsList.backColor = white
dncWeightsList.GridLines = false
dncWeightsList.CheckBoxes = true
dncWeightsList.HideSelection = false
dncWeightsList.MultiSelect = false
dncWeightsList.Columns.Add "Bone" 132
dncWeightsList.Columns.Add "Weight" 63
dncWeightsList.Columns.Item[1].TextAlign = dncWeightsList.Columns.Item[1].TextAlign.Center
dncWeightsList.ContextMenuStrip = dncWeightsListContextMenu
)
fn updateUndoButtonsState =
(
bnUndo.enabled = undoSystem.canUndo()
bnUndo.toolTip = undoSystem.getNextUndoDecription()
bnRedo.enabled = undoSystem.canRedo()
bnRedo.toolTip = undoSystem.getNextRedoDecription()
)
fn updateUI =
(
-- Store the selected BoneId to restore it later.
local selectedItem = getSelectedListItem()
local selectedTag = if selectedItem != undefined then selectedItem.Tag else undefined
--Store locked bones BoneIDs to restore it later
local lockedItems = getLockedItems()
local lockedBoneIDs = (for i in lockedItems collect dncWeightsList.Items.Item[i - 1].Tag) as bitArray
local currentMod = modPanel.getCurrentObject()
if isKindOf currentMod skin then (
workingSkinMod = currentMod
local selectedVerts = getSelectedSkinVerts workingSkinMod
if selectedVerts.count > 0 then
workingVerts = selectedVerts
else
workingVerts = undefined
) else (
workingSkinMod = undefined
workingVerts = undefined
)
lblSelectedVerts.text = if workingVerts == undefined then "No vertices selected."
else if workingVerts.count == 1 then ("Selected vertex: " + (workingVerts[1] - 1) as string)
else (workingVerts.count as string + " vertices selected.")
populateWeightList workingSkinMod workingVerts
-- Restore the previously stored selected boneID
for i = 0 to (dncWeightsList.Items.Count - 1) do (
local item = dncWeightsList.Items.Item[i]
item.Selected = item.Tag == selectedTag
)
-- Restore locked bones
for i = 0 to (dncWeightsList.Items.Count - 1) do (
local item = dncWeightsList.Items.Item[i]
item.Checked = lockedBoneIDs[item.Tag]
)
-- Update undo buttons
updateUndoButtonsState()
)
-- Vertex selection changed callback
fn objectParamentersChangedCH =
(
if not suspendVertSelectionChangeUpdate then (
local preSkin = workingSkinMod
local preVerts = workingVerts
local currentMod = modPanel.getCurrentObject()
if workingSkinMod != currentMod then
updateUI()
else (
local selectedVets = getSelectedSkinVerts currentMod
selectedVets = selectedVets as bitArray
if workingVerts == undefined then
local workingVertsBA = #{}
else
local workingVertsBA = workingVerts as bitArray
if selectedVets.numberSet != workingVertsBA.numberSet
or (selectedVets - workingVertsBA).numberSet != 0
or (workingVertsBA - selectedVets).numberSet != 0 then (
updateUI()
undoSystem.storeUndoState preSkin preVerts selectionOnly:true description:"vertex selection."
updateUndoButtonsState()
)
)
)
)
-- Change handlers and callbacks.
fn unregisterChangeHandlers =
(
deleteAllChangeHandlers id:#SkinHelperCH
)
fn registerChangeHandlers =
(
unregisterChangeHandlers()
local currentMod = modPanel.getCurrentObject()
if isKindOf currentMod skin then (
local objs = refs.dependentNodes currentMod
when parameters objs changes id:#SkinHelperCH do (try(ro_SkinTools.objectParamentersChangedCH())catch(print "Error in ro_SkinTools.objectParamentersChangedCH"))
)
)
fn unregisterCallbacks =
(
unregisterChangeHandlers()
callbacks.removeScripts id:#SkinHelperCB
)
fn registerCallbacks =
(
unregisterCallbacks()
callbacks.addScript #modPanelObjPostChange "try(ro_SkinTools.registerChangeHandlers())catch(print "Error registring change handler")" id:#SkinHelperCB
)
-- Initialize when starting
fn init =
(
registerCallbacks()
initWeightsListView()
updateUI()
registerChangeHandlers()
)
-- Clean up on close.
fn done =
(
unregisterChangeHandlers()
unregisterCallbacks()
)
-- Event Handlers
-------------------------------------------------
fn dncWeightsListContextMenu_ItemClicked sender args =
(
local addSubtract = if keyboard.shiftPressed then #Subtract else if keyboard.ControlPressed then #Add else #Replace
case args.ClickedItem.Tag of (
0: (HideUnusedBones = not HideUnusedBones; args.ClickedItem.Checked = HideUnusedBones; updateUI())
)
)
on bnUndo pressed do (
local values = undoSystem.performUndo()
workingSkinMod = values[1]
workingVerts = values[2]
updateUI force:true
)
on bnRedo pressed do (
local values = undoSystem.performRedo()
workingSkinMod = values[1]
workingVerts = values[2]
updateUI force:true
)
on tmUpdateDelay tick do (
tmUpdateDelay.active = on
suspendVertSelectionChangeUpdate = false
)
on dncWeightsList ItemSelectionChanged sender args do (
tmUpdateDelay.active = on
suspendVertSelectionChangeUpdate = true
skinOps.SelectBone workingSkinMod args.Item.Tag
if cbValueSet.checked then (
local val = getSelectedListItemWeight()
if isKindOf val number then
spValue.value = val
else if val == "Mixed" then
spValue.indeterminate = true
else
spValue.value = 0
)
tmUpdateDelay.active = on
)
-- Bouton spinner
------------------------------------------------
on spValue buttonDown do (
undoSystem.storeUndoState workingSkinMod workingVerts description:"set weights."
undoSystem.suspend = true
)
on spValue changed val do (
if cbValueSet.checked then (
local newValues = for i = 1 to workingVerts.count collect val
setNewWeights newValues
)
)
on spValue buttonUp do (
undoSystem.suspend = false
updateUndoButtonsState()
)
on cbValueSet changed state do (
if keyboard.controlPressed then (
local newValues = for i = 1 to workingVerts.count collect spValue.value
setNewWeights newValues
cbValueSet.checked = not state
) else if state then (
local val = getSelectedListItemWeight()
if isKindOf val number then
spValue.value = val
else if val == "Mixed" then
spValue.indeterminate = true
else
spValue.value = 0
)
)
-- Bouton +
------------------------------------------------
on bnValueAdd pressed do (
--local selectedItem = getSelectedListItem()
local selectedItem = getSelectedListItem()
if selectedItem != undefined then (
local currentVals = for v in workingVerts collect (getCurrentWeights workingSkinMod v)[selectedItem.Tag]
local newValues = for i = 1 to workingVerts.count collect if currentVals[i] != undefined then currentVals[i] + spValue.value else spValue.value
setNewWeights newValues
)
)
-- Bouton -
------------------------------------------------
on bnValueSubtract pressed do (
local selectedItem = getSelectedListItem()
if selectedItem != undefined then (
local currentVals = for v in workingVerts collect (getCurrentWeights workingSkinMod v)[selectedItem.Tag]
local newValues = for i = 1 to workingVerts.count collect if currentVals[i] != undefined then currentVals[i] - spValue.value else 0
setNewWeights newValues
)
)
-- Bouton Grow
------------------------------------------------
on bnGrow pressed do
(
skinOps.growSelection (modPanel.GetcurrentObject())
)
-- Bouton Shrink
------------------------------------------------
on bnShrink pressed do
(
skinOps.shrinkSelection (modPanel.GetcurrentObject())
)
-- Bouton Loop
------------------------------------------------
on bnLoop pressed do
(
skinOps.loopSelection (modPanel.GetcurrentObject())
)
-- Bouton Ring
------------------------------------------------
on bnRing pressed do
(
skinOps.ringSelection (modPanel.GetcurrentObject())
)
on ro_SkinTools resized s do resizeWindow s
on ro_SkinTools open do init()
on ro_SkinTools close do done()
-- Boutons value
------------------------------------------------
on bnPresetValue0_0 pressed do setNewFixedValue 0.0
on bnPresetValue0_1 pressed do setNewFixedValue 0.1
on bnPresetValue0_25 pressed do setNewFixedValue 0.25
on bnPresetValue0_5 pressed do setNewFixedValue 0.5
on bnPresetValue0_75 pressed do setNewFixedValue 0.75
on bnPresetValue0_9 pressed do setNewFixedValue 0.9
on bnPresetValue1_0 pressed do setNewFixedValue 1.0
-- Bouton Exclude
------------------------------------------------
on bnExclude pressed do
(
skinOps.ButtonExclude (modPanel.GetcurrentObject())
updateUI force:true
)
-- Bouton Copy
------------------------------------------------
on bnCopy pressed do
(
skinOps.CopyWeights (modPanel.GetcurrentObject())
updateUI force:true
)
-- Bouton Paste
------------------------------------------------
on bnPaste pressed do
(
skinOps.pasteWeights (modPanel.GetcurrentObject())
updateUI force:true
)
-- Bouton Blend
------------------------------------------------
on bnBlend pressed do
(
skinOps.blendSelected (modPanel.GetcurrentObject())
updateUI force:true
)
-- Select Element
------------------------------------------------
on SelectElement changed state do (
if SelectElement.state == true then
(
$.modifiers[#Skin].selectElement = on
)
if SelectElement.state == false then
(
$.modifiers[#Skin].selectElement = off
)
)
-- Bouton bnAllbones
------------------------------------------------
on bnAllbones pressed do (
--HideUnusedBones = not HideUnusedBones; args.ClickedItem.Checked = HideUnusedBones; updateUI()
--HideUnusedBones ; updateUI()
updateUI force:true
)
-- Bones RemoveZeroWeights
------------------------------------------------
on RemoveZeroWeights pressed do (
$.modifiers[#Skin].clearZeroLimit = spRemoveZeroWeights.value
skinOps.RemoveZeroWeights (modPanel.GetcurrentObject())
updateUI force:true
)
-- Always Deform
------------------------------------------------
on AlwaysDeform changed state do (
if AlwaysDeform.state == true then
(
$.modifiers[#Skin].always_deform = true
)
if AlwaysDeform.state == false then
(
$.modifiers[#Skin].always_deform = false
)
updateUI force:true
)
-- Show no Envelopes
------------------------------------------------
on ShowNoEnvelopes changed state do (
if ShowNoEnvelopes.state == true then
(
$.modifiers[#Skin].ShowNoEnvelopes = on
)
if ShowNoEnvelopes.state == false then
(
$.modifiers[#Skin].ShowNoEnvelopes = off
)
)
-- Bones Affect Limit
------------------------------------------------
on spBonesLimit changed val do (
$.modifiers[#Skin].bone_Limit = spBonesLimit.value
updateUI force:true
)
-- Boouton RefreshMe
------------------------------------------------
on RefreshMe pressed do (
updateUI force:true
)
--timer clock "testClock" interval:2000 --tick once a second
--label test "1"
--on clock tick do
--(
--valUp = (test.text as integer)+1
--test.text = valUp as string
--updateUI force:true
--)
) -- end of ro_SkinTools rollout
createDialog ro_SkinTools width:210 height:430 style:#(#style_titlebar, #style_border, #style_sysmenu )
setdialogpos ro_SkinTools [10,100]
you mean your interface GUI needs to update if you select a bone in the viewport? I see you played already with a timer to check if bones where selected?
I am not sure what you want but wouldn't it be easier if you'd start off with the skin-helper script to your own tool? Usually the official maxscripts that come with the max tools are full of xtra little security stuff like avoiding auto-Save hang ups etc. which is often confusing when trying to read them.
yeah with the official "Weight tool" when you select a bone in the viewport, this bone is highlighted in the list.
With the original "skin-helper" when you select a bone in the viewport, nothing happen. you have to select it, in his boneslist
We can show all bones with a right clik=> Hide un-used bones, but it's not very readable
I just add buttons with a "force update UI" and tweak the UI of skin-helper
Replies
http://scriptspot.com/3ds-max/skin-helper
http://scriptspot.com/3ds-max/skin-or-die
http://scriptspot.com/3ds-max/skin-tools
The Skin Helper seem to be really good, and quite easy to tweak!
:poly121: thanks!
Currently if you select a bone in the viewport, the popup Skintools don't follow. You have to select the bone in Skintool's list to change the weight of a vertex.
I'm looking since yesterday, but I feel that it's beyond my capacity with MAXScript/Dotnet ...
Someone have an idea?
Here the code
--***************************************************************************** --* Skin Helper Tweak&Rename => SkinTools_v3 by zOffTy, May 11 2009 => http://zoffty.free.fr --* by Ofer Zelichover (c) 11/2008 --* Last update: 11:30 AM Tuesday, November 11, 2008 --* http://www.oferz.com ; maxscripts@oferz.com --* http://scriptspot.com/3ds-max/skin-helper --***************************************************************************** try(cui.UnRegisterDialogBar ro_SkinTools)catch() try(destroyDialog ro_SkinTools)catch() rollout ro_SkinTools "Skin Tools v3" ( -- Local Struct Declerations ----------------------------------------------- struct s_UndoRedoAction ( _skinMod = undefined, _vertices = #{}, _oldWeights = #(), _boneNodes = #(), _selectionOnly = false, _description = "", fn getSelectedSkinVerts = ( for v = 1 to skinOps.GetNumberVertices _skinMod where skinOps.IsVertexSelected _skinMod v == 1 collect v ), fn getBoneNodes = ( local numBones = skinOps.getNumberBones _skinMod for boneID = 1 to numBones collect getNodeByName (skinOps.GetBoneName _skinMod boneID 1) ), fn getBoneWeights = ( local numBones = skinOps.getNumberBones _skinMod for v in _vertices collect ( local weightsCount = skinOps.GetVertexWeightCount _skinMod v local weightBoneIDs = for i = 1 to weightsCount collect skinOps.GetVertexWeightBoneID _skinMod v i for boneID = 1 to numBones collect ( local n = findItem weightBoneIDs boneID if n > 0 then skinOps.GetVertexWeight _skinMod v n else undefined ) ) ), -- Checks if the fn isValidAction = ( if not _selectionOnly then ( local currentBones = getBoneNodes() local validAction = (currentBones.count == _boneNodes.count) for i = 1 to _boneNodes.count where validAction and _boneNodes[i] != currentBones[i] do validAction = false validAction ) else true ), fn store skinMod vertices selectionOnly:false description: = ( _skinMod = skinMod if isKindOf vertices array then _vertices = vertices else _vertices = getSelectedSkinVerts() if not selectionOnly then ( _boneNodes = getBoneNodes() _oldWeights = getBoneWeights() ) _selectionOnly = selectionOnly if isKindOf description string then _description = description true ), fn restore = ( if isValidAction() then ( if not _selectionOnly then ( local verts = _vertices as array for v = 1 to verts.count do ( local vert = verts[v] local currentWeights = getBoneWeights() local oldWeights = _oldWeights[v] local boneIDs = #() local weights = #() for i = 1 to oldWeights.count do ( if oldWeights[i] != undefined or currentWeights[i] != undefined then ( append boneIDs i if oldWeights[i] != undefined then append weights oldWeights[i] else append weights 0.0 ) ) skinOps.unNormalizeVertex _skinMod vert true skinOps.SetVertexWeights _skinMod vert boneIDs weights skinOps.unNormalizeVertex _skinMod vert false ) ) if modPanel.getCurrentObject() != _skinMod then ( max modify mode modPanel.setCurrentObject _skinMod subObjectLevel = 1 ) skinOps.SelectVertices _skinMod _vertices #(_skinMod, _vertices) ) else undefined ) ) -- End of s_UndoRedoAction struct struct s_UndoRedoSystem ( undoLevels = 100, suspend = false, undoStack = #(), redoStack = #(), fn storeUndoState skinMod verts selectionOnly:false description: clearRedo:true = ( if suspend then return() local newUndoAction = s_UndoRedoAction() newUndoAction.store skinMod verts selectionOnly:selectionOnly description:description append undoStack newUndoAction if undoStack.count > undoLevels then deleteItem undoStack 1 if clearRedo then redoStack = #() ), fn storeRedoState skinMod verts selectionOnly:false description: = ( if suspend then return() local newUndoAction = s_UndoRedoAction() newUndoAction.store skinMod verts selectionOnly:selectionOnly description:description append redoStack newUndoAction if redoStack.count > undoLevels then deleteItem redoStack 1 ), fn canUndo = ( undoStack.count > 0 and undoStack[undoStack.count].isValidAction() ), fn canRedo = ( redoStack.count > 0 and redoStack[redoStack.count].isValidAction() ), fn performUndo = ( if canUndo() then ( local undoItem = undoStack[undoStack.count] storeRedoState undoItem._skinMod #selection selectionOnly:undoItem._selectionOnly description:undoItem._description local values = undoItem.restore() deleteItem undoStack undoStack.count values ) else undefined ), fn performRedo = ( if canRedo() then ( local redoItem = redoStack[redoStack.count] storeUndoState redoItem._skinMod #selection selectionOnly:redoItem._selectionOnly clearRedo:false description:redoItem._description local values = redoItem.restore() deleteItem redoStack redoStack.count values ) else undefined ), fn getNextUndoDecription = ( local txt = "Undo" if canUndo() then ( local undoItem = undoStack[undoStack.count] if undoItem._description != "" then txt += " " + undoItem._description ) txt ), fn getNextRedoDecription = ( local txt = "Redo" if canRedo() then ( local redoItem = redoStack[redoStack.count] if redoItem._description != "" then txt += " " + redoItem._description ) txt ) ) -- End of s_UndoRedoSystem struct -- Local Functions Forward Declerations ----------------------------------------------- local inverseImage local updateUI, updateUndoButtonsState local dncWeightsListContextMenu_ItemClicked -- Local Variable Declerations ----------------------------------------------- local workingVerts local workingSkinMod local HideUnusedBones = true local undoSystem = s_UndoRedoSystem() local suspendVertSelectionChangeUpdate = false local weightPrecision = 3 -- User Interface ----------------------------------------------- button bnGrow "Grow" width:50 height:30 align:#left pos:[5,5] button bnShrink "Shrink" width:50 height:30 align:#left pos:[56,5] button bnRing "Ring" width:50 height:30 align:#left pos:[107,5] button bnLoop "Loop" width:50 height:30 align:#left pos:[158,5] button bnPresetValue0_0 "0.0" width:28 height:20 align:#left pos:[5,40] button bnPresetValue0_1 "0.1" width:28 height:20 align:#left pos:[34,40] button bnPresetValue0_25 "0.25" width:28 height:20 align:#left pos:[63,40] button bnPresetValue0_5 "0.5" width:28 height:20 align:#left pos:[92,40] button bnPresetValue0_75 "0.75" width:28 height:20 align:#left pos:[121,40] button bnPresetValue0_9 "0.9" width:28 height:20 align:#left pos:[150,40] button bnPresetValue1_0 "1.0" width:28 height:20 align:#left pos:[179,40] spinner spValue "" fieldWidth:40 type:#float range:[0.0, 10, 0.1] scale:0.01 align:#left pos:[5, 72] checkButton cbValueSet "=" width:25 height:20 align:#left pos:[407,65] button bnValueAdd "+" width:40 height:30 align:#left pos:[60,65] button bnValueSubtract "-" width:40 height:30 align:#left pos:[105,65] --button bnValueMult "*" width:25 height:20 align:#left pos: [134,65] --button bnValueDivide "/" width:25 height:20 align:#left pos:[159,65] button bnCopy "Copy" width:50 height:20 align:#left pos:[5,100] button bnPaste "Paste" width:50 height:20 align:#left pos:[56,100] button bnBlend "Blend" width:50 height:20 align:#left pos:[107,100] button bnExclude "Exclude" width:50 height:20 align:#left pos:[158,100] checkbox SelectElement "SelectElement" checked: false width:150 height:25 pos:[5,125] label lblSelectedVerts "No vertices selected." pos:[7,150] button bnAllbones "All Bones" width:54 height:20 pos:[150,148] button bnUndo "U" width:18 height:18 pos:[545,155] tooltip:"Undo" images:#("Maintoolbar_16i.bmp", undefined, 100, 1, 1, 2, 2) button bnRedo "R" width:18 height:18 pos:[565,155] tooltip:"Redo" images:#("Maintoolbar_16i.bmp", undefined, 100, 3, 3, 4, 4) --checkButton cbDockState "D" width:18 height:18 pos:[27,0] tooltip:"Make window dockable." dotNetControl dncWeightsList "System.Windows.Forms.ListView" height:150 pos:[5,170] width:200 local dncWeightsListContextMenu button RemoveZeroWeights "Remove Zero Weights" width:120 height:25 pos:[5,325] spinner spRemoveZeroWeights "" fieldWidth:50 type:#float range:[0, 1, 0.03] scale:0.01 pos:[135, 329] checkbox AlwaysDeform "Always Deform" checked: true width:150 height:25 pos:[5,355] checkbox ShowNoEnvelopes "Show No Envelopes" checked: true width:150 height:25 pos:[5,376] spinner spBonesLimit "Bones Affect Limit: " fieldWidth:40 type:#integer range:[1, 10, 3] scale:1 pos:[5, 405] button RefreshMe "Refresh" width:57 height:25 pos:[150,400] timer tmUpdateDelay interval:1000 --active:on -- Functions ------------------------------------------------ fn inverseImage bm = ( for y = 0 to (bm.height - 1) do ( local colors = getPixels bm [0,y] bm.width for i = 1 to colors.count do ( local a = colors[i].a colors[i] = white - colors[i] colors[i].a = a ) setPixels bm [0,y] colors ) bm ) fn roundNumber num precision:weightPrecision = ( local multiplier = 10 ^ precision ( floor ( (num * multiplier) + 0.5) ) / multiplier ) fn getFormattedWeight weights = ( weights = makeUniqueArray weights if weights.count > 1 then ( local n = findItem weights undefined if weights.count == 2 and n > 0 then ( --"0.0/- - -" n = if n == 1 then 2 else 1 formattedPrint weights[n] format:("0." + weightPrecision as string + "f") + "/- - -" ) else "Mixed" ) else if weights[1] == undefined then "- - -" else formattedPrint weights[1] format:("0." + weightPrecision as string + "f") ) fn getSelectedSkinVerts skinMod = ( for v = 1 to skinOps.GetNumberVertices skinMod where skinOps.IsVertexSelected skinMod v == 1 collect v ) fn getLockedItems = ( local items = dncWeightsList.checkedItems local locks = for i = 0 to (items.count - 1) collect items.Item[i].Tag locks as bitArray ) fn getSelectedListItem = ( local selectedItems = dncWeightsList.selectedIndices if selectedItems.count > 0 then dncWeightsList.Items.Item[selectedItems.Item[0]] else undefined ) fn getSelectedListItemWeight = ( local selectedItem = getSelectedListItem() if selectedItem != undefined then ( local weight = selectedItem.SubItems.Item[1].Text if weight as float != undefined then weight as float else weight ) else undefined ) fn getVertexWeightBoneIDs skinMod vert = ( local weightsCount = skinOps.GetVertexWeightCount skinMod vert for i = 1 to weightsCount collect skinOps.GetVertexWeightBoneID skinMod vert i ) fn getCurrentWeights skinMod vert = ( local numBones = skinOps.getNumberBones skinMod local vertBones = getVertexWeightBoneIDs skinMod vert for boneID = 1 to numBones collect ( local n = findItem vertBones boneID if n > 0 then roundNumber (skinOps.GetVertexWeight skinMod vert n) precision:weightPrecision else undefined ) ) fn calculateNormalizedValues skinMod vert valueID newVal locks = ( if locks[valueID] then ( messageBox "Can not set value of a locked bone." return() ) -- Get the currnet weights local weights = getCurrentWeights skinMod vert -- Check if the valueID is of a bone with no weight, if so, initialize it's weight to 0 if weights[valueID] == undefined then weights[valueID] = 0 -- Calculate the total of the weights local totalWeight = 0 for i = 1 to weights.count where not locks[i] and i != valueID and weights[i] != undefined do totalWeight += weights[i] -- Calculate the weight percentages local percentages = for w in weights collect if w != undefined and totalWeight > 0 then (w / totalWeight) else undefined -- Make sure the sum of the new value and the locked values don't go over 1.0 local totalLockedWeights = 0 for i = 1 to weights.count where weights[i] != undefined and locks[i] and i != valueID do totalLockedWeights += weights[i] newVal = amax (amin newVal (1.0 - totalLockedWeights)) 0.0 -- Sanity check local totalPercentages = 0 for i = 1 to percentages.count where percentages[i] != undefined and not locks[i] and i != valueID do totalPercentages += percentages[i] if totalPercentages <= 1 then ( -- Calculate new values local valueDiff = weights[valueID] - newVal for i = 1 to weights.count where percentages[i] != undefined and not locks[i] and i != valueID do weights[i] += valueDiff * percentages[i] weights[valueID] = newVal ) weights ) fn setWeights skinMod vert newValues = ( local boneIDs = for i = 1 to newValues.count where newValues[i] != undefined collect i newValues = for v in newValues where v != undefined collect v skinOps.unNormalizeVertex skinMod vert true skinOps.SetVertexWeights skinMod vert boneIDs newValues skinOps.unNormalizeVertex skinMod vert false ) fn updateValuesInList skinMod verts = ( local vertWeights = for v in verts collect (getCurrentWeights skinMod v) local numBones = skinOps.getNumberBones skinMod for i = 0 to (dncWeightsList.Items.Count - 1) do ( local item = dncWeightsList.Items.Item[i] local boneID = item.Tag local weights = for w in vertWeights collect w[boneID] item.SubItems.Item[1].Text = getFormattedWeight weights ) updateUndoButtonsState() ) fn setNewWeights newValues = ( suspendVertSelectionChangeUpdate = true local locks = getLockedItems() local selectedItem = getSelectedListItem() if selectedItem != undefined then ( local breakLoop = false local boneID = selectedItem.Tag undo "Change skin weights" on ( -- Create undo state undoSystem.storeUndoState workingSkinMod workingVerts description:"set weights." for i = 1 to workingVerts.count where not breakLoop do ( local newWeights = calculateNormalizedValues workingSkinMod workingVerts[i] boneID newValues[i] locks if newWeights != undefined then ( setWeights workingSkinMod workingVerts[i] newWeights ) else breakLoop = true ) ) if not breakLoop then updateValuesInList workingSkinMod workingVerts ) suspendVertSelectionChangeUpdate = false ) fn setNewFixedValue newVal = ( if workingVerts != undefined then ( local newValues = for i = 1 to workingVerts.count collect newVal setNewWeights newValues ) ) fn populateWeightList skinMod verts = ( dncWeightsList.BeginUpdate() dncWeightsList.Items.Clear() if isKindOf skinMod skin and verts != undefined then ( local vertWeights = for v in verts collect (getCurrentWeights skinMod v) local numBones = skinOps.getNumberBones skinMod for boneID = 1 to numBones do( local weights = for w in vertWeights collect w[boneID] local weight = (getFormattedWeight weights) if not HideUnusedBones or weight != "- - -" then ( local lvi = dotNetObject "System.Windows.Forms.listViewItem" lvi.Text = skinOps.GetBoneName skinMod boneID 1 lvi.Tag = boneID lvi.SubItems.Add weight dncWeightsList.Items.Add lvi ) ) ) dncWeightsList.EndUpdate() ) fn selectBoneVerts threshold below:false above:true addSubtract: = ( local selectedItem = getSelectedListItem() if workingSkinMod != undefined and selectedItem != undefined then ( local boneID = selectedItem.Tag local boneVets = #{} local numVerts = skinOps.GetNumberVertices workingSkinMod for v = 1 to numVerts do ( local vertBones = getVertexWeightBoneIDs workingSkinMod v local n = findItem vertBones boneID if n > 0 then ( local weight = roundNumber (skinOps.GetVertexWeight workingSkinMod v n) precision:weightPrecision if (above and weight >= threshold) or (below and weight <= threshold) then append boneVets v ) ) local currentVertSelection = (getSelectedSkinVerts workingSkinMod) as bitArray case addSubtract of ( #Subtract: boneVets = currentVertSelection - boneVets #Add: boneVets = currentVertSelection + boneVets ) skinOps.SelectVertices workingSkinMod boneVets updateUI() ) ) fn initWeightsListView = ( -- Create right-click menu dncWeightsListContextMenu = dotNetObject "System.Windows.Forms.ContextMenuStrip" dncWeightsListContextMenu.Items.Add "Hide un-used bones." for i = 0 to (dncWeightsListContextMenu.Items.count - 1) do dncWeightsListContextMenu.Items.Item[i].Tag = i dncWeightsListContextMenu.ShowImageMargin = false dncWeightsListContextMenu.ShowCheckMargin = true dotNet.addEventHandler dncWeightsListContextMenu #ItemClicked dncWeightsListContextMenu_ItemClicked dncWeightsList.View = dncWeightsList.View.Details dncWeightsList.FullRowSelect = true --dncWeightsList.backColor = white dncWeightsList.GridLines = false dncWeightsList.CheckBoxes = true dncWeightsList.HideSelection = false dncWeightsList.MultiSelect = false dncWeightsList.Columns.Add "Bone" 132 dncWeightsList.Columns.Add "Weight" 63 dncWeightsList.Columns.Item[1].TextAlign = dncWeightsList.Columns.Item[1].TextAlign.Center dncWeightsList.ContextMenuStrip = dncWeightsListContextMenu ) fn updateUndoButtonsState = ( bnUndo.enabled = undoSystem.canUndo() bnUndo.toolTip = undoSystem.getNextUndoDecription() bnRedo.enabled = undoSystem.canRedo() bnRedo.toolTip = undoSystem.getNextRedoDecription() ) fn updateUI = ( -- Store the selected BoneId to restore it later. local selectedItem = getSelectedListItem() local selectedTag = if selectedItem != undefined then selectedItem.Tag else undefined --Store locked bones BoneIDs to restore it later local lockedItems = getLockedItems() local lockedBoneIDs = (for i in lockedItems collect dncWeightsList.Items.Item[i - 1].Tag) as bitArray local currentMod = modPanel.getCurrentObject() if isKindOf currentMod skin then ( workingSkinMod = currentMod local selectedVerts = getSelectedSkinVerts workingSkinMod if selectedVerts.count > 0 then workingVerts = selectedVerts else workingVerts = undefined ) else ( workingSkinMod = undefined workingVerts = undefined ) lblSelectedVerts.text = if workingVerts == undefined then "No vertices selected." else if workingVerts.count == 1 then ("Selected vertex: " + (workingVerts[1] - 1) as string) else (workingVerts.count as string + " vertices selected.") populateWeightList workingSkinMod workingVerts -- Restore the previously stored selected boneID for i = 0 to (dncWeightsList.Items.Count - 1) do ( local item = dncWeightsList.Items.Item[i] item.Selected = item.Tag == selectedTag ) -- Restore locked bones for i = 0 to (dncWeightsList.Items.Count - 1) do ( local item = dncWeightsList.Items.Item[i] item.Checked = lockedBoneIDs[item.Tag] ) -- Update undo buttons updateUndoButtonsState() ) -- Vertex selection changed callback fn objectParamentersChangedCH = ( if not suspendVertSelectionChangeUpdate then ( local preSkin = workingSkinMod local preVerts = workingVerts local currentMod = modPanel.getCurrentObject() if workingSkinMod != currentMod then updateUI() else ( local selectedVets = getSelectedSkinVerts currentMod selectedVets = selectedVets as bitArray if workingVerts == undefined then local workingVertsBA = #{} else local workingVertsBA = workingVerts as bitArray if selectedVets.numberSet != workingVertsBA.numberSet or (selectedVets - workingVertsBA).numberSet != 0 or (workingVertsBA - selectedVets).numberSet != 0 then ( updateUI() undoSystem.storeUndoState preSkin preVerts selectionOnly:true description:"vertex selection." updateUndoButtonsState() ) ) ) ) -- Change handlers and callbacks. fn unregisterChangeHandlers = ( deleteAllChangeHandlers id:#SkinHelperCH ) fn registerChangeHandlers = ( unregisterChangeHandlers() local currentMod = modPanel.getCurrentObject() if isKindOf currentMod skin then ( local objs = refs.dependentNodes currentMod when parameters objs changes id:#SkinHelperCH do (try(ro_SkinTools.objectParamentersChangedCH())catch(print "Error in ro_SkinTools.objectParamentersChangedCH")) ) ) fn unregisterCallbacks = ( unregisterChangeHandlers() callbacks.removeScripts id:#SkinHelperCB ) fn registerCallbacks = ( unregisterCallbacks() callbacks.addScript #modPanelObjPostChange "try(ro_SkinTools.registerChangeHandlers())catch(print "Error registring change handler")" id:#SkinHelperCB ) -- Initialize when starting fn init = ( registerCallbacks() initWeightsListView() updateUI() registerChangeHandlers() ) -- Clean up on close. fn done = ( unregisterChangeHandlers() unregisterCallbacks() ) -- Event Handlers ------------------------------------------------- fn dncWeightsListContextMenu_ItemClicked sender args = ( local addSubtract = if keyboard.shiftPressed then #Subtract else if keyboard.ControlPressed then #Add else #Replace case args.ClickedItem.Tag of ( 0: (HideUnusedBones = not HideUnusedBones; args.ClickedItem.Checked = HideUnusedBones; updateUI()) ) ) on bnUndo pressed do ( local values = undoSystem.performUndo() workingSkinMod = values[1] workingVerts = values[2] updateUI force:true ) on bnRedo pressed do ( local values = undoSystem.performRedo() workingSkinMod = values[1] workingVerts = values[2] updateUI force:true ) on tmUpdateDelay tick do ( tmUpdateDelay.active = on suspendVertSelectionChangeUpdate = false ) on dncWeightsList ItemSelectionChanged sender args do ( tmUpdateDelay.active = on suspendVertSelectionChangeUpdate = true skinOps.SelectBone workingSkinMod args.Item.Tag if cbValueSet.checked then ( local val = getSelectedListItemWeight() if isKindOf val number then spValue.value = val else if val == "Mixed" then spValue.indeterminate = true else spValue.value = 0 ) tmUpdateDelay.active = on ) -- Bouton spinner ------------------------------------------------ on spValue buttonDown do ( undoSystem.storeUndoState workingSkinMod workingVerts description:"set weights." undoSystem.suspend = true ) on spValue changed val do ( if cbValueSet.checked then ( local newValues = for i = 1 to workingVerts.count collect val setNewWeights newValues ) ) on spValue buttonUp do ( undoSystem.suspend = false updateUndoButtonsState() ) on cbValueSet changed state do ( if keyboard.controlPressed then ( local newValues = for i = 1 to workingVerts.count collect spValue.value setNewWeights newValues cbValueSet.checked = not state ) else if state then ( local val = getSelectedListItemWeight() if isKindOf val number then spValue.value = val else if val == "Mixed" then spValue.indeterminate = true else spValue.value = 0 ) ) -- Bouton + ------------------------------------------------ on bnValueAdd pressed do ( --local selectedItem = getSelectedListItem() local selectedItem = getSelectedListItem() if selectedItem != undefined then ( local currentVals = for v in workingVerts collect (getCurrentWeights workingSkinMod v)[selectedItem.Tag] local newValues = for i = 1 to workingVerts.count collect if currentVals[i] != undefined then currentVals[i] + spValue.value else spValue.value setNewWeights newValues ) ) -- Bouton - ------------------------------------------------ on bnValueSubtract pressed do ( local selectedItem = getSelectedListItem() if selectedItem != undefined then ( local currentVals = for v in workingVerts collect (getCurrentWeights workingSkinMod v)[selectedItem.Tag] local newValues = for i = 1 to workingVerts.count collect if currentVals[i] != undefined then currentVals[i] - spValue.value else 0 setNewWeights newValues ) ) -- Bouton Grow ------------------------------------------------ on bnGrow pressed do ( skinOps.growSelection (modPanel.GetcurrentObject()) ) -- Bouton Shrink ------------------------------------------------ on bnShrink pressed do ( skinOps.shrinkSelection (modPanel.GetcurrentObject()) ) -- Bouton Loop ------------------------------------------------ on bnLoop pressed do ( skinOps.loopSelection (modPanel.GetcurrentObject()) ) -- Bouton Ring ------------------------------------------------ on bnRing pressed do ( skinOps.ringSelection (modPanel.GetcurrentObject()) ) on ro_SkinTools resized s do resizeWindow s on ro_SkinTools open do init() on ro_SkinTools close do done() -- Boutons value ------------------------------------------------ on bnPresetValue0_0 pressed do setNewFixedValue 0.0 on bnPresetValue0_1 pressed do setNewFixedValue 0.1 on bnPresetValue0_25 pressed do setNewFixedValue 0.25 on bnPresetValue0_5 pressed do setNewFixedValue 0.5 on bnPresetValue0_75 pressed do setNewFixedValue 0.75 on bnPresetValue0_9 pressed do setNewFixedValue 0.9 on bnPresetValue1_0 pressed do setNewFixedValue 1.0 -- Bouton Exclude ------------------------------------------------ on bnExclude pressed do ( skinOps.ButtonExclude (modPanel.GetcurrentObject()) updateUI force:true ) -- Bouton Copy ------------------------------------------------ on bnCopy pressed do ( skinOps.CopyWeights (modPanel.GetcurrentObject()) updateUI force:true ) -- Bouton Paste ------------------------------------------------ on bnPaste pressed do ( skinOps.pasteWeights (modPanel.GetcurrentObject()) updateUI force:true ) -- Bouton Blend ------------------------------------------------ on bnBlend pressed do ( skinOps.blendSelected (modPanel.GetcurrentObject()) updateUI force:true ) -- Select Element ------------------------------------------------ on SelectElement changed state do ( if SelectElement.state == true then ( $.modifiers[#Skin].selectElement = on ) if SelectElement.state == false then ( $.modifiers[#Skin].selectElement = off ) ) -- Bouton bnAllbones ------------------------------------------------ on bnAllbones pressed do ( --HideUnusedBones = not HideUnusedBones; args.ClickedItem.Checked = HideUnusedBones; updateUI() --HideUnusedBones ; updateUI() updateUI force:true ) -- Bones RemoveZeroWeights ------------------------------------------------ on RemoveZeroWeights pressed do ( $.modifiers[#Skin].clearZeroLimit = spRemoveZeroWeights.value skinOps.RemoveZeroWeights (modPanel.GetcurrentObject()) updateUI force:true ) -- Always Deform ------------------------------------------------ on AlwaysDeform changed state do ( if AlwaysDeform.state == true then ( $.modifiers[#Skin].always_deform = true ) if AlwaysDeform.state == false then ( $.modifiers[#Skin].always_deform = false ) updateUI force:true ) -- Show no Envelopes ------------------------------------------------ on ShowNoEnvelopes changed state do ( if ShowNoEnvelopes.state == true then ( $.modifiers[#Skin].ShowNoEnvelopes = on ) if ShowNoEnvelopes.state == false then ( $.modifiers[#Skin].ShowNoEnvelopes = off ) ) -- Bones Affect Limit ------------------------------------------------ on spBonesLimit changed val do ( $.modifiers[#Skin].bone_Limit = spBonesLimit.value updateUI force:true ) -- Boouton RefreshMe ------------------------------------------------ on RefreshMe pressed do ( updateUI force:true ) --timer clock "testClock" interval:2000 --tick once a second --label test "1" --on clock tick do --( --valUp = (test.text as integer)+1 --test.text = valUp as string --updateUI force:true --) ) -- end of ro_SkinTools rollout createDialog ro_SkinTools width:210 height:430 style:#(#style_titlebar, #style_border, #style_sysmenu ) setdialogpos ro_SkinTools [10,100]Thanks for help :thumbup:
I am not sure what you want but wouldn't it be easier if you'd start off with the skin-helper script to your own tool? Usually the official maxscripts that come with the max tools are full of xtra little security stuff like avoiding auto-Save hang ups etc. which is often confusing when trying to read them.
With the original "skin-helper" when you select a bone in the viewport, nothing happen. you have to select it, in his boneslist
We can show all bones with a right clik=> Hide un-used bones, but it's not very readable
I just add buttons with a "force update UI" and tweak the UI of skin-helper
SkinTools_v7