diff --git a/Themes/Rebirth/BGAnimations/ScreenEvaluation decorations/mainDisplay.lua b/Themes/Rebirth/BGAnimations/ScreenEvaluation decorations/mainDisplay.lua index e820076f1b..1f662f9b39 100644 --- a/Themes/Rebirth/BGAnimations/ScreenEvaluation decorations/mainDisplay.lua +++ b/Themes/Rebirth/BGAnimations/ScreenEvaluation decorations/mainDisplay.lua @@ -4,29 +4,34 @@ local pss = STATSMAN:GetCurStageStats():GetPlayerStageStats() local chosenScore local mostRecentScore = SCOREMAN:GetMostRecentScore() local screen - -local function evalInput(event) - if event.type == "InputEventType_FirstPress" then - local btn = event.GameButton - if btn ~= nil then - if btn == "EffectUp" then - -- judge window increase - judgeSetting = clamp(judgeSetting + 1, 4, 9) - MESSAGEMAN:Broadcast("JudgeWindowChanged") - elseif btn == "EffectDown" then - -- judge window decrease - judgeSetting = clamp(judgeSetting - 1, 4, 9) - MESSAGEMAN:Broadcast("JudgeWindowChanged") - end - end - end -end +local usingCustomWindows = false local t = Def.ActorFrame { Name = "MainDisplayFile", BeginCommand = function(self) screen = SCREENMAN:GetTopScreen() - screen:AddInputCallback(evalInput) + screen:AddInputCallback(function(event) + if event.type == "InputEventType_FirstPress" then + local btn = event.GameButton + if btn ~= nil then + local dir = 0 + if btn == "EffectUp" then + -- judge window increase + dir = 1 + elseif btn == "EffectDown" then + -- judge window decrease + dir = -1 + end + + if dir ~= 0 and not usingCustomWindows then + judgeSetting = clamp(judgeSetting + dir, 4, 9) + MESSAGEMAN:Broadcast("JudgeWindowChanged") + elseif dir ~= 0 and usingCustomWindows then + self:playcommand("MoveCustomWindowIndex", {direction = dir}) + end + end + end + end) updateDiscordStatus(true) end, OnCommand = function(self) @@ -42,7 +47,7 @@ local t = Def.ActorFrame { forcedScreenEntryJudgeWindow = 4 end -- update replaysnapshots and pss for current score being rejudged to whatever judge - screen:RescoreReplay(pss, ms.JudgeScalers[forcedScreenEntryJudgeWindow or judgeSetting], score) + screen:RescoreReplay(pss, ms.JudgeScalers[forcedScreenEntryJudgeWindow or judgeSetting], score, usingCustomWindows and currentCustomWindowConfigUsesOldestNoteFirst()) --- propagate set command through children with the song self:playcommand("Set", { @@ -62,7 +67,7 @@ local t = Def.ActorFrame { -- we assume the score has a replay -- recalculate all stats using the replay - screen:RescoreReplay(pss, ms.JudgeScalers[judgeSetting], params.score) + screen:RescoreReplay(pss, ms.JudgeScalers[judgeSetting], params.score, usingCustomWindows and currentCustomWindowConfigUsesOldestNoteFirst()) chosenScore = params.score @@ -87,6 +92,50 @@ local t = Def.ActorFrame { rejudged = true, }) end, + ToggleCustomWindowsMessageCommand = function(self) + usingCustomWindows = not usingCustomWindows + + if usingCustomWindows then + loadCurrentCustomWindowConfig() + screen:RescoreReplay(pss, 1, chosenScore, currentCustomWindowConfigUsesOldestNoteFirst()) + self:playcommand("Set", { + song = GAMESTATE:GetCurrentSong(), + steps = GAMESTATE:GetCurrentSteps(), + score = chosenScore, + judgeSetting = judgeSetting, + rejudged = true, + usingCustomWindows = usingCustomWindows, + }) + else + unloadCustomWindowConfig() + self:playcommand("UpdateScore", { + judgeSetting = judgeSetting, + rejudged = true, + score = chosenScore, + usingCustomWindows = usingCustomWindows, + }) + end + + end, + MoveCustomWindowIndexMessageCommand = function(self, params) + if not usingCustomWindows then return end + + moveCustomWindowConfigIndex(params.direction) + loadCurrentCustomWindowConfig() + screen:RescoreReplay(pss, 1, chosenScore, currentCustomWindowConfigUsesOldestNoteFirst()) + self:playcommand("Set", { + song = GAMESTATE:GetCurrentSong(), + steps = GAMESTATE:GetCurrentSteps(), + score = chosenScore, + judgeSetting = judgeSetting, + rejudged = true, + usingCustomWindows = usingCustomWindows, + }) + + end, + EndCommand = function(self) + unloadCustomWindowConfig() + end, LoginMessageCommand = function(self) self:playcommand("UpdateLoginStatus") end, @@ -438,8 +487,9 @@ local function accuracyStats() -- calculates the statData based on the given score local function calculateStatData(score) - local offsetTable = score:GetOffsetVector() - local typeTable = score:GetTapNoteTypeVector() + local replay = REPLAYS:GetActiveReplay() + local offsetTable = usingCustomWindows and replay:GetOffsetVector() or score:GetOffsetVector() + local typeTable = usingCustomWindows and replay:GetTapNoteTypeVector() or score:GetTapNoteTypeVector() -- must match statData above local output = { @@ -454,10 +504,17 @@ local function accuracyStats() return output end - local ridicThreshold = ms.JudgeScalers[judgeSetting] * 11.25 -- this is the J7 Marvelous window - local marvThreshold = ms.JudgeScalers[judgeSetting] * 22.5 -- J4 Marvelous window - local perfThreshold = ms.JudgeScalers[judgeSetting] * 45 -- J4 Perfect window - local greatThreshold = ms.JudgeScalers[judgeSetting] * 90 -- J4 Great window + local windowtable = usingCustomWindows and getCurrentCustomWindowConfigJudgmentWindowTable() or { + TapNoteScore_W1 = 22.5 * ms.JudgeScalers[judgeSetting], + TapNoteScore_W2 = 45 * ms.JudgeScalers[judgeSetting], + TapNoteScore_W3 = 90 * ms.JudgeScalers[judgeSetting], + } + windowtable["TapNoteScore_W0"] = windowtable["TapNoteScore_W1"] / 2 + + local ridicThreshold = windowtable["TapNoteScore_W0"] -- this is the J7 Marvelous window + local marvThreshold = windowtable["TapNoteScore_W1"] -- J4 Marvelous window + local perfThreshold = windowtable["TapNoteScore_W2"] -- J4 Perfect window + local greatThreshold = windowtable["TapNoteScore_W3"] -- J4 Great window local currentRFC = 0 local currentMFC = 0 local currentPFC = 0 @@ -627,8 +684,9 @@ local function calculatedStats() local cbInfo = {0,0,0,0} -- per column cb info local function calculateStatData(score, numColumns) - local tracks = score:GetTrackVector() - local offsetTable = score:GetOffsetVector() + local replay = REPLAYS:GetActiveReplay() + local tracks = usingCustomWindows and replay:GetTrackVector() or score:GetTrackVector() + local offsetTable = usingCustomWindows and replay:GetOffsetVector() or score:GetOffsetVector() local middleColumn = numColumns / 2 @@ -651,7 +709,8 @@ local function calculatedStats() return output, cbInfo end - local cbThreshold = ms.JudgeScalers[judgeSetting] * 90 + + local cbThreshold = usingCustomWindows and getCurrentCustomWindowConfigJudgmentWindowTable()["TapNoteScore_W3"] or (ms.JudgeScalers[judgeSetting] * 90) local leftCB = 0 local middleCB = 0 local rightCB = 0 @@ -873,7 +932,87 @@ local function wifePercentDisplay() self:playcommand("UpdateParameters", {decimals = nothoverdecimals}) end self:playcommand("UpdateText") - end + end, + MouseDownCommand = function(self) + MESSAGEMAN:Broadcast("ToggleCustomWindows") + end, + } +end + +local function customScoringDisplay() + -- internal value storage defaults + local value = 0 + local decimals = 2 + local stringformat = "%05."..decimals.."f%% [%s]" + + -- """constants""" + local nothoverdecimals = 2 -- when not hovering + local hoverdecimals = 4 -- when hovering + local infostr = "" -- example: W3 J4 + + return UIElements.TextToolTip(1, 1, "Common Large") .. { + Name = "CustomPercent", + InitCommand = function(self) + self:halign(1):valign(1) + self:zoom(scoreInfoTextSize) + self:maxwidth(actuals.RightHalfRightAlignLeftGap / 2 / scoreInfoTextSize - textzoomFudge) + end, + UpdateParametersCommand = function(self, params) + if params.decimals ~= nil then + decimals = params.decimals + stringformat = "%05."..decimals.."f%% [%s]" + end + if params.infostr ~= nil then + infostr = params.infostr + end + if params.value ~= nil then + value = params.value + end + end, + UpdateTextCommand = function(self) + self:settextf(stringformat, notShit.floor(value, decimals), infostr) + end, + ColorConfigUpdatedMessageCommand = function(self) + self:playcommand("Set") + end, + SetCommand = function(self, params) + if params.score ~= nil then + + self:visible(usingCustomWindows) + if not usingCustomWindows then return end + + local lastSnapshot = REPLAYS:GetActiveReplay():GetLastReplaySnapshot() + local percent = lastSnapshot:GetWifePercent() * 100 + local ss = getCurrentCustomWindowConfigName() + + -- scores over 99% should show more decimals + if percent > 99 or isOver(self) then + decimals = 4 + end + local pg = notShit.floor(percent, decimals) + local grade = GetGradeFromPercent(pg / 100) + self:diffuse(colorByGrade(grade)) + self:playcommand("UpdateParameters", {decimals = decimals, infostr = ss, value = percent}) + self:playcommand("UpdateText") + else + self:settext("") + end + end, + MouseOverCommand = function(self) self:playcommand("RolloverUpdate",{update = "over"}) end, + MouseOutCommand = function(self) self:playcommand("RolloverUpdate",{update = "out"}) end, + RolloverUpdateCommand = function(self, params) + -- hovering + if params.update == "over" then + self:playcommand("UpdateParameters", {decimals = hoverdecimals}) + elseif params.update == "out" then + self:playcommand("UpdateParameters", {decimals = nothoverdecimals}) + end + self:playcommand("UpdateText") + end, + MouseDownCommand = function(self, params) + if self:IsInvisible() then return end + MESSAGEMAN:Broadcast("MoveCustomWindowIndex", {direction = params.event == "DeviceButton_left mouse button" and 1 or -1}) + end, } end @@ -1183,6 +1322,9 @@ t[#t+1] = Def.ActorFrame { self:maxwidth(actuals.RightHalfRightAlignLeftGap / 4 / scoreInfoTextSize - textzoomFudge) end, SetCommand = function(self, params) + self:visible(not usingCustomWindows) + if usingCustomWindows then return end + if params.score ~= nil then local percent = params.score:GetWifeScore() * 100 if params.judgeSetting ~= nil then @@ -1197,6 +1339,15 @@ t[#t+1] = Def.ActorFrame { else self:settext("") end + end, + }, + + -- this replaces the grade when custom window scoring is turned on + -- by default it is turned off + customScoringDisplay() .. { + InitCommand = function(self) + self:y(-actuals.GradeLowerGap) + self:visible(false) end }, @@ -1256,17 +1407,18 @@ t[#t+1] = Def.ActorFrame { SetCommand = function(self, params) if params.score ~= nil and params.steps ~= nil then if params.score:HasReplayData() then - local offsets = params.score:GetOffsetVector() + local replay = REPLAYS:GetActiveReplay() + local offsets = usingCustomWindows and replay:GetOffsetVector() or params.score:GetOffsetVector() -- for online offset vectors a 180 offset is a miss for i, o in ipairs(offsets) do if o >= 180 then offsets[i] = 1000 end end - local tracks = params.score:GetTrackVector() - local types = params.score:GetTapNoteTypeVector() - local noterows = params.score:GetNoteRowVector() - local holds = params.score:GetHoldNoteVector() + local tracks = usingCustomWindows and replay:GetTrackVector() or params.score:GetTrackVector() + local types = usingCustomWindows and replay:GetTapNoteTypeVector() or params.score:GetTapNoteTypeVector() + local noterows = usingCustomWindows and replay:GetNoteRowVector() or params.score:GetNoteRowVector() + local holds = usingCustomWindows and replay:GetHoldNoteVector() or params.score:GetHoldNoteVector() local timingdata = params.steps:GetTimingData() local lastSecond = params.steps:GetLastSecond() @@ -1281,6 +1433,7 @@ t[#t+1] = Def.ActorFrame { judgeSetting = params.judgeSetting, columns = params.steps:GetNumColumns(), rejudged = params.rejudged, + usingCustomWindows = usingCustomWindows, }) end end diff --git a/Themes/Rebirth/BGAnimations/judgmentBars.lua b/Themes/Rebirth/BGAnimations/judgmentBars.lua index 5439e835eb..2cf343eaaf 100644 --- a/Themes/Rebirth/BGAnimations/judgmentBars.lua +++ b/Themes/Rebirth/BGAnimations/judgmentBars.lua @@ -49,6 +49,12 @@ local function makeJudgment(i) self:y((((i-1) * sizing.JudgmentBarHeight + (i-1) * sizing.JudgmentBarSpacing) / sizing.JudgmentBarAllottedSpace) * sizing.JudgmentBarAllottedSpace) end, SetCommand = function(self, params) + if params.usingCustomWindows then + local lastSnapshot = REPLAYS:GetActiveReplay():GetLastReplaySnapshot() + count = lastSnapshot:GetJudgments()[jdg:gsub("TapNoteScore_", "")] + return + end + if params.score ~= nil then if params.judgeSetting ~= nil and params.score:HasReplayData() then count = getRescoredJudge(params.score:GetOffsetVector(), params.judgeSetting, i) diff --git a/Themes/Rebirth/BGAnimations/offsetplot.lua b/Themes/Rebirth/BGAnimations/offsetplot.lua index 4adab1155a..3bb7453814 100644 --- a/Themes/Rebirth/BGAnimations/offsetplot.lua +++ b/Themes/Rebirth/BGAnimations/offsetplot.lua @@ -24,6 +24,7 @@ local translations = { local judgeSetting = (PREFSMAN:GetPreference("SortBySSRNormPercent") and 4 or GetTimingDifficulty()) local timingScale = ms.JudgeScalers[judgeSetting] +local usingCustomWindows = false -- cap the graph to this local maxOffset = 180 @@ -359,6 +360,7 @@ for i, j in ipairs(barJudgments) do self:finishtweening() self:smooth(resizeAnimationSeconds) local window = ms.getLowerWindowForJudgment(j, timingScale) + if usingCustomWindows then window = getCustomWindowConfigJudgmentWindowLowerBound(j) end self:y(fitY(window, maxOffset)) self:zoomto(sizing.Width, lineThickness) end @@ -376,6 +378,7 @@ for i, j in ipairs(barJudgments) do self:finishtweening() self:smooth(resizeAnimationSeconds) local window = ms.getLowerWindowForJudgment(j, timingScale) + if usingCustomWindows then window = getCustomWindowConfigJudgmentWindowLowerBound(j) end self:y(fitY(-window, maxOffset)) self:zoomto(sizing.Width, lineThickness) end @@ -475,6 +478,8 @@ t[#t+1] = Def.ActorMultiVertex { self:queuecommand("DrawOffsets") end, LoadOffsetsCommand = function(self, params) + usingCustomWindows = params.usingCustomWindows + -- makes sure all sizes are updated self:GetParent():playcommand("UpdateSizing", params) @@ -533,6 +538,9 @@ t[#t+1] = Def.ActorMultiVertex { if types[i] ~= "TapNoteType_Mine" then -- handle highlighting logic local dotColor = colorByTapOffset(offset, timingScale) + if usingCustomWindows then + dotColor = colorByTapOffsetCustomWindow(offset, getCurrentCustomWindowConfigJudgmentWindowTable()) + end if not columnIsHighlighted(column) then dotColor[4] = unHighlightedAlpha end diff --git a/Themes/Rebirth/Scripts/01 color_config.lua b/Themes/Rebirth/Scripts/01 color_config.lua index 4777a7723d..aaf209f93c 100644 --- a/Themes/Rebirth/Scripts/01 color_config.lua +++ b/Themes/Rebirth/Scripts/01 color_config.lua @@ -515,6 +515,23 @@ function COLORS.colorByTapOffset(self, offset, scale) end end +function COLORS.colorByTapOffsetCustomWindow(self, offset, windows) + local offset = math.abs(offset) + if offset <= windows.TapNoteScore_W1 then + return self:colorByJudgment("TapNoteScore_W1") + elseif offset <= windows.TapNoteScore_W2 then + return self:colorByJudgment("TapNoteScore_W2") + elseif offset <= windows.TapNoteScore_W3 then + return self:colorByJudgment("TapNoteScore_W3") + elseif offset <= windows.TapNoteScore_W4 then + return self:colorByJudgment("TapNoteScore_W4") + elseif offset <= windows.TapNoteScore_W5 then + return self:colorByJudgment("TapNoteScore_W5") + else + return self:colorByJudgment("TapNoteScore_Miss") + end +end + function colorByMSD(x) if x then return HSV(math.max(95 - (x / 40) * 150, -50), 0.9, 0.9) @@ -565,6 +582,7 @@ function colorByJudgment(x) return COLORS:colorByJudgment(x) end function colorByDifficulty(x) return COLORS:colorByDifficulty(x) end function colorByGrade(x) return COLORS:colorByGrade(x) end function colorByTapOffset(x, ts) return COLORS:colorByTapOffset(x, ts) end +function colorByTapOffsetCustomWindow(x, windows) return COLORS:colorByTapOffsetCustomWindow(x, windows) end ---=======- UTIL -- convert a given color = {r,g,b,a} to the 4 HSV+alpha values diff --git a/Themes/_fallback/Scripts/72 custom_windows_config.lua b/Themes/_fallback/Scripts/72 custom_windows_config.lua index eb0dded94b..5670006a4e 100644 --- a/Themes/_fallback/Scripts/72 custom_windows_config.lua +++ b/Themes/_fallback/Scripts/72 custom_windows_config.lua @@ -363,6 +363,22 @@ function getCustomWindowConfigJudgmentWindow(judgmentName) return getcurrentrealconfig().customWindowWindows and getcurrentrealconfig().customWindowWindows[nm] or baseWindows[nm] or 0 end +function getCustomWindowConfigJudgmentWindowLowerBound(judgmentName) + local baseWindows = { + W0 = 0, + W1 = 22.5, + W2 = 45, + W3 = 90, + W4 = 135, + W5 = 180, + } + if judgmentName:gsub("TapNoteScore_", "") == "Miss" then return 180 end + local nm = judgmentName:gsub("TapNoteScore_W", "") + -- nm here should be a number, we need to subtract 1 from it. + nm = "W" .. tostring(tonumber(nm) - 1) + return getcurrentrealconfig().customWindowWindows and getcurrentrealconfig().customWindowWindows[nm] or baseWindows[nm] or 0 +end + function getCurrentCustomWindowConfigJudgmentWindowTable() local baseWindows = { TapNoteScore_W1 = getcurrentrealconfig().customWindowWindows and getcurrentrealconfig().customWindowWindows["W1"] or 22.5,