@Jmv38 Ok. Actually, I think my preferred method would be, rather than a keyword, nesting the data in a sub table with an appropriate key, eg a vec3 called pos looks like this: "pos":{"vec3":{"y":18.0,"x":17.0,"z":19.0}}
. Edit, added exception method, has feature parity with meta-method:
--# Main
-- Json Test
-- Use this function to perform your initial setup
function setup()
-- VecToJson() --establish metamethods for encoding vec2, vec3, vec4, matrix as json objects
objects={
MyClass{pos=vec3(17,18,19), angle=0, foo="bar"},
MyClass{pos=vec2(123,124), angle=-45, marzipan="tasty", foo="boo"},
MyClass{pos=vec3(257,263,278), angle=-90, boolean=true, foo="bah"}
}
for i=1,2 do --do this twice to check back-conversion
tabSave(objects, "Test")
local loadBack=tabLoad("Test")
loadBack=tabIterate(loadBack) --decode json objects back to vec2, vec3, vec4
print("---------------------\
DECODING COMPLETE, CHECKING\
---------------------")
loadBack=tabIterate(loadBack) --re-iterate to see if decoding has stuck
print("=====================\
RECREATING OBJECTS FROM DECODED DATA, CHECKING\
=====================")
objects = {} --clear objects
for i,v in ipairs(loadBack) do
objects[i]=MyClass(v) --recreate them from loaded table
end
end --rinse and repeat
end
--meta-methods
function VecToJson()
local meta = getmetatable(vec2())
meta.__tojson = function(t)
return json.encode({vec2={x=t.x,y=t.y}})
end
meta = getmetatable(vec3())
meta.__tojson = function(t)
return json.encode({vec3={x=t.x,y=t.y,z=t.z}})
end
meta = getmetatable(vec4())
meta.__tojson = function(t)
return json.encode({vec4={x=t.x,y=t.y,z=t.z,w=t.w}})
end
meta = getmetatable(matrix())
meta.__tojson = function(t)
return json.encode({mat4={t[1],t[2],t[3],t[4], t[5],t[6],t[7],t[8], t[9],t[10],t[11],t[12], t[13],t[14],t[15],t[16]}}) --a matrix.unpack function would've been handy here!
end
end
--encode exception func can be used instead of meta-methods
function jsonException(reason, t, state, message)
if t.x and t.y and t.z and t.w then --vec4
return json.encode({vec4={x=t.x,y=t.y,z=t.z,w=t.w}})
elseif t.x and t.y and t.z then --vec3
return json.encode({vec3={x=t.x,y=t.y,z=t.z}})
elseif t.x and t.y then --vec2
return json.encode({vec2={x=t.x,y=t.y}})
elseif t[16] then --matrix, presumably. nb #t not allowed. what other "userdata" types are there?
return json.encode({mat4={t[1],t[2],t[3],t[4], t[5],t[6],t[7],t[8], t[9],t[10],t[11],t[12], t[13],t[14],t[15],t[16]}}) --a matrix.unpack function would've been handy here!
end
end
function tabSave(tab, loc)
local str=json.encode(tab, {indent = true, exception = jsonException})
saveProjectTab(loc, "--["..str.."]\
")
end
function tabLoad(loc)
local str=readProjectTab(loc)
return json.decode(string.sub(str,4,-3))
end
local underscore = {"=","~","-","."} --underscore characters indicate table depth
function tabIterate(tab, i)
local new = {}
local i = i or 0
local indent = string.rep(" ", i*3) --depth of indentation
for k,v in pairs(tab) do
if type(v)=="table" then --check first whether its a pseudo-table representing a vec2, vec3, vec4, mat4
if v.vec2 then --convert back to vec2
local vec = v.vec2
new[k] = vec2(vec.x, vec.y)
print (indent..k..": decoding vec2"..tostring(new[k]))
elseif v.vec3 then --convert back to vec3
local vec = v.vec3
new[k] = vec3(vec.x, vec.y, vec.z)
print (indent..k..": decoding vec3"..tostring(new[k]))
elseif v.vec4 then --convert back to vec4
local vec = v.vec4
new[k] = vec4(vec.x, vec.y, vec.z, vec.w)
print (indent..k..": decoding vec4"..tostring(new[k]))
elseif v.mat4 then --convert back to matrix
new[k] = matrix(table.unpack(v.mat4))
print (indent..k..": decoding matrix"..tostring(new[k]))
else --genuine table
local under = string.rep(underscore[math.min(#underscore, i+1)], string.len(k))
print(indent..k.."\
"..indent..under)
new[k]=tabIterate(v, i+1) --increase indent upon recursion
end
else
print(indent..k..": "..tostring(v))
new[k]=v
end
end
return new
end
--# MyClass
MyClass = class()
function MyClass:init(t)
for k,v in pairs(t) do
self[k]=v
end
self:draw()
end
function MyClass:draw() --some pseudo drawing
translate(self.pos:unpack()) --(self.pos.x, self.pos.y, self.pos.z)
rotate(self.angle)
self.matrix=modelMatrix()
print(self.foo)
resetMatrix()
end
--# Test
--[[{
"pos":{"vec3":{"y":18.0,"z":19.0,"x":17.0}},
"angle":0,
"matrix":{"mat4":[1.0,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0,0.0,17.0,18.0,19.0,1.0]},
"foo":"bar"
},{
"foo":"boo",
"matrix":{"mat4":[0.70710676908493,-0.70710676908493,0.0,0.0,0.70710676908493,0.70710676908493,0.0,0.0,0.0,0.0,1.0,0.0,123.0,124.0,0.0,1.0]},
"pos":{"vec2":{"y":124.0,"x":123.0}},
"angle":-45,
"marzipan":"tasty"
},{
"foo":"bah",
"angle":-90,
"boolean":true,
"pos":{"vec3":{"y":263.0,"z":278.0,"x":257.0}},
"matrix":{"mat4":[-4.3711388286738e-08,-1.0,0.0,0.0,1.0,-4.3711388286738e-08,0.0,0.0,0.0,0.0,0.99999994039536,0.0,257.0,263.0,278.0,1.0]}
}]]