version = "" modulesTable = {} assetsTable = {} propertiesTable = {} timeTable = {} cameraTable = {} markNodesTable = {} keybindingsTable = {} resultTable = {} insideSection = false currFunction = "None" currSection = "None" numLinesVersion = 0 lineIndex = 1 function printError(message) print("Error @ line "..lineIndex..": "..message) end function splitByTab (inputstr) sep = "\t" t = {} for match in (inputstr..sep):gmatch("(.-)"..sep) do table.insert(t, match) end return t; end function parseVersion(line) numLinesVersion = numLinesVersion + 1 if numLinesVersion > 1 then printError("Too many lines in Version section.") os.exit() else lineS = splitByTab(line) if tableLen(lineS) > 1 then printError("No tabs allowed in version entry.") os.exit() else version = line end end end function parseMarkNodes(line) lineS = splitByTab(line) if tableLen(lineS) > 1 then printError("No tabs allowed in MarkNodes entry.") os.exit() else table.insert(markNodesTable, line) end end function parseModule(line) t = {} t = splitByTab(line) if tableLen(t) ~= 3 then printError("3 fields requried in a Module entry.") os.exit() else table.insert(modulesTable, t) end end function parseAsset(line) t = {} t = splitByTab(line) if tableLen(t) ~= 2 then printError("2 fields required in a Asset entry.") os.exit() else local req = "required" if t[2] == "requested" then req = "requested" end table.insert(assetsTable, {t[1], req}) end end function parseProperty(line) t = {} t = splitByTab(line) if tableLen(t) ~= 3 then printError("3 fields required in a Property entry.") os.exit() elseif isBlank(t[1]) then printError("Property set command (arg 1/3) is required.") os.exit() elseif isBlank(t[2]) then printError("Property name (arg 2/3) is required.") os.exit() elseif isBlank(t[3]) then printError("Property value to set (arg 3/3) is required.") os.exit() end if t[1] ~= "setPropertyValue" and t[1] ~= "setPropertyValueSingle" then printError("Property set command '"..t[1].."' is not supported.") os.exit() end table.insert(propertiesTable, t) end function parseKeybinding(line) local numReqFields = 6 t = {} t = splitByTab(line) if tableLen(t) < numReqFields then printError(numReqFields.." fields required in a Keybinding entry.") os.exit() elseif isBlank(t[1]) then printError("Keybinding key (arg 1/6) is required.") os.exit() elseif isBlank(t[2]) then printError("Keybinding documentation (arg 2/6) is required.") os.exit() elseif isBlank(t[3]) then printError("Keybinding name (arg 3/6) is required.") os.exit() elseif isBlank(t[4]) then printError("Keybinding GuiPath (arg 4/6) is required.") os.exit() elseif isBlank(t[5]) then printError("Keybinding local(T/F) (arg 5/6) is required.") os.exit() elseif isBlank(t[6]) then printError("Keybinding script to execute (arg 6/6) is required.") os.exit() end --If there are more than 6 fields then combine the final fields together --assuming that this is a lua script that contains tabs if tableLen(t) > numReqFields then for i=(numReqFields + 1),tableLen(t) do t[numReqFields] = t[numReqFields]..t[i] end end if t[5] ~= "true" and t[5] ~= "false" then printError("Keybinding local arg must be true or false.") os.exit() end table.insert(keybindingsTable, {t[1], t[2], t[3], t[4], t[5], t[6]}) end function parseTime(line) t = {} t = splitByTab(line) if tableLen(t) ~= 2 then printError("2 fields required in a Time entry.") os.exit() elseif isBlank(t[1]) then printError("Time set type (arg 1/2) is required.") os.exit() elseif isBlank(t[2]) then printError("Time value to set (arg 2/2) is required.") os.exit() end if t[1] ~= "absolute" and t[1] ~= "relative" then printError("Time set type '"..t[1].."' is not supported.") os.exit() end table.insert(timeTable, t) end function parseCamera(line) t = {} t = splitByTab(line) local cmd = t[1] if cmd == "setNavigationState" then if tableLen(t) ~= 8 then printError("8 fields required in camera 'setNavigationState' line.") os.exit() elseif isBlank(t[2]) then printError("Camera setNavigationState Anchor (arg 1/7) is required.") os.exit() elseif isBlank(t[5]) then printError("Camera setNavigationState position vector (arg 4/7) is required.") os.exit() end elseif cmd == "goToGeo" then if tableLen(t) ~= 5 then printError("5 fields required in camera 'goToGeo' line.") os.exit() elseif isBlank(t[3]) then printError("Camera goToGeo Latitude (arg 2/4) is required.") os.exit() elseif isBlank(t[4]) then printError("Camera goToGeo Longitude (arg 3/4) is required.") os.exit() end else printError("Camera position command '"..cmd.."' is not supported.") os.exit() end table.insert(cameraTable, t) end function file_exists(file) local f = io.open(file, "rb") if f then f:close() end return f ~= nil end function lines_from(file) if not file_exists(file) then return {} end lines = {} for line in io.lines(file) do lines[#lines + 1] = line end return lines end function determineSection(header) header = header:sub(2) for _,i in pairs(parsingSections) do if i.section == header then currSection = i.section currFunction = i.func return true end end return false end function isBlank(line) return line:match("%S") == nil end function parseCurrentSection(line) currFunction(line) end function tableLen(T) local size = 0 for _ in pairs(T) do size = size + 1 end return size end function parseProfile(fileIn) local lines = lines_from(fileIn) for k,v in pairs(lines) do if insideSection then if isBlank(v) then insideSection = false else parseCurrentSection(v) end elseif v:sub(1, 1) == "#" then if determineSection(v) then insideSection = true end end lineIndex = lineIndex + 1 end resultTable["Version"] = version resultTable["Module"] = modulesTable resultTable["Asset"] = assetsTable resultTable["Property"] = propertiesTable resultTable["Time"] = timeTable resultTable["Camera"] = cameraTable resultTable["MarkNodes"] = markNodesTable resultTable["Keybinding"] = keybindingsTable return resultTable end function tableSize(T) local size = 0 for _ in pairs(T) do size = size + 1 end return size end function generateAsset(T, fileOut) file = io.open(fileOut, "w") io.output(file) --Module section for i,j in pairs(T["Module"]) do if not isBlank(j[2]) and not isBlank(j[3]) then ModuleStr = ModuleStr.."if openspace.modules.isLoaded('"..j[1].."') then\n" ModuleStr = ModuleStr.." "..j[2].."\nelse\n".." "..j[3].."\nend\n" elseif not isBlank(j[3]) then ModuleStr = ModuleStr.."if not openspace.modules.isLoaded('"..j[1].."') then\n" ModuleStr = ModuleStr.." "..j[3].."\nend\n" elseif not isBlank(j[2]) then ModuleStr = ModuleStr.."if openspace.modules.isLoaded('"..j[1].."') then\n" ModuleStr = ModuleStr.." "..j[2].."\nend\n" end end --Asset section AssetStr = AssetStr.."asset.require('./base');\n" AssetStr = AssetStr.."local assetHelper = asset.require('util/asset_helper')\n" AssetStr = AssetStr.."local propertyHelper = asset.require('util/property_helper')\n" AssetStr = AssetStr.."local sceneHelper = asset.require('util/scene_helper')\n" AssetStr = AssetStr.."local renderableHelper = asset.require('util/renderable_helper')\n" local assetType = "" for i,j in pairs(T["Asset"]) do if isBlank(j[2]) then assetType = "require" else if (j[2] == "required") then assetType = "require" elseif (j[2] == "requested") then assetType = "request" else printError("Asset arg 2/2 must be either 'required' or 'requested'.") os.exit() end end AssetStr = AssetStr.."asset."..assetType.."('"..j[1].."')\n" end --Keybindings section if not (tableSize(T["Keybinding"]) == 0) then KeyStr = KeyStr.."local Keybindings = {\n" for i,j in pairs(T["Keybinding"]) do KeyStr = KeyStr.." {\n" KeyStr = KeyStr.." Key = \""..j[1].."\",\n" KeyStr = KeyStr.." Documentation = \""..j[2].."\",\n" KeyStr = KeyStr.." Name = \""..j[3].."\",\n" KeyStr = KeyStr.." GuiPath = \""..j[4].."\",\n" KeyStr = KeyStr.." Local = "..j[5]..",\n" KeyStr = KeyStr.." Command = \""..j[6].."\"\n" KeyStr = KeyStr.." },\n" end KeyStr = KeyStr.."}\n" end --Time section for i,j in pairs(T["Time"]) do if not (j[1] == "absolute") and not (j[1] == "relative") then printError("Time arg 1/1 must be either 'absolute' or 'relative'.") os.exit() elseif (j[1] == "absolute") then TimeStr = TimeStr.." openspace.time.setTime(\""..j[2].."\")\n" elseif (j[1] == "relative") then TimeStr = TimeStr.." openspace.time.setTime(" TimeStr = TimeStr.."openspace.time.advancedTime(now, \"" TimeStr = TimeStr..j[2].."\"))\n" end end --MarkNodes section mkNodLen = tableSize(T["MarkNodes"]) if not (mkNodLen == 0) then MarkNodesStr = MarkNodesStr.." openspace.markInterestingNodes({" for i,j in pairs(T["MarkNodes"]) do MarkNodesStr = MarkNodesStr.."\""..j.."\"" if (i < mkNodLen) then MarkNodesStr = MarkNodesStr..", " end end MarkNodesStr = MarkNodesStr.."})\n" end --Property section for i,j in pairs(T["Property"]) do if not (j[1] == "setPropertyValue") and not (j[1] == "setPropertyValueSingle") then printError("Property arg 1/1 must be 'setPropertyValue[Single]'.") os.exit() else PropertyStr = PropertyStr.." openspace."..j[1].."('"..j[2].."', "..j[3]..")\n" end end --Camera section for i,j in pairs(T["Camera"]) do if (j[1] == "setNavigationState") then CameraStr = CameraStr.." openspace.navigation.setNavigationState({" CameraStr = CameraStr.."Anchor = "..j[2]..", " if not isBlank(j[3]) then CameraStr = CameraStr.."Aim = "..j[3]..", " end if not isBlank(j[4]) then CameraStr = CameraStr.."ReferenceFrame = "..j[4]..", " end CameraStr = CameraStr.."Position = {"..j[5].."}, " if not isBlank(j[6]) then CameraStr = CameraStr.."Up = {"..j[6].."}, " end if not isBlank(j[7]) then CameraStr = CameraStr.."Yaw = "..j[7]..", " end if not isBlank(j[8]) then CameraStr = CameraStr.."Pitch = "..j[8] end CameraStr = CameraStr.."})\n" elseif (j[1] == "goToGeo") then CameraStr = CameraStr.." openspace.globebrowsing.goToGeo(" if not isBlank(j[2]) then CameraStr = CameraStr..j[2]..", " end CameraStr = CameraStr..j[3]..", "..j[4] if not isBlank(j[5]) then CameraStr = CameraStr..", "..j[5] end CameraStr = CameraStr..")\n" else printError("Camera arg 1/1 must be 'setNavigationState' or 'goToGeo'.") os.exit() end end --Write the file io.write(ModuleStr.."\n") io.write(AssetStr.."\n") io.write(KeyStr.."\n") io.write("asset.onInitialize(function ()\n") io.write(TimeStr.."\n") if not (tableSize(T["Keybinding"]) == 0) then io.write(" sceneHelper.bindKeys(Keybindings)\n") end io.write(MarkNodesStr.."\n") io.write(PropertyStr.."\n") io.write(CameraStr.."\n") io.write("end)\n") io.close(file) end --[[ ########################################################################################## M a i n ########################################################################################## ]]-- ModuleStr = "" AssetStr = "" KeyStr = "" TimeStr = "" MarkNodesStr = "" PropertyStr = "" CameraStr = "" parsingSections = { {section = "Version", func = parseVersion}, {section = "Module", func = parseModule}, {section = "Asset", func = parseAsset}, {section = "Property", func = parseProperty}, {section = "Keybinding", func = parseKeybinding}, {section = "Time", func = parseTime}, {section = "Camera", func = parseCamera}, {section = "MarkNodes", func = parseMarkNodes} } profileFilename = openspace.profile.getFilename() profilePath = openspace.profile.getPath() profileIn = profilePath.."\\"..profileFilename assetOut = profilePath.."\\"..profileFilename:match("^.+%.").."scene" local resultTable = parseProfile(profileIn) generateAsset(resultTable, assetOut)