From f9ce673501b0d22ced8d49cfb614bb5fe3ccecef Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Thu, 5 Sep 2024 07:00:14 +0100 Subject: [PATCH] script: Add beginnings of config + script system Port our known display configs to this system, and expose some basic features such as logging and printing convars. Very early work. See README.md in the scripts folder for more info. --- default_scripts_install.sh | 6 + meson.build | 3 + scripts/00-gamescope/common/inspect.lua | 359 + scripts/00-gamescope/common/modegen.lua | 36 + scripts/00-gamescope/common/util.lua | 19 + .../displays/deckhd.steamdeck.deckhd-lcd.lua | 50 + .../displays/valve.steamdeck.lcd.lua | 73 + .../displays/valve.steamdeck.oled.lua | 100 + scripts/README.md | 75 + src/Backends/DRMBackend.cpp | 237 +- src/Script/Script.cpp | 245 + src/Script/Script.h | 208 + src/Utils/Dict.h | 23 + src/convar.cpp | 19 + src/convar.h | 81 +- src/gamescope_shared.h | 9 - src/log.cpp | 17 +- src/log.hpp | 3 +- src/main.cpp | 7 + src/meson.build | 10 +- src/modegen.cpp | 118 +- src/modegen.hpp | 2 +- src/reshade_effect_manager.cpp | 18 +- src/steamcompmgr.cpp | 5 + src/wlserver.cpp | 7 +- thirdparty/sol/config.hpp | 55 + thirdparty/sol/forward.hpp | 1340 + thirdparty/sol/sol.hpp | 29208 ++++++++++++++++ 28 files changed, 32058 insertions(+), 275 deletions(-) create mode 100755 default_scripts_install.sh create mode 100644 scripts/00-gamescope/common/inspect.lua create mode 100644 scripts/00-gamescope/common/modegen.lua create mode 100644 scripts/00-gamescope/common/util.lua create mode 100644 scripts/00-gamescope/displays/deckhd.steamdeck.deckhd-lcd.lua create mode 100644 scripts/00-gamescope/displays/valve.steamdeck.lcd.lua create mode 100644 scripts/00-gamescope/displays/valve.steamdeck.oled.lua create mode 100644 scripts/README.md create mode 100644 src/Script/Script.cpp create mode 100644 src/Script/Script.h create mode 100644 src/Utils/Dict.h create mode 100644 thirdparty/sol/config.hpp create mode 100644 thirdparty/sol/forward.hpp create mode 100644 thirdparty/sol/sol.hpp diff --git a/default_scripts_install.sh b/default_scripts_install.sh new file mode 100755 index 0000000000..11751167e6 --- /dev/null +++ b/default_scripts_install.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +# Remove old Gamescope default configs and add our own. +mkdir -p "${DESTDIR}/${MESON_INSTALL_PREFIX}/share/gamescope" +rm -rf "${DESTDIR}/${MESON_INSTALL_PREFIX}/share/gamescope/scripts" || true +cp -r "${MESON_SOURCE_ROOT}/scripts" "${DESTDIR}/${MESON_INSTALL_PREFIX}/share/gamescope/scripts" diff --git a/meson.build b/meson.build index b562ec3512..24c9c777ef 100644 --- a/meson.build +++ b/meson.build @@ -94,3 +94,6 @@ endif if get_option('enable_gamescope') subdir('src') endif + +# Handle default script/config stuff +meson.add_install_script('default_scripts_install.sh') diff --git a/scripts/00-gamescope/common/inspect.lua b/scripts/00-gamescope/common/inspect.lua new file mode 100644 index 0000000000..774c4c55a1 --- /dev/null +++ b/scripts/00-gamescope/common/inspect.lua @@ -0,0 +1,359 @@ +-- Slightly modified from https://github.com/kikito/inspect.lua +-- MIT license. + +local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table + +inspect = {Options = {}, } + +inspect._VERSION = 'inspect.lua 3.1.0' +inspect._URL = 'http://github.com/kikito/inspect.lua' +inspect._DESCRIPTION = 'human-readable representations of tables' +inspect._LICENSE = [[ + MIT LICENSE + + Copyright (c) 2022 Enrique García Cota + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] +inspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end }) +inspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end }) + +local tostring = tostring +local rep = string.rep +local match = string.match +local char = string.char +local gsub = string.gsub +local fmt = string.format + +local _rawget +if rawget then + _rawget = rawget +else + _rawget = function(t, k) return t[k] end +end + +local function rawpairs(t) + return next, t, nil +end + + + +local function smartQuote(str) + if match(str, '"') and not match(str, "'") then + return "'" .. str .. "'" + end + return '"' .. gsub(str, '"', '\\"') .. '"' +end + + +local shortControlCharEscapes = { + ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", + ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\127"] = "\\127", +} +local longControlCharEscapes = { ["\127"] = "\127" } +for i = 0, 31 do + local ch = char(i) + if not shortControlCharEscapes[ch] then + shortControlCharEscapes[ch] = "\\" .. i + longControlCharEscapes[ch] = fmt("\\%03d", i) + end +end + +local function escape(str) + return (gsub(gsub(gsub(str, "\\", "\\\\"), + "(%c)%f[0-9]", longControlCharEscapes), + "%c", shortControlCharEscapes)) +end + +local luaKeywords = { + ['and'] = true, + ['break'] = true, + ['do'] = true, + ['else'] = true, + ['elseif'] = true, + ['end'] = true, + ['false'] = true, + ['for'] = true, + ['function'] = true, + ['goto'] = true, + ['if'] = true, + ['in'] = true, + ['local'] = true, + ['nil'] = true, + ['not'] = true, + ['or'] = true, + ['repeat'] = true, + ['return'] = true, + ['then'] = true, + ['true'] = true, + ['until'] = true, + ['while'] = true, +} + +local function isIdentifier(str) + return type(str) == "string" and + not not str:match("^[_%a][_%a%d]*$") and + not luaKeywords[str] +end + +local flr = math.floor +local function isSequenceKey(k, sequenceLength) + return type(k) == "number" and + flr(k) == k and + 1 <= (k) and + k <= sequenceLength +end + +local defaultTypeOrders = { + ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, + ['function'] = 5, ['userdata'] = 6, ['thread'] = 7, +} + +local function sortKeys(a, b) + local ta, tb = type(a), type(b) + + + if ta == tb and (ta == 'string' or ta == 'number') then + return (a) < (b) + end + + local dta = defaultTypeOrders[ta] or 100 + local dtb = defaultTypeOrders[tb] or 100 + + + return dta == dtb and ta < tb or dta < dtb +end + +local function getKeys(t) + + local seqLen = 1 + while _rawget(t, seqLen) ~= nil do + seqLen = seqLen + 1 + end + seqLen = seqLen - 1 + + local keys, keysLen = {}, 0 + for k in rawpairs(t) do + if not isSequenceKey(k, seqLen) then + keysLen = keysLen + 1 + keys[keysLen] = k + end + end + table.sort(keys, sortKeys) + return keys, keysLen, seqLen +end + +local function countCycles(x, cycles) + if type(x) == "table" then + if cycles[x] then + cycles[x] = cycles[x] + 1 + else + cycles[x] = 1 + for k, v in rawpairs(x) do + countCycles(k, cycles) + countCycles(v, cycles) + end + countCycles(getmetatable(x), cycles) + end + end +end + +local function makePath(path, a, b) + local newPath = {} + local len = #path + for i = 1, len do newPath[i] = path[i] end + + newPath[len + 1] = a + newPath[len + 2] = b + + return newPath +end + + +local function processRecursive(process, + item, + path, + visited) + if item == nil then return nil end + if visited[item] then return visited[item] end + + local processed = process(item, path) + if type(processed) == "table" then + local processedCopy = {} + visited[item] = processedCopy + local processedKey + + for k, v in rawpairs(processed) do + processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) + if processedKey ~= nil then + processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited) + end + end + + local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited) + if type(mt) ~= 'table' then mt = nil end + setmetatable(processedCopy, mt) + processed = processedCopy + end + return processed +end + +local function puts(buf, str) + buf.n = buf.n + 1 + buf[buf.n] = str +end + + + +local Inspector = {} + + + + + + + + + + +local Inspector_mt = { __index = Inspector } + +local function tabify(inspector) + puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level)) +end + +function Inspector:getId(v) + local id = self.ids[v] + local ids = self.ids + if not id then + local tv = type(v) + id = (ids[tv] or 0) + 1 + ids[v], ids[tv] = id, id + end + return tostring(id) +end + +function Inspector:putValue(v) + local buf = self.buf + local tv = type(v) + if tv == 'string' then + puts(buf, smartQuote(escape(v))) + elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or + tv == 'cdata' or tv == 'ctype' then + puts(buf, tostring(v)) + elseif tv == 'table' and not self.ids[v] then + local t = v + + if t == inspect.KEY or t == inspect.METATABLE then + puts(buf, tostring(t)) + elseif self.level >= self.depth then + puts(buf, '{...}') + else + if self.cycles[t] > 1 then puts(buf, fmt('<%d>', self:getId(t))) end + + local keys, keysLen, seqLen = getKeys(t) + + puts(buf, '{') + self.level = self.level + 1 + + for i = 1, seqLen + keysLen do + if i > 1 then puts(buf, ',') end + if i <= seqLen then + puts(buf, ' ') + self:putValue(t[i]) + else + local k = keys[i - seqLen] + tabify(self) + if isIdentifier(k) then + puts(buf, k) + else + puts(buf, "[") + self:putValue(k) + puts(buf, "]") + end + puts(buf, ' = ') + self:putValue(t[k]) + end + end + + local mt = getmetatable(t) + if type(mt) == 'table' then + if seqLen + keysLen > 0 then puts(buf, ',') end + tabify(self) + puts(buf, ' = ') + self:putValue(mt) + end + + self.level = self.level - 1 + + if keysLen > 0 or type(mt) == 'table' then + tabify(self) + elseif seqLen > 0 then + puts(buf, ' ') + end + + puts(buf, '}') + end + + else + puts(buf, fmt('<%s %d>', tv, self:getId(v))) + end +end + + + + +function inspect.inspect(root, options) + options = options or {} + + local depth = options.depth or (math.huge) + local newline = options.newline or '\n' + local indent = options.indent or ' ' + local process = options.process + + if process then + root = processRecursive(process, root, {}, {}) + end + + local cycles = {} + countCycles(root, cycles) + + local inspector = setmetatable({ + buf = { n = 0 }, + ids = {}, + cycles = cycles, + depth = depth, + level = 0, + newline = newline, + indent = indent, + }, Inspector_mt) + + inspector:putValue(root) + + return table.concat(inspector.buf) +end + +setmetatable(inspect, { + __call = function(_, root, options) + return inspect.inspect(root, options) + end, +}) + +return inspect diff --git a/scripts/00-gamescope/common/modegen.lua b/scripts/00-gamescope/common/modegen.lua new file mode 100644 index 0000000000..90db2ed7aa --- /dev/null +++ b/scripts/00-gamescope/common/modegen.lua @@ -0,0 +1,36 @@ +gamescope.modegen = {} + +gamescope.modegen.adjust_front_porch = function(mode, vfp) + local vsync = mode.vsync_end - mode.vsync_start + local vbp = mode.vtotal - mode.vsync_end + + mode.vsync_start = mode.vdisplay + vfp + mode.vsync_end = mode.vsync_start + vsync + mode.vtotal = mode.vsync_end + vbp +end + +gamescope.modegen.set_h_timings = function(mode, hfp, hsync, hbp) + mode.hsync_start = mode.hdisplay + hfp + mode.hsync_end = mode.hsync_start + hsync + mode.htotal = mode.hsync_end + hbp +end + +gamescope.modegen.set_v_timings = function(mode, vfp, vsync, vbp) + mode.vsync_start = mode.vdisplay + vfp + mode.vsync_end = mode.vsync_start + vsync + mode.vtotal = mode.vsync_end + vbp +end + +gamescope.modegen.set_resolution = function(mode, width, height) + mode.hdisplay = width + mode.vdisplay = height +end + +gamescope.modegen.calc_max_clock = function(mode, refresh) + -- LuaJIT does not have // operator, sad face. + return math.floor( ( ( mode.htotal * mode.vtotal * refresh ) + 999 ) / 1000 ) +end + +gamescope.modegen.calc_vrefresh = function(mode, refresh) + return math.floor( (1000 * mode.clock) / (mode.htotal * mode.vtotal) ) +end diff --git a/scripts/00-gamescope/common/util.lua b/scripts/00-gamescope/common/util.lua new file mode 100644 index 0000000000..98cf66b480 --- /dev/null +++ b/scripts/00-gamescope/common/util.lua @@ -0,0 +1,19 @@ +function zero_index(index) + return index + 1 +end + +function error(text) + gamescope.log(gamescope.log_priority.error, text) +end + +function warn(text) + gamescope.log(gamescope.log_priority.warning, text) +end + +function info(text) + gamescope.log(gamescope.log_priority.info, text) +end + +function debug(text) + gamescope.log(gamescope.log_priority.debug, text) +end diff --git a/scripts/00-gamescope/displays/deckhd.steamdeck.deckhd-lcd.lua b/scripts/00-gamescope/displays/deckhd.steamdeck.deckhd-lcd.lua new file mode 100644 index 0000000000..5d1e3755ce --- /dev/null +++ b/scripts/00-gamescope/displays/deckhd.steamdeck.deckhd-lcd.lua @@ -0,0 +1,50 @@ +gamescope.config.known_displays.steamdeck_deckhd_lcd = { + pretty_name = "Steam Deck DeckHD - Unofficial Screen Replacement", + dynamic_refresh_rates = { + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60 + }, + hdr = { + -- Setup some fallbacks or undocking with HDR + -- for this display. + supported = false, + force_enabled = false, + eotf = gamescope.eotf.gamma22, + max_content_light_level = 400, + max_frame_average_luminance = 400, + min_content_light_level = 0.5 + }, + -- No colorimetry was provided in the original PR, + -- and I have no idea if their BIOS mod/whatever has colorimetry + -- in their edid. + -- Someone that works on this or uses this should go fix that. + dynamic_modegen = function(base_mode, refresh) + debug("Generating mode "..refresh.."Hz for DeckHD") + local mode = base_mode + + -- These are only tuned for 1200x1920. + gamescope.modegen.set_resolution(mode, 1200, 1920) + + -- hfp, hsync, hbp + gamescope.modegen.set_h_timings(mode, 40, 20, 40) + -- vfp, vsync, vbp + gamescope.modegen.set_v_timings(mode, 18, 2, 20) + + mode.clock = gamescope.modegen.calc_max_clock(mode, refresh) + mode.vrefresh = gamescope.modegen.calc_vrefresh(mode) + + --debug(inspect(mode)) + return mode + end, + matches = function(vendor, product, model) + if vendor == "DHD" and model == "DeckHD-1200p" and product == 0x4001 then + debug("[steamdeck_deckhd_lcd] Matched vendor: "..value.vendor.." model: "..value.model.." product:"..value.product) + return 5000 + end + + return -1 + end +} +debug("Registered Steam Deck DeckHD - Unofficial Screen Replacement as a known display") +--debug(inspect(gamescope.config.known_displays.steamdeck_deckhd_lcd)) diff --git a/scripts/00-gamescope/displays/valve.steamdeck.lcd.lua b/scripts/00-gamescope/displays/valve.steamdeck.lcd.lua new file mode 100644 index 0000000000..56923c1e51 --- /dev/null +++ b/scripts/00-gamescope/displays/valve.steamdeck.lcd.lua @@ -0,0 +1,73 @@ +-- TODO: Make a vec2 class so we can alias .x and indices. + +local steamdeck_lcd_colorimetry_spec = { + r = { x = 0.602, y = 0.355 }, + g = { x = 0.340, y = 0.574 }, + b = { x = 0.164, y = 0.121 }, + w = { x = 0.3070, y = 0.3220 } +} + +local steamdeck_lcd_colorimetry_measured = { + r = { x = 0.603, y = 0.349 }, + g = { x = 0.335, y = 0.571 }, + b = { x = 0.163, y = 0.115 }, + w = { x = 0.296, y = 0.307 } +} + +gamescope.config.known_displays.steamdeck_lcd = { + pretty_name = "Steam Deck LCD", + dynamic_refresh_rates = { + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60 + }, + hdr = { + -- Setup some fallbacks or undocking with HDR + -- for this display. + supported = false, + force_enabled = false, + eotf = gamescope.eotf.gamma22, + max_content_light_level = 500, + max_frame_average_luminance = 500, + min_content_light_level = 0.5 + }, + -- Use measured colorimetry instead. + --colorimetry = steamdeck_lcd_colorimetry_spec, + colorimetry = steamdeck_lcd_colorimetry_measured, + dynamic_modegen = function(base_mode, refresh) + debug("Generating mode "..refresh.."Hz for Steam Deck LCD") + local mode = base_mode + + -- These are only tuned for 800x1280. + gamescope.modegen.set_resolution(mode, 800, 1280) + + -- hfp, hsync, hbp + gamescope.modegen.set_h_timings(mode, 40, 4, 40) + -- vfp, vsync, vbp + gamescope.modegen.set_v_timings(mode, 30, 4, 8) + mode.clock = gamescope.modegen.calc_max_clock(mode, refresh) + mode.vrefresh = gamescope.modegen.calc_vrefresh(mode) + + --debug(inspect(mode)) + return mode + end, + matches = function(vendor, product, model) + local lcd_types = { + { vendor = "WLC", model = "ANX7530 U" }, + { vendor = "ANX", model = "ANX7530 U" }, + { vendor = "VLV", model = "ANX7530 U" }, + { vendor = "VLV", model = "Jupiter" }, + } + + for index, value in ipairs(lcd_types) do + if value.vendor == vendor and value.model == model then + debug("[steamdeck_lcd] Matched vendor: "..value.vendor.." model: "..value.model) + return 5000 + end + end + + return -1 + end +} +debug("Registered Steam Deck LCD as a known display") +--debug(inspect(gamescope.config.known_displays.steamdeck_lcd)) diff --git a/scripts/00-gamescope/displays/valve.steamdeck.oled.lua b/scripts/00-gamescope/displays/valve.steamdeck.oled.lua new file mode 100644 index 0000000000..4b6375f2ee --- /dev/null +++ b/scripts/00-gamescope/displays/valve.steamdeck.oled.lua @@ -0,0 +1,100 @@ +local steamdeck_oled_hdr = { + supported = true, + force_enabled = true, + eotf = gamescope.eotf.gamma22, + max_content_light_level = 1000, + max_frame_average_luminance = 800, + min_content_light_level = 0 +} + +local steamdeck_oled_refresh_rates = { + 45, 47, 48, 49, + 50, 51, 53, 55, 56, 59, + 60, 62, 64, 65, 66, 68, + 72, 73, 76, 77, 78, + 80, 81, 82, 84, 85, 86, 87, 88, + 90 +} + +gamescope.config.known_displays.steamdeck_oled_sdc = { + pretty_name = "Steam Deck OLED (SDC)", + hdr = steamdeck_oled_hdr, + dynamic_refresh_rates = steamdeck_oled_refresh_rates, + dynamic_modegen = function(base_mode, refresh) + debug("Generating mode "..refresh.."Hz for Steam Deck OLED (SDC)") + local vfps = { + 1321, 1264, 1209, 1157, 1106, + 1058, 993, 967, 925, 883, 829, 805, 768, 732, 698, + 665, 632, 601, 571, 542, 501, 486, 459, 433, 408, + 383, 360, 337, 314, 292, 271, 250, 230, 210, 191, + 173, 154, 137, 119, 102, 86, 70, 54, 38, 23, + 9 + } + local vfp = vfps[zero_index(refresh - 45)] + if vfp == nil then + warn("Couldn't do refresh "..refresh.." on Steam Deck OLED (SDC)") + return base_mode + end + + local mode = base_mode + + gamescope.modegen.adjust_front_porch(mode, vfp) + mode.vrefresh = gamescope.modegen.calc_vrefresh(mode) + + --debug(inspect(mode)) + return mode + end, + matches = function(vendor, product, model) + if vendor == "VLV" and product == 0x3003 then + debug("[steamdeck_oled_sdc] Matched VLV and product 0x3003") + -- Higher priorty than LCD. + return 5100 + end + + return -1 + end +} +debug("Registered Steam Deck OLED (SDC) as a known display") +--debug(inspect(gamescope.config.known_displays.steamdeck_oled_sdc)) + +gamescope.config.known_displays.steamdeck_oled_boe = { + pretty_name = "Steam Deck OLED (BOE)", + hdr = steamdeck_oled_hdr, + dynamic_refresh_rates = steamdeck_oled_refresh_rates, + dynamic_modegen = function(base_mode, refresh) + debug("Generating mode for "..refresh.." for Steam Deck OLED (BOE)") + + local vfps = { + 1320, 1272, 1216, 1156, 1112, + 1064, 992, 972, 928, 888, 828, 808, 772, 736, 700, + 664, 636, 604, 572, 544, 500, 488, 460, 436, 408, + 384, 360, 336, 316, 292, 272, 252, 228, 212, 192, + 172, 152, 136, 120, 100, 84, 68, 52, 36, 20, + 8 + } + local vfp = vfps[zero_index(refresh - 45)] + if vfp == nil then + warn("Couldn't do refresh "..refresh.." on Steam Deck OLED (BOE)") + return base_mode + end + + local mode = base_mode + + gamescope.modegen.adjust_front_porch(mode, vfp) + mode.vrefresh = gamescope.modegen.calc_vrefresh(mode) + + --debug(inspect(mode)) + return mode + end, + matches = function(vendor, product, model) + if vendor == "VLV" and product == 0x3004 then + debug("[steamdeck_oled_boe] Matched VLV and product 0x3004") + -- Higher priorty than LCD. + return 5100 + end + + return -1 + end +} +debug("Registered Steam Deck OLED (BOE) as a known display") +--debug(inspect(gamescope.config.known_displays.steamdeck_oled_boe)) diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000000..337719b9c4 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,75 @@ +# Gamescope Script/Config Files + +## ⚠️ Health Warning ⚠️ + +Gamescope scripting/configuration is currently experimental and subject to change massively. + +Scripts and configs working between revisions is not guaranteed to work, it should at least not crash... probably. + +## The Basics + +Gamescope uses Lua for it's configuration and scripting system. + +Scripts ending in `.lua` are executed recursively in alphabetical order from the following directories: + - `/usr/share/gamescope` + - `/etc/gamescope` + - `$XDG_CONFIG_DIR/gamescope` + +You can develop easily without overriding your installation by setting `script_use_local_scripts` which will eliminate `/usr/share/gamescope` and `/etc/gamescope` from being read, and instead read from `../config` of where Gamescope is run instead of those. + +When errors are encountered, it will simply output that to the terminal. There is no visual indicator of this currently. + +Things should mostly fail-safe, unless you actually made an egregious mistake in your config like setting the refresh rate to 0 or the colorimetry to all 0, 0 or something. + +# Making modifications as a user + +If you wish to make modifications that will persist as a user, simply make a new `.lua` file in `$XDG_CONFIG_DIR/gamescope` which is usually `$HOME/.config/gamescope` with what you want to change. + +For example, to make the Steam Deck LCD use spec colorimetry instead of the measured colorimetry you could create the following file `~/.config/gamescope/my_deck_lcd_colorimetry.lua` with the following contents: + +```lua +local steamdeck_lcd_colorimetry_spec = { + r = { x = 0.602, y = 0.355 }, + g = { x = 0.340, y = 0.574 }, + b = { x = 0.164, y = 0.121 }, + w = { x = 0.3070, y = 0.3220 } +} + +gamescope.config.known_displays.steamdeck_lcd.colorimetry = steamdeck_lcd_colorimetry_spec +``` + +and it would override that. + +You could also place this in `/etc/gamescope` if you really want it to apply to all users/system-wide, but that would need root privelages. + +# Features + +Being able to set known displays (`gamescope.config.known_displays`) + +The ability to set convars. + +Hooks + +# Examples + +A script that will enable composite debug and force composition on and off every 60 frames. + +```lua +my_counter = 0 + +gamescope.convars.composite_debug.value = 3 + +gamescope.hook("OnPostPaint", function() + my_counter = my_counter + 1 + + if my_counter > 60 then + gamescope.convars.composite_force.value = not gamescope.convars.composite_force.value + my_counter = 0 + warn("Changed composite_force to "..tostring(gamescope.convars.composite_force.value)..".") + end +end) +``` + +# Hot Reloading? + +Coming soon... diff --git a/src/Backends/DRMBackend.cpp b/src/Backends/DRMBackend.cpp index c62635f190..224d76f5d7 100644 --- a/src/Backends/DRMBackend.cpp +++ b/src/Backends/DRMBackend.cpp @@ -1,5 +1,7 @@ // DRM output stuff +#include "Script/Script.h" + #include #include #include @@ -287,7 +289,6 @@ namespace gamescope const char *GetModel() const override { return m_Mutable.szModel; } uint32_t GetPossibleCRTCMask() const { return m_Mutable.uPossibleCRTCMask; } std::span GetValidDynamicRefreshRates() const override { return m_Mutable.ValidDynamicRefreshRates; } - GamescopeKnownDisplays GetKnownDisplayType() const { return m_Mutable.eKnownDisplay; } const displaycolorimetry_t& GetDisplayColorimetry() const { return m_Mutable.DisplayColorimetry; } std::span GetRawEDID() const override { return std::span{ m_Mutable.EdidData.begin(), m_Mutable.EdidData.end() }; } @@ -372,11 +373,15 @@ namespace gamescope void UpdateEffectiveOrientation( const drmModeModeInfo *pMode ); + using DRMModeGenerator = std::function; + const DRMModeGenerator &GetModeGenerator() const + { + return m_Mutable.fnDynamicModeGenerator; + } + private: void ParseEDID(); - static std::optional GetKnownDisplayHDRInfo( GamescopeKnownDisplays eKnownDisplay ); - CAutoDeletePtr m_pConnector; struct MutableConnectorState @@ -388,8 +393,8 @@ namespace gamescope char szMakePNP[4]{}; char szModel[16]{}; const char *pszMake = ""; // Not owned, no free. This is a pointer to pnp db or szMakePNP. - GamescopeKnownDisplays eKnownDisplay = GAMESCOPE_KNOWN_DISPLAY_UNKNOWN; - std::span ValidDynamicRefreshRates{}; + std::vector ValidDynamicRefreshRates{}; + DRMModeGenerator fnDynamicModeGenerator; std::vector EdidData; // Raw, unmodified. std::vector BackendModes; @@ -2111,71 +2116,113 @@ namespace gamescope drm_log.infof("Connector %s -> %s - %s", m_Mutable.szName, m_Mutable.szMakePNP, m_Mutable.szModel ); - const bool bIsDeckHDUnofficial = ( m_Mutable.szMakePNP == "DHD"sv && m_Mutable.szModel == "DeckHD-1200p"sv ); + bool bHasKnownColorimetry = false; + bool bHasKnownHDRInfo = false; - const bool bSteamDeckDisplay = - ( m_Mutable.szMakePNP == "WLC"sv && m_Mutable.szModel == "ANX7530 U"sv ) || - ( m_Mutable.szMakePNP == "ANX"sv && m_Mutable.szModel == "ANX7530 U"sv ) || - ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "ANX7530 U"sv ) || - ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Jupiter"sv ) || - ( m_Mutable.szMakePNP == "VLV"sv && m_Mutable.szModel == "Galileo"sv ); - - if ( bSteamDeckDisplay ) { - static constexpr uint32_t kPIDGalileoSDC = 0x3003; - static constexpr uint32_t kPIDGalileoBOE = 0x3004; + CScriptScopedLock script; - if ( pProduct->product == kPIDGalileoSDC ) - { - m_Mutable.eKnownDisplay = GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_SDC; - m_Mutable.ValidDynamicRefreshRates = std::span( s_kSteamDeckOLEDRates ); - } - else if ( pProduct->product == kPIDGalileoBOE ) - { - m_Mutable.eKnownDisplay = GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_BOE; - m_Mutable.ValidDynamicRefreshRates = std::span( s_kSteamDeckOLEDRates ); - } - else + auto oKnownDisplay = script.Manager().Gamescope().Config.LookupDisplay( m_Mutable.szMakePNP, pProduct->product, m_Mutable.szModel ); + if ( oKnownDisplay ) { - m_Mutable.eKnownDisplay = GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD; - m_Mutable.ValidDynamicRefreshRates = std::span( s_kSteamDeckLCDRates ); - } - } + sol::table tTable = oKnownDisplay->second; - if ( bIsDeckHDUnofficial ) - { - static constexpr uint32_t kPIDJupiterDHD = 0x4001; + std::string_view psvPrettyName = tTable.get_or( "pretty_name", std::string_view{ "Untitled Display" } ); + drm_log.infof( "Got known display: %.*s (%.*s)", + (int)oKnownDisplay->first.size(), oKnownDisplay->first.data(), + (int)psvPrettyName.size(), psvPrettyName.data() ); - if ( pProduct->product == kPIDJupiterDHD ) - { - m_Mutable.eKnownDisplay = GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD_DHD; - m_Mutable.ValidDynamicRefreshRates = std::span( s_kSteamDeckLCDRates ); - } - } + m_Mutable.fnDynamicModeGenerator = nullptr; + m_Mutable.ValidDynamicRefreshRates.clear(); - // Colorimetry - const char *pszColorOverride = getenv( "GAMESCOPE_INTERNAL_COLORIMETRY_OVERRIDE" ); - if ( pszColorOverride && *pszColorOverride && GetScreenType() == GAMESCOPE_SCREEN_TYPE_INTERNAL ) - { - if ( sscanf( pszColorOverride, "%f %f %f %f %f %f %f %f", - &m_Mutable.DisplayColorimetry.primaries.r.x, &m_Mutable.DisplayColorimetry.primaries.r.y, - &m_Mutable.DisplayColorimetry.primaries.g.x, &m_Mutable.DisplayColorimetry.primaries.g.y, - &m_Mutable.DisplayColorimetry.primaries.b.x, &m_Mutable.DisplayColorimetry.primaries.b.y, - &m_Mutable.DisplayColorimetry.white.x, &m_Mutable.DisplayColorimetry.white.y ) == 8 ) - { - drm_log.infof( "[colorimetry]: GAMESCOPE_INTERNAL_COLORIMETRY_OVERRIDE detected" ); - } - else - { - drm_log.errorf( "[colorimetry]: GAMESCOPE_INTERNAL_COLORIMETRY_OVERRIDE specified, but could not parse \"rx ry gx gy bx by wx wy\"" ); + sol::optional otDynamicRefreshRates = tTable["dynamic_refresh_rates"]; + sol::optional ofnDynamicModegen = tTable["dynamic_modegen"]; + + if ( otDynamicRefreshRates && ofnDynamicModegen ) + { + m_Mutable.ValidDynamicRefreshRates = TableToVector( *otDynamicRefreshRates ); + + m_Mutable.fnDynamicModeGenerator = [ fnDynamicModegen = *ofnDynamicModegen ]( const drmModeModeInfo *pBaseMode, int nRefreshHz ) -> drmModeModeInfo + { + CScriptScopedLock script; + + sol::table tInMode = script->create_table(); + tInMode["clock"] = pBaseMode->clock; + + tInMode["hdisplay"] = pBaseMode->hdisplay; + tInMode["hsync_start"] = pBaseMode->hsync_start; + tInMode["hsync_end"] = pBaseMode->hsync_end; + tInMode["htotal"] = pBaseMode->htotal; + + tInMode["vdisplay"] = pBaseMode->vdisplay; + tInMode["vsync_start"] = pBaseMode->vsync_start; + tInMode["vsync_end"] = pBaseMode->vsync_end; + tInMode["vtotal"] = pBaseMode->vtotal; + + tInMode["vrefresh"] = pBaseMode->vrefresh; + + sol::function_result ret = fnDynamicModegen(tInMode, nRefreshHz); + if ( !ret.valid() || !ret.get() ) + return *pBaseMode; + + sol::table tOutMode = ret; + + drmModeModeInfo outMode = *pBaseMode; + outMode.clock = tOutMode["clock"]; + + outMode.hdisplay = tOutMode["hdisplay"]; + outMode.hsync_start = tOutMode["hsync_start"]; + outMode.hsync_end = tOutMode["hsync_end"]; + outMode.htotal = tOutMode["htotal"]; + + outMode.vdisplay = tOutMode["vdisplay"]; + outMode.vsync_start = tOutMode["vsync_start"]; + outMode.vsync_end = tOutMode["vsync_end"]; + outMode.vtotal = tOutMode["vtotal"]; + + outMode.vrefresh = tOutMode["vrefresh"]; + + snprintf( outMode.name, sizeof( outMode.name ), "%dx%d@%d.00", outMode.hdisplay, outMode.vdisplay, nRefreshHz ); + + return outMode; + }; + } + + if ( sol::optional otColorimetry = tTable["colorimetry"] ) + { + sol::table tColorimetry = *otColorimetry; + + // TODO: Add a vec2 + colorimetry type? + sol::optional otR = tColorimetry["r"]; + sol::optional otG = tColorimetry["g"]; + sol::optional otB = tColorimetry["b"]; + sol::optional otW = tColorimetry["w"]; + + if ( otR && otG && otB && otW ) + { + m_Mutable.DisplayColorimetry.primaries.r = TableToVec( *otR ); + m_Mutable.DisplayColorimetry.primaries.g = TableToVec( *otG ); + m_Mutable.DisplayColorimetry.primaries.b = TableToVec( *otB ); + m_Mutable.DisplayColorimetry.white = TableToVec( *otW ); + + bHasKnownColorimetry = true; + } + } + + if ( sol::optional otHDRInfo = tTable["hdr"] ) + { + m_Mutable.HDR.bExposeHDRSupport = otHDRInfo->get_or( "supported", false ); + m_Mutable.HDR.eOutputEncodingEOTF = otHDRInfo->get_or( "eotf", EOTF_Gamma22 ); + m_Mutable.HDR.uMaxContentLightLevel = nits_to_u16( otHDRInfo->get_or( "max_content_light_level", 400.0f ) ); + m_Mutable.HDR.uMaxFrameAverageLuminance = nits_to_u16( otHDRInfo->get_or( "max_frame_average_luminance", 400.0f ) ); + m_Mutable.HDR.uMinContentLightLevel = nits_to_u16_dark( otHDRInfo->get_or( "min_content_light_level", 0.1f ) ); + + bHasKnownHDRInfo = true; + } } } - else if ( m_Mutable.eKnownDisplay == GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD ) - { - drm_log.infof( "[colorimetry]: Steam Deck LCD detected. Using known colorimetry" ); - m_Mutable.DisplayColorimetry = displaycolorimetry_steamdeck_measured; - } - else + + if ( !bHasKnownColorimetry ) { // Steam Deck OLED has calibrated chromaticity coordinates in the EDID // for each unit. @@ -2191,6 +2238,11 @@ namespace gamescope .white = { pChroma->white_x, pChroma->white_y }, }; } + else + { + // Assume 709 if we have no data at all. + m_Mutable.DisplayColorimetry = displaycolorimetry_709; + } } drm_log.infof( "[colorimetry]: r %f %f", m_Mutable.DisplayColorimetry.primaries.r.x, m_Mutable.DisplayColorimetry.primaries.r.y ); @@ -2201,12 +2253,7 @@ namespace gamescope ///////////////////// // Parse HDR stuff. ///////////////////// - std::optional oKnownHDRInfo = GetKnownDisplayHDRInfo( m_Mutable.eKnownDisplay ); - if ( oKnownHDRInfo ) - { - m_Mutable.HDR = *oKnownHDRInfo; - } - else + if ( !bHasKnownHDRInfo ) { const di_cta_hdr_static_metadata_block *pHDRStaticMetadata = nullptr; const di_cta_colorimetry_block *pColorimetry = nullptr; @@ -2289,38 +2336,6 @@ namespace gamescope } } - /*static*/ std::optional CDRMConnector::GetKnownDisplayHDRInfo( GamescopeKnownDisplays eKnownDisplay ) - { - if ( eKnownDisplay == GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_BOE || eKnownDisplay == GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_SDC ) - { - // The stuff in the EDID for the HDR metadata does not fully - // reflect what we can achieve on the display by poking at more - // things out-of-band. - return BackendConnectorHDRInfo - { - .bExposeHDRSupport = true, - .eOutputEncodingEOTF = EOTF_Gamma22, - .uMaxContentLightLevel = nits_to_u16( 1000.0f ), - .uMaxFrameAverageLuminance = nits_to_u16( 800.0f ), // Full-frame sustained. - .uMinContentLightLevel = nits_to_u16_dark( 0 ), - }; - } - else if ( eKnownDisplay == GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD || eKnownDisplay == GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD_DHD ) - { - // Set up some HDR fallbacks for undocking - return BackendConnectorHDRInfo - { - .bExposeHDRSupport = false, - .eOutputEncodingEOTF = EOTF_Gamma22, - .uMaxContentLightLevel = nits_to_u16( 500.0f ), - .uMaxFrameAverageLuminance = nits_to_u16( 500.0f ), - .uMinContentLightLevel = nits_to_u16_dark( 0.5f ), - }; - } - - return std::nullopt; - } - ///////////////////////// // CDRMFb ///////////////////////// @@ -3015,17 +3030,25 @@ bool drm_set_refresh( struct drm_t *drm, int refresh ) } else { - /* TODO: check refresh is within the EDID limits */ - switch ( g_eGamescopeModeGeneration ) + if ( g_DRM.pConnector && g_DRM.pConnector->GetModeGenerator() ) { - case gamescope::GAMESCOPE_MODE_GENERATE_CVT: - generate_cvt_mode( &mode, width, height, refresh, true, false ); - break; - case gamescope::GAMESCOPE_MODE_GENERATE_FIXED: + const drmModeModeInfo *preferred_mode = find_mode(connector, 0, 0, 0); + mode = g_DRM.pConnector->GetModeGenerator()( preferred_mode, refresh ); + } + else + { + /* TODO: check refresh is within the EDID limits */ + switch ( g_eGamescopeModeGeneration ) { - const drmModeModeInfo *preferred_mode = find_mode(connector, 0, 0, 0); - generate_fixed_mode( &mode, preferred_mode, refresh, drm->pConnector->GetKnownDisplayType() ); + case gamescope::GAMESCOPE_MODE_GENERATE_CVT: + generate_cvt_mode( &mode, width, height, refresh, true, false ); break; + case gamescope::GAMESCOPE_MODE_GENERATE_FIXED: + { + const drmModeModeInfo *preferred_mode = find_mode(connector, 0, 0, 0); + generate_fixed_mode( &mode, preferred_mode, refresh ); + break; + } } } } diff --git a/src/Script/Script.cpp b/src/Script/Script.cpp new file mode 100644 index 0000000000..261b2b03da --- /dev/null +++ b/src/Script/Script.cpp @@ -0,0 +1,245 @@ +#include "Script.h" +#include "convar.h" +#include "color_helpers.h" +#include "../log.hpp" + +#include +#include + +std::string_view GetHomeDir(); + +namespace gamescope +{ + using namespace std::literals; + + static LogScope s_ScriptLog{ "script" }; + static LogScope s_ScriptMgrLog{ "scriptmgr" }; + + static ConVar cv_script_use_local_scripts{ "script_use_local_scripts", false, "Whether or not to use the local scripts (../config) as opposed to the ones in /etc/gamescope.d" }; + static ConVar cv_script_use_user_scripts{ "script_use_user_scripts", true, "Whether or not to use user config scripts ($XDG_CONFIG_DIR/gamescope) at all." }; + + static std::string_view GetConfigDir() + { + static std::string s_sConfigDir = []() -> std::string + { + const char *pszConfigHome = getenv( "XDG_CONFIG_HOME" ); + if ( pszConfigHome && *pszConfigHome ) + return pszConfigHome; + + return std::string{ GetHomeDir() } + "/.config"; + }(); + + return s_sConfigDir; + } + + static inline void PanicFunction( sol::optional oMsg ) + { + s_ScriptLog.errorf( "Lua is in a panic state and will now abort() the application" ); + if ( oMsg ) + { + s_ScriptLog.errorf( "\tError Message: %s", oMsg->c_str() ); + } + // When this function exits, Lua will exhibit default behavior and abort() + } + + static inline int ExceptionFunction( lua_State* pState, sol::optional oException, sol::string_view psvDescription ) + { + // L is the lua state, which you can wrap in a state_view if necessary + // maybe_exception will contain exception, if it exists + // description will either be the what() of the exception or a description saying that we hit the general-case catch(...) + + s_ScriptLog.errorf( "An exception occurred:\n %.*s", + (int)psvDescription.length(), psvDescription.data() ); + + // you must push 1 element onto the stack to be + // transported through as the error object in Lua + // note that Lua -- and 99.5% of all Lua users and libraries -- expects a string + // so we push a single string (in our case, the description of the error) + return sol::stack::push( pState, psvDescription ); + } + + static inline void LuaErrorHandler( const std::string &msg ) + { + s_ScriptLog.errorf( "An error occurred:\n %.*s", + (int)msg.length(), msg.data() ); + } + + int32_t CScriptManager::s_nNextScriptId = 0; + + CScriptManager &CScriptManager::GlobalScriptScope() + { + static CScriptManager s_State; + return s_State; + } + + CScriptManager::CScriptManager() + { + m_State.open_libraries(); + + static bool s_bSetDefaultHandler = false; + if ( !s_bSetDefaultHandler ) + { + m_State["_gamescope_error_handler"] = LuaErrorHandler; + + sol::protected_function::set_default_handler( m_State["_gamescope_error_handler"] ); + s_bSetDefaultHandler = true; + } + + m_State.set_panic( sol::c_call ); + m_State.set_exception_handler( &ExceptionFunction ); + + m_Gamescope.Base = m_State.create_named_table( "gamescope" ); + m_Gamescope.Base["hook"] = [this]( std::string_view svName, sol::function fnFunc ) + { + m_Hooks.emplace( std::make_pair( svName, Hook_t{ std::move( fnFunc ), m_nCurrentScriptId } ) ); + }; + m_Gamescope.Base.new_enum( "eotf", + { + { "gamma22", EOTF_Gamma22 }, + { "pq", EOTF_PQ }, + { "count", EOTF_Count }, + } + ); + m_Gamescope.Base.new_enum( "log_priority", + { + { "silent", LOG_SILENT }, + { "error", LOG_ERROR }, + { "warning", LOG_WARNING }, + { "info", LOG_INFO }, + { "debug", LOG_DEBUG }, + } + ); + m_Gamescope.Base["log"] = []( LogPriority ePriority, std::string_view svText ) { s_ScriptLog.log( ePriority, svText ); }; + + m_Gamescope.Convars.Base = m_State.create_table(); + m_Gamescope.Base.set( "convars", m_Gamescope.Convars.Base ); + + m_Gamescope.Config.Base = m_State.create_table(); + m_Gamescope.Base.set( "config", m_Gamescope.Config.Base ); + + m_Gamescope.Config.KnownDisplays = m_State.create_table(); + m_Gamescope.Config.Base.set( "known_displays", m_Gamescope.Config.KnownDisplays ); + } + + void CScriptManager::RunDefaultScripts() + { + if ( cv_script_use_local_scripts ) + { + RunFolder( "../scripts", true ); + } + else + { + RunFolder( "/usr/share/gamescope/scripts", true ); + RunFolder( "/etc/gamescope/scripts", true ); + } + + if ( cv_script_use_user_scripts ) + { + std::string sUserConfigs = std::string{ GetConfigDir() } + "/gamescope/scripts"; + RunFolder( sUserConfigs, true ); + } + } + + void CScriptManager::RunScriptText( std::string_view svContents ) + { + uint32_t uScriptId = s_nNextScriptId++; + + { + int32_t nPreviousScriptId = m_nCurrentScriptId; + + m_nCurrentScriptId = uScriptId; + State().script( svContents ); + m_nCurrentScriptId = nPreviousScriptId; + } + } + void CScriptManager::RunFile( std::string_view svPath ) + { + uint32_t uScriptId = s_nNextScriptId++; + + s_ScriptMgrLog.infof( "Running script file '%.*s' (id: %u)", + int( svPath.length() ), svPath.data(), + uScriptId ); + + std::string sPath = std::string( svPath ); + + { + int32_t nPreviousScriptId = m_nCurrentScriptId; + + m_nCurrentScriptId = uScriptId; + State().script_file( std::move( sPath ) ); + m_nCurrentScriptId = nPreviousScriptId; + } + } + bool CScriptManager::RunFolder( std::string_view svDirectory, bool bRecursive ) + { + s_ScriptMgrLog.infof( "Loading scripts from: '%.*s'", + int( svDirectory.size() ), svDirectory.data() ); + + std::filesystem::path dirConfig = std::filesystem::path{ svDirectory }; + if ( !std::filesystem::is_directory( dirConfig ) ) + { + s_ScriptMgrLog.warnf( "Directory '%.*s' does not exist", + int( svDirectory.size() ), svDirectory.data() ); + return false; + } + + if ( access( dirConfig.c_str(), R_OK | X_OK ) != 0 ) + { + s_ScriptMgrLog.warnf( "Cannot open directory '%.*s'", + int( svDirectory.size() ), svDirectory.data() ); + return false; + } + + std::vector sFiles; + std::vector sDirectories; + for ( const auto &iter : std::filesystem::directory_iterator( dirConfig ) ) + { + const std::filesystem::path &path = iter.path(); + // XXX: is_regular_file -> What about symlinks? + if ( std::filesystem::is_regular_file( iter.status() ) && path.extension() == ".lua"sv ) + { + sFiles.push_back( path ); + } + + if ( bRecursive && std::filesystem::is_directory( iter.status() ) ) + { + sDirectories.push_back( path ); + } + } + + std::sort( sFiles.begin(), sFiles.end() ); + std::sort( sDirectories.begin(), sDirectories.end() ); + + for ( const auto &sPath : sFiles ) + { + RunFile( sPath ); + } + + if ( bRecursive ) + { + for ( const auto &sPath : sDirectories ) + { + RunFolder( sPath, bRecursive ); + } + } + + return true; + } + + void CScriptManager::InvalidateAllHooks() + { + m_Hooks.clear(); + } + + void CScriptManager::InvalidateHooksForScript( int32_t nScriptId ) + { + if ( nScriptId < 0 ) + return; + + std::erase_if( m_Hooks, [ nScriptId ]( const auto &iter ) -> bool + { + return iter.second.nScriptId == nScriptId; + }); + } + +} diff --git a/src/Script/Script.h b/src/Script/Script.h new file mode 100644 index 0000000000..7f671b814f --- /dev/null +++ b/src/Script/Script.h @@ -0,0 +1,208 @@ +#pragma once + +#include "../Utils/Dict.h" + +#include + +#if HAVE_SCRIPTING + +#include + +namespace gamescope +{ + struct GamescopeScript_t + { + // Stores table entries, and caches sol::table + // handles for things we use frequently. + + sol::table Base; + + struct ConVars_t + { + sol::table Base; + } Convars; + + struct Config_t + { + sol::table Base; + + sol::table KnownDisplays; + + std::optional> LookupDisplay( std::string_view psvVendor, uint16_t uProduct, std::string_view psvModel ) + { + int nMaxPrority = -1; + std::optional> oOutDisplay; + + for ( auto iter : KnownDisplays ) + { + sol::table tTable = iter.second.as(); + if ( !tTable ) + continue; + + sol::function fnMatches = tTable["matches"]; + if ( !fnMatches ) + continue; + + int nPriority = fnMatches( psvVendor, uProduct, psvModel ); + if ( nPriority <= nMaxPrority ) + continue; + + std::string_view psvKey = iter.first.as(); + + nMaxPrority = nPriority; + oOutDisplay = std::make_pair( psvKey, tTable ); + } + + return oOutDisplay; + } + } Config; + }; + + class CScriptScopedLock; + + class CScriptManager + { + public: + CScriptManager(); + + template + void CallHook( std::string_view svName, Args&&... args ) + { + auto range = m_Hooks.equal_range( svName ); + for ( auto iter = range.first; iter != range.second; iter++ ) + { + int32_t nPreviousScriptId = m_nCurrentScriptId; + + Hook_t *pHook = &iter->second; + + m_nCurrentScriptId = pHook->nScriptId; + iter->second.fnCallback( std::forward( args )... ); + m_nCurrentScriptId = nPreviousScriptId; + } + } + + void RunDefaultScripts(); + + void RunScriptText( std::string_view svContents ); + + void RunFile( std::string_view svPath ); + bool RunFolder( std::string_view svPath, bool bRecursive = false ); + + void InvalidateAllHooks(); + void InvalidateHooksForScript( int32_t nScriptId ); + + sol::state *operator->() { return &m_State; } + + sol::state &State() { return m_State; } + GamescopeScript_t &Gamescope() { return m_Gamescope; } + + std::mutex &Mutex() { return m_mutMutex; } + + protected: + static CScriptManager &GlobalScriptScope(); + friend CScriptScopedLock; + private: + mutable std::mutex m_mutMutex; + + sol::state m_State; + GamescopeScript_t m_Gamescope; + + struct Hook_t + { + sol::function fnCallback; + int32_t nScriptId = -1; + }; + + MultiDict m_Hooks; + + int32_t m_nCurrentScriptId = -1; + + static int32_t s_nNextScriptId; + }; + + class CScriptScopedLock + { + public: + CScriptScopedLock() + : CScriptScopedLock{ CScriptManager::GlobalScriptScope() } + { + } + + CScriptScopedLock( CScriptManager &manager ) + : m_Lock{ manager.Mutex() } + , m_ScriptManager{ manager } + { + } + + ~CScriptScopedLock() + { + } + + CScriptManager &Manager() { return m_ScriptManager; } + sol::state *operator ->() { return &m_ScriptManager.State(); } + private: + std::scoped_lock m_Lock; + CScriptManager &m_ScriptManager; + }; + + template + T TableToVec( const sol::table &table ) + { + if ( !table ) + return T{}; + + T out{}; + for ( int i = 0; i < T::length(); i++ ) + { + std::array ppsvIndices + { + "x", "y", "z", "w" + }; + + if ( table[ppsvIndices[i]] ) + out[i] = (float)table[ppsvIndices[i]]; + else + out[i] = 0; + } + return out; + } + + template + std::vector TableToVector( const sol::table &table ) + { + std::vector out; + + if ( table ) + { + for ( auto &iter : table ) + { + out.emplace_back( iter.second.as() ); + } + } + + return out; + } + + #define SCRIPTDESC_TEMPLATE( type ) template + #define DECLARE_SCRIPTDESC( type ) \ + static sol::usertype< type > s_ScriptType; \ + class CEnsureScriptTypeInstantiation { public: CEnsureScriptTypeInstantiation() { (void) type :: s_ScriptType; } } m_EnsureTemplateInstantiation_ScriptDesc; + + #define START_SCRIPTDESC( type, lua_name ) \ + inline sol::usertype type::s_ScriptType = CScriptScopedLock()->new_usertype( lua_name + #define START_SCRIPTDESC_ANON( type ) \ + inline sol::usertype type::s_ScriptType = CScriptScopedLock()->new_usertype( typeid( type ).name() + #define SCRIPTDESC( x, y ) , x, y + #define END_SCRIPTDESC() ); +} + +#else + + #define SCRIPTDESC_TEMPLATE( type ) + #define DECLARE_SCRIPTDESC( x ) + #define START_SCRIPTDESC( type, lua_name ) + #define START_SCRIPTDESC_ANON( type ) + #define SCRIPTDESC( x, y ) + #define END_SCRIPTDESC() + +#endif \ No newline at end of file diff --git a/src/Utils/Dict.h b/src/Utils/Dict.h new file mode 100644 index 0000000000..c17efd77c6 --- /dev/null +++ b/src/Utils/Dict.h @@ -0,0 +1,23 @@ +#pragma once + +#include +#include +#include +#include + +namespace gamescope +{ + struct StringHash + { + using is_transparent = void; + [[nodiscard]] size_t operator()( const char *string ) const { return std::hash{}( string ); } + [[nodiscard]] size_t operator()( std::string_view string ) const { return std::hash{}( string ); } + [[nodiscard]] size_t operator()( const std::string &string ) const { return std::hash{}( string ); } + }; + + template + using Dict = std::unordered_map>; + + template + using MultiDict = std::unordered_multimap>; +} diff --git a/src/convar.cpp b/src/convar.cpp index ed2d0b125c..7fdc8a450e 100644 --- a/src/convar.cpp +++ b/src/convar.cpp @@ -8,6 +8,25 @@ extern void PrintGamescopeVersion(); namespace gamescope { + ConCommand::ConCommand( std::string_view pszName, std::string_view pszDescription, ConCommandFunc func, bool bRegisterScript ) + : m_pszName{ pszName } + , m_pszDescription{ pszDescription } + , m_Func{ func } + { + assert( !GetCommands().contains( pszName ) ); + GetCommands()[ std::string( pszName ) ] = this; + +#if HAVE_SCRIPTING + if ( bRegisterScript ) + CScriptScopedLock().Manager().Gamescope().Convars.Base[pszName] = this; +#endif + } + + ConCommand::~ConCommand() + { + GetCommands().erase( GetCommands().find( m_pszName ) ); + } + bool ConCommand::Exec( std::span args ) { if ( args.size() < 1 ) diff --git a/src/convar.h b/src/convar.h index 0bcdcff7d8..5a90bfbdcd 100644 --- a/src/convar.h +++ b/src/convar.h @@ -12,6 +12,9 @@ #include #include +#include "Script/Script.h" +#include "Utils/Dict.h" + #include "log.hpp" extern LogScope console_log; @@ -62,10 +65,8 @@ namespace gamescope return false; } - inline std::vector Split( std::string_view string, std::string_view delims = " " ) + inline void Split( std::vector &tokens, std::string_view string, std::string_view delims = " " ) { - std::vector tokens; - size_t end = 0; for ( size_t start = 0; start < string.size() && end != std::string_view::npos; start = end + 1 ) { @@ -74,39 +75,24 @@ namespace gamescope if ( start != end ) tokens.emplace_back( string.substr( start, end-start ) ); } - - return tokens; } - struct StringHash + inline std::vector Split( std::string_view string, std::string_view delims = " " ) { - using is_transparent = void; - [[nodiscard]] size_t operator()( const char *string ) const { return std::hash{}( string ); } - [[nodiscard]] size_t operator()( std::string_view string ) const { return std::hash{}( string ); } - [[nodiscard]] size_t operator()( const std::string &string ) const { return std::hash{}( string ); } - }; - - template - using Dict = std::unordered_map>; + std::vector tokens; + Split( tokens, string, delims ); + return tokens; + } class ConCommand { using ConCommandFunc = std::function )>; public: - ConCommand( std::string_view pszName, std::string_view pszDescription, ConCommandFunc func ) - : m_pszName{ pszName } - , m_pszDescription{ pszDescription } - , m_Func{ func } - { - assert( !GetCommands().contains( pszName ) ); - GetCommands()[ std::string( pszName ) ] = this; - } + DECLARE_SCRIPTDESC( ConCommand ); - ~ConCommand() - { - GetCommands().erase( GetCommands().find( m_pszName ) ); - } + ConCommand( std::string_view pszName, std::string_view pszDescription, ConCommandFunc func, bool bRegisterScript = true ); + ~ConCommand(); void Invoke( std::span args ) { @@ -114,6 +100,16 @@ namespace gamescope m_Func( args ); } + // Calls it with space separated args. + void CallWithArgString( std::string_view args ) + { + std::vector sArgs; + sArgs.push_back( m_pszName ); + Split( sArgs, args, " " ); + + Invoke( sArgs ); + } + static bool Exec( std::span args ); std::string_view GetName() const { return m_pszName; } @@ -126,13 +122,21 @@ namespace gamescope ConCommandFunc m_Func; }; + START_SCRIPTDESC( ConCommand, "concommand" ) + SCRIPTDESC( "name", &ConCommand::m_pszName ) + SCRIPTDESC( "description", &ConCommand::m_pszDescription ) + SCRIPTDESC( "call", &ConCommand::CallWithArgString ) + END_SCRIPTDESC() + template class ConVar : public ConCommand { using ConVarCallbackFunc = std::function &)>; public: - ConVar( std::string_view pszName, T defaultValue = T{}, std::string_view pszDescription = "", ConVarCallbackFunc func = nullptr, bool bRunCallbackAtStartup = false ) - : ConCommand( pszName, pszDescription, [this]( std::span pArgs ){ this->InvokeFunc( pArgs ); } ) + DECLARE_SCRIPTDESC( ConVar ); + + ConVar( std::string_view pszName, T defaultValue = T{}, std::string_view pszDescription = "", ConVarCallbackFunc func = nullptr, bool bRunCallbackAtStartup = false, bool bRegisterScript = true ) + : ConCommand( pszName, pszDescription, [this]( std::span pArgs ){ this->InvokeFunc( pArgs ); }, false ) , m_Value{ defaultValue } , m_Callback{ func } { @@ -140,6 +144,13 @@ namespace gamescope { RunCallback(); } + +#if HAVE_SCRIPTING + if ( bRegisterScript ) + { + CScriptScopedLock().Manager().Gamescope().Convars.Base[pszName] = this; + } +#endif } const T& Get() const @@ -177,6 +188,10 @@ namespace gamescope template bool operator != ( const J &other ) const { return m_Value != other; } template auto operator <=>( const J &other ) const { return m_Value <=> other; } + template bool operator == ( const ConVar &other ) const { return *this == other.Get(); } + template bool operator != ( const ConVar &other ) const { return *this != other.Get(); } + template auto operator <=>( const ConVar &other ) const { return *this <=> other.Get(); } + T operator | (T other) { return m_Value | other; } T &operator |=(T other) { return m_Value |= other; } T operator & (T other) { return m_Value & other; } @@ -221,4 +236,14 @@ namespace gamescope ConVarCallbackFunc m_Callback; bool m_bInCallback; }; + + SCRIPTDESC_TEMPLATE( T ) + START_SCRIPTDESC_ANON( ConVar ) + SCRIPTDESC( "name", &ConVar::m_pszName ) + SCRIPTDESC( "description", &ConVar::m_pszDescription ) + SCRIPTDESC( "call", &ConVar::CallWithArgString ) + + SCRIPTDESC( "value", &ConVar::m_Value ) + END_SCRIPTDESC() + } diff --git a/src/gamescope_shared.h b/src/gamescope_shared.h index 5ce859123c..1ff54bdcff 100644 --- a/src/gamescope_shared.h +++ b/src/gamescope_shared.h @@ -6,15 +6,6 @@ namespace gamescope { class BackendBlob; - enum GamescopeKnownDisplays - { - GAMESCOPE_KNOWN_DISPLAY_UNKNOWN, - GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD, // Jupiter - GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD_DHD, // Jupiter Deck HD - GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_SDC, // Galileo SDC - GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_BOE, // Galileo BOE - }; - enum GamescopeModeGeneration { GAMESCOPE_MODE_GENERATE_CVT, diff --git a/src/log.cpp b/src/log.cpp index 50e5bb48c3..7b502a4ae1 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -104,18 +104,27 @@ void LogScope::vlogf(enum LogPriority priority, const char *fmt, va_list args) return; defer( free(buf); ); + std::string_view svBuf = buf; + log(priority, svBuf); +} + +void LogScope::log(enum LogPriority priority, std::string_view psvText) +{ + if ( !Enabled( priority ) ) + return; + for (auto& listener : m_LoggingListeners) - listener.second( priority, m_psvPrefix, buf ); + listener.second( priority, m_psvPrefix, psvText ); std::string_view psvLogName = GetLogPriorityText( priority ); if ( bPrefixEnabled ) - fprintf(stderr, "[%s] %.*s \e[0;37m%.*s:\e[0m %s\n", + fprintf(stderr, "[%s] %.*s \e[0;37m%.*s:\e[0m %.*s\n", gamescope::Process::GetProcessName(), (int)psvLogName.size(), psvLogName.data(), (int)this->m_psvPrefix.size(), this->m_psvPrefix.data(), - buf); + (int)psvText.size(), psvText.data()); else - fprintf(stderr, "%s\n", buf); + fprintf(stderr, "%.*s\n", (int)psvText.size(), psvText.data()); } void LogScope::logf(enum LogPriority priority, const char *fmt, ...) { diff --git a/src/log.hpp b/src/log.hpp index 5d28da6106..8225b0038e 100644 --- a/src/log.hpp +++ b/src/log.hpp @@ -35,6 +35,7 @@ class LogScope void SetPriority( LogPriority ePriority ) { m_eMaxPriority = ePriority; } void vlogf(enum LogPriority priority, const char *fmt, va_list args) ATTRIB_PRINTF(3, 0); + void log(enum LogPriority priority, std::string_view psvText); void warnf(const char *fmt, ...) ATTRIB_PRINTF(2, 3); void errorf(const char *fmt, ...) ATTRIB_PRINTF(2, 3); @@ -45,7 +46,7 @@ class LogScope bool bPrefixEnabled = true; - using LoggingListenerFunc = std::function; + using LoggingListenerFunc = std::function; std::unordered_map m_LoggingListeners; private: diff --git a/src/main.cpp b/src/main.cpp index a9cdaa2e21..c074f82e2e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,3 +1,5 @@ +#include "Script/Script.h" + #include #include @@ -808,6 +810,11 @@ int main(int argc, char **argv) fprintf( stderr, "Tracing is enabled\n"); } + { + gamescope::CScriptScopedLock script; + script.Manager().RunDefaultScripts(); + } + XInitThreads(); g_mainThread = pthread_self(); diff --git a/src/meson.build b/src/meson.build index 5174de6700..74fc0334d4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -90,6 +90,8 @@ reshade_include = include_directories([ '../thirdparty/SPIRV-Headers/include/spirv/unified1' ]) +sol2_include = include_directories(['../thirdparty']) + required_wlroots_features = ['xwayland'] src = [ @@ -98,6 +100,7 @@ src = [ 'Utils/TempFiles.cpp', 'Utils/Version.cpp', 'Utils/Process.cpp', + 'Script/Script.cpp', 'BufferMemo.cpp', 'steamcompmgr.cpp', 'convar.cpp', @@ -118,6 +121,8 @@ src = [ 'InputEmulation.cpp', ] +luajit_dep = dependency( 'luajit' ) + gamescope_cpp_args = [] if drm_dep.found() src += 'Backends/DRMBackend.cpp' @@ -142,6 +147,7 @@ gamescope_cpp_args += '-DHAVE_SDL2=@0@'.format(sdl2_dep.found().to_int()) gamescope_cpp_args += '-DHAVE_AVIF=@0@'.format(avif_dep.found().to_int()) gamescope_cpp_args += '-DHAVE_LIBCAP=@0@'.format(cap_dep.found().to_int()) gamescope_cpp_args += '-DHAVE_LIBEIS=@0@'.format(eis_dep.found().to_int()) +gamescope_cpp_args += '-DHAVE_SCRIPTING=1' src += spirv_shaders src += protocols_server_src @@ -181,14 +187,14 @@ gamescope_version = configure_file( executable( 'gamescope', src, reshade_src, gamescope_version, - include_directories : [reshade_include], + include_directories : [reshade_include, sol2_include], dependencies: [ dep_wayland, dep_x11, dep_xdamage, dep_xcomposite, dep_xrender, dep_xext, dep_xfixes, dep_xxf86vm, dep_xres, glm_dep, drm_dep, wayland_server, xkbcommon, thread_dep, sdl2_dep, wlroots_dep, vulkan_dep, liftoff_dep, dep_xtst, dep_xmu, cap_dep, epoll_dep, pipewire_dep, librt_dep, stb_dep, displayinfo_dep, openvr_dep, dep_xcursor, avif_dep, dep_xi, - libdecor_dep, eis_dep, + libdecor_dep, eis_dep, luajit_dep ], install: true, cpp_args: gamescope_cpp_args, diff --git a/src/modegen.cpp b/src/modegen.cpp index 5dd113697c..1cf317c6c9 100644 --- a/src/modegen.cpp +++ b/src/modegen.cpp @@ -268,127 +268,13 @@ void generate_cvt_mode(drmModeModeInfo *mode, int hdisplay, int vdisplay, } } -// galielo SDC rev B ds.10 spec'd rates -// fps 45 48 51 55 60 65 72 80 90 -// VFP 1321 1157 993 829 665 501 337 173 9 - -// galielo BOE spec'd rates -// fps 45 48 51 55 60 65 72 80 90 -// VFP 1320 1156 992 828 664 500 336 172 8 - -// SDC VFP values for 45 Hz to 90 Hz -unsigned int galileo_sdc_vfp[] = -{ - 1321,1264,1209,1157,1106,1058,993,967,925,883,829,805,768,732,698, - 665,632,601,571,542,501,486,459,433,408,383,360,337,314,292,271,250,230,210,191, - 173,154,137,119,102,86,70,54,38,23,9 -}; - -// BOE VFP values for 45 Hz to 90 Hz -// BOE Vtotal must be a multiple of 4 -unsigned int galileo_boe_vfp[] = -{ - 1320,1272,1216,1156,1112,1064,992,972,928,888,828,808,772,736,700, - 664,636,604,572,544,500,488,460,436,408,384,360,336,316,292,272,252,228,212,192, - 172,152,136,120,100,84,68,52,36,20,8 -}; - -//SD LCD Stock Timings -#define JUPITER_BOE_PID 0x3001 -#define JUPITER_B_PID 0x3002 -#define JUPITER_HFP 40 -#define JUPITER_HSYNC 4 -#define JUPITER_HBP 40 -#define JUPITER_VFP 30 -#define JUPITER_VSYNC 4 -#define JUPITER_VBP 8 -//SD LCD DeckHD Timings -#define JUPITER_DHD_PID 0x4001 -#define JUPITER_DHD_HFP 40 -#define JUPITER_DHD_HSYNC 20 -#define JUPITER_DHD_HBP 40 -#define JUPITER_DHD_VFP 18 -#define JUPITER_DHD_VSYNC 2 -#define JUPITER_DHD_VBP 20 -//SD OLED SDC Timings -#define GALILEO_SDC_PID 0x3003 -#define GALILEO_SDC_VSYNC 1 -#define GALILEO_SDC_VBP 22 -//SD OLED BOE Timings -#define GALILEO_BOE_PID 0x3004 -#define GALILEO_BOE_VSYNC 2 -#define GALILEO_BOE_VBP 30 -#define GALILEO_MIN_REFRESH 45 -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) - -unsigned int get_galileo_vfp( int vrefresh, unsigned int * vfp_array, unsigned int num_rates ) -{ - for ( unsigned int i = 0; i < num_rates; i++ ) { - if ( i+GALILEO_MIN_REFRESH == (unsigned int)vrefresh ) { - return vfp_array[i]; - } - } - return 0; -} - -void generate_fixed_mode(drmModeModeInfo *mode, const drmModeModeInfo *base, int vrefresh, gamescope::GamescopeKnownDisplays eKnownDisplay ) +void generate_fixed_mode(drmModeModeInfo *mode, const drmModeModeInfo *base, int vrefresh ) { *mode = *base; if (!vrefresh) vrefresh = 60; - if ( eKnownDisplay == gamescope::GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_SDC || - eKnownDisplay == gamescope::GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_BOE ) { - unsigned int vfp = 0, vsync = 0, vbp = 0; - if ( eKnownDisplay == gamescope::GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_SDC ) - { - vfp = get_galileo_vfp( vrefresh, galileo_sdc_vfp, ARRAY_SIZE(galileo_sdc_vfp) ); - // if we did not find a matching rate then we default to 60 Hz - if ( !vfp ) { - vrefresh = 60; - vfp = 665; - } - vsync = GALILEO_SDC_VSYNC; - vbp = GALILEO_SDC_VBP; - } else if ( eKnownDisplay == gamescope::GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_OLED_BOE ) { // BOE Panel - vfp = get_galileo_vfp( vrefresh, galileo_boe_vfp, ARRAY_SIZE(galileo_boe_vfp) ); - // if we did not find a matching rate then we default to 60 Hz - if ( !vfp ) { - vrefresh = 60; - vfp = 664; - } - vsync = GALILEO_BOE_VSYNC; - vbp = GALILEO_BOE_VBP; - } - mode->vsync_start = mode->vdisplay + vfp; - mode->vsync_end = mode->vsync_start + vsync; - mode->vtotal = mode->vsync_end + vbp; - } else { - if ( eKnownDisplay == gamescope::GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD_DHD ) { - mode->hdisplay = 1200; - mode->hsync_start = mode->hdisplay + JUPITER_DHD_HFP; - mode->hsync_end = mode->hsync_start + JUPITER_DHD_HSYNC; - mode->htotal = mode->hsync_end + JUPITER_DHD_HBP; - - mode->vdisplay = 1920; - mode->vsync_start = mode->vdisplay + JUPITER_DHD_VFP; - mode->vsync_end = mode->vsync_start + JUPITER_DHD_VSYNC; - mode->vtotal = mode->vsync_end + JUPITER_DHD_VBP; - } - else if ( eKnownDisplay == gamescope::GAMESCOPE_KNOWN_DISPLAY_STEAM_DECK_LCD ) - { - mode->hdisplay = 800; - mode->hsync_start = mode->hdisplay + JUPITER_HFP; - mode->hsync_end = mode->hsync_start + JUPITER_HSYNC; - mode->htotal = mode->hsync_end + JUPITER_HBP; - - mode->vdisplay = 1280; - mode->vsync_start = mode->vdisplay + JUPITER_VFP; - mode->vsync_end = mode->vsync_start + JUPITER_VSYNC; - mode->vtotal = mode->vsync_end + JUPITER_VBP; - } - mode->clock = ( ( mode->htotal * mode->vtotal * vrefresh ) + 999 ) / 1000; - } + mode->clock = ( ( mode->htotal * mode->vtotal * vrefresh ) + 999 ) / 1000; mode->vrefresh = (1000 * mode->clock) / (mode->htotal * mode->vtotal); snprintf(mode->name, sizeof(mode->name), "%dx%d@%d.00", mode->hdisplay, mode->vdisplay, vrefresh); diff --git a/src/modegen.hpp b/src/modegen.hpp index 010d9cab33..7c2e690890 100644 --- a/src/modegen.hpp +++ b/src/modegen.hpp @@ -10,4 +10,4 @@ void generate_cvt_mode(drmModeModeInfo *mode, int hdisplay, int vdisplay, float vrefresh, bool reduced, bool interlaced); void generate_fixed_mode(drmModeModeInfo *mode, const drmModeModeInfo *base, - int vrefresh, gamescope::GamescopeKnownDisplays eKnownDisplay); + int vrefresh ); diff --git a/src/reshade_effect_manager.cpp b/src/reshade_effect_manager.cpp index 87f886b140..d9f1d0270b 100644 --- a/src/reshade_effect_manager.cpp +++ b/src/reshade_effect_manager.cpp @@ -36,14 +36,22 @@ static std::mutex g_runtimeUniformsMutex; const char *homedir; -static std::string GetLocalUsrDir() +std::string_view GetHomeDir() { - const char *homedir = nullptr; + static std::string s_sHomeDir = []() -> std::string + { + const char *pszHomeDir = getenv( "HOME" ); + if ( pszHomeDir ) + return pszHomeDir; - if ((homedir = getenv("HOME")) == nullptr) - homedir = getpwuid(getuid())->pw_dir; + return getpwuid( getuid() )->pw_dir; + }(); + return s_sHomeDir; +} - return std::string(homedir) + "/.local"; +static std::string GetLocalUsrDir() +{ + return std::string{ GetHomeDir() } + "/.local"; } static std::string GetUsrDir() diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 8c9920e315..22a4d60080 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -7988,6 +7988,11 @@ steamcompmgr_main(int argc, char **argv) hasRepaint = false; hasRepaintNonBasePlane = false; nIgnoredOverlayRepaints = 0; + + { + gamescope::CScriptScopedLock script; + script.Manager().CallHook( "OnPostPaint" ); + } } if ( bIsVBlankFromTimer ) diff --git a/src/wlserver.cpp b/src/wlserver.cpp index 670cf6896d..0a8ee386ca 100644 --- a/src/wlserver.cpp +++ b/src/wlserver.cpp @@ -1155,11 +1155,14 @@ static const struct gamescope_private_interface gamescope_private_impl = { static void gamescope_private_bind( struct wl_client *client, void *data, uint32_t version, uint32_t id ) { struct wl_resource *resource = wl_resource_create( client, &gamescope_private_interface, version, id ); - console_log.m_LoggingListeners[(uintptr_t)resource] = [ resource ]( LogPriority ePriority, std::string_view psvScope, const char *pText ) + console_log.m_LoggingListeners[(uintptr_t)resource] = [ resource ]( LogPriority ePriority, std::string_view psvScope, std::string_view psvText ) { if ( !wlserver_is_lock_held() ) return; - gamescope_private_send_log( resource, pText ); + + // Can't send a length with string on Wayland api currently... :( + std::string sText = std::string{ psvText }; + gamescope_private_send_log( resource, sText.c_str() ); }; wl_resource_set_implementation( resource, &gamescope_private_impl, NULL, [](struct wl_resource *resource) diff --git a/thirdparty/sol/config.hpp b/thirdparty/sol/config.hpp new file mode 100644 index 0000000000..888c336c13 --- /dev/null +++ b/thirdparty/sol/config.hpp @@ -0,0 +1,55 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2024-09-03 03:46:49.901324 UTC +// This header was generated with sol v3.3.1 (revision 2b0d2fe8) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_SOL_CONFIG_HPP +#define SOL_SINGLE_SOL_CONFIG_HPP + +// beginning of sol/config.hpp + +/* Base, empty configuration file! + + To override, place a file in your include paths of the form: + +. (your include path here) +| sol (directory, or equivalent) + | config.hpp (your config.hpp file) + + So that when sol2 includes the file + +#include + + it gives you the configuration values you desire. Configuration values can be +seen in the safety.rst of the doc/src, or at +https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through +the build system, or the command line options of your compiler. + +*/ + +#define SOL_NO_EXCEPTIONS 1 + +// end of sol/config.hpp + +#endif // SOL_SINGLE_SOL_CONFIG_HPP diff --git a/thirdparty/sol/forward.hpp b/thirdparty/sol/forward.hpp new file mode 100644 index 0000000000..453bcdebf1 --- /dev/null +++ b/thirdparty/sol/forward.hpp @@ -0,0 +1,1340 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2024-09-03 03:46:49.899874 UTC +// This header was generated with sol v3.3.1 (revision 2b0d2fe8) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_SOL_FORWARD_HPP +#define SOL_SINGLE_INCLUDE_SOL_FORWARD_HPP + +// beginning of sol/forward.hpp + +#ifndef SOL_FORWARD_HPP +#define SOL_FORWARD_HPP + +// beginning of sol/version.hpp + +#include + +#define SOL_VERSION_MAJOR 3 +#define SOL_VERSION_MINOR 2 +#define SOL_VERSION_PATCH 3 +#define SOL_VERSION_STRING "3.2.3" +#define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH)) + +#define SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN +#define SOL_TOKEN_TO_STRING_I_(_TOKEN) SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) + +#define SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT +#define SOL_CONCAT_TOKENS_I_(_LEFT, _RIGHT) SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) + +#define SOL_RAW_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) +#define SOL_RAW_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) +#define SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) +#define SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) + +#define SOL_IS_ON(OP_SYMBOL) SOL_RAW_IS_ON(OP_SYMBOL ## _I_) +#define SOL_IS_OFF(OP_SYMBOL) SOL_RAW_IS_OFF(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_ON(OP_SYMBOL) SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_OFF(OP_SYMBOL) SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL ## _I_) + +#define SOL_ON | +#define SOL_OFF ^ +#define SOL_DEFAULT_ON + +#define SOL_DEFAULT_OFF - + +#if defined(SOL_BUILD_CXX_MODE) + #if (SOL_BUILD_CXX_MODE != 0) + #define SOL_BUILD_CXX_MODE_I_ SOL_ON + #else + #define SOL_BUILD_CXX_MODE_I_ SOL_OFF + #endif +#elif defined(__cplusplus) + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_BUILD_C_MODE) + #if (SOL_BUILD_C_MODE != 0) + #define SOL_BUILD_C_MODE_I_ SOL_ON + #else + #define SOL_BUILD_C_MODE_I_ SOL_OFF + #endif +#elif defined(__STDC__) + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if SOL_IS_ON(SOL_BUILD_C_MODE) + #include + #include + #include +#else + #include + #include + #include +#endif + +#if defined(SOL_HAS_BUILTIN) + #define SOL_HAS_BUILTIN_I_(...) SOL_HAS_BUILTIN(__VA_ARGS__) +#elif defined(__has_builtin) + #define SOL_HAS_BUILTIN_I_(...) __has_builtin(__VA_ARGS__) +#else + #define SOL_HAS_BUILTIN_I_(...) 0 +#endif + +#if defined(SOL_COMPILER_VCXX) + #if (SOL_COMPILER_VCXX != 0) + #define SOL_COMPILER_VCXX_I_ SOL_ON + #else + #define SOL_COMPILER_VCXX_I_ SOL_OFF + #endif +#elif defined(_MSC_VER) + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_GCC) + #if (SOL_COMPILER_GCC != 0) + #define SOL_COMPILER_GCC_I_ SOL_ON + #else + #define SOL_COMPILER_GCC_I_ SOL_OFF + #endif +#elif defined(__GNUC__) + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_CLANG) + #if (SOL_COMPILER_CLANG != 0) + #define SOL_COMPILER_CLANG_I_ SOL_ON + #else + #define SOL_COMPILER_CLANG_I_ SOL_OFF + #endif +#elif defined(__clang__) + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_EDG) + #if (SOL_COMPILER_EDG != 0) + #define SOL_COMPILER_EDG_I_ SOL_ON + #else + #define SOL_COMPILER_EDG_I_ SOL_OFF + #endif +#else + #define SOL_COMPILER_EDG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_MINGW) + #if (SOL_COMPILER_MINGW != 0) + #define SOL_COMPILER_MINGW_I_ SOL_ON + #else + #define SOL_COMPILER_MINGW_I_ SOL_OFF + #endif +#elif defined(__MINGW32__) + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_OFF +#endif + +#if SIZE_MAX <= 0xFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_ON + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_OFF +#elif SIZE_MAX <= 0xFFFFFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_ON + #define SOL_PLATFORM_X64_I_ SOL_OFF +#else + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_ON +#endif + +#define SOL_PLATFORM_ARM32_I_ SOL_OFF +#define SOL_PLATFORM_ARM64_I_ SOL_OFF + +#if defined(SOL_PLATFORM_WINDOWS) + #if (SOL_PLATFORM_WINDOWS != 0) + #define SOL_PLATFORM_WINDOWS_I_ SOL_ON + #else + #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF + #endif +#elif defined(_WIN32) + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_CYGWIN) + #if (SOL_PLATFORM_CYGWIN != 0) + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #else + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #endif +#elif defined(__CYGWIN__) + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_APPLE) + #if (SOL_PLATFORM_APPLE != 0) + #define SOL_PLATFORM_APPLE_I_ SOL_ON + #else + #define SOL_PLATFORM_APPLE_I_ SOL_OFF + #endif +#elif defined(__APPLE__) + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_UNIX) + #if (SOL_PLATFORM_UNIX != 0) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF + #endif +#elif defined(__unix__) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_LINUX) + #if (SOL_PLATFORM_LINUX != 0) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF + #endif +#elif defined(__LINUX__) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF +#define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF + +#if defined(SOL_IN_DEBUG_DETECTED) + #if (SOL_IN_DEBUG_DETECTED != 0) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#elif !defined(NDEBUG) + #if SOL_IS_ON(SOL_COMPILER_VCXX) && defined(_DEBUG) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #elif (SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC)) && !defined(__OPTIMIZE__) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF +#endif // We are in a debug mode of some sort + +#if defined(SOL_NO_EXCEPTIONS) + #if (SOL_NO_EXCEPTIONS != 0) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPUNWIND) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__EXCEPTIONS) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#else + #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_RTTI) + #if (SOL_NO_RTTI != 0) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPRTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__GXX_RTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#else + #define SOL_RTTI_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_THREAD_LOCAL) + #if (SOL_NO_THREAD_LOCAL != 0) + #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF + #else + #define SOL_USE_THREAD_LOCAL_I_ SOL_ON + #endif +#else + #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON +#endif // thread_local keyword is bjorked on some platforms + +#if defined(SOL_ALL_SAFETIES_ON) + #if (SOL_ALL_SAFETIES_ON != 0) + #define SOL_ALL_SAFETIES_ON_I_ SOL_ON + #else + #define SOL_ALL_SAFETIES_ON_I_ SOL_OFF + #endif +#else + #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_GETTER) + #if (SOL_SAFE_GETTER != 0) + #define SOL_SAFE_GETTER_I_ SOL_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_GETTER_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_USERTYPE) + #if (SOL_SAFE_USERTYPE != 0) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_REFERENCES) + #if (SOL_SAFE_REFERENCES != 0) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTIONS) + #if (SOL_SAFE_FUNCTIONS != 0) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#elif defined (SOL_SAFE_FUNCTION_OBJECTS) + #if (SOL_SAFE_FUNCTION_OBJECTS != 0) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTION_CALLS) + #if (SOL_SAFE_FUNCTION_CALLS != 0) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_PROXIES) + #if (SOL_SAFE_PROXIES != 0) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_NUMERICS) + #if (SOL_SAFE_NUMERICS != 0) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_ALL_INTEGER_VALUES_FIT) + #if (SOL_ALL_INTEGER_VALUES_FIT != 0) + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON + #else + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF + #endif +#elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_SAFE_NUMERICS) + // if numerics is intentionally turned off, flip this on + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON +#else + // default to off + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_STACK_CHECK) + #if (SOL_SAFE_STACK_CHECK != 0) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_CHECK_NUMBER_PRECISION) + #if (SOL_NO_CHECK_NUMBER_PRECISION != 0) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#elif defined(SOL_NO_CHECKING_NUMBER_PRECISION) + #if (SOL_NO_CHECKING_NUMBER_PRECISION != 0) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_SAFE_NUMERICS) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_STRINGS_ARE_NUMBERS) + #if (SOL_STRINGS_ARE_NUMBERS != 0) + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON + #else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF + #endif +#else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ENABLE_INTEROP) + #if (SOL_ENABLE_INTEROP != 0) + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#elif defined(SOL_USE_INTEROP) + #if (SOL_USE_INTEROP != 0) + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#else + #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_NIL) + #if (SOL_NO_NIL != 0) + #define SOL_NIL_I_ SOL_OFF + #else + #define SOL_NIL_I_ SOL_ON + #endif +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) + #define SOL_NIL_I_ SOL_DEFAULT_OFF +#else + #define SOL_NIL_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USERTYPE_TYPE_BINDING_INFO) + #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0) + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON + #else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF + #endif +#else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON +#endif // We should generate a my_type.__type table with lots of class information for usertypes + +#if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT) + #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES) + #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON +#endif // make is_automagical on/off by default + +#if defined(SOL_STD_VARIANT) + #if (SOL_STD_VARIANT != 0) + #define SOL_STD_VARIANT_I_ SOL_ON + #else + #define SOL_STD_VARIANT_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_COMPILER_CLANG) && SOL_IS_ON(SOL_PLATFORM_APPLE) + #if defined(__has_include) + #if __has_include() + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #endif +#endif // make is_automagical on/off by default + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) + #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #endif +#else + #if defined(__cpp_noexcept_function_type) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L)) + // There is a bug in the VC++ compiler?? + // on /std:c++latest under x86 conditions (VS 15.5.2), + // compiler errors are tossed for noexcept markings being on function types + // that are identical in every other way to their non-noexcept marked types function types... + // VS 2019: There is absolutely a bug. + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON + #endif +#endif // noexcept is part of a function's type + +#if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && (SOL_STACK_STRING_OPTIMIZATION_SIZE > 0) + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE +#else + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024 +#endif + +#if defined(SOL_ID_SIZE) && (SOL_ID_SIZE > 0) + #define SOL_ID_SIZE_I_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_I_ 512 +#endif + +#if defined(LUA_IDSIZE) && (LUA_IDSIZE > 0) + #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_I_ 2048 +#endif + +#if defined(SOL_PRINT_ERRORS) + #if (SOL_PRINT_ERRORS != 0) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#endif + +#if defined(SOL_DEFAULT_PASS_ON_ERROR) + #if (SOL_DEFAULT_PASS_ON_ERROR != 0) + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON + #else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUA) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USING_CXX_LUA_I_ SOL_ON + #else + #define SOL_USING_CXX_LUA_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUA) + // alternative spelling + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USING_CXX_LUA_I_ SOL_ON + #else + #define SOL_USING_CXX_LUA_I_ SOL_OFF + #endif +#else + #define SOL_USING_CXX_LUA_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUAJIT) + #if (SOL_USING_CXX_LUAJIT != 0) + #define SOL_USING_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USING_CXX_LUAJIT_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUAJIT) + #if (SOL_USE_CXX_LUAJIT != 0) + #define SOL_USING_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USING_CXX_LUAJIT_I_ SOL_OFF + #endif +#else + #define SOL_USING_CXX_LUAJIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_LUA_HPP) + #if (SOL_NO_LUA_HPP != 0) + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #else + #define SOL_USE_LUA_HPP_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_USING_CXX_LUA) + #define SOL_USE_LUA_HPP_I_ SOL_OFF +#elif defined(__has_include) + #if __has_include() + #define SOL_USE_LUA_HPP_I_ SOL_ON + #else + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #endif +#else + #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_CONTAINERS_START) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START +#elif defined(SOL_CONTAINERS_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX +#elif defined(SOL_CONTAINER_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX +#else + #define SOL_CONTAINER_START_INDEX_I_ 1 +#endif + +#if defined (SOL_NO_MEMORY_ALIGNMENT) + #if (SOL_NO_MEMORY_ALIGNMENT != 0) + #define SOL_ALIGN_MEMORY_I_ SOL_OFF + #else + #define SOL_ALIGN_MEMORY_I_ SOL_ON + #endif +#else + #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USE_BOOST) + #if (SOL_USE_BOOST != 0) + #define SOL_USE_BOOST_I_ SOL_ON + #else + #define SOL_USE_BOOST_I_ SOL_OFF + #endif +#else + #define SOL_USE_BOOST_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USE_UNSAFE_BASE_LOOKUP) + #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0) + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON + #else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF + #endif +#else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_INSIDE_UNREAL) + #if (SOL_INSIDE_UNREAL != 0) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF + #endif +#else + #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_COMPAT) + #if (SOL_NO_COMPAT != 0) + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF + #else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON + #endif +#else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE) + #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0) + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON + #else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF + #endif +#else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CONTAINER_CHECK_IS_EXHAUSTIVE) + #if (SOL_CONTAINER_CHECK_IS_EXHAUSTIVE != 0) + #define SOL_CONTAINER_CHECK_IS_EXHAUSTIVE_I_ SOL_ON + #else + #define SOL_CONTAINER_CHECK_IS_EXHAUSTIVE_I_ SOL_OFF + #endif +#else + #define SOL_CONTAINER_CHECK_IS_EXHAUSTIVE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + #if (SOL_FUNCTION_CALL_VALUE_SEMANTICS != 0) + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_ON + #else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_OFF + #endif +#else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_MINGW_CCTYPE_IS_POISONED) + #if (SOL_MINGW_CCTYPE_IS_POISONED != 0) + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON + #else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_MINGW) && defined(__GNUC__) && (__GNUC__ < 6) + // MinGW is off its rocker in some places... + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_ON +#else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CHAR8_T) + #if (SOL_CHAR8_T != 0) + #define SOL_CHAR8_T_I_ SOL_ON + #else + #define SOL_CHAR8_T_I_ SOL_OFF + #endif +#else + #if defined(__cpp_char8_t) + #define SOL_CHAR8_T_I_ SOL_DEFAULT_ON + #else + #define SOL_CHAR8_T_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if SOL_IS_ON(SOL_USE_BOOST) + #include + + #if BOOST_VERSION >= 107500 // Since Boost 1.75.0 boost::none is constexpr + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr + #else + #define SOL_BOOST_NONE_CONSTEXPR_I_ const + #endif // BOOST_VERSION +#else + // assume boost isn't using a garbage version + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr +#endif + +#if defined(SOL2_CI) + #if (SOL2_CI != 0) + #define SOL2_CI_I_ SOL_ON + #else + #define SOL2_CI_I_ SOL_OFF + #endif +#else + #define SOL2_CI_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ASSERT) + #define SOL_USER_ASSERT_I_ SOL_ON +#else + #define SOL_USER_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ASSERT_MSG) + #define SOL_USER_ASSERT_MSG_I_ SOL_ON +#else + #define SOL_USER_ASSERT_MSG_I_ SOL_DEFAULT_OFF +#endif + +// beginning of sol/prologue.hpp + +#if defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue." +#endif + +#define SOL_PROLOGUE_I_ 1 + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define _FWD(...) static_cast( __VA_ARGS__ ) + + #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) + #else + #include + + #define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) + #endif +#endif + +// end of sol/prologue.hpp + +// beginning of sol/epilogue.hpp + +#if !defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue is missing from this translation unit." +#else + #undef SOL_PROLOGUE_I_ +#endif + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #undef _FWD + #undef _MOVE +#endif + +// end of sol/epilogue.hpp + +// beginning of sol/detail/build_version.hpp + +#if defined(SOL_DLL) + #if (SOL_DLL != 0) + #define SOL_DLL_I_ SOL_ON + #else + #define SOL_DLL_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL)) + #define SOL_DLL_I_ SOL_DEFAULT_ON +#else + #define SOL_DLL_I_ SOL_DEFAULT_OFF +#endif // DLL definition + +#if defined(SOL_HEADER_ONLY) + #if (SOL_HEADER_ONLY != 0) + #define SOL_HEADER_ONLY_I_ SOL_ON + #else + #define SOL_HEADER_ONLY_I_ SOL_OFF + #endif +#else + #define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_BUILD) + #if (SOL_BUILD != 0) + #define SOL_BUILD_I_ SOL_ON + #else + #define SOL_BUILD_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_BUILD_I_ SOL_DEFAULT_OFF +#else + #define SOL_BUILD_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_UNITY_BUILD) + #if (SOL_UNITY_BUILD != 0) + #define SOL_UNITY_BUILD_I_ SOL_ON + #else + #define SOL_UNITY_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_C_FUNCTION_LINKAGE) + #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE +#else + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + // C++ + #define SOL_C_FUNCTION_LINKAGE_I_ extern "C" + #else + // normal + #define SOL_C_FUNCTION_LINKAGE_I_ + #endif // C++ or not +#endif // Linkage specification for C functions + +#if defined(SOL_API_LINKAGE) + #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE +#else + #if SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN) + // MSVC Compiler; or, Windows, or Cygwin platforms + #if SOL_IS_ON(SOL_BUILD) + // Building the library + #if SOL_IS_ON(SOL_COMPILER_GCC) + // Using GCC + #define SOL_API_LINKAGE_I_ __attribute__((dllexport)) + #else + // Using Clang, MSVC, etc... + #define SOL_API_LINKAGE_I_ __declspec(dllexport) + #endif + #else + #if SOL_IS_ON(SOL_COMPILER_GCC) + #define SOL_API_LINKAGE_I_ __attribute__((dllimport)) + #else + #define SOL_API_LINKAGE_I_ __declspec(dllimport) + #endif + #endif + #else + // extern if building normally on non-MSVC + #define SOL_API_LINKAGE_I_ extern + #endif + #elif SOL_IS_ON(SOL_UNITY_BUILD) + // Built-in library, like how stb typical works + #if SOL_IS_ON(SOL_HEADER_ONLY) + // Header only, so functions are defined "inline" + #define SOL_API_LINKAGE_I_ inline + #else + // Not header only, so seperately compiled files + #define SOL_API_LINKAGE_I_ extern + #endif + #else + // Normal static library + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define SOL_API_LINKAGE_I_ + #else + #define SOL_API_LINKAGE_I_ extern + #endif + #endif // DLL or not +#endif // Build definitions + +#if defined(SOL_PUBLIC_FUNC_DECL) + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL +#else + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DECL_) + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_ +#else + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_PUBLIC_FUNC_DEF) + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF +#else + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DEF) + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF +#else + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_FUNC_DECL) + #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_FUNC_DEFN) + #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DEFN_I_ __declspec(dllexport) + #else + #define SOL_FUNC_DEFN_I_ __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DEFN_I_ + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DECL) + #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DEFN) + #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DEFN_I_ + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif +#endif + +// end of sol/detail/build_version.hpp + +// end of sol/version.hpp + +#include +#include +#include + +#if SOL_IS_ON(SOL_USING_CXX_LUA) || SOL_IS_ON(SOL_USING_CXX_LUAJIT) +struct lua_State; +#else +extern "C" { +struct lua_State; +} +#endif // C++ Mangling for Lua vs. Not + +namespace sol { + + enum class type; + + class stateless_reference; + template + class basic_reference; + using reference = basic_reference; + using main_reference = basic_reference; + class stateless_stack_reference; + class stack_reference; + + template + class basic_bytecode; + + struct lua_value; + + struct proxy_base_tag; + template + struct proxy_base; + template + struct table_proxy; + + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using main_table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = basic_table_core; + using table = table_core; + using global_table = table_core; + using main_table = main_table_core; + using main_global_table = main_table_core; + using stack_table = stack_table_core; + using stack_global_table = stack_table_core; + + template + struct basic_lua_table; + using lua_table = basic_lua_table; + using stack_lua_table = basic_lua_table; + + template + class basic_usertype; + template + using usertype = basic_usertype; + template + using stack_usertype = basic_usertype; + + template + class basic_metatable; + using metatable = basic_metatable; + using stack_metatable = basic_metatable; + + template + struct basic_environment; + using environment = basic_environment; + using main_environment = basic_environment; + using stack_environment = basic_environment; + + template + class basic_function; + template + class basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using main_unsafe_function = basic_function; + using main_safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; + using stack_aligned_unsafe_function = basic_function; + using stack_aligned_safe_function = basic_protected_function; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; + using stack_aligned_function = stack_aligned_safe_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; + using stack_aligned_function = stack_aligned_unsafe_function; +#endif + using stack_aligned_stack_handler_function = basic_protected_function; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template + class basic_object_base; + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + template + class basic_coroutine; + template + class basic_packaged_coroutine; + template + class basic_thread; + + using object = basic_object; + using userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using thread = basic_thread; + using coroutine = basic_coroutine; + using packaged_coroutine = basic_packaged_coroutine; + using main_object = basic_object; + using main_userdata = basic_userdata; + using main_lightuserdata = basic_lightuserdata; + using main_coroutine = basic_coroutine; + using stack_object = basic_object; + using stack_userdata = basic_userdata; + using stack_lightuserdata = basic_lightuserdata; + using stack_thread = basic_thread; + using stack_coroutine = basic_coroutine; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + class state_view; + class state; + + template + struct as_table_t; + template + struct as_container_t; + template + struct nested; + template + struct light; + template + struct user; + template + struct as_args_t; + template + struct protect_t; + template + struct policy_wrapper; + + template + struct usertype_traits; + template + struct unique_usertype_traits; + + template + struct types { + typedef std::make_index_sequence indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + + template + struct derive : std::false_type { + typedef types<> type; + }; + + template + struct base : std::false_type { + typedef types<> type; + }; + + template + struct weak_derive { + static bool value; + }; + + template + bool weak_derive::value = false; + + namespace stack { + struct record; + } + +#if SOL_IS_OFF(SOL_USE_BOOST) + template + class optional; + + template + class optional; +#endif + + using check_handler_type = int(lua_State*, int, type, type, const char*); + +} // namespace sol + +#define SOL_BASE_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct base : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + static_assert(true, "") +#define SOL_DERIVED_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct derive : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + static_assert(true, "") + +#endif // SOL_FORWARD_HPP +// end of sol/forward.hpp + +#endif // SOL_SINGLE_INCLUDE_SOL_FORWARD_HPP diff --git a/thirdparty/sol/sol.hpp b/thirdparty/sol/sol.hpp new file mode 100644 index 0000000000..2197ef5a7c --- /dev/null +++ b/thirdparty/sol/sol.hpp @@ -0,0 +1,29208 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2024-09-03 03:46:49.867770 UTC +// This header was generated with sol v3.3.1 (revision 2b0d2fe8) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_SOL_HPP +#define SOL_SINGLE_INCLUDE_SOL_HPP + +// beginning of sol/sol.hpp + +#ifndef SOL_HPP +#define SOL_HPP + +// beginning of sol/version.hpp + +#include + +#define SOL_VERSION_MAJOR 3 +#define SOL_VERSION_MINOR 2 +#define SOL_VERSION_PATCH 3 +#define SOL_VERSION_STRING "3.2.3" +#define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH)) + +#define SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN +#define SOL_TOKEN_TO_STRING_I_(_TOKEN) SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) + +#define SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT +#define SOL_CONCAT_TOKENS_I_(_LEFT, _RIGHT) SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) + +#define SOL_RAW_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) +#define SOL_RAW_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) +#define SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) +#define SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) + +#define SOL_IS_ON(OP_SYMBOL) SOL_RAW_IS_ON(OP_SYMBOL ## _I_) +#define SOL_IS_OFF(OP_SYMBOL) SOL_RAW_IS_OFF(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_ON(OP_SYMBOL) SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_OFF(OP_SYMBOL) SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL ## _I_) + +#define SOL_ON | +#define SOL_OFF ^ +#define SOL_DEFAULT_ON + +#define SOL_DEFAULT_OFF - + +#if defined(SOL_BUILD_CXX_MODE) + #if (SOL_BUILD_CXX_MODE != 0) + #define SOL_BUILD_CXX_MODE_I_ SOL_ON + #else + #define SOL_BUILD_CXX_MODE_I_ SOL_OFF + #endif +#elif defined(__cplusplus) + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_BUILD_C_MODE) + #if (SOL_BUILD_C_MODE != 0) + #define SOL_BUILD_C_MODE_I_ SOL_ON + #else + #define SOL_BUILD_C_MODE_I_ SOL_OFF + #endif +#elif defined(__STDC__) + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if SOL_IS_ON(SOL_BUILD_C_MODE) + #include + #include + #include +#else + #include + #include + #include +#endif + +#if defined(SOL_HAS_BUILTIN) + #define SOL_HAS_BUILTIN_I_(...) SOL_HAS_BUILTIN(__VA_ARGS__) +#elif defined(__has_builtin) + #define SOL_HAS_BUILTIN_I_(...) __has_builtin(__VA_ARGS__) +#else + #define SOL_HAS_BUILTIN_I_(...) 0 +#endif + +#if defined(SOL_COMPILER_VCXX) + #if (SOL_COMPILER_VCXX != 0) + #define SOL_COMPILER_VCXX_I_ SOL_ON + #else + #define SOL_COMPILER_VCXX_I_ SOL_OFF + #endif +#elif defined(_MSC_VER) + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_GCC) + #if (SOL_COMPILER_GCC != 0) + #define SOL_COMPILER_GCC_I_ SOL_ON + #else + #define SOL_COMPILER_GCC_I_ SOL_OFF + #endif +#elif defined(__GNUC__) + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_CLANG) + #if (SOL_COMPILER_CLANG != 0) + #define SOL_COMPILER_CLANG_I_ SOL_ON + #else + #define SOL_COMPILER_CLANG_I_ SOL_OFF + #endif +#elif defined(__clang__) + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_EDG) + #if (SOL_COMPILER_EDG != 0) + #define SOL_COMPILER_EDG_I_ SOL_ON + #else + #define SOL_COMPILER_EDG_I_ SOL_OFF + #endif +#else + #define SOL_COMPILER_EDG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_MINGW) + #if (SOL_COMPILER_MINGW != 0) + #define SOL_COMPILER_MINGW_I_ SOL_ON + #else + #define SOL_COMPILER_MINGW_I_ SOL_OFF + #endif +#elif defined(__MINGW32__) + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_OFF +#endif + +#if SIZE_MAX <= 0xFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_ON + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_OFF +#elif SIZE_MAX <= 0xFFFFFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_ON + #define SOL_PLATFORM_X64_I_ SOL_OFF +#else + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_ON +#endif + +#define SOL_PLATFORM_ARM32_I_ SOL_OFF +#define SOL_PLATFORM_ARM64_I_ SOL_OFF + +#if defined(SOL_PLATFORM_WINDOWS) + #if (SOL_PLATFORM_WINDOWS != 0) + #define SOL_PLATFORM_WINDOWS_I_ SOL_ON + #else + #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF + #endif +#elif defined(_WIN32) + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_CYGWIN) + #if (SOL_PLATFORM_CYGWIN != 0) + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #else + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #endif +#elif defined(__CYGWIN__) + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_APPLE) + #if (SOL_PLATFORM_APPLE != 0) + #define SOL_PLATFORM_APPLE_I_ SOL_ON + #else + #define SOL_PLATFORM_APPLE_I_ SOL_OFF + #endif +#elif defined(__APPLE__) + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_UNIX) + #if (SOL_PLATFORM_UNIX != 0) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF + #endif +#elif defined(__unix__) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_LINUX) + #if (SOL_PLATFORM_LINUX != 0) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF + #endif +#elif defined(__LINUX__) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF +#define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF + +#if defined(SOL_IN_DEBUG_DETECTED) + #if (SOL_IN_DEBUG_DETECTED != 0) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#elif !defined(NDEBUG) + #if SOL_IS_ON(SOL_COMPILER_VCXX) && defined(_DEBUG) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #elif (SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC)) && !defined(__OPTIMIZE__) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF +#endif // We are in a debug mode of some sort + +#if defined(SOL_NO_EXCEPTIONS) + #if (SOL_NO_EXCEPTIONS != 0) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPUNWIND) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__EXCEPTIONS) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#else + #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_RTTI) + #if (SOL_NO_RTTI != 0) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPRTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__GXX_RTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#else + #define SOL_RTTI_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_THREAD_LOCAL) + #if (SOL_NO_THREAD_LOCAL != 0) + #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF + #else + #define SOL_USE_THREAD_LOCAL_I_ SOL_ON + #endif +#else + #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON +#endif // thread_local keyword is bjorked on some platforms + +#if defined(SOL_ALL_SAFETIES_ON) + #if (SOL_ALL_SAFETIES_ON != 0) + #define SOL_ALL_SAFETIES_ON_I_ SOL_ON + #else + #define SOL_ALL_SAFETIES_ON_I_ SOL_OFF + #endif +#else + #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_GETTER) + #if (SOL_SAFE_GETTER != 0) + #define SOL_SAFE_GETTER_I_ SOL_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_GETTER_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_USERTYPE) + #if (SOL_SAFE_USERTYPE != 0) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_REFERENCES) + #if (SOL_SAFE_REFERENCES != 0) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTIONS) + #if (SOL_SAFE_FUNCTIONS != 0) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#elif defined (SOL_SAFE_FUNCTION_OBJECTS) + #if (SOL_SAFE_FUNCTION_OBJECTS != 0) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTION_CALLS) + #if (SOL_SAFE_FUNCTION_CALLS != 0) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_PROXIES) + #if (SOL_SAFE_PROXIES != 0) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_NUMERICS) + #if (SOL_SAFE_NUMERICS != 0) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_ALL_INTEGER_VALUES_FIT) + #if (SOL_ALL_INTEGER_VALUES_FIT != 0) + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON + #else + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF + #endif +#elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_SAFE_NUMERICS) + // if numerics is intentionally turned off, flip this on + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON +#else + // default to off + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_STACK_CHECK) + #if (SOL_SAFE_STACK_CHECK != 0) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_CHECK_NUMBER_PRECISION) + #if (SOL_NO_CHECK_NUMBER_PRECISION != 0) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#elif defined(SOL_NO_CHECKING_NUMBER_PRECISION) + #if (SOL_NO_CHECKING_NUMBER_PRECISION != 0) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_SAFE_NUMERICS) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_STRINGS_ARE_NUMBERS) + #if (SOL_STRINGS_ARE_NUMBERS != 0) + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON + #else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF + #endif +#else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ENABLE_INTEROP) + #if (SOL_ENABLE_INTEROP != 0) + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#elif defined(SOL_USE_INTEROP) + #if (SOL_USE_INTEROP != 0) + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#else + #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_NIL) + #if (SOL_NO_NIL != 0) + #define SOL_NIL_I_ SOL_OFF + #else + #define SOL_NIL_I_ SOL_ON + #endif +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) + #define SOL_NIL_I_ SOL_DEFAULT_OFF +#else + #define SOL_NIL_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USERTYPE_TYPE_BINDING_INFO) + #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0) + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON + #else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF + #endif +#else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON +#endif // We should generate a my_type.__type table with lots of class information for usertypes + +#if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT) + #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES) + #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON +#endif // make is_automagical on/off by default + +#if defined(SOL_STD_VARIANT) + #if (SOL_STD_VARIANT != 0) + #define SOL_STD_VARIANT_I_ SOL_ON + #else + #define SOL_STD_VARIANT_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_COMPILER_CLANG) && SOL_IS_ON(SOL_PLATFORM_APPLE) + #if defined(__has_include) + #if __has_include() + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #endif +#endif // make is_automagical on/off by default + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) + #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #endif +#else + #if defined(__cpp_noexcept_function_type) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L)) + // There is a bug in the VC++ compiler?? + // on /std:c++latest under x86 conditions (VS 15.5.2), + // compiler errors are tossed for noexcept markings being on function types + // that are identical in every other way to their non-noexcept marked types function types... + // VS 2019: There is absolutely a bug. + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON + #endif +#endif // noexcept is part of a function's type + +#if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && (SOL_STACK_STRING_OPTIMIZATION_SIZE > 0) + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE +#else + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024 +#endif + +#if defined(SOL_ID_SIZE) && (SOL_ID_SIZE > 0) + #define SOL_ID_SIZE_I_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_I_ 512 +#endif + +#if defined(LUA_IDSIZE) && (LUA_IDSIZE > 0) + #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_I_ 2048 +#endif + +#if defined(SOL_PRINT_ERRORS) + #if (SOL_PRINT_ERRORS != 0) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#endif + +#if defined(SOL_DEFAULT_PASS_ON_ERROR) + #if (SOL_DEFAULT_PASS_ON_ERROR != 0) + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON + #else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUA) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USING_CXX_LUA_I_ SOL_ON + #else + #define SOL_USING_CXX_LUA_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUA) + // alternative spelling + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USING_CXX_LUA_I_ SOL_ON + #else + #define SOL_USING_CXX_LUA_I_ SOL_OFF + #endif +#else + #define SOL_USING_CXX_LUA_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUAJIT) + #if (SOL_USING_CXX_LUAJIT != 0) + #define SOL_USING_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USING_CXX_LUAJIT_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUAJIT) + #if (SOL_USE_CXX_LUAJIT != 0) + #define SOL_USING_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USING_CXX_LUAJIT_I_ SOL_OFF + #endif +#else + #define SOL_USING_CXX_LUAJIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_LUA_HPP) + #if (SOL_NO_LUA_HPP != 0) + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #else + #define SOL_USE_LUA_HPP_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_USING_CXX_LUA) + #define SOL_USE_LUA_HPP_I_ SOL_OFF +#elif defined(__has_include) + #if __has_include() + #define SOL_USE_LUA_HPP_I_ SOL_ON + #else + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #endif +#else + #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_CONTAINERS_START) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START +#elif defined(SOL_CONTAINERS_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX +#elif defined(SOL_CONTAINER_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX +#else + #define SOL_CONTAINER_START_INDEX_I_ 1 +#endif + +#if defined (SOL_NO_MEMORY_ALIGNMENT) + #if (SOL_NO_MEMORY_ALIGNMENT != 0) + #define SOL_ALIGN_MEMORY_I_ SOL_OFF + #else + #define SOL_ALIGN_MEMORY_I_ SOL_ON + #endif +#else + #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USE_BOOST) + #if (SOL_USE_BOOST != 0) + #define SOL_USE_BOOST_I_ SOL_ON + #else + #define SOL_USE_BOOST_I_ SOL_OFF + #endif +#else + #define SOL_USE_BOOST_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USE_UNSAFE_BASE_LOOKUP) + #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0) + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON + #else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF + #endif +#else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_INSIDE_UNREAL) + #if (SOL_INSIDE_UNREAL != 0) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF + #endif +#else + #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_COMPAT) + #if (SOL_NO_COMPAT != 0) + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF + #else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON + #endif +#else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE) + #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0) + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON + #else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF + #endif +#else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CONTAINER_CHECK_IS_EXHAUSTIVE) + #if (SOL_CONTAINER_CHECK_IS_EXHAUSTIVE != 0) + #define SOL_CONTAINER_CHECK_IS_EXHAUSTIVE_I_ SOL_ON + #else + #define SOL_CONTAINER_CHECK_IS_EXHAUSTIVE_I_ SOL_OFF + #endif +#else + #define SOL_CONTAINER_CHECK_IS_EXHAUSTIVE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + #if (SOL_FUNCTION_CALL_VALUE_SEMANTICS != 0) + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_ON + #else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_OFF + #endif +#else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_MINGW_CCTYPE_IS_POISONED) + #if (SOL_MINGW_CCTYPE_IS_POISONED != 0) + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON + #else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_MINGW) && defined(__GNUC__) && (__GNUC__ < 6) + // MinGW is off its rocker in some places... + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_ON +#else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CHAR8_T) + #if (SOL_CHAR8_T != 0) + #define SOL_CHAR8_T_I_ SOL_ON + #else + #define SOL_CHAR8_T_I_ SOL_OFF + #endif +#else + #if defined(__cpp_char8_t) + #define SOL_CHAR8_T_I_ SOL_DEFAULT_ON + #else + #define SOL_CHAR8_T_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if SOL_IS_ON(SOL_USE_BOOST) + #include + + #if BOOST_VERSION >= 107500 // Since Boost 1.75.0 boost::none is constexpr + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr + #else + #define SOL_BOOST_NONE_CONSTEXPR_I_ const + #endif // BOOST_VERSION +#else + // assume boost isn't using a garbage version + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr +#endif + +#if defined(SOL2_CI) + #if (SOL2_CI != 0) + #define SOL2_CI_I_ SOL_ON + #else + #define SOL2_CI_I_ SOL_OFF + #endif +#else + #define SOL2_CI_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ASSERT) + #define SOL_USER_ASSERT_I_ SOL_ON +#else + #define SOL_USER_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ASSERT_MSG) + #define SOL_USER_ASSERT_MSG_I_ SOL_ON +#else + #define SOL_USER_ASSERT_MSG_I_ SOL_DEFAULT_OFF +#endif + +// beginning of sol/prologue.hpp + +#if defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue." +#endif + +#define SOL_PROLOGUE_I_ 1 + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define _FWD(...) static_cast( __VA_ARGS__ ) + + #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) + #else + #include + + #define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) + #endif +#endif + +// end of sol/prologue.hpp + +// beginning of sol/epilogue.hpp + +#if !defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue is missing from this translation unit." +#else + #undef SOL_PROLOGUE_I_ +#endif + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #undef _FWD + #undef _MOVE +#endif + +// end of sol/epilogue.hpp + +// beginning of sol/detail/build_version.hpp + +#if defined(SOL_DLL) + #if (SOL_DLL != 0) + #define SOL_DLL_I_ SOL_ON + #else + #define SOL_DLL_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL)) + #define SOL_DLL_I_ SOL_DEFAULT_ON +#else + #define SOL_DLL_I_ SOL_DEFAULT_OFF +#endif // DLL definition + +#if defined(SOL_HEADER_ONLY) + #if (SOL_HEADER_ONLY != 0) + #define SOL_HEADER_ONLY_I_ SOL_ON + #else + #define SOL_HEADER_ONLY_I_ SOL_OFF + #endif +#else + #define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_BUILD) + #if (SOL_BUILD != 0) + #define SOL_BUILD_I_ SOL_ON + #else + #define SOL_BUILD_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_BUILD_I_ SOL_DEFAULT_OFF +#else + #define SOL_BUILD_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_UNITY_BUILD) + #if (SOL_UNITY_BUILD != 0) + #define SOL_UNITY_BUILD_I_ SOL_ON + #else + #define SOL_UNITY_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_C_FUNCTION_LINKAGE) + #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE +#else + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + // C++ + #define SOL_C_FUNCTION_LINKAGE_I_ extern "C" + #else + // normal + #define SOL_C_FUNCTION_LINKAGE_I_ + #endif // C++ or not +#endif // Linkage specification for C functions + +#if defined(SOL_API_LINKAGE) + #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE +#else + #if SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN) + // MSVC Compiler; or, Windows, or Cygwin platforms + #if SOL_IS_ON(SOL_BUILD) + // Building the library + #if SOL_IS_ON(SOL_COMPILER_GCC) + // Using GCC + #define SOL_API_LINKAGE_I_ __attribute__((dllexport)) + #else + // Using Clang, MSVC, etc... + #define SOL_API_LINKAGE_I_ __declspec(dllexport) + #endif + #else + #if SOL_IS_ON(SOL_COMPILER_GCC) + #define SOL_API_LINKAGE_I_ __attribute__((dllimport)) + #else + #define SOL_API_LINKAGE_I_ __declspec(dllimport) + #endif + #endif + #else + // extern if building normally on non-MSVC + #define SOL_API_LINKAGE_I_ extern + #endif + #elif SOL_IS_ON(SOL_UNITY_BUILD) + // Built-in library, like how stb typical works + #if SOL_IS_ON(SOL_HEADER_ONLY) + // Header only, so functions are defined "inline" + #define SOL_API_LINKAGE_I_ inline + #else + // Not header only, so seperately compiled files + #define SOL_API_LINKAGE_I_ extern + #endif + #else + // Normal static library + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define SOL_API_LINKAGE_I_ + #else + #define SOL_API_LINKAGE_I_ extern + #endif + #endif // DLL or not +#endif // Build definitions + +#if defined(SOL_PUBLIC_FUNC_DECL) + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL +#else + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DECL_) + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_ +#else + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_PUBLIC_FUNC_DEF) + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF +#else + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DEF) + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF +#else + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_FUNC_DECL) + #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_FUNC_DEFN) + #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DEFN_I_ __declspec(dllexport) + #else + #define SOL_FUNC_DEFN_I_ __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DEFN_I_ + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DECL) + #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DEFN) + #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DEFN_I_ + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif +#endif + +// end of sol/detail/build_version.hpp + +// end of sol/version.hpp + +#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE) +#ifdef check +#pragma push_macro("check") +#undef check +#endif +#endif // Unreal Engine 4 Bullshit + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wconversion" +#if __GNUC__ > 6 +#pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) +#elif SOL_IS_ON(SOL_COMPILER_VCXX) +#pragma warning(push) +#pragma warning(disable : 4505) // unreferenced local function has been removed GEE THANKS +#endif // clang++ vs. g++ vs. VC++ + +// beginning of sol/forward.hpp + +#ifndef SOL_FORWARD_HPP +#define SOL_FORWARD_HPP + +#include +#include +#include + +#if SOL_IS_ON(SOL_USING_CXX_LUA) || SOL_IS_ON(SOL_USING_CXX_LUAJIT) +struct lua_State; +#else +extern "C" { +struct lua_State; +} +#endif // C++ Mangling for Lua vs. Not + +namespace sol { + + enum class type; + + class stateless_reference; + template + class basic_reference; + using reference = basic_reference; + using main_reference = basic_reference; + class stateless_stack_reference; + class stack_reference; + + template + class basic_bytecode; + + struct lua_value; + + struct proxy_base_tag; + template + struct proxy_base; + template + struct table_proxy; + + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using main_table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = basic_table_core; + using table = table_core; + using global_table = table_core; + using main_table = main_table_core; + using main_global_table = main_table_core; + using stack_table = stack_table_core; + using stack_global_table = stack_table_core; + + template + struct basic_lua_table; + using lua_table = basic_lua_table; + using stack_lua_table = basic_lua_table; + + template + class basic_usertype; + template + using usertype = basic_usertype; + template + using stack_usertype = basic_usertype; + + template + class basic_metatable; + using metatable = basic_metatable; + using stack_metatable = basic_metatable; + + template + struct basic_environment; + using environment = basic_environment; + using main_environment = basic_environment; + using stack_environment = basic_environment; + + template + class basic_function; + template + class basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using main_unsafe_function = basic_function; + using main_safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; + using stack_aligned_unsafe_function = basic_function; + using stack_aligned_safe_function = basic_protected_function; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; + using stack_aligned_function = stack_aligned_safe_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; + using stack_aligned_function = stack_aligned_unsafe_function; +#endif + using stack_aligned_stack_handler_function = basic_protected_function; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template + class basic_object_base; + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + template + class basic_coroutine; + template + class basic_packaged_coroutine; + template + class basic_thread; + + using object = basic_object; + using userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using thread = basic_thread; + using coroutine = basic_coroutine; + using packaged_coroutine = basic_packaged_coroutine; + using main_object = basic_object; + using main_userdata = basic_userdata; + using main_lightuserdata = basic_lightuserdata; + using main_coroutine = basic_coroutine; + using stack_object = basic_object; + using stack_userdata = basic_userdata; + using stack_lightuserdata = basic_lightuserdata; + using stack_thread = basic_thread; + using stack_coroutine = basic_coroutine; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + class state_view; + class state; + + template + struct as_table_t; + template + struct as_container_t; + template + struct nested; + template + struct light; + template + struct user; + template + struct as_args_t; + template + struct protect_t; + template + struct policy_wrapper; + + template + struct usertype_traits; + template + struct unique_usertype_traits; + + template + struct types { + typedef std::make_index_sequence indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + + template + struct derive : std::false_type { + typedef types<> type; + }; + + template + struct base : std::false_type { + typedef types<> type; + }; + + template + struct weak_derive { + static bool value; + }; + + template + bool weak_derive::value = false; + + namespace stack { + struct record; + } + +#if SOL_IS_OFF(SOL_USE_BOOST) + template + class optional; + + template + class optional; +#endif + + using check_handler_type = int(lua_State*, int, type, type, const char*); + +} // namespace sol + +#define SOL_BASE_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct base : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + static_assert(true, "") +#define SOL_DERIVED_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct derive : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + static_assert(true, "") + +#endif // SOL_FORWARD_HPP +// end of sol/forward.hpp + +// beginning of sol/forward_detail.hpp + +#ifndef SOL_FORWARD_DETAIL_HPP +#define SOL_FORWARD_DETAIL_HPP + +// beginning of sol/traits.hpp + +// beginning of sol/tuple.hpp + +// beginning of sol/base_traits.hpp + +#include + +namespace sol { + namespace detail { + struct unchecked_t { }; + const unchecked_t unchecked = unchecked_t {}; + } // namespace detail + + namespace meta { + using sfinae_yes_t = std::true_type; + using sfinae_no_t = std::false_type; + + template + using void_t = void; + + template + using unqualified = std::remove_cv>; + + template + using unqualified_t = typename unqualified::type; + + namespace meta_detail { + template + struct unqualified_non_alias : unqualified { }; + + template