diff --git a/Docs/Changelog_sm5.txt b/Docs/Changelog_sm5.txt
index a1a191eb6e..e7146c1df8 100644
--- a/Docs/Changelog_sm5.txt
+++ b/Docs/Changelog_sm5.txt
@@ -4,6 +4,15 @@ The StepMania 5 Changelog covers all post-sm-ssc changes. For a list of changes
from StepMania 4 alpha 5 to sm-ssc v1.2.5, see Changelog_sm-ssc.txt.
________________________________________________________________________________
+2015/06/05
+----------
+* [global] update_centering lua function exposed. [kyzentun]
+* [ScreenOverscanConfig] New screen in _fallback for interactively adjusting
+ the preferences that already existed for dealing with overscan. [kyzentun]
+* [Actor] BlendMode_Subtract no longer crashes on the d3d renderer. It does
+ not do subtraction blending correctly, this just prevents the crash.
+ [kyzentun]
+
2015/06/03
----------
* [Actor] bounce and bob effects no longer round pixel coords. [kyzentun]
diff --git a/Docs/Luadoc/Lua.xml b/Docs/Luadoc/Lua.xml
index 170755ff33..426391f963 100644
--- a/Docs/Luadoc/Lua.xml
+++ b/Docs/Luadoc/Lua.xml
@@ -193,6 +193,7 @@
+
diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/Luadoc/LuaDocumentation.xml
index bf4546734f..6cc77d8986 100644
--- a/Docs/Luadoc/LuaDocumentation.xml
+++ b/Docs/Luadoc/LuaDocumentation.xml
@@ -622,6 +622,10 @@ save yourself some time, copy this for undocumented things:
Returns a string with characters escaped for URLs. (e.g. a space becomes '%20')
+
+ This tells Stepmania to update the screen position for any changes to these preferences: CenterImageAddWidth, CenterImageAddHeight, CenterImageTranslateX, CenterImageTranslateY.
+ This way, a theme can implement a custom interactive screen for adjusting those preferences.
+
[01 base.lua] Alias for lua.GetThreadVariable.
diff --git a/Themes/_fallback/BGAnimations/ScreenOverscanConfig overlay.lua b/Themes/_fallback/BGAnimations/ScreenOverscanConfig overlay.lua
new file mode 100644
index 0000000000..2543c2fa97
--- /dev/null
+++ b/Themes/_fallback/BGAnimations/ScreenOverscanConfig overlay.lua
@@ -0,0 +1,124 @@
+-- Screen written by Kyzentun, so if it's confusingly advanced/simple, that's
+-- why.
+
+-- The names of the elements in this table will be used to know the names of
+-- the preferences they affect.
+local valtex_buttons= {
+ CenterImageAddWidth= {"d", "a"},
+ CenterImageAddHeight= {"w", "s"},
+ CenterImageTranslateX= {"l", "j"},
+ CenterImageTranslateY= {"k", "i"},
+}
+
+-- valtex will be used to store the actors that show the current values for
+-- easy access.
+local valtex= {}
+
+-- change_center_val is a convenience function so that things that need to
+-- change a value only need one line of code, and so that if the method for
+-- changing a value changes, it only needs to be changed here.
+local function change_center_val(valname, amount)
+ local new_val= PREFSMAN:GetPreference(valname) + amount
+ PREFSMAN:SetPreference(valname, new_val)
+ valtex[valname]:settext(new_val)
+ update_centering()
+end
+
+-- valtext_frames will store the ActorFrames that each name and value actor
+-- is inside. Then each ActorFrame can update widest_name and tell all the
+-- frames to adjust their position for the new width. This is how the text
+-- is reasonably centered.
+local valtex_frames= {}
+local widest_name= 0
+
+-- valtexact is a convenience function because each preference needs the same
+-- actors: one for the name and buttons, and one for the value. This way,
+-- there are fewer lines of code, and they all behave the same.
+-- The value is left aligned and the name right aligned so they don't overlap.
+-- Normally, all text displayed should be translated by using THEME:GetString,
+-- but in this case, these are the exact names of the preferences, so it's
+-- important for people to be able to find them easily in Preferences.ini by
+-- recognizing the name shown on the screen.
+local function valtexact(name, x, y, c)
+ return Def.ActorFrame{
+ InitCommand= function(self)
+ valtex_frames[name]= self
+ local name_w= self:GetChild("Name"):GetWidth()
+ if name_w > widest_name then widest_name= name_w end
+ self:y(y)
+ for frame_name, frame in pairs(valtex_frames) do
+ frame:playcommand("recenter")
+ end
+ end,
+ recenterCommand= function(self)
+ self:x(x + (widest_name / 2))
+ end,
+ Def.BitmapText{
+ Font= "Common Normal", Name= "Value", InitCommand= function(self)
+ valtex[name]= self
+ self:x(4):settext(PREFSMAN:GetPreference(name)):horizalign(left)
+ end,
+ },
+ Def.BitmapText{
+ Font= "Common Normal", Name= "Name", InitCommand= function(self)
+ self:x(-4):settext(
+ name .. "(" .. valtex_buttons[name][1] .. " or " ..
+ valtex_buttons[name][2] .. "): "):horizalign(right):diffuse(c)
+ end,
+ },
+ }
+end
+
+-- This is the callback that processes input. It ignores releases so only
+-- first press and repeat events are processed. It uses valtex_buttons to
+-- figure out what value was modified. This way, all the prefs have the same
+-- interface, and the definition of that interface is short and simple.
+-- One button to increase the value by one, one button to decrease by one.
+local function input(event)
+ if event.type == "InputEventType_Release" then return false end
+ local button= ToEnumShortString(event.DeviceInput.button)
+ for valname, button_set in pairs(valtex_buttons) do
+ if button == button_set[1] then
+ change_center_val(valname, 1)
+ elseif button == button_set[2] then
+ change_center_val(valname, -1)
+ end
+ end
+end
+
+-- Another convenience function, this time for a simple aligned quad.
+local function quaid(x, y, w, h, c, ha, va)
+ return Def.Quad{
+ InitCommand= function(self)
+ self:xy(x, y):setsize(w, h):diffuse(c):horizalign(ha):vertalign(va)
+ end
+ }
+end
+
+-- Simple colors. Note that the quads and the text are color coded: the text
+-- for the prefs that affect the width and the vertical quads on the sides are
+-- the same color. The text for the prefs that affect the height is the same
+-- color as the quads at the top and bottom.
+local red= color("#ff0000")
+local blue= color("#0000ff")
+
+local args= {
+ OnCommand= function(self)
+ SCREENMAN:GetTopScreen():AddInputCallback(input)
+ end,
+ -- Note that the quads are aligned. This way, they are drawn entirely
+ -- inside the screen, and their edge starts at the edge of the screen.
+ -- This is important because the user needs them to verify that their
+ -- settings bring everything into view.
+ quaid(0, 0, _screen.w, 1, red, left, top),
+ quaid(0, _screen.h, _screen.w, 1, red, left, bottom),
+ quaid(0, 0, 1, _screen.h, blue, left, top),
+ quaid(_screen.w, 0, 1, _screen.h, blue, right, top),
+ -- The text is centered to minimize the chance of some of it being cut off.
+ valtexact("CenterImageAddHeight", _screen.cx, _screen.cy-36, red),
+ valtexact("CenterImageAddWidth", _screen.cx, _screen.cy-12, blue),
+ valtexact("CenterImageTranslateX", _screen.cx, _screen.cy+12, blue),
+ valtexact("CenterImageTranslateY", _screen.cx, _screen.cy+36, red),
+}
+
+return Def.ActorFrame(args)
diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini
index 3d4789dc19..3e0b0a06c8 100644
--- a/Themes/_fallback/Languages/en.ini
+++ b/Themes/_fallback/Languages/en.ini
@@ -457,6 +457,7 @@ OnlyDedicatedMenuButtons=Choose between allowing game buttons (dance pad, etc.)
OptionsRandomJukebox=
OsMountPlayer1=
OsMountPlayer2=
+Overscan Correction=If part of the screen sticks off the side, use this.
Persp=Tilt
Player1Profile=
Player2Profile=
@@ -1156,6 +1157,7 @@ OptionsRandomJukebox=Modifiers
OnlyDedicatedMenuButtons=Menu Buttons
OsMountPlayer1=OS Mount Player1
OsMountPlayer2=OS Mount Player2
+Overscan Correction=Overscan Correction
Paste at begin marker=Paste at begin marker
Paste at current beat=Paste at current beat
Paste timing data=Paste timing data
diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini
index b730e0ac1e..dd63a26c2f 100644
--- a/Themes/_fallback/metrics.ini
+++ b/Themes/_fallback/metrics.ini
@@ -1664,6 +1664,13 @@ NextScreen="ScreenOptionsDisplaySub"
RepeatRate=10
RepeatDelay=.25
+[ScreenOverscanConfig]
+Class="ScreenWithMenuElements"
+Fallback="ScreenWithMenuElements"
+NextScreen="ScreenOptionsDisplaySub"
+RepeatRate=10
+RepeatDelay=.25
+
[ScreenWithMenuElementsBlank]
Fallback="ScreenWithMenuElements"
UpdateOnMessage=""
@@ -2739,6 +2746,7 @@ LineReload="gamecommand;screen,ScreenReloadSongs;name,Reload Songs"
LineArcade="gamecommand;screen,ScreenOptionsArcade;name,Arcade Options"
LineAppearance="gamecommand;screen,ScreenAppearanceOptions;name,Appearance Options"
LineBGFit="gamecommand;screen,ScreenSetBGFit;name,Set BG Fit Mode"
+LineOverscan="gamecommand;screen,ScreenOverscanConfig;name,Overscan Correction"
LineGraphicSound="gamecommand;screen,ScreenOptionsGraphicsSound;name,Graphics/Sound Options"
LineProfiles="gamecommand;screen,ScreenOptionsManageProfiles;name,Profiles"
LineNetwork="gamecommand;screen,ScreenNetworkOptions;name,Network Options"
@@ -2785,9 +2793,10 @@ LineSync="gamecommand;screen,ScreenGameplaySyncMachine;name,Calibrate Machine Sy
Fallback="ScreenOptionsService"
NextScreen="ScreenOptionsService"
PrevScreen="ScreenOptionsService"
-LineNames="BGFit,Appearance,UI"
+LineNames="BGFit,Appearance,UI,Overscan"
LineAppearance="gamecommand;screen,ScreenAppearanceOptions;name,Appearance Options"
LineBGFit="gamecommand;screen,ScreenSetBGFit;name,Set BG Fit Mode"
+LineOverscan="gamecommand;screen,ScreenOverscanConfig;name,Overscan Correction"
LineUI="gamecommand;screen,ScreenOptionsUI;name,UI Options"
diff --git a/src/RageDisplay_D3D.cpp b/src/RageDisplay_D3D.cpp
index cbfcf72e19..7e9413bc21 100644
--- a/src/RageDisplay_D3D.cpp
+++ b/src/RageDisplay_D3D.cpp
@@ -1117,6 +1117,12 @@ void RageDisplay_D3D::SetBlendMode( BlendMode mode )
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
break;
+ // This is not the right way to do BLEND_SUBTRACT. This code is only here
+ // to prevent crashing when someone tries to use it. -Kyz
+ case BLEND_SUBTRACT:
+ g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
+ g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ZERO );
+ break;
case BLEND_MODULATE:
g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO );
g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCCOLOR );
diff --git a/src/StepMania.cpp b/src/StepMania.cpp
index a27f10d4d2..6f4e8020c1 100644
--- a/src/StepMania.cpp
+++ b/src/StepMania.cpp
@@ -185,6 +185,13 @@ bool StepMania::GetHighResolutionTextures()
}
}
+static void update_centering()
+{
+ DISPLAY->ChangeCentering(
+ PREFSMAN->m_iCenterImageTranslateX, PREFSMAN->m_iCenterImageTranslateY,
+ PREFSMAN->m_fCenterImageAddWidth, PREFSMAN->m_fCenterImageAddHeight);
+}
+
static void StartDisplay()
{
if( DISPLAY != NULL )
@@ -192,11 +199,7 @@ static void StartDisplay()
DISPLAY = CreateDisplay();
- DISPLAY->ChangeCentering(
- PREFSMAN->m_iCenterImageTranslateX,
- PREFSMAN->m_iCenterImageTranslateY,
- PREFSMAN->m_fCenterImageAddWidth,
- PREFSMAN->m_fCenterImageAddHeight );
+ update_centering();
TEXTUREMAN = new RageTextureManager;
TEXTUREMAN->SetPrefs(
@@ -228,11 +231,7 @@ void StepMania::ApplyGraphicOptions()
if( sError != "" )
RageException::Throw( "%s", sError.c_str() );
- DISPLAY->ChangeCentering(
- PREFSMAN->m_iCenterImageTranslateX,
- PREFSMAN->m_iCenterImageTranslateY,
- PREFSMAN->m_fCenterImageAddWidth,
- PREFSMAN->m_fCenterImageAddHeight );
+ update_centering();
bNeedReload |= TEXTUREMAN->SetPrefs(
RageTextureManagerPrefs(
@@ -1642,6 +1641,13 @@ void LuaFunc_Register_SaveScreenshot(lua_State *L)
{ lua_register(L, "SaveScreenshot", LuaFunc_SaveScreenshot); }
REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_SaveScreenshot);
+static int LuaFunc_update_centering(lua_State* L)
+{
+ update_centering();
+ return 0;
+}
+LUAFUNC_REGISTER_COMMON(update_centering);
+
/*
* (c) 2001-2004 Chris Danford, Glenn Maynard
* All rights reserved.