3ds Max maxscript Faceshift Morpher controllers + History Log

一樣是工作紀錄 Z_Z

try(destroyDialog allControls )catch()
rollout allControls "Morpher to FaceShift" (
	--global arr26 = # (0.0, "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n")

	global arr26frames = #()
	global arrframes = #()

	fn compareFN v1 v2 =
	(
		case of
		(
			(v1[1] < v2[1]) : -1

			(v1[1] > v2[1]) : 1

			default: 0
		)
	)

	fn fnNextKeyFrame =
	(
		try
		(
			nextkeyframe = (trackbar.getNextKeyTime() as string)
			inextkeyframe = ((substring nextkeyframe 1 (nextkeyframe.count-1)) as integer)
			if inextkeyframe == undefined then return 0 else return inextkeyframe
		)
		catch
		(
			return 0
		)
	)

	fn fnCurFrameNum = 
	(
		return ( ((substring (slidertime as string) 1 ((slidertime as string).count-1)) as Integer) )
	)

	fn fnFindInArr26Frames iIndex =
	(
		ifoundIndex = -1
		for i = 1 to arr26frames.count do
		(
			if arr26frames[i][1] == iIndex then
			(
				ifoundIndex = i

				return ifoundIndex
			)
		)

		return ifoundIndex
	)

	fn fnFindNearestArr26Frames iIndex =
	(
		ifoundIndex = -1
		for i = 1 to arr26frames.count do
		(
			if arr26frames[i][1] <= iIndex then
			(
				ifoundIndex = i
			)
			else
			(
				break
			)
		)

		return ifoundIndex
	)

	fn dump_arr26frames_data =
	(
		print(arr26frames.count as string)
		for i = 1 to arr26frames.count do
		(
			for j = 1 to arr26frames[i].count do
			(
				print(arr26frames[i][j] as string)
			)

			print("==========")
		)
	)

	fn fnCheckModel =
	(
		animButtonState = true

		-- check model selected or not.
		arr = (selection as array)
		if arr.count == 0 do
		(
			messageBox "Select Head Model !!"

			return false
		)

		-- check contain Morphers or not
		try 
		(
			for i = 1 to 46 do
			(
				strtmp = ($.morpher[i] as string)
				if ( substring strtmp (strtmp.count-6) 7) == "__empty" do
				(
					messageBox "Select Model with Morpher!!"

					return false
				)
			)
		)
		catch
		(
			messageBox "Select Model with Morpher!!"

			return false
		)

		return true
	)

	fn fnChangeMorpherSum =
	(
	/*省略*/
	)

	fn fnChangeMorpher bsid bsvalue =
	(
	/*省略*/
	)

	fn fnNeutual = 
	(
		if fnCheckModel() == true do
		(
			for i = 1 to 26 do
			(
				execute ("allControls.slider" + i as string + ".value = 0.0")
				execute ("allControls.tb" + i as string + ".text = \"0.0\"")

				for j = 1 to 46 do
				(
					$.morpher[j].value = 0
				)
			)

			---------------------------------------------------------------
			-- save facial motion data into array
			---------------------------------------------------------------
			iIndex = fnCurFrameNum()

			bfound = false
			ifoundIndex = -1
			for i = 1 to arr26frames.count do
			(
				if arr26frames[i][1] == iIndex then
				(
					bfound = true
					ifoundIndex = i
				)
			)

			if bfound == false then
			(
				append arr26frames (#(iIndex, "N", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n"))

				qsort arr26frames compareFN 
			)
			else
			(
				for i = 3 to arr26frames[ifoundIndex].count do
				(
					arr26frames[ifoundIndex][i] = "n"
				)

				arr26frames[ifoundIndex][2] = "N"
			)
		)
	)

	fn save_arr26frames_data =
	(
		strfile = getSaveFileName caption:"Save History File:"

		if strfile == undefined then return false

		if (getfiles strfile).count == 0 then createFile strfile

		fs = openFile strfile mode:"w"

		slidertime = 0

		-- save data into file
		for i = 1 to arr26frames.count do
		(
			-- frame 0 special case
			if arr26frames[i][1] == 0 then
			(
				for j = 1 to arr26frames[i].count-1 do
				(
					format "%," arr26frames[i][j] to:fs
				)

				format "%\n" arr26frames[i][arr26frames[i].count] to:fs
			)
			else
			(
				while arr26frames[i][1] > fnNextKeyFrame() do
				(
					--supposed this case never happen.
					if fnNextKeyFrame() <= 0 then exit
					slidertime = fnNextKeyFrame()
				)
				if arr26frames[i][1] == fnNextKeyFrame() then
				(
					-- save data
					for j = 1 to arr26frames[i].count-1 do
					(
						format "%," arr26frames[i][j] to:fs
					)

					format "%\n" arr26frames[i][arr26frames[i].count] to:fs
				)
				else
				(
					--do nothing, supposed the keyframe is deleted, so this frame data won't be saved
				)
			)
		)
		flush fs
		close fs

		Messagebox "SAVED !!"
	)

	fn load_arr26frames_data =
	(
		if fnCheckModel() == false then return false

		strfile = getOpenFileName caption:"Open History File:"

		if strfile == undefined then return false

		if (getfiles strfile).count == 0 do
		(
			Messagebox "File does not Exist !!"

			return false
		)

		fs = openFile strfile mode:"r"

		-- load data from file
		iIndex = 1
		while eof fs == false do
		(
			strtmp = readline fs
			--print strtmp
			arrtmp = filterstring strtmp ","

			append arr26frames (#(0, "N", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n"))
			for i = 1 to arrtmp.count do
			(
				if i > 2 then
				(
					arr26frames[iIndex][i] = (arrtmp[i] as string)
				)
				else
				(
					if i == 1 then
					(
						arr26frames[iIndex][i] = (arrtmp[i] as integer)
					)
					else
					(
						arr26frames[iIndex][i] = (arrtmp[i] as string)
					)
				)
			)

			iIndex = iIndex+1
		)

		-- change morpher
		for i = 1 to arr26frames.count do
		(
			slidertime = arr26frames[i][1]

			if arr26frames[i][2] == "N" then
			(
				for k = 1 to 100 do
				(
					try
					(
						$.morpher[k].value = 0.0
					)
					catch
					(
					)
				)
			)

			for j = 3 to arr26frames[i].count do
			(
				if arr26frames[i][j] == "n" then continue

				execute ("allControls.tb" + ( (j-2) as string ) + ".text = \"" + (arr26frames[i][j] as string) + "\"")
				execute ("allControls.slider" + ( (j-2) as string ) + ".value = " + (arr26frames[i][j] as string) )

				fnChangeMorpher (j-2) (arr26frames[i][j] as string)
			)
		)

		close fs
	)

	fn fnSumToCurrentFrameMorpher iFrame =
	(
		arrtmp = #(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)

		for i = 1 to arr26frames.count do
		(
			if arr26frames[i][1] <= iFrame then
			(
				if arr26frames[i][2] == "N" then
				(
					arrtmp = #(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
				)

				for j = 1 to 26 do
				(
					if arr26frames[i][j+2] != "n" then
					(
						--print ((i as string) + "_" + (j as string))
						arrtmp[j] = (arr26frames[i][j+2] as float)
					)
				)
			)
		)

		return arrtmp
	)

	fn fn26FacialChange a b =
	(
		iIndex = fnCurFrameNum()
		ifoundIndex = fnFindInArr26Frames(iIndex)

		arrtmp = fnSumToCurrentFrameMorpher iIndex

		if ifoundIndex == -1 then
		(
			ifoundNearestIndex = fnFindNearestArr26Frames(iIndex)

			if ifoundNearestIndex == -1 then
			(
				append arr26frames (#(iIndex, "T", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n"))

				arr26frames[arr26frames.count][a+2] = (b as string)

				qsort arr26frames compareFN 
			)
			else
			(
				append arr26frames (#(iIndex, "T", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n", "n"))
				arr26frames[arr26frames.count][a+2] = (b as string)

				qsort arr26frames compareFN
			)
		)

		try
		(
			if ifoundIndex >= 1 or ifoundNearestIndex >= 1 then
				itmp = b - arrtmp[a]
			else
			(
				itmp = b
			)
		)
		catch
		(
			itmp = b
		)
		--print (itmp as string)
		fnChangeMorpher a (itmp as string)

		if ifoundIndex > 0 then
		(
			arr26frames[ifoundIndex][a+2] = (b as string)
		)
	)

	fn fnTBValueChanged a b =
	(
		try
		(
			if trimleft(trimright(b)) == "" do
				(
					return false
				)

			itmp = (b as float)

			if itmp == undefined do
			(
				return false
			)
		)
		catch
		(
			return false
		)

		if fnCheckModel() == true do
		(
			execute ("allControls.slider" + a as string + ".value = " + b)

			fn26FacialChange a (b as float)
		)
	)

	fn fnSliderValueChanged a b =
	(
		if fnCheckModel() == true do
		(
			execute ("allControls.tb" + a as string + ".text = \"" + (b as string) + "\"")

			fn26FacialChange a b
		)
	)

	fn fnSliding =
	(
		iIndex = fnCurFrameNum()

		arrtmp = fnSumToCurrentFrameMorpher iIndex

		for i = 1 to 26 do
		(
			try
			(
				execute ("allControls.slider" + i as string + ".value = " + (arrtmp[i]  as string))
				execute ("allControls.tb" + i as string + ".text = \"" + (arrtmp[i]  as string) + "\"")
			)
			catch
			(
			)
		)
	)

	fn fnResetTbSlider =
	(
		fnSliding()
	)

-- UI
	button bNeutual "Neutual Head" width:90 align:#left across: 4 on bNeutual pressed do fnNeutual()
	label labNull ""
	button bSave "Save Facial Data" width:100 on bSave pressed do save_arr26frames_data()
	button bLoad "Load Facial Data" width:100 on bLoad pressed do load_arr26frames_data()

	button bdump "dump" width:100 on bdump pressed do dump_arr26frames_data()

	label lab1 "SmileClose:" across:6 align:#right
	edittext tb1 width:50  text:"0.0" on tb1 changed txt do fnTBValueChanged 1 tb1.text
	slider slider1 orient:#horizontal width:100 range:[-100,100,1] type:#float on slider1 changed v do fnSliderValueChanged 1 slider1.value
	label lab2 "SmileOpen:" align:#right
	edittext tb2 width:50 text:"0.0" on tb2 changed txt do fnTBValueChanged 2 tb2.text
	slider slider2 orient:#horizontal width:100 range:[-100,100,1] type:#float on slider2 changed v do fnSliderValueChanged 2 slider2.value

/*省略*/
)

theNewFloater = newRolloutFloater "Morpher to FaceShift" 600 600
addRollout allControls theNewFloater

registerTimeCallback allControls.fnResetTbSlider
allControls.fnInitFacialFrames()