557be7cf1b
* Use XRandR 1.2 to set fullscreen resolution for single output Squash of roothorick's PR #497 (also includes Kyzentun's CMake changes from PR #716) * Cherry-pick json c++1x stuff (b9e3d7174e) * Cherry-pick c++11 support from 5bba5c0038 and 9f8b045309 * rework Linux (X11) fullscreen, improve display-related Graphics Options Implement option to select between monitors for exclusive fullscreen mode on X11 (using XRandR 1.2), or use a fullscreen borderless window. Reimplement resolution/refresh rate/display mode-related option rows using Lua, update choices dynamically so only known-good groupings of resolution/refresh rate/aspect ratio can be selected. Minimally update Windows/MacOS LowLevelWindow implementations to support changes made for Linux side. Fullscreen Borderless Window/multi monitor support from X11 not implemented for those in this commit. * allow forcibly disabling xinerama use on Linux When libXinerama is available, SM tries to use it to find the proper monitor indexes to use to set _NET_WM_FULLSCREEN_MONITORS (on borderless fullscreen). xfwm4 seems to assume that monitors are numbered in increasing order from left to right (rather than using the Xinerama-assigned numbers), so _NET_WM_FULLSCREEN_MONITORS misbehaves on Xfce. This commit bypasses use of libXinerama, and instead forces SM to induce fullscreen on the desired monitor in the backup, hacky way: remove all window hints, move window to desired monitor, then add _NET_WM_STATE_FULLSCREEN hint. This works on mutter and Xfce. * Remove multiple warnings on redundant define. This used to be hard-coded due to pthread related items, but now it's dynamically determined. * fix _fallback menu behavior for unrecognized aspect ratios * Fix error recreating existing FS texture * Bump deployment target to 10.7 to use libc++ on XCode 8 * Add explicit casts to please clang * Update changelog
163 lines
6.9 KiB
Lua
163 lines
6.9 KiB
Lua
-- This will discuss how to create an option row in lua for use on a normal options screen.
|
|
|
|
-- To try out this example, copy this file to Scripts/ and add the following
|
|
-- line to metrics.ini, on one of the options screens. Change the "1" to an
|
|
-- appropriate line name and make sure it's in the LineNames list for that
|
|
-- screen.
|
|
-- Line1="lua,FooMods()"
|
|
|
|
-- Make sure you test this with Player 2, Player 1 can't interact with this
|
|
-- option row as part of the example.
|
|
-- When on the screen testing the example, flush the log and read it when
|
|
-- interacting with the option row. This example doesn't actually apply any
|
|
-- modifiers to the player, it just prints messages to the log file so you can
|
|
-- see what functions are being called.
|
|
|
|
-- Comments explaining an element come before the element they explain.
|
|
|
|
-- The function "FooMods" returns a table containing all the information the
|
|
-- option row handler needs to build the option row.
|
|
function FooMods()
|
|
return {
|
|
-- A string with the name of the row. This name will be localized using
|
|
-- the entry in the "OptionTitles" section of the language file.
|
|
Name= "Foo",
|
|
|
|
-- A boolean that controls whether this row goes to the "next row"
|
|
-- element when NavigationMode for the screen is "toggle" and the
|
|
-- ArcadeOptionsNavigation preference is 1.
|
|
GoToFirstOnStart= false,
|
|
|
|
-- A boolean controlling whether the choice affects all players.
|
|
OneChoiceForAllPlayers= false,
|
|
|
|
-- A boolean controlling whether SaveSelections is called after every
|
|
-- change. If this is true, SaveSelections will be called every time
|
|
-- the player moves the cursor on the row.
|
|
ExportOnChange= false,
|
|
|
|
-- A LayoutType enum value. "ShowAllInRow" shows all items in the row,
|
|
-- "ShowOneInRow" shows only the choice with focus is shown.
|
|
-- "ShowOneInRow" is forced if there are enough choices that they would go
|
|
-- off screen.
|
|
LayoutType= "ShowAllInRow",
|
|
|
|
-- A SelectType enum value. "SelectOne" allows only one choice to be
|
|
-- selected. "SelectMultiple" allows multiple to be selected.
|
|
-- "SelectNone" allows none to be selected.
|
|
SelectType= "SelectMultiple",
|
|
|
|
-- Optional function. If non-nil, this function must return a table of
|
|
-- PlayerNumbers that are allowed to use the row.
|
|
-- A row that can't be used by one player can be confusing for the players
|
|
-- so consider carefully before using this.
|
|
-- This function will be called an extra time during loading to ensure
|
|
-- it returns a table.
|
|
EnabledForPlayers= function(self)
|
|
Trace("FooMods:EnabledForPlayers() called.")
|
|
-- Leave out PLAYER_1 just for example.
|
|
return {PLAYER_2}
|
|
end,
|
|
|
|
-- Optional function. If non-nil, this function must return the string representation
|
|
-- of a member of the ReloadChanged enum. This function is called in response to a message
|
|
-- listed in the optional ReloadRowMessages table below. For example,
|
|
-- to completely change the Choices presented by this OptionRow, modify
|
|
-- self.Choices in the body of this function and return "ReloadChanged_All"
|
|
Reload= function(self)
|
|
Trace("FooMods:Reload() called.")
|
|
return "ReloadChanged_None"
|
|
end,
|
|
|
|
-- A table of strings that are the names of choices. Choice names are not
|
|
-- localized.
|
|
Choices= {"a", "b", "c", "d"},
|
|
|
|
-- Optional table. If non-nil, this table must contain a list of messages
|
|
-- this row should listen for. If one of the messages is recieved, the
|
|
-- row is reloaded (and each of the EnabledForPlayers/Reload functions is called if it is
|
|
-- non-nil).
|
|
ReloadRowMessages= {"ReloadFooMods"},
|
|
|
|
-- LoadSelections should examine the player and figure out which options
|
|
-- on the row the player has selected.
|
|
-- self is the table returned by the original function used to create the
|
|
-- option row. (the table being created right now).
|
|
-- list is a table of bools, all initially false. Set them to true to
|
|
-- indicate which options are on.
|
|
-- pn is the PlayerNumber of the player the selections are for.
|
|
LoadSelections= function(self, list, pn)
|
|
Trace("FooMods:LoadSelections(" .. pn .. ")")
|
|
for i, choice in ipairs(self.Choices) do
|
|
-- Randomly set some to true just for an example.
|
|
if math.random(0, 1) == 1 then
|
|
Trace(choice .. " (" .. i .. ")" .. " set to true.")
|
|
list[i]= true
|
|
end
|
|
end
|
|
end,
|
|
|
|
-- SaveSelections should examine the list of what the player has selected
|
|
-- and apply the appropriate modifiers to the player.
|
|
-- Same args as LoadSelections.
|
|
--
|
|
-- May optionally return an "effects" bit mask (constructed by combination of
|
|
-- the bit masks from the OptEffect enum), which dictates actions the
|
|
-- game should take in response to the selected option. For example,
|
|
-- OPT_SAVE_PREFERENCES directs the game to save Preferences.ini,
|
|
-- OPT_APPLY_ASPECT_RATIO directs the game to recompute the projection matrix, etc.
|
|
SaveSelections= function(self, list, pn)
|
|
Trace("FooMods:SaveSelections(" .. pn .. ")")
|
|
for i, choice in ipairs(self.Choices) do
|
|
if list[i] then
|
|
Trace(choice .. " (" .. i .. ")" .. " set to true.")
|
|
end
|
|
end
|
|
end,
|
|
|
|
-- Optional function. If non-nil, this function must take 3 parameters
|
|
-- (self, pn, choice), and return a bool. It is called when a player
|
|
-- selects an item in the row by pressing start.
|
|
-- self is the same as for LoadSelections.
|
|
-- pn is the PlayerNumber of the player that made the selection.
|
|
-- choice is the choice the player's cursor is on.
|
|
-- The return value should be true if the Choices table is changed. If it
|
|
-- is true, then LoadSelections will be called to update which choices are
|
|
-- underlined for each player.
|
|
-- This function is meant to provide a way for a menu to change the text of
|
|
-- its choices. If it returns true, LoadSelections will be called for each
|
|
-- player. If OneChoiceForAllPlayers is true, this function will be called
|
|
-- for each player, which means LoadSelections will be called twice for
|
|
-- each player. Well written code shouldn't have a problem with this.
|
|
NotifyOfSelection= function(self, pn, choice)
|
|
Trace("FooMods:NotifyOfSelection(" .. pn .. ", " .. choice .. ")")
|
|
-- Randomly decide whether to change, as an example.
|
|
local change= math.random(0, 3)
|
|
-- No change half the time, lengthen or clip strings the other half.
|
|
if change < 2 then
|
|
Trace("Not changing choices.")
|
|
else
|
|
Trace("Changing choices.")
|
|
end
|
|
if change == 2 then
|
|
for i, choice in ipairs(self.Choices) do
|
|
self.Choices[i]= choice .. choice
|
|
end
|
|
elseif change == 3 then
|
|
for i, choice in ipairs(self.Choices) do
|
|
self.Choices[i]= choice:sub(1, 1)
|
|
end
|
|
end
|
|
-- Don't actually broadcast a reload message from here, do it from some
|
|
-- other place that actually has a reason to trigger a reload. This is
|
|
-- just here so that nothing needs to be added to a screen's lua files
|
|
-- for this example.
|
|
if math.random(0, 5) == 0 then
|
|
Trace("Broadcasting reload message.")
|
|
MESSAGEMAN:Broadcast("ReloadFooMods")
|
|
end
|
|
return change >= 2
|
|
end
|
|
}
|
|
end
|