Export/Import pose module is not importing/exporting correctly

I am trying to make a pose module that allows you to easily export and import poses of R6 rigs through tables, but the current predicament is that when I import the pose data back into the same rig I exported from; the resulting pose is not at all what it should be.

The rig on the left is after importing, the rig on the right is before importing. (The pose is supposed to be for when the player is blocking incoming attacks.)

There seems to be some sort of reason or rhyme to the odd result, but nothing seems to be a good solution without making special exceptions to specific Motor6Ds in rigs.

Here’s the ModuleScript code:

local module = {}

local function getM6(scope: {string}?, callback: ((number, Motor6D) -> ())?): {[string]: Motor6D}
	local joints = {}
	local count = 0
	for _,v in ipairs(script.Parent:GetDescendants()) do
		if v:IsA("Motor6D") and (not scope or table.find(scope, v.Name)) then
			joints[v.Name] = v
			count += 1
			if callback then callback(count, v) end
		end
	end
	return joints
end

function module.getPose(scope: {string}?, c: number?, compact: boolean?): {[string]: {CFrame}} | {[string]: CFrame}
	local function bulk(...: number): (...number)
		local cache = {...}
		local ret = {}
		for _,v in ipairs(cache) do
			table.insert(ret, v)
		end
		return table.unpack(ret)
	end
	
	local function decompV3(vec: Vector3): (number, number, number)
		return vec.X, vec.Y, vec.Z
	end
	
	local double =
		not compact and 'CFrame.new(%s, %s, %s) * CFrame.Angles(%s, %s, %s)'
		or 'CFrame.new(%s,%s,%s)*CFrame.Angles(%s,%s,%s)'
	local separator =
		not compact and ',\n	'
		or ','
	local pdef =
		not compact and '\n{\n	%s\n}'
		or '{%s}'
	
	local str = ""
	if not c then
		local cf: {[string]: {CFrame}} = {}
		
		local double =
			not compact and 'CFrame.new(%s, %s, %s) * CFrame.Angles(%s, %s, %s)'
			or 'CFrame.new(%s,%s,%s)*CFrame.Angles(%s,%s,%s)'
		local template =
			not compact and '%s["%s"] = {\n		'..double..',\n		'..double..'\n	}'
			or '%s["%s"]={'..double..','..double..'}'
		local separator =
			not compact and ',\n	'
			or ','
		local pdef =
			not compact and '\n{\n	%s\n}'
			or '{%s}'
		
		getM6(scope, function(i,v)
			local p0 = v.C0.Position
			local o0 = Vector3.new(bulk(v.C0:ToOrientation()))
			local p1 = v.C1.Position
			local o1 = Vector3.new(bulk(v.C1:ToOrientation()))
			
			str = str .. string.format(
				template,

				i>1 and separator or '',
				v.Name,
				p0.X,p0.Y,p0.Z, o0.X,o0.Y,o0.Z,
				p1.X,p1.Y,p1.Z, o1.X,o1.Y,o1.Z
			)
			
			cf[v.Name] = {v.C0, v.C1}
		end)
		
		print(string.format(pdef, str))
		return cf
	else
		local cf: {[string]: CFrame} = {}
		
		local template =
			not compact and '%s["%s"] = '..double
			or '%s["%s"]='..double
		
		getM6(scope, function(i,v)
			local p0 = v["C"..c].Position
			local o0 = Vector3.new(bulk(v["C"..c]:ToOrientation()))
			
			str = str .. string.format(
				template,
				
				i>1 and separator or '',
				v.Name,
				p0.X,p0.Y,p0.Z, o0.X,o0.Y,o0.Z
			)
			
			cf[v.Name] = v["C"..c]
		end)
		
		print(string.format(pdef, str))
		return cf
	end
end

function module.setPose(pose: {[string]: {CFrame} | CFrame}, c: number?)
	getM6(nil, function(_,v)
		if pose[v.Name] then
			if not c then
				if pose[v.Name][1] then
					v.C0 = pose[v.Name][1]
				end
				if pose[v.Name][2] then
					v.C1 = pose[v.Name][2]
				end
			else
				v["C"..c] = pose[v.Name]
			end
		end
	end)
end

return module

The module should be inserted into a newly made rig (I get mine from Moon Animator’s Import Avatar menu). After that, use this line of code in the command bar in your studio:

require(workspace.TemplateR61.ModuleScript).setPose({["Right Shoulder"]=CFrame.new(-0.5,0.699999988079071,0)*CFrame.Angles(-0.8726646304130554,1.5707963705062866,-2.0071287155151367),["Left Shoulder"]=CFrame.new(0.5,0.699999988079071,0)*CFrame.Angles(-0.8726646304130554,-1.5707963705062866,2.181661605834961),["Right Hip"]=CFrame.new(0.5,0.699999988079071,0.20000000298023224)*CFrame.Angles(0,1.5707963705062866,0.2617993950843811),["Left Hip"]=CFrame.new(-0.5,0.800000011920929,0.30000001192092896)*CFrame.Angles(0,-1.5707963705062866,0.2617993950843811),["Neck"]=CFrame.new(0,-0.5,0)*CFrame.Angles(1.2217304706573486,-3.1415927410125732,0),["RootJoint"]=CFrame.new(0,0.30000001192092896,0)*CFrame.Angles(1.3962633609771729,-3.1415927410125732,0)}, 1)

This line of code will set the rig to the exact pose that is seen in the included screenshot.

Please help, I really need to fix my export/import module.

1 Like

Figured out why it doesn’t work. Fixed it by using CFrame.fromMatrix().

local module = {}

local function getM6(scope: {string}?, callback: ((number, Motor6D) -> ())?): {[string]: Motor6D}
	local joints = {}
	local count = 0
	for _,v in ipairs(script.Parent:GetDescendants()) do
		if v:IsA("Motor6D") and (not scope or table.find(scope, v.Name)) then
			joints[v.Name] = v
			count += 1
			if callback then callback(count, v) end
		end
	end
	return joints
end

function module.getPose(scope: {string}?, c: number?, compact: boolean?): {[string]: {CFrame}} | {[string]: CFrame}
	local function bulk(...: number): (...number)
		local cache = {...}
		local ret = {}
		for _,v in ipairs(cache) do
			table.insert(ret, v)
		end
		return table.unpack(ret)
	end
	
	local function decompV3(vec: Vector3): (number, number, number)
		return vec.X, vec.Y, vec.Z
	end
	local function visV3(vec: Vector3): string
		local sep = compact and ',' or ', '
		return 'Vector3.new('..vec.X..sep..vec.Y..sep..vec.Z..')'
	end
	
	local double =
		not compact and 'CFrame.fromMatrix(%s, %s, %s, %s)'
		or 'CFrame.fromMatrix(%s,%s,%s,%s)'
	local separator =
		not compact and ',\n	'
		or ','
	local pdef =
		not compact and '\n{\n	%s\n}'
		or '{%s}'
	
	local str = ""
	if not c then
		local cf: {[string]: {CFrame}} = {}
		
		local template =
			not compact and '%s["%s"] = {\n		'..double..',\n		'..double..'\n	}'
			or '%s["%s"]={'..double..','..double..'}'
		
		getM6(scope, function(i,v)
			local p0 = v.C0.Position
			local o0 = Vector3.new(bulk(v.C0:ToOrientation()))
			local p1 = v.C1.Position
			local o1 = Vector3.new(bulk(v.C1:ToOrientation()))
			
			str = str .. string.format(
				template,

				i>1 and separator or '',
				v.Name,
				visV3(v.C0.Position),visV3(v.C0.XVector),visV3(v.C0.YVector),visV3(v.C0.ZVector),
				visV3(v.C1.Position),visV3(v.C1.XVector),visV3(v.C1.YVector),visV3(v.C1.ZVector)
			)
			
			cf[v.Name] = {v.C0, v.C1}
		end)
		
		print(string.format(pdef, str))
		return cf
	else
		local cf: {[string]: CFrame} = {}
		
		local template =
			not compact and '%s["%s"] = '..double
			or '%s["%s"]='..double
		
		getM6(scope, function(i,v)
			local p0 = v["C"..c].Position
			local o0 = Vector3.new(bulk(v["C"..c]:ToOrientation()))
			
			str = str .. string.format(
				template,
				
				i>1 and separator or '',
				v.Name,
				visV3(v["C"..c].Position),
				visV3(v["C"..c].XVector),
				visV3(v["C"..c].YVector),
				visV3(v["C"..c].ZVector)
			)
			
			cf[v.Name] = v["C"..c]
		end)
		
		print(string.format(pdef, str))
		return cf
	end
end

function module.setPose(pose: {[string]: {CFrame} | CFrame}, c: number?)
	getM6(nil, function(_,v)
		if pose[v.Name] then
			if not c then
				if pose[v.Name][1] then
					v.C0 = pose[v.Name][1]
				end
				if pose[v.Name][2] then
					v.C1 = pose[v.Name][2]
				end
			else
				v["C"..c] = pose[v.Name]
			end
		end
	end)
end

return module
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.