'Made by Padovan Andrea &Daniele Pieroni & Daniele Tagliaferri -- PLAYSTOS entertainment
'Date 06-04-2002 17:40
'/////////////////////////MAIN ///////////////////////
Dim oDialog 

set oDialog = CreateUIDialog

On Error Resume Next

InspectObj oDialog,,,4

if Err.Number = 0 then
	BoneAssembler
end if

DeleteObj oDialog


'/////////////////////////CORE////////////////////////
'funzione che opera sulla pesatura dei vertici
Sub BoneAssembler
Dim boneCount, minWeightValue, minWeightValueIndex, factorToAdd
Dim selectedMode, maxBone, bVerbose

'prendiamo i parametri impostati dalla dialogbox
selectedMode = oDialog.parameters("MXE_BONE_ASSEMBLER_MODE").value
maxBone = oDialog.parameters("MXE_BONE_ASSEMBLER_MAXBONE").value
bVerbose = oDialog.parameters("MXE_BONE_ASSEMBLER_VERBOSE").value


for each oSel in selection

	  if oSel.type = "polymsh" then

		set oEnvelope = oSel.Envelopes(0)

		aWeights = oEnvelope.Weights.Array

		for iElement = lbound(aWeights,2) to ubound(aweights,2)

			boneCount = maxBone + 1
			
			'ci fermiamo solo quando rimangono maxBone deformer
			while boneCount > maxBone
			
				boneCount = 0
				minWeightValue = 10000.0
				minWeightValueIndex = 0
				factorToAdd = 0
						
				'contiamo quanti deformer(bone) influenzano questo vertice e troviamo quello con minor peso
				for iDeformer = lbound(aWeights,1) to ubound(aWeights,1)
			
					if aWeights(iDeformer, iElement) > 0 then
						boneCount = boneCount + 1
					
						if aWeights(iDeformer, iElement) < minWeightValue then
							minWeightValue = aWeights(iDeformer, iElement)
							minWeightValueIndex = iDeformer
						end if
					end if
				next
				
				'espressione numero 0
				if selectedMode = 0 then
					'operiamo sui pesi di questo vertice solo se hanno almeno maxBone deformer
					if boneCount > maxBone then
						factorToAdd = minWeightValue / (boneCount - 1)
						
						for iDeformer = lbound(aWeights,1) to ubound(aWeights,1)
			
							'azzeriamo il deformer pił piccolo precedentemente trovato
							if iDeformer = minWeightValueIndex then
								aWeights(iDeformer, iElement) = 0.0000
							'aggiungiamo parte del deformer pił piccolo agli altri
							else
								if aWeights(iDeformer, iElement) > 0 then
									aWeights(iDeformer, iElement) = aWeights(iDeformer, iElement) + factorToAdd
								end if
							end if
						next

						if bVerbose = TRUE then
							logmessage "Weight (" & iElement & ") modified. Previous DEFORMER number: " & boneCount 
						end if
						
					end if
				
				end if
				
				'espressione numero 1
				if selectedMode = 1 then
					'operiamo sui pesi di questo vertice solo se hanno almeno maxBone deformer
					if boneCount > maxBone then
						
						Dim newMinWeightValueIndex, newMinWeightValue
						
						newMinWeightValueIndex = 0
						newMinWeightValue = 10000.00
												
						for iDeformer = lbound(aWeights,1) to ubound(aWeights,1)
				
							'azzeriamo il deformer pił piccolo precedentemente trovato
							if iDeformer = minWeightValueIndex then
								aWeights(iDeformer, iElement) = 0.0000
							else
								if aWeights(iDeformer, iElement) > 0 then
									if aWeights(iDeformer, iElement) < newMinWeightValue then
										newMinWeightValue = aWeights(iDeformer, iElement)
										newMinWeightValueIndex = iDeformer
									end if
								end if
							end if
						next
						
						'ora che abbiamo azzerato il deformer meno influente aggiungiamo il suo valore al nuovo deformer meno influente
						aWeights(newMinWeightValueIndex, iElement) = aWeights(newMinWeightValueIndex, iElement) + minWeightValue 
						
						if bVerbose = TRUE then
							logmessage "Weight (" & iElement & ") modified. Previous DEFORMER number: " & boneCount 
						end if
						
					end if
				end if
				
			wend
		next
		

	'salvo sul modello la nuova envelope
	oEnvelope.Weights.Array = aWeights
	
	else
	
	logmessage "-========== ERROR: PLEASE, SELECT A POLYMESH ! -=========="

	
	end if
		
next

end sub



'///////////////////////UTILITY///////////////////////////////
'Funzione che crea la finestra di dialogo globale tramite i custom parameters
function CreateUIDialog()
 Dim oRoot, oDialog, oParam
 set oRoot = ActiveProject.ActiveScene.Root
 
 On Error Resume Next
 
 'Build a custom dialog
 set oDialog = oRoot.AddProperty("Custom_Parameter_List",,"MXE_BONE_ASSEMBLER")
 
 set oParam = oDialog.AddParameter("Str1", siString, , 4, ,"Modus Operandi", , "Default" )
 oDialog.parameters("Str1").Value = "0 = Minor to all  1 = Minor to minor "

 set oParam = oDialog.AddParameter("MXE_BONE_ASSEMBLER_MODE", siInt4,,4,,"Modus Operandi", , 0, 0, 1)

 set oParam = oDialog.AddParameter("MXE_BONE_ASSEMBLER_MAXBONE", siInt4,,4,,"Max Number of Bones", , 2, 2, 1000)
 
 set oParam = oDialog.AddParameter("MXE_BONE_ASSEMBLER_VERBOSE", siBool,,4,,"Show Info",,TRUE)

 'Return the Dialog Object
 set CreateUIDialog = oDialog 
end function





