Home Technical Talk

Tweak the Weight Tool?

polycounter lvl 18
Offline / Send Message
zOffTy polycounter lvl 18
hi

you know if it's possible to tweak this popup with maxscript?
skinningtw.gif

i don't find the file of this tool :poly141:

Replies

  • renderhjs
  • zOffTy
    Offline / Send Message
    zOffTy polycounter lvl 18
    I wanted to modify the 3dsmax's "weigh tool" directly, but apparently it's coded in C++...!

    The Skin Helper seem to be really good, and quite easy to tweak!
    :poly121: thanks!
  • zOffTy
    Offline / Send Message
    zOffTy polycounter lvl 18
    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 ...


    SkinToolsv3.jpg

    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:
  • renderhjs
    Offline / Send Message
    renderhjs sublime tool
    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.
  • zOffTy
    Offline / Send Message
    zOffTy polycounter lvl 18
    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
  • zOffTy
    Offline / Send Message
    zOffTy polycounter lvl 18
    I did some cleaning and modification :)

    SkinTools_v7
Sign In or Register to comment.