------All the tables defining stuff local bools = { ["false"]=false, ["true"]=true } local xmlVariants = { ["enableSounds"]="enablesounds", ["normalMove"]="camera_normal_speed", ["fastMove"]="camera_max_speed", ["slowMove"]="camera_min_speed", ["mouseSensitivity"]="camera_look_sensitivity", ["smoothCamMove"]="camera_smooth_movement", ["invertMouseLook"]="invert_mouse_look", ["iconSize"]="icon_size", ["topAlign"]="alignment_topmenu", ["bottomAlign"]="alignment_bottommenu", ["normalElemMove"]="movement_normal_speed", ["fastElemMove"]="movement_max_speed", ["slowElemMove"]="movement_min_speed", ["normalElemRotate"]="rotate_normal_speed", ["fastElemRotate"]="rotate_fast_speed", ["slowElemRotate"]="rotate_slow_speed", ["normalElemScale"]="scaling_normal_speed", ["fastElemScale"]="scaling_fast_speed", ["slowElemScale"]="scaling_slow_speed", ["lockToAxes"]="movement_lock_to_axes", ["autosnap"]="currentbrowser_autosnap", ["tutorialOnStart"]="tutorial_on_start", ["enableBox"]="enablebox", ["enableHoverBoundingBox"]="enablehoverboundingbox", ["enableXYZlines"]="enablexyzlines", ["precisionLevel"]="precisionlevel", ["precisionRotLevel"]="precisionrotlevel", ["elemScalingSnap"]="elemscalingsnap", ["enablePrecisionSnap"]="enableprecisionsnap", ["enablePrecisionRotation"]="enableprecisionrotation", ["enableColPatch"]="enablecolpatch", ["enableRotPatch"]="enablerotpatch", ["randomizeRotation"]="enablerandomrot", ["randomizeRotationAxis"]="randomizerotaxis", ["fov"]="fov", } local nodeTypes = { ["enableSounds"]="bool", ["normalMove"]="progress", ["fastMove"]="progress", ["slowMove"]="progress", ["mouseSensitivity"]="progress", ["smoothCamMove"]="bool", ["invertMouseLook"]="bool", ["iconSize"]={"small","medium","large"}, ["topAlign"]={"left","right","center"}, ["bottomAlign"]={"left","right","center"}, ["normalElemMove"]="progress", ["fastElemMove"]="progress", ["slowElemMove"]="progress", ["normalElemRotate"]="progress", ["fastElemRotate"]="progress", ["slowElemRotate"]="progress", ["normalElemScale"]="progress", ["fastElemScale"]="progress", ["slowElemScale"]="progress", ["lockToAxes"]="bool", ["autosnap"]="bool", ["tutorialOnStart"]="bool", ["enableDumpSave"]="bool", ["enableBox"]="bool", ["enableHoverBoundingBox"]="bool", ["precisionLevel"]={"10","5","2","1","0.1","0.01","0.001","0.0001"}, ["precisionRotLevel"]={"180","90","45","30","20","10","5","1"}, ["elemScalingSnap"]={"1","0.1","0.01","0.001","0.0001"}, ["enablePrecisionSnap"]="bool", ["enablePrecisionRotation"]="bool", ["enableXYZlines"]="bool", ["enableColPatch"]="bool", ["enableRotPatch"]="bool", ["randomizeRotation"]="bool", ["randomizeRotationAxis"]={"X","Y","Z","XY","XZ","YZ","XYZ"}, ["fov"]="progress", } local defaults = { ["enableSounds"]=true, ["normalMove"]=2, ["fastMove"]=12, ["slowMove"]=.2, ["mouseSensitivity"]=.73, ["smoothCamMove"]=true, ["invertMouseLook"]=false, ["iconSize"]="medium", ["topAlign"]="center", ["bottomAlign"]="left", ["normalElemMove"]=.25, ["fastElemMove"]=1.57, ["slowElemMove"]=.025, ["normalElemRotate"]=2, ["fastElemRotate"]=10, ["slowElemRotate"]=0.25, ["normalElemScale"]=0.1, ["fastElemScale"]=1, ["slowElemScale"]=0.01, ["lockToAxes"]=false, ["autosnap"]=true, ["tutorialOnStart"]=true, ["enableBox"]=true, ["enableHoverBoundingBox"]=false, ["precisionLevel"]="0.1", ["precisionRotLevel"]="30", ["elemScalingSnap"]="0.0001", ["enablePrecisionSnap"]=true, ["enablePrecisionRotation"]=false, ["enableXYZlines"]=true, ["enableColPatch"]=false, ["enableRotPatch"]=true, ["randomizeRotation"]=false, ["randomizeRotationAxis"]="XYZ", ["fov"]=dxGetStatus()["SettingFOV"], } --stuff involving xml and dumping function doActions() for name,v in pairs(nodeTypes) do if ( optionsActions[name] ) and ( dialog[name] ) then optionsActions[name]( dialog[name]:getValue() ) end end end function loadXMLSettings() --this should use xmlLoadFile afterwards if settingsXML then xmlUnloadFile ( settingsXML ) end settingsXML = xmlLoadFile ( "settings.xml" ) if not settingsXML then createSettingsXML() end if not settingsXML then outputMessage ( "Map editor settings could not be created!.", 255,0,0 ) return end -- check if the entries in the XML are valid, and remove invalid ones local validNodes = {} for _, nodeName in pairs(xmlVariants) do validNodes[nodeName] = true end local children = xmlNodeGetChildren(settingsXML) for i = #children, 1, -1 do local node = children[i] local nodeName = xmlNodeGetName(node) if not validNodes[nodeName] then --xmlDestroyNode(node) -- Disabled this and replaced it with a debug output because all this check does is delete new valid nodes when someone goes on an outdated version. outputDebugString("Found an invalid settings node: "..tostring(nodeName)) end end xmlSaveFile(settingsXML) -- local settingsTable = {} for gui, nodeName in pairs(xmlVariants) do local node = xmlFindChild(settingsXML, nodeName, 0) -- Node should exist after validation, but check anyway if node then local value if nodeTypes[gui] == "bool" then local nodeValue = xmlNodeGetValue(node) value = bools[nodeValue] -- If value is nil (invalid boolean), use default if value == nil then value = defaults[gui] xmlNodeSetValue(node, tostring(value)) outputDebugString("Fixed invalid boolean value for " .. nodeName) end elseif nodeTypes[gui] == "progress" then local nodeValue = xmlNodeGetValue(node) value = tonumber(nodeValue) -- If value is nil or out of range, use default if value == nil then value = defaults[gui] xmlNodeSetValue(node, tostring(value)) outputDebugString("Fixed invalid numeric value for " .. nodeName) end elseif type(nodeTypes[gui]) == "table" then local nodeValue = xmlNodeGetValue(node) value = tostring(nodeValue) -- Validate enum values local valid = false for _, valuePossibility in pairs(nodeTypes[gui]) do if value == valuePossibility then valid = true break end end -- If invalid value, use default if not valid then value = defaults[gui] xmlNodeSetValue(node, tostring(value)) outputDebugString("Fixed invalid enum value for " .. nodeName) end end settingsTable[gui] = value else -- This should never happen after validation, but as a fallback settingsTable[gui] = defaults[gui] node = xmlCreateChild(settingsXML, nodeName) xmlNodeSetValue(node, tostring(settingsTable[gui])) if node then xmlSaveFile(settingsXML) end end end inputSettings ( settingsTable ) doActions() end function getNodeValue ( node, default ) local value = xmlNodeGetValue ( node ) if ( value ) then return value else xmlNodeSetValue ( node, tostring(default) ) end xmlSaveFile ( settingsXML ) end function createSettingsXML() local xml = xmlCreateFile ( "settings.xml", "settings" ) for gui,nodeName in pairs(xmlVariants) do local node = xmlCreateChild ( xml, nodeName ) if not node then node = xmlCreateChild ( xml, nodeName ) xmlNodeSetValue ( node, tostring(defaults[gui]) ) end end xmlSaveFile ( xml ) xmlUnloadFile ( xml ) if settingsXML then xmlUnloadFile ( settingsXML ) end settingsXML = xmlLoadFile ( "settings.xml" ) end function inputSettings ( settingsTable ) for gui,value in pairs(settingsTable) do if dialog[gui] then dialog[gui]:setValue(value) if nodeTypes[gui] == "progress" then if optionsActions[gui] then optionsActions[gui](value) end end end end optionsSettings = settingsTable end function dumpSettings() --this does the reverse of input settings. Dumps the current GUI into a table, and saves it to XML. for gui,nodeName in pairs(xmlVariants) do local value = dialog[gui]:getValue() optionsSettings[gui] = value --save to xml local node = xmlFindChild ( settingsXML, nodeName, 0 ) if not node then node = xmlCreateChild ( settingsXML, nodeName ) end xmlNodeSetValue ( node, tostring(value) ) end end function restoreDefaults() for gui,value in pairs(defaults) do dialog[gui]:setValue(value) end end