GE Lua Documentation

Press F to search!

buildOptionHelpers

Definition


-- @/lua/ge/extensions/core/settings/graphic.lua:137

local function buildOptionHelpers()
  local o = {}

  -- Settings GraphicDisplayModes
  o.GraphicDisplayModes = {
    displayMode = "Window",
    get = function ()
      return o.GraphicDisplayModes.displayMode
    end,
    set = function ( value )
      o.GraphicDisplayModes.displayMode = value
    end,
    getModes = function()
      return {keys={"Borderless", "Fullscreen", "Window"},
      values={"ui.options.graphics.displayMode.borderless", "ui.options.graphics.displayMode.fullScreen", "ui.options.graphics.displayMode.window"}}
    end,
    isFullscreen = function()
      return o.GraphicDisplayModes.displayMode == "Fullscreen"
    end,
    isWindow = function()
      return o.GraphicDisplayModes.displayMode == "Window"
    end,
    isBorderless = function()
      return o.GraphicDisplayModes.displayMode == "Borderless"
    end,
    sanitize = function(shouldLog)
      local current = o.GraphicDisplayModes.get()
      local modes = o.GraphicDisplayModes.getModes()
      for _,v in ipairs(modes.keys) do
        if current == v then
          if shouldLog then log('D', 'graphic',"Sanitizing display mode - "..tostring(current)..": Passed.") end
          return
        end
      end
      if shouldLog then log('D', 'graphic',"Sanitizing display mode - "..tostring(current)..": Failed. Patching to display mode 'Window'") end
      o.GraphicDisplayModes.set('Window')
    end
  }

  -- Settings GraphicResolutions
  o.GraphicDisplayResolutions = {
    width = 0,
    height = 0,
    SelectHighestForDisplay = function (displayName)
      local displayResolution = GFXDevice.getDisplayDesktopResolution(displayName:gsub("/","\\"))
      o.GraphicDisplayResolutions.width = displayResolution.width or 1280
      o.GraphicDisplayResolutions.height = displayResolution.height or 720
    end,
    getWidthHeight = function ()
      if o.GraphicDisplayResolutions.width == 0 or o.GraphicDisplayResolutions.height == 0 then
        o.GraphicDisplayResolutions.get()
      end
      return o.GraphicDisplayResolutions.width, o.GraphicDisplayResolutions.height
    end,
    get = function ()
      if o.GraphicDisplayResolutions.width == 0 or o.GraphicDisplayResolutions.height == 0 then
        local videoMode = GFXDevice.getDesktopMode()
        o.GraphicDisplayResolutions.width = videoMode.width or 1280
        o.GraphicDisplayResolutions.height = videoMode.height or 720
      end
      return o.GraphicDisplayResolutions.width .. ' ' .. o.GraphicDisplayResolutions.height
    end,
    set = function ( value )
      o.GraphicDisplayResolutions.width, o.GraphicDisplayResolutions.height = value:match(' *(%d*) +(%d*)')
      o.GraphicDisplayResolutions.width = tonumber(o.GraphicDisplayResolutions.width) or 1280
      o.GraphicDisplayResolutions.height = tonumber(o.GraphicDisplayResolutions.height) or 720
    end,
    getModes = function()
      local keys = {}
      local values = {}
      local addedRes = {}

      local getKey = function(vm)
        return vm.width ..' '.. vm.height
      end

      local getValue = function(vm)
        return vm.width..' x '..vm.height..' '..getAspectRatio(vm.width, vm.height)
      end

      local videoModeList = GFXDevice.getDisplayVideoModes(o.GraphicDisplayDriver.get():gsub("/","\\"))
      table.sort(videoModeList, function(a, b)
                                if a.width == b.width then
                                  return a.height > b.height
                                end
                                return a.width > b.width
                              end
                              )

      for k, vm in ipairs(videoModeList) do
        local key = getKey(vm)
        if addedRes[key] == nil and vm.height > 400 then
          addedRes[key] = 1
          table.insert(keys, key)
          table.insert(values, getValue(vm) )
        end
      end
      return {keys=keys, values=values}
    end,
    sanitize = function(shouldLog)
      local current = o.GraphicDisplayResolutions.get()
      local displayMode = o.GraphicDisplayModes.get()
      if displayMode == 'Window' then
        if shouldLog then log('D', 'graphic',"Sanitizing display resolution for Window mode - "..tostring(current)..": Passed.") end
        return
      end
      local modes = o.GraphicDisplayResolutions.getModes()
      for _,v in ipairs(modes.keys) do
        if current == v then
          if shouldLog then log('D', 'graphic',"Sanitizing display resolution - "..tostring(current)..": Passed.") end
          return
        end
      end
      local canvas = scenetree.findObject("Canvas")
      local desktopMode = GFXDevice.getDesktopMode() or {width = 1280, height = 720}
      local newMode = tostring(desktopMode.width)..' '..tostring(desktopMode.height)
      if shouldLog then log('D', 'graphic',"Sanitizing display resolution - "..tostring(current)..": Failed. Patching to "..newMode) end
      o.GraphicDisplayResolutions.set(newMode)
    end,
    init = function ( value )
      o.GraphicDisplayResolutions.width, o.GraphicDisplayResolutions.height = value:match(' *(%d*) +(%d*)')
      o.GraphicDisplayResolutions.width = tonumber(o.GraphicDisplayResolutions.width) or 1280
      o.GraphicDisplayResolutions.height = tonumber(o.GraphicDisplayResolutions.height) or 720
    end,
  }

  -- Settings GraphicDisplayRefreshRates
  o.GraphicDisplayRefreshRates = {
    hertz = 0,
    get = function ()
      if o.GraphicDisplayRefreshRates.hertz == 0 then
        local refreshRates = o.GraphicDisplayRefreshRates.getModes()
        local found = false
        for _,v in ipairs(refreshRates.keys) do
          if o.GraphicDisplayRefreshRates.hertz == v then
            found = true
            break
          end
        end
        if not found then
          local desktopRes = getDesktopVideoMode()
          o.GraphicDisplayRefreshRates.hertz = refreshRates.keys[1] or desktopRes.refreshRate or 60
        end
      end
      return o.GraphicDisplayRefreshRates.hertz
    end,
    set = function ( value )
      local displayMode = o.GraphicDisplayModes.get()
      if displayMode == 'Window' then return end
      if value then
        o.GraphicDisplayRefreshRates.hertz = tonumber(value)
      end
    end,
    getModes = function()
      local keys = {}
      local values = {}
      local addedRes = {}

      local resolutionWidth, resolutionHeight = o.GraphicDisplayResolutions.getWidthHeight()
      local videoModeList = GFXDevice.getDisplayVideoModes(o.GraphicDisplayDriver.get():gsub("/","\\"))
      for k, vm in ipairs(videoModeList) do
        if vm.width == resolutionWidth and vm.height == resolutionHeight then
          local key = vm.refreshRate
          if addedRes[key] == nil and vm.height > 400 then
            addedRes[key] = 1
            table.insert(keys, key)
          end
        end
      end
      table.sort(keys, function(a, b) return a > b end)
      for i=1,#keys do
        table.insert(values, keys[i]..'Hz')
      end
      return {keys=keys, values=values}
    end,
    sanitize = function(shouldLog)
      local current = o.GraphicDisplayRefreshRates.get()
      local displayMode = o.GraphicDisplayModes.get()
      if displayMode == 'Window' then return end
      local modes = o.GraphicDisplayRefreshRates.getModes()
      for _,v in ipairs(modes.keys) do
        if current == v then
          if shouldLog then log('D', 'graphic', "Sanitizing refresh rate - "..tostring(current)..": Passed.") end
          return
        end
      end
      if shouldLog then log('D', 'graphic',"Sanitizing refresh rate - "..tostring(current)..": Failed. Patching to "..tostring(modes.keys[1]).." hertz") end
      o.GraphicDisplayRefreshRates.set(modes.keys[1])
    end
  }

  -- SettingsGraphicDisplayDriver
  o.GraphicDisplayDriver = {
    adapter = nil,
    get = function ()
      if not o.GraphicDisplayDriver.adapter then
        local adapters = GFXInit.getAdapters()
        o.GraphicDisplayDriver.adapter = adapters[1]
      end

      return o.GraphicDisplayDriver.adapter.output:gsub("\\","/")
    end,
    set = function ( value )
      value = value and value:gsub("/","\\") or ""
      local adapters = GFXInit.getAdapters()
      for i, a in ipairs(adapters) do
        if a.output == value then
          o.GraphicDisplayDriver.adapter = a
          return
        end
      end
    end,
    getModes = function()
      local keys = {}
      local values = {}
      local currentGPU = getGPU()
      local currentGFX = getGFX()
      local adapters = GFXInit.getAdapters()
      for k, a in ipairs(adapters) do
        if a.gpu == currentGPU and a.gfx == currentGFX then
          a.output = a.output:gsub("\\","/")
          table.insert(keys, a.output)
          table.insert(values, a.monitor)
        end
      end
      return {keys=keys, values=values}
    end,
    sanitize = function(shouldLog)
      local current = o.GraphicDisplayDriver.get()
      local modes = o.GraphicDisplayDriver.getModes()
      for _,v in pairs(modes.keys) do
        if current == v then
          if shouldLog then log('D', 'graphic',"Sanitizing display - "..tostring(current)..": Passed.") end
          return
        end
      end
      if shouldLog then log('D', 'graphic',"Sanitizing display - "..tostring(current)..": Failed. Patching to display '"..tostring(modes.keys[1]).."'") end
      o.GraphicDisplayDriver.adapter = o.GraphicDisplayDriver.set(modes.keys[1])
    end
  }

  o.GraphicGPU = {
    get = function ()
      return getGPU()
    end,
    set = function ( value )
      local currentGPU = getGPU()
      TorqueScriptLua.setVar( '$pref::Video::gpu', value )
      local newGPU = getGPU()

      if currentGPU ~= newGPU then
        local adapters = GFXInit.getAdapters()
        for k, a in ipairs(adapters) do
          if a.gpu == newGPU then
            a.output = a.output:gsub("/","\\")
            GFXDevice.setDisplayDevice(newGPU)
            return
          end
        end
        openNeedRestartDialog("GraphicGPU")
      end
    end,
    getModes = function()
      local keys = {}
      local values = {}
      local gpus = {}
      local adapters = GFXInit.getAdapters()
      for k, a in ipairs(adapters) do
        if not gpus[a.gpu] then
          table.insert(keys, a.gpu)
          table.insert(values, a.gpu)
          gpus[a.gpu] = true
        end
      end
      return {keys=keys, values=values}
    end
  }

  o.WindowPlacement = {
    placement = "",
    get = function ()
      if o.WindowPlacement.placement == "" then
        local canvas = scenetree.findObject("Canvas")
        o.WindowPlacement.placement =  canvas and canvas:getPlacement() or ""
      end
      return o.WindowPlacement.placement
    end,
    set = function ( value )
      o.WindowPlacement.placement = value
      updateDisplayInfoWindowRegion()
    end,
    init = function ( value )
      o.WindowPlacement.placement = value
    end,
  }

  o.uiUpscaling = {
    get = function()
      return CEF_UI_maxSizeHeight
    end,

    set = function(value)
      CEF_UI_maxSizeHeight = value
      if value ~= TorqueScriptLua.getVar('$CEF_UI::maxSizeHeight') then
        TorqueScriptLua.setVar('$CEF_UI::maxSizeHeight', value)
      end
    end,
    getModes = function()
      return {keys={'1440', '1080', '720', '0'}, values={'2560 x 1440', '1920 x 1080', '1280 x 720', 'Disabled'}}
    end
  }

  o.vulkanEnabled = {
    get = function ()
      return Engine.getVulkanEnabled()
    end,
    set = function ( value )
      Engine.setVulkanEnabled(value)
    end
  }

  -- SettingsGraphicSync
  o.vsync = {
    get = function ()
      local v = tonumber( TorqueScriptLua.getVar('$video::vsync') )
      return v == true or (type(v)=="number" and v > 0)
    end,
    set = function ( value )
      local boolValue = value == true or (type(value)=="number" and value > 0)
      TorqueScriptLua.setVar( '$video::vsync', boolValue )
    end,
    getModes = function()
      return {keys={false, true}, values={'Off', 'On'}}
    end
  }

  o.GraphicAntialiasType = {
    get = function ()
      local value = settings.getValue('GraphicAntialiasType')
      -- log('I','','get GraphicAntialiasType = '..tostring(value))
      return value
    end,
    set = function ( value )
      local enabled = o.GraphicAntialias.get();
      if enabled == 0 then return end

      local smaaPostEffect = scenetree.findObject("SMAA_PostEffect")
      local fxaaPostEffect = scenetree.findObject("FXAA_PostEffect")
      if value == "fxaa" then
        if smaaPostEffect then smaaPostEffect:disable() end
        if fxaaPostEffect then fxaaPostEffect:enable() end
      elseif value == "smaa" then
        if fxaaPostEffect then fxaaPostEffect:disable() end
        if smaaPostEffect then smaaPostEffect:enable() end
      end
      settings.setValue('GraphicAntialiasType', value)
    end,
    getModes = function ()
      return {keys={'smaa', 'fxaa'}, values={'SMAA', 'FXAA'}}
    end
  }

  -- SettingsGraphicAntialias
  o.GraphicAntialias = {
    get = function ()
      return settings.getValue('GraphicAntialias')
    end,
    set = function ( value )
      local SMAA_PostEffect = scenetree.findObject("SMAA_PostEffect")
      if not SMAA_PostEffect then return end
      local FXAA_PostEffect = scenetree.findObject("FXAA_PostEffect")
      if not FXAA_PostEffect then return end
      if tonumber(value) == 0 then
        SMAA_PostEffect:disable()
        FXAA_PostEffect:disable()
      else
        local antialiasType = settings.getValue('GraphicAntialiasType')
        if antialiasType == 'fxaa' then
          FXAA_PostEffect:enable()
        else
          SMAA_PostEffect:enable()
        end
      end
      settings.setValue('GraphicAntialias', value)
    end,
    getModes = function()
      return {keys={"0", "1", "2", "4"}, values={"Off", "x1", "x2", "x4"}}
    end
  }

  -- SettingsGraphicAnisotropic
  o.GraphicAnisotropic = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::Video::defaultAnisotropy' ) )
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::Video::defaultAnisotropy', value )
    end,
    getModes = function()
      return {keys={"0", "4", "8", "16"}, values={"Off", "x4", "x8", "x16"}}
    end
  }

  -- SettingsGraphicOverallQuality
  o.GraphicOverallQuality = {
    presetKeys = {},
    qualityLevel = '3',
    get = function (value)
      return o.GraphicOverallQuality.qualityLevel
    end,
    set = function (value)
      -- log('I','graphic',' setting GraphicOverallQuality = '..tostring(value))
      if type(value) == 'string' and tonumber(value) then
        value = tonumber(value)
      end
      if type(value) == 'number' then
        local upgrade_old_id_to_name = {'Custom', 'Lowest', 'Low', 'Normal', 'High', 'Ultra'}
        value = upgrade_old_id_to_name[clamp(value + 1, 1, #upgrade_old_id_to_name)]
      end

      o.GraphicOverallQuality.qualityLevel = tostring(value)
      local levelData = overallQualityPresets[value]
      -- log('I','','Overall quality to be applied is '..value..' : '..dumps(levelData))
      for k,v in pairs(levelData) do
        o[k].set(v)
      end
    end,
    getModes = function()
      return {keys={'Custom', 'Lowest', 'Low', 'SteamDeck', 'Normal', 'High', 'Ultra'}, values={'ui.options.graphics.Custom', 'ui.options.graphics.Lowest', 'ui.options.graphics.Low', 'ui.options.graphics.SteamDeck', 'ui.options.graphics.Normal', 'ui.options.graphics.High', 'ui.options.graphics.Ultra'}}
    end,
    init = function ()
      local temp = {}
      for index, group in pairs(overallQualityPresets) do
        for key, presetValue in pairs(group) do
          temp[key] = true
        end
      end
      presetKeys = {}
      for k,v in pairs(temp) do
        table.insert(presetKeys, k)
      end
      -- log('I','','building preset keys: '..dumps(presetKeys))
    end,
    onSettingsChanged = function ()
      -- log('I','','onSettingsChanged called.....')
      local matchedGroupIndex = nil
      for index, group in pairs(overallQualityPresets) do
        -- log('I','','  Checking group: '..tostring(index))
        local matchFound = true
        for _, presetKey in ipairs(presetKeys) do
          local current = o[presetKey].get()
          local presetValue = group[presetKey]
          -- log('I','','      Key: '..presetKey..':  preset = '..tostring(presetValue)..'  current = '..tostring(current))
          if tostring(presetValue) ~= tostring(current) then
            matchFound = false
            break
          end
        end
        if matchFound then
          matchedGroupIndex = index
        end
        -- log('I','','  ---------------- End of: '..index..' match found = '..tostring(matchFound)..'---------------------------')
      end
      -- log('I','','Matched Group Index: '..tostring(matchedGroupIndex))
      if matchedGroupIndex == nil then
        -- log('I','','                              Setting quality to Custom')
        o.GraphicOverallQuality.set(0) -- custom
        return
      end
    end
  }

  -- SettingsGraphicMeshQuality
  o.GraphicMeshQuality = {
    qualityLevel = "Normal",

    get = function ()
      return o.GraphicMeshQuality.qualityLevel
    end,

    set = function ( value )
      if type(value) == 'string' and tonumber(value) then
        value = tonumber(value)
      end
      if type(value) == 'number' then
        local upgrade_old_id_to_name = {'Lowest', 'Low', 'Normal', 'High', 'Ultra'}
        value = upgrade_old_id_to_name[clamp(value + 1, 1, #upgrade_old_id_to_name)]
      end

      meshQualityGroup:applyLevel(value)
      o.GraphicMeshQuality.qualityLevel = value
    end,

    getModes = function()
      return {keys={'Ultra', 'High', 'Normal', 'Low', 'Lowest'}, values={'ui.options.graphics.Ultra', 'ui.options.graphics.High', 'ui.options.graphics.Normal', 'ui.options.graphics.Low', 'ui.options.graphics.Lowest'}}
    end
  }

  -- SettingsGraphicTextureQuality
  o.GraphicTextureQuality = {
    qualityLevel = "Normal",

    get = function ()
      return o.GraphicTextureQuality.qualityLevel
    end,

    set = function ( value )
      if type(value) == 'string' and tonumber(value) then
        value = tonumber(value)
      end
      if type(value) == 'number' then
        local upgrade_old_id_to_name = {'Lowest', 'Low', 'Normal', 'High'}
        value = upgrade_old_id_to_name[clamp(value + 1, 1, #upgrade_old_id_to_name)]
      end

      textureQualityGroup:applyLevel(value)
      o.GraphicTextureQuality.qualityLevel = value
    end,

    getModes = function()
      return {keys={'High', 'Normal', 'Low', 'Lowest'}, values={'ui.options.graphics.High', 'ui.options.graphics.Normal', 'ui.options.graphics.Low', 'ui.options.graphics.Lowest'}}
    end
  }

  -- SettingsGraphicLightingQuality
  o.GraphicLightingQuality = {
    qualityLevel = "High",

    get = function ()
      return o.GraphicLightingQuality.qualityLevel
    end,

    set = function ( value )
      if type(value) == 'string' and tonumber(value) then
        value = tonumber(value)
      end
      if type(value) == 'number' then
        local upgrade_old_id_to_name = {'Lowest', 'Low', 'High', 'Ultra'}
        value = upgrade_old_id_to_name[clamp(value + 1, 1, #upgrade_old_id_to_name)]
      end

      lightingQualityGroup:applyLevel(value)
      o.GraphicLightingQuality.qualityLevel = value
    end,

    getModes = function()
      return {keys={'Ultra', 'High', 'Low', 'Lowest'}, values={'ui.options.graphics.Ultra', 'ui.options.graphics.High', 'ui.options.graphics.Low', 'ui.options.graphics.Lowest'}}
    end
  }

  -- SettingsGraphicShadowQuality
  o.GraphicShadowsQuality = {
    qualityLevel = "Normal",

    get = function ()
      return o.GraphicShadowsQuality.qualityLevel
    end,

    set = function ( value )
      if type(value) == 'string' and tonumber(value) then
        value = tonumber(value)
      end
      if type(value) == 'number' then
        local upgrade_old_id_to_name = {'Lowest', 'Low', 'Normal', 'High'}
        value = upgrade_old_id_to_name[clamp(value + 1, 1, #upgrade_old_id_to_name)]
      end

      shadowsQualityGroup:applyLevel(value)
      o.GraphicShadowsQuality.qualityLevel = value
    end,

    getModes = function()
      return {keys={'High', 'Normal', 'Low', 'Lowest'}, values={'ui.options.graphics.High', 'ui.options.graphics.Normal', 'ui.options.graphics.Low', 'ui.options.graphics.Lowest'}}
    end
  }

  -- SettingsGraphicShaderQuality
  o.GraphicShaderQuality = {
    qualityLevel = "High",

    get = function ()
      return o.GraphicShaderQuality.qualityLevel
    end,

    set = function ( value )
      if type(value) == 'string' and tonumber(value) then
        value = tonumber(value)
      end
      if type(value) == 'number' then
        local upgrade_old_id_to_name = {'Low', 'High'}
        value = upgrade_old_id_to_name[clamp(value + 1, 1, #upgrade_old_id_to_name)]
      end
      shaderQualityGroup:applyLevel(value)
      o.GraphicShaderQuality.qualityLevel = value
    end,

    getModes = function()
      return {keys={'High', 'Low'}, values={'ui.options.graphics.High', 'ui.options.graphics.Low'}}
    end
  }

  -- GraphicDynReflectionEnabled
  o.GraphicDynReflectionEnabled = {
    get = function ()
      return TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicReflection::enabled' ) ~= "0"
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicReflection::enabled', value )
    end
  }

  -- GraphicDynReflectionFacesPerupdate
  o.GraphicDynReflectionFacesPerupdate = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicReflection::facesPerUpdate' ) )
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicReflection::facesPerUpdate', value )
    end
  }

  -- GraphicDynReflectionDetail
  o.GraphicDynReflectionDetail = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicReflection::detail' ) )
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicReflection::detail', value )
    end
  }

  -- GraphicDynReflectionDistance
  o.GraphicDynReflectionDistance = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicReflection::distance' ) )
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicReflection::distance', value )
    end
  }

  -- GraphicDynReflectionTexsize
  o.GraphicDynReflectionTexsize = {
    get = function ()
      local value = math.log(tonumber( TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicReflection::textureSize' ) ) )/math.log( 2 )
      return value - 7
    end,
    set = function ( value )
      value = math.pow(2, value + 7)
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicReflection::textureSize', value )
    end
  }

  -- GraphicDynMirrorsEnabled
  o.GraphicDynMirrorsEnabled = {
    get = function ()
      return TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicMirrors::enabled' ) ~= "0"
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicMirrors::enabled', value )
    end
  }

  -- GraphicDynMirrorsDetail
  o.GraphicDynMirrorsDetail = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicMirrors::detail' ) )
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicMirrors::detail', value )
    end
  }

  -- GraphicDynMirrorsDistance
  o.GraphicDynMirrorsDistance = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicMirrors::distance' ) )
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicMirrors::distance', value )
    end
  }

  -- GraphicDynMirrorsTexsize
  o.GraphicDynMirrorsTexsize = {
    get = function ()
      local value = math.log(tonumber( TorqueScriptLua.getVar( '$pref::BeamNGVehicle::dynamicMirrors::textureSize' ) ) )/math.log( 2 )
      return value - 7
    end,
    set = function ( value )
      value = math.pow(2, value + 7)
      TorqueScriptLua.setVar( '$pref::BeamNGVehicle::dynamicMirrors::textureSize', value )
    end
  }

  -- SettingsPostFXDOFGeneralEnabled
  o.PostFXDOFGeneralEnabled = {
    get = function ()
      local DOFPostEffect = scenetree.findObject("DOFPostEffect")
      if not DOFPostEffect then return end
      return DOFPostEffect:isEnabled() ~= false
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$DOFPostFx::Enable', value )
      local DOFPostEffect = scenetree.findObject("DOFPostEffect")
      if not DOFPostEffect then return end
      if value then
        DOFPostEffect:enable()
      else
        DOFPostEffect:disable()
      end
    end
  }

  -- SettingsPostFXBloomGeneralEnabled
  o.PostFXBloomGeneralEnabled = {
    get = function ()
      return settings.getValue("PostFXBloomGeneralEnabled")
    end,
    set = function ( value )
      settings.setValue("PostFXBloomGeneralEnabled", value)
      local postFX = scenetree.findObject("PostEffectBloomObject")
      if not postFX then return end
      if value then
        postFX:enable()
      else
        postFX:disable()
      end
    end
  }

  -- SettingsPostFXLightRaysEnabled
  o.PostFXLightRaysEnabled = {
    get = function ()
      local LightRayPostFX = scenetree.findObject("LightRayPostFX")
      if not LightRayPostFX then return end
      return LightRayPostFX:isEnabled() ~= false
    end,
    set = function ( value )
      --print("*************LightRayPostFX 2 set")
      local LightRayPostFX = scenetree.findObject("LightRayPostFX")
      if not LightRayPostFX then return end
      TorqueScriptLua.setVar( '$LightRayPostFX::Enable', value )
      if value then
        LightRayPostFX:enable()
      else
        LightRayPostFX:disable()
      end
    end
  }

  -- SettingsPostFXMotionBlurEnabled
  o.PostFXMotionBlurEnabled = {
    get = function ()
      return settings.getValue("PostFXMotionBlurEnabled")
    end,
    set = function ( value )
      settings.setValue("PostFXMotionBlurEnabled", value)
      local fx = scenetree.findObject("PostFxMotionBlur")
      if not fx then return end
      if value then
        fx:enable()
      else
        fx:disable()
      end
    end
  }

  -- SettingsPostFXMotionBlurStrength
  o.PostFXMotionBlurStrength = {
    get = function ()
      return settings.getValue("PostFXMotionBlurStrength")
    end,
    set = function ( value )
      settings.setValue("PostFXMotionBlurStrength", value)
      if scenetree.PostFxMotionBlur then
        scenetree.PostFxMotionBlur.strength = value
      end
    end
  }

  -- PostFXMotionBlurPlayerVehicle
  o.PostFXMotionBlurPlayerVehicle = {
    get = function ()
      return settings.getValue("PostFXMotionBlurPlayerVehicle")
    end,
    set = function ( value )
      settings.setValue("PostFXMotionBlurPlayerVehicle", value)
      BeamNGVehicle.motionBlurPlayerVehiclesEnabled = value
    end
  }

  -- SettingsPostFXSSAOGeneralEnabled
  o.PostFXSSAOGeneralEnabled = {
    get = function ()
      local SSAOPostFx = scenetree.findObject("SSAOPostFx")
      if not SSAOPostFx then return end
      return SSAOPostFx:isEnabled() ~= false
    end,
    set = function ( value )
      --print("********PostFXSSAOGeneralEnabled 2 set") --not tested
      TorqueScriptLua.setVar( '$SSAOPostFx::Enable', value )
      local SSAOPostFx = scenetree.findObject("SSAOPostFx")
      if not SSAOPostFx then return end
      if value then
        SSAOPostFx:enable()
      else
        SSAOPostFx:disable()
      end
    end
  }

  -- SettingsPostFXSSAOGeneralQuality
  o.PostFXSSAOGeneralQuality = {
    get = function ()
      local value = settings.getValue('PostFXSSAOGeneralQuality')
      -- log('I','','get PostFXSSAOGeneralQuality = '..tostring(value))
      return value
    end,
    set = function ( value )
      local enabled = o.PostFXSSAOGeneralEnabled.get();
      if enabled == 0 then return end
      local ssao = scenetree.findObject("SSAOPostFx")
      if not ssao then return end
      if value == "High" then
        scenetree.SSAOPostFx:setSamples(64)
      elseif value == "Normal" then
        scenetree.SSAOPostFx:setSamples(16)
      end
      settings.setValue('PostFXSSAOGeneralQuality', value)
    end,
    getModes = function ()
      return {keys={'High', 'Normal'}, values={'ui.options.graphics.High', 'ui.options.graphics.Normal'}}
    end
  }

  -- SettingsGraphicGrassDensity
  o.GraphicGrassDensity = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::GroundCover::densityScale' ))
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::GroundCover::densityScale', value )
    end
  }

  -- SettingsGraphicMaxDecalCount
  o.GraphicMaxDecalCount = {
    get = function ()
      return tonumber( TorqueScriptLua.getVar( '$pref::TS::maxDecalCount' ))
    end,
    set = function ( value )
      TorqueScriptLua.setVar( '$pref::TS::maxDecalCount', value )
    end
  }

  -- SettingsGraphicDisableShadows
  o.GraphicDisableShadows = {
    get = function ()
      local levelStr = getConsoleVariable( '$pref::Shadows::disable' )
      if levelStr == "" then
        levelStr = "0"
      end
      return (levelStr)
    end,
    set = function ( value )
      value = tostring(value)
      setConsoleVariable( '$pref::Shadows::disable', value)
    end,
    getModes = function()
      return {keys={'2', '1', '0'}, values={'ui.options.graphics.shadows.none', 'ui.options.graphics.shadows.partial', 'ui.options.graphics.shadows.all'}}
    end
  }

    -- SkipGenerateLicencePlate
    o.SkipGenerateLicencePlate = {
      get = function()
        return settings.getValue("SkipGenerateLicencePlate")
      end,
      set = function( value )
        settings.setValue("SkipGenerateLicencePlate",value)
      end
    }

  graphicsOptions = o

  return o
end

Callers

@/lua/ge/extensions/core/settings/settings.lua
  extensions.load({"core_settings_graphic","core_settings_audio","core_settings_rally"})
  tableMerge(options, core_settings_graphic.buildOptionHelpers())
  tableMerge(options, core_settings_audio.buildOptionHelpers())
  tableMerge(options, core_settings_graphic.buildOptionHelpers())
  tableMerge(options, core_settings_audio.buildOptionHelpers())
  tableMerge(options, core_settings_rally.buildOptionHelpers())
  tableMerge(options, core_settings_audio.buildOptionHelpers())
  tableMerge(options, core_settings_rally.buildOptionHelpers())
  -- add C++ propagation wherever possible
@/lua/ge/extensions/core/settings/audio.lua
local audioOptions = nil
local function buildOptionHelpers()
  local o = {}
@/lua/ge/extensions/core/settings/rally.lua

local function buildOptionHelpers()
  local o = {}
  if not rallyOptions then
    buildOptionHelpers()
  end