From dbaa975302fce60421e82b731edc21c365ad184e Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 23 Nov 2018 15:43:31 -0300 Subject: [PATCH 001/320] Fix RequestChartLeaderboard callbacks --- .../ScreenGameplay overlay/leaderboard.lua | 9 +- .../ScreenSelectMusic decorations/default.lua | 19 +- .../ScreenSelectMusic decorations/score.lua | 251 +++++++++--------- .../BGAnimations/superscoreboard.lua | 20 +- src/DownloadManager.cpp | 112 ++++---- src/DownloadManager.h | 5 +- src/LuaReference.cpp | 2 +- src/LuaReference.h | 2 +- 8 files changed, 223 insertions(+), 197 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index be11a63d7f..26f1fc6cc2 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -27,17 +27,20 @@ local jdgs = { local function arbitraryLeaderboardSpacing(value) for i, entry in ipairs(entryActors) do - entry.container:addy((i-1) * value) + entry.container:addy((i - 1) * value) end if allowedCustomization then - Movable.DeviceButton_s.Border:playcommand("ChangeHeight", {val = entryActors[#entryActors].container:GetY() + ENTRY_HEIGHT}) + Movable.DeviceButton_s.Border:playcommand( + "ChangeHeight", + {val = entryActors[#entryActors].container:GetY() + ENTRY_HEIGHT} + ) end end if not DLMAN:GetCurrentRateFilter() then DLMAN:ToggleRateFilter() end -local onlineScores = DLMAN:RequestChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey()) +local onlineScores = DLMAN:GetChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey()) local sortFunction = function(h1, h2) return h1[CRITERIA](h1) > h2[CRITERIA](h2) end diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua index d0ee07d08e..78b3f38f79 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua @@ -44,16 +44,21 @@ t[#t + 1] = end end, PlayingSampleMusicMessageCommand = function(self) - local leaderboardEnabled = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() + local leaderboardEnabled = + playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() if leaderboardEnabled then local chartkey = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() - DLMAN:RequestChartLeaderBoardFromOnline(chartkey) + DLMAN:RequestChartLeaderBoardFromOnline( + chartkey, + function(leaderboard) + end + ) end end, - ChartPreviewOnMessageCommand=function(self) + ChartPreviewOnMessageCommand = function(self) self:addx(capWideScale(12, 0)):addy(capWideScale(18, 0)) end, - ChartPreviewOffMessageCommand=function(self) + ChartPreviewOffMessageCommand = function(self) self:addx(capWideScale(-12, 0)):addy(capWideScale(-18, 0)) end, Def.StepsDisplayList { @@ -74,15 +79,13 @@ t[#t + 1] = end } }, - CursorP2 = Def.ActorFrame { - }, + CursorP2 = Def.ActorFrame {}, CursorP1Frame = Def.Actor { ChangeCommand = function(self) self:stoptweening():decelerate(0.05) end }, - CursorP2Frame = Def.Actor { - }, + CursorP2Frame = Def.Actor {} } } diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 2c1c6dc9b7..ac5c82fb02 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -93,8 +93,12 @@ local function updateLeaderBoardForCurrentChart() local top = SCREENMAN:GetTopScreen() if top:GetMusicWheel():IsSettled() and ((getTabIndex() == 2 and nestedTab == 2) or collapsed) then local steps = GAMESTATE:GetCurrentSteps(PLAYER_1) - if steps then - DLMAN:RequestChartLeaderBoardFromOnline(steps:GetChartKey()) + if steps then + DLMAN:RequestChartLeaderBoardFromOnline( + steps:GetChartKey(), + function(leaderboard) + end + ) moped:queuecommand("ChartLeaderboardUpdate") else moped:queuecommand("Bort") @@ -108,12 +112,12 @@ local ret = moped = self:GetChild("ScoreDisplay") self:queuecommand("Set"):visible(false) self:GetChild("LocalScores"):xy(frameX, frameY):visible(false) - self:GetChild("ScoreDisplay"):xy(frameX, frameY):visible(false) + moped:xy(frameX, frameY):visible(false) if FILTERMAN:oopsimlazylol() then -- set saved position and auto collapse nestedTab = 2 self:GetChild("LocalScores"):visible(false) - self:GetChild("ScoreDisplay"):xy(FILTERMAN:grabposx("Doot"), FILTERMAN:grabposy("Doot")):visible(true) + moped:xy(FILTERMAN:grabposx("Doot"), FILTERMAN:grabposy("Doot")):visible(true) self:playcommand("Collapse") end end, @@ -168,7 +172,8 @@ local ret = MESSAGEMAN:Broadcast("TabChanged") end, PlayingSampleMusicMessageCommand = function(self) - local leaderboardEnabled = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() + local leaderboardEnabled = + playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() if not leaderboardEnabled then -- this is taken care of by default.lua instead. updateLeaderBoardForCurrentChart() end @@ -283,9 +288,7 @@ local t = Def.Quad { Name = "FrameDisplay", InitCommand = function(self) - self:zoomto(frameWidth, frameHeight):halign(0):valign(0):diffuse( - color("#333333CC") - ) + self:zoomto(frameWidth, frameHeight):halign(0):valign(0):diffuse(color("#333333CC")) end, CollapseCommand = function(self) self:visible(false) @@ -300,45 +303,42 @@ local t = t[#t + 1] = Def.Quad { InitCommand = function(self) - self:zoomto(frameWidth, offsetY):halign(0):valign(0):diffuse(getMainColor("frames")):diffusealpha( - 0.5 - ) + self:zoomto(frameWidth, offsetY):halign(0):valign(0):diffuse(getMainColor("frames")):diffusealpha(0.5) end } -local l = Def.ActorFrame{ -- stuff inside the frame.. so we can move it all at once - InitCommand=function(self) - self:xy(offsetX, offsetY+headeroffY) +local l = + Def.ActorFrame { + -- stuff inside the frame.. so we can move it all at once + InitCommand = function(self) + self:xy(offsetX, offsetY + headeroffY) end, LoadFont("Common Large") .. - { - Name = "Grades", - InitCommand = function(self) - self:y(20):zoom(0.6):halign(0):maxwidth(50 / 0.6):settext("") - end, - DisplayCommand = function(self) - self:settext(THEME:GetString("Grade", ToEnumShortString(score:GetWifeGrade()))) - self:diffuse(getGradeColor(score:GetWifeGrade())) - end - }, - --- Wife display + { + Name = "Grades", + InitCommand = function(self) + self:y(20):zoom(0.6):halign(0):maxwidth(50 / 0.6):settext("") + end, + DisplayCommand = function(self) + self:settext(THEME:GetString("Grade", ToEnumShortString(score:GetWifeGrade()))) + self:diffuse(getGradeColor(score:GetWifeGrade())) + end + }, + -- Wife display LoadFont("Common Normal") .. - { - Name = "Wife", - InitCommand = function(self) - self:xy(55, 15):zoom(0.6):halign(0):settext("") - end, - DisplayCommand = function(self) - if score:GetWifeScore() == 0 then - self:settextf("NA") - else - self:settextf("%05.2f%%", notShit.floor(score:GetWifeScore() * 10000) / 100):diffuse(byGrade(score:GetWifeGrade())) + { + Name = "Wife", + InitCommand = function(self) + self:xy(55, 15):zoom(0.6):halign(0):settext("") + end, + DisplayCommand = function(self) + if score:GetWifeScore() == 0 then + self:settextf("NA") + else + self:settextf("%05.2f%%", notShit.floor(score:GetWifeScore() * 10000) / 100):diffuse(byGrade(score:GetWifeGrade())) + end end - end - }, - - + }, LoadFont("Common Normal") .. { Name = "Score", @@ -350,11 +350,9 @@ local l = Def.ActorFrame{ -- stuff inside the frame.. so we can move it all at o self:settext("") else local overall = score:GetSkillsetSSR("Overall") - self:settextf("%.2f", overall):diffuse(byMSD(overall)) + self:settextf("%.2f", overall):diffuse(byMSD(overall)) end - end - }, - + }, LoadFont("Common Normal") .. { Name = "Score", @@ -382,92 +380,91 @@ local l = Def.ActorFrame{ -- stuff inside the frame.. so we can move it all at o self:settext(getClearTypeFromScore(pn, score, 0)) self:diffuse(getClearTypeFromScore(pn, score, 2)) end - }, - + },rtLeaderboard callbacks LoadFont("Common Normal") .. - { - Name = "Combo", - InitCommand = function(self) - self:y(58):zoom(0.4):halign(0):settext("Max Combo:") - end, - DisplayCommand = function(self) - self:settextf("Max Combo: %d", score:GetMaxCombo()) - end - }, - - + { + Name = "Combo", + InitCommand = function(self) + self:y(58):zoom(0.4):halign(0):settext("Max Combo:") + end, + DisplayCommand = function(self) + self:settextf("Max Combo: %d", score:GetMaxCombo()) + end + }, LoadFont("Common Normal") .. - { - Name = "MissCount", - InitCommand = function(self) - self:y(73):zoom(0.4):halign(0):settext("Miss Count:") - end, - DisplayCommand = function(self) - local missCount = getScoreMissCount(score) - if missCount ~= nil then - self:settext("Miss Count: " .. missCount) - else - self:settext("Miss Count: -") + { + Name = "MissCount", + InitCommand = function(self) + self:y(73):zoom(0.4):halign(0):settext("Miss Count:") + end, + DisplayCommand = function(self) + local missCount = getScoreMissCount(score) + if missCount ~= nil then + self:settext("Miss Count: " .. missCount) + else + self:settext("Miss Count: -") + end end - end - }, - + }, LoadFont("Common Normal") .. - { - Name = "Date", - InitCommand = function(self) - self:y(88):zoom(0.4):halign(0):settext("Date Achieved:") - end, - DisplayCommand = function(self) - self:settext("Date Achieved: " .. getScoreDate(score)) - end - }, + { + Name = "Date", + InitCommand = function(self) + self:y(88):zoom(0.4):halign(0):settext("Date Achieved:") + end, + DisplayCommand = function(self) + self:settext("Date Achieved: " .. getScoreDate(score)) + end + }, LoadFont("Common Normal") .. - { - Name = "Mods", - InitCommand = function(self) - self:y(103):zoom(0.4):halign(0):settext("Mods:") - end, - DisplayCommand = function(self) - self:settext("Mods: " .. score:GetModifiers()) - end - }, + { + Name = "Mods", + InitCommand = function(self) + self:y(103):zoom(0.4):halign(0):settext("Mods:") + end, + DisplayCommand = function(self) + self:settext("Mods: " .. score:GetModifiers()) + end + }, LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(frameWidth - offsetX - frameX, frameHeight - headeroffY - 10 - offsetY):zoom(0.4):halign(1):settext( - "No Scores Saved" - ) - end, - DisplayCommand = function(self) - self:settextf("Rate %s - Showing %d/%d", rates[rateIndex], scoreIndex, #rtTable[rates[rateIndex]]) - end - }, + { + InitCommand = function(self) + self:xy(frameWidth - offsetX - frameX, frameHeight - headeroffY - 10 - offsetY):zoom(0.4):halign(1):settext( + "No Scores Saved" + ) + end, + DisplayCommand = function(self) + self:settextf("Rate %s - Showing %d/%d", rates[rateIndex], scoreIndex, #rtTable[rates[rateIndex]]) + end + }, LoadFont("Common Normal") .. - { - Name = "ChordCohesion", - InitCommand = function(self) - self:y(frameHeight - headeroffY - 10 - offsetY):zoom(0.4):halign(0):settext("Chord Cohesion:") - end, - DisplayCommand = function(self) - if score:GetChordCohesion() then - self:settext("Chord Cohesion: Yes") - else - self:settext("Chord Cohesion: No") + { + Name = "ChordCohesion", + InitCommand = function(self) + self:y(frameHeight - headeroffY - 10 - offsetY):zoom(0.4):halign(0):settext("Chord Cohesion:") + end, + DisplayCommand = function(self) + if score:GetChordCohesion() then + self:settext("Chord Cohesion: Yes") + else + self:settext("Chord Cohesion: No") + end end - end - }, - LoadFont("Common Normal") .. { - Name = "Judge", - InitCommand = function(self) - self:xy((frameWidth - offsetX - frameX) / 2, frameHeight - headeroffY - 10 - offsetY):zoom(0.4):settext("") - end, - DisplayCommand = function(self) - local j = table.find(ms.JudgeScalers , notShit.round(score:GetJudgeScale(), 2)) - if not j then j = 4 end - self:settext("Judge "..j) - end - } + }, + LoadFont("Common Normal") .. + { + Name = "Judge", + InitCommand = function(self) + self:xy((frameWidth - offsetX - frameX) / 2, frameHeight - headeroffY - 10 - offsetY):zoom(0.4):settext("") + end, + DisplayCommand = function(self) + local j = table.find(ms.JudgeScalers, notShit.round(score:GetJudgeScale(), 2)) + if not j then + j = 4 + end + self:settext("Judge " .. j) + end + } } local function makeText(index) @@ -668,14 +665,15 @@ l[#l + 1] = if nestedTab == 1 then if getTabIndex() == 2 and isOver(self) then DLMAN:SendReplayDataForOldScore(score:GetScoreKey()) - ms.ok("Uploading Replay Data...") --should have better feedback -mina + ms.ok("Uploading Replay Data...") --should have better feedback -mina end end end } t[#t + 1] = l -t[#t+1] = Def.Quad { +t[#t + 1] = + Def.Quad { Name = "ScrollBar", InitCommand = function(self) self:x(frameWidth):zoomto(4, 0):halign(1):valign(1):diffuse(getMainColor("highlight")):diffusealpha(0.75) @@ -688,13 +686,12 @@ t[#t+1] = Def.Quad { end } - ret[#ret + 1] = t function nestedTabButton(i) return Def.ActorFrame { InitCommand = function(self) - self:xy(frameX + offsetX + (i - 1) * (nestedTabButtonWidth - capWideScale(100,80)), frameY + offsetY - 2) + self:xy(frameX + offsetX + (i - 1) * (nestedTabButtonWidth - capWideScale(100, 80)), frameY + offsetY - 2) self:SetUpdateFunction(highlight) end, CollapseCommand = function(self) @@ -736,7 +733,7 @@ function nestedTabButton(i) } end --- online score display +-- online score display ret[#ret + 1] = LoadActor("../superscoreboard") for i = 1, #nestedTabs do diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index bced658842..8f5d89d137 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -9,7 +9,7 @@ local ind = 0 local offx = 5 local width = SCREEN_WIDTH * 0.56 local dwidth = width - offx * 2 -local height = (numscores + 2) * packspaceY - packspaceY/3 -- account dumbly for header being moved up +local height = (numscores + 2) * packspaceY - packspaceY / 3 -- account dumbly for header being moved up local adjx = 14 local c0x = 10 @@ -106,7 +106,7 @@ local o = SCREENMAN:GetTopScreen():AddInputCallback(input) end, ChartLeaderboardUpdateMessageCommand = function(self) - scoretable = DLMAN:RequestChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), currentCountry) + scoretable = DLMAN:GetChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), currentCountry) ind = 0 self:playcommand("Update") end, @@ -183,7 +183,7 @@ local o = offx = 5 width = SCREEN_WIDTH * 0.56 dwidth = width - offx * 2 - height = (numscores + 2) * packspaceY - packspaceY/3 + height = (numscores + 2) * packspaceY - packspaceY / 3 adjx = 14 c0x = 10 @@ -230,7 +230,9 @@ local o = -- grabby thing Def.Quad { InitCommand = function(self) - self:xy(dwidth / 4, headeroff):zoomto(dwidth - dwidth / 4, pdh - 8 * tzoom):halign(0):diffuse(getMainColor("frames")):diffusealpha(0.5):valign(1) + self:xy(dwidth / 4, headeroff):zoomto(dwidth - dwidth / 4, pdh - 8 * tzoom):halign(0):diffuse(getMainColor("frames")):diffusealpha( + 0.5 + ):valign(1) end, WHAZZZAAAACommand = function(self) if isOver(self) and collapsed then @@ -407,8 +409,9 @@ local function makeScoreDisplay(i) self:addy(-row2yoff) end }, - LoadFont("Common normal") .. { - Name = "Burt"..i, + LoadFont("Common normal") .. + { + Name = "Burt" .. i, InitCommand = function(self) self:x(c2x):zoom(tzoom + 0.1):maxwidth((c3x - c2x - capWideScale(10, 40)) / tzoom):halign(0):valign(1) if collapsed then @@ -433,8 +436,9 @@ local function makeScoreDisplay(i) end end }, - LoadFont("Common normal") .. { - Name = "Ernie"..i, + LoadFont("Common normal") .. + { + Name = "Ernie" .. i, InitCommand = function(self) if not collapsed then self:x(c2x):zoom(tzoom - 0.05):halign(0):valign(0):maxwidth(width / 2 / tzoom):addy(row2yoff) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index c570009d5f..0de3356e75 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -26,7 +26,7 @@ #include #include "PlayerStageStats.h" #include "Grade.h" -#include "SongManager.h" // i didn't want to do this but i also didn't want to figure how not to have to so... -mina +#include "SongManager.h" // i didn't want to do this but i also didn't want to figure how not to have to so... -mina using json = nlohmann::json; #ifdef _WIN32 #include @@ -1024,11 +1024,11 @@ DownloadManager::UploadScoreWithReplayData(HighScore* hs) HTTPRequests.push_back(req); return; } -void // not tested exhaustively -mina +void // not tested exhaustively -mina DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) { if (!LoggedIn()) - return; + return; auto doot = SCOREMAN->GetScoresByKey(); auto hs = doot[sk]; @@ -1089,7 +1089,8 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) DLMAN->sessionPass, [hs](bool logged) { if (logged) { - DLMAN->UploadScoreWithReplayDataFromDisk(hs->GetScoreKey()); + DLMAN->UploadScoreWithReplayDataFromDisk( + hs->GetScoreKey()); } }); } else if (status == 404 || status == 405 || @@ -1379,29 +1380,10 @@ DownloadManager::RefreshCountryCodes() void DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) { - RequestChartLeaderBoard(chartkey); - if (unlikely(!ref.IsNil())) { - Lua* L = LUA->Get(); - ref.PushSelf(L); - if (lua_isnil(L, -1)) { - LUA->Release(L); - LuaHelpers::ReportScriptErrorFmt("Error compiling RequestChartLeaderBoard Finish Function"); - return; - } - RString Error = "Error running RequestChartLeaderBoard Finish Function: "; - LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); // 1 args, 0 results - LUA->Release(L); - } -} - -void -DownloadManager::RequestChartLeaderBoard(string chartkey) -{ - auto done = [chartkey](HTTPRequest& req, CURLMsg*) { + auto done = [chartkey, ref](HTTPRequest& req, CURLMsg*) { vector& vec = DLMAN->chartLeaderboards[chartkey]; vec.clear(); // unordered_set userswithscores; - Message msg("ChartLeaderboardUpdate"); try { auto j = json::parse(req.result); if (j.find("errors") != j.end()) @@ -1410,13 +1392,10 @@ DownloadManager::RequestChartLeaderBoard(string chartkey) for (auto scoreJ : (*scores)) { auto score = *(scoreJ.find("attributes")); - // i don't really want to do this very iteration but oh well - // -mina - msg.SetParam("songid", - RString(score.value("songId", "").c_str())); - OnlineScore tmp; + // tmp.songId = score.value("songId", 0); auto user = *(score.find("user")); + tmp.songId = score.value("songId", 0); tmp.username = user.value("userName", "").c_str(); tmp.avatar = user.value("avatar", "").c_str(); tmp.userid = user.value("userId", 0); @@ -1515,13 +1494,33 @@ DownloadManager::RequestChartLeaderBoard(string chartkey) // json failed } + Message msg("ChartLeaderboardUpdate"); + vector leaderboardHS; + // This is like a functional map + transform(vec.begin(), + vec.end(), + back_inserter(leaderboardHS), + [](auto s) { return &(s.hs); }); + + if (!ref.IsNil() && ref.IsSet()) { + Lua* L = LUA->Get(); + ref.PushSelf(L); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::CreateTableFromArray(leaderboardHS, L); + LuaHelpers::RunScriptOnStack( + L, Error, 1, 0, true); // 1 args, 0 results + } + LUA->Release(L); + } // float ProbablyUnderratedness = // mythicalmathymathsProbablyUnderratedness(chartkey); float coop = // overratedness(chartkey); // Renaming these 2 requires renaming them in lua wherever theyre used // msg.SetParam("mmm", ProbablyUnderratedness); // msg.SetParam("ixmixblixb", 2); - MESSAGEMAN->Broadcast(msg); // see start of function + MESSAGEMAN->Broadcast(msg); }; SendRequest("/charts/" + chartkey + "/leaderboards", vector>(), @@ -2229,23 +2228,38 @@ class LunaDownloadManager : public Luna // this will not update a leaderboard to a new state. static int RequestChartLeaderBoardFromOnline(T* p, lua_State* L) { - if (!lua_isfunction(L, 2)) { - LuaReference ref; + string chart = SArg(1); + LuaReference ref; + auto& leaderboardScores = DLMAN->chartLeaderboards[chart]; + if (lua_isfunction(L, 2)) { lua_pushvalue(L, 2); ref.SetFromStack(L); - if (DLMAN->chartLeaderboards[SArg(1)].size() == 0) { - DLMAN->RequestChartLeaderBoard(SArg(1), ref); + } + if (leaderboardScores.size() != 0) { + vector leaderboardHS; + // This is like a functional map + transform(leaderboardScores.begin(), + leaderboardScores.end(), + back_inserter(leaderboardHS), + [](auto s) { return &(s.hs); }); + if (!ref.IsNil()) { + ref.PushSelf(L); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::CreateTableFromArray(leaderboardHS, L); + LuaHelpers::RunScriptOnStack( + L, Error, 1, 0, true); // 1 args, 0 results + } } - } else { - if (DLMAN->chartLeaderboards[SArg(1)].size() == 0) - DLMAN->RequestChartLeaderBoard(SArg(1)); + return 0; } - return 1; + DLMAN->RequestChartLeaderBoard(chart, ref); + + return 0; } - // This does not actually request the leaderboard from online. - // It gets the already retrieved data from DLMAN - static int RequestChartLeaderBoard(T* p, lua_State* L) + static int GetChartLeaderBoard(T* p, lua_State* L) { vector filteredLeaderboardScores; unordered_set userswithscores; @@ -2258,12 +2272,12 @@ class LunaDownloadManager : public Luna for (auto& score : leaderboardScores) { auto& leaderboardHighScore = score.hs; - if (lround(leaderboardHighScore.GetMusicRate() * 10000.f) != - lround(currentrate * 10000.f) && - p->currentrateonly) + if (p->currentrateonly && + lround(leaderboardHighScore.GetMusicRate() * 10000.f) != + lround(currentrate * 10000.f)) continue; - if (userswithscores.count(leaderboardHighScore.GetName()) == 1 && - p->topscoresonly) + if (p->topscoresonly && + userswithscores.count(leaderboardHighScore.GetName()) == 1) continue; if (country != "" && country != "Global" && leaderboardHighScore.countryCode != country) @@ -2324,7 +2338,11 @@ class LunaDownloadManager : public Luna ADD_METHOD(GetLastVersion); ADD_METHOD(GetRegisterPage); ADD_METHOD(RequestChartLeaderBoardFromOnline); - ADD_METHOD(RequestChartLeaderBoard); + ADD_METHOD(GetChartLeaderBoard); + // This does not actually request the leaderboard from online. + // It gets the already retrieved data from DLMAN + // Why does this alias exist? + AddMethod("GetChartLeaderboard", GetChartLeaderBoard); ADD_METHOD(ToggleRateFilter); ADD_METHOD(GetCurrentRateFilter); ADD_METHOD(ToggleTopScoresOnlyFilter); diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 541354df42..d236536a07 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -148,6 +148,7 @@ class OnlineScore int marvelous{ 0 }; int minehits{ 0 }; int held{ 0 }; + int songId{ 0 }; int letgo{ 0 }; bool valid{ false }; bool nocc{ false }; @@ -275,8 +276,8 @@ class DownloadManager bool currentrateonly = false; bool topscoresonly = true; void RefreshCountryCodes(); - void RequestChartLeaderBoard(string chartkey, LuaReference ref); - void RequestChartLeaderBoard(string chartkey); + void RequestChartLeaderBoard(string chartkey, + LuaReference ref = LuaReference()); void RefreshUserData(); string countryCode; void RefreshUserRank(); diff --git a/src/LuaReference.cpp b/src/LuaReference.cpp index 5451ff8061..a59c777fdc 100644 --- a/src/LuaReference.cpp +++ b/src/LuaReference.cpp @@ -5,7 +5,7 @@ REGISTER_CLASS_TRAITS(LuaReference, new LuaReference(*pCopy)) LuaReference::LuaReference() { - m_iReference = LUA_NOREF; + m_iReference = LUA_REFNIL; } LuaReference::~LuaReference() diff --git a/src/LuaReference.h b/src/LuaReference.h index fb4fd41b14..9d0ab7e859 100644 --- a/src/LuaReference.h +++ b/src/LuaReference.h @@ -19,7 +19,7 @@ class LuaReference // Convenience constructor. LuaReference(Lua* L) - : m_iReference(LUA_NOREF) + : m_iReference(LUA_REFNIL) { SetFromStack(L); } From b9382228c384d46c39b8de792dbdcfaf5c04b8c0 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 16:38:08 -0300 Subject: [PATCH 002/320] Fix lua reference initialization --- src/LuaReference.cpp | 2 +- src/LuaReference.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LuaReference.cpp b/src/LuaReference.cpp index a59c777fdc..5451ff8061 100644 --- a/src/LuaReference.cpp +++ b/src/LuaReference.cpp @@ -5,7 +5,7 @@ REGISTER_CLASS_TRAITS(LuaReference, new LuaReference(*pCopy)) LuaReference::LuaReference() { - m_iReference = LUA_REFNIL; + m_iReference = LUA_NOREF; } LuaReference::~LuaReference() diff --git a/src/LuaReference.h b/src/LuaReference.h index 9d0ab7e859..fb4fd41b14 100644 --- a/src/LuaReference.h +++ b/src/LuaReference.h @@ -19,7 +19,7 @@ class LuaReference // Convenience constructor. LuaReference(Lua* L) - : m_iReference(LUA_REFNIL) + : m_iReference(LUA_NOREF) { SetFromStack(L); } From bcb5fb898afb12e2f6875553b9aadbead2454624 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 16:39:20 -0300 Subject: [PATCH 003/320] Properly delete cancelled downloads --- src/DownloadManager.cpp | 62 ++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 0de3356e75..a37bc9c970 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -540,7 +540,7 @@ DownloadManager::UpdateHTTP(float fDeltaSeconds) break; } - // Check for finished downloads + // Check for finished http requests CURLMsg* msg; int msgs_left; while ((msg = curl_multi_info_read(mHTTPHandle, &msgs_left))) { @@ -641,36 +641,46 @@ DownloadManager::UpdatePacks(float fDeltaSeconds) while ((msg = curl_multi_info_read(mPackHandle, &msgs_left))) { /* Find out which handle this message is about */ for (auto i = downloads.begin(); i != downloads.end(); i++) { - if (msg->easy_handle == i->second->handle && - msg->msg == CURLMSG_DONE && - msg->data.result != CURLE_PARTIAL_FILE) { - finishedADownload = true; - i->second->p_RFWrapper.file.Flush(); - if (i->second->p_RFWrapper.file.IsOpen()) - i->second->p_RFWrapper.file.Close(); - if (msg->msg == CURLMSG_DONE && - i->second->progress.total <= - i->second->progress.downloaded) { - timeSinceLastDownload = 0; - i->second->Done(i->second); - if (!gameplay) { - installedPacks = true; - i->second->Install(); - finishedDownloads[i->second->m_Url] = i->second; + if (msg->easy_handle == i->second->handle) { + if (msg->msg == CURLMSG_DONE) { + finishedADownload = true; + i->second->p_RFWrapper.file.Flush(); + if (i->second->p_RFWrapper.file.IsOpen()) + i->second->p_RFWrapper.file.Close(); + if (msg->data.result != CURLE_PARTIAL_FILE && + i->second->progress.total <= + i->second->progress.downloaded) { + timeSinceLastDownload = 0; + i->second->Done(i->second); + if (!gameplay) { + installedPacks = true; + i->second->Install(); + finishedDownloads[i->second->m_Url] = i->second; + } else { + pendingInstallDownloads[i->second->m_Url] = + i->second; + } } else { - pendingInstallDownloads[i->second->m_Url] = i->second; + i->second->Failed(); + finishedDownloads[i->second->m_Url] = i->second; } - } else { + if (i->second->handle != nullptr) + curl_easy_cleanup(i->second->handle); + i->second->handle = nullptr; + if (i->second->p_Pack != nullptr) + i->second->p_Pack->downloading = false; + downloads.erase(i); + break; + } else if (i->second->p_RFWrapper.stop) { i->second->Failed(); finishedDownloads[i->second->m_Url] = i->second; + if (i->second->handle != nullptr) + curl_easy_cleanup(i->second->handle); + i->second->handle = nullptr; + if (i->second->p_Pack != nullptr) + i->second->p_Pack->downloading = false; + downloads.erase(i); } - if (i->second->handle != nullptr) - curl_easy_cleanup(i->second->handle); - i->second->handle = nullptr; - if (i->second->p_Pack != nullptr) - i->second->p_Pack->downloading = false; - downloads.erase(i); - break; } } } From eed136a383089359db30fc73439b6bd258d59029 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 16:39:46 -0300 Subject: [PATCH 004/320] Uncomment ETTP multi --- src/NetworkSyncManager.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 15b1890960..df2769b0d6 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -501,12 +501,12 @@ NetworkSyncManager::PostStartUp(const RString& ServerIP) "Attempting to connect to: %s, Port: %i", sAddress.c_str(), iPort); curProtocol = nullptr; CloseConnection(); - /* + if (ETTP.Connect(this, iPort, sAddress)) curProtocol = &ETTP; else - */ - if (SMOP.Connect(this, iPort, sAddress)) + + if (SMOP.Connect(this, iPort, sAddress)) curProtocol = &SMOP; if (curProtocol == nullptr) return; @@ -785,12 +785,14 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) HighScore hs; EndOfGame_PlayerData result; hs.SetScoreKey(score.value("scorekey", "")); - hs.SetSSRNormPercent(static_cast(score.value("ssr_norm", 0))); + hs.SetSSRNormPercent( + static_cast(score.value("ssr_norm", 0))); hs.SetEtternaValid(score.value("valid", 0) != 0); hs.SetModifiers(score.value("mods", "")); FOREACH_ENUM(Skillset, ss) - hs.SetSkillsetSSR( - ss, static_cast(score.value(SkillsetToString(ss).c_str(), 0))); + hs.SetSkillsetSSR(ss, + static_cast(score.value( + SkillsetToString(ss).c_str(), 0))); hs.SetSSRNormPercent(score.value("score", 0.0f)); hs.SetWifeScore(score.value("score", 0.0f)); result.tapScores[0] = score.value("marv", 0); From 63846a2827467615da73d5516bd60df8dde6b026 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 19:31:54 -0300 Subject: [PATCH 005/320] Fix lambda param type inference in linux By expliciting it --- src/DownloadManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index a37bc9c970..3d27f7ed8e 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1510,7 +1510,7 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) transform(vec.begin(), vec.end(), back_inserter(leaderboardHS), - [](auto s) { return &(s.hs); }); + [](OnlineScore s) { return &(s.hs); }); if (!ref.IsNil() && ref.IsSet()) { Lua* L = LUA->Get(); @@ -2251,7 +2251,7 @@ class LunaDownloadManager : public Luna transform(leaderboardScores.begin(), leaderboardScores.end(), back_inserter(leaderboardHS), - [](auto s) { return &(s.hs); }); + [](OnlineScore s) { return &(s.hs); }); if (!ref.IsNil()) { ref.PushSelf(L); if (!lua_isnil(L, -1)) { From 0bba0c6e5f0a27ddc7cebba25f1c0963c3b98c0f Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 19:43:15 -0300 Subject: [PATCH 006/320] Lua doc stuff --- Themes/Til Death/Graphics/asdaasd.png | Bin 0 -> 12324 bytes Themes/Til Death/Scripts/11 Wheel.lua | 252 ++++++++++++++++++ Themes/_fallback/Scripts/02 ActorDef.lua | 11 +- .../_fallback/docs/markdown/Actor-Commands.md | 187 +++++++++++++ Themes/_fallback/docs/markdown/QuickStart.md | 15 ++ Utils/config.ld | 11 +- 6 files changed, 472 insertions(+), 4 deletions(-) create mode 100644 Themes/Til Death/Graphics/asdaasd.png create mode 100644 Themes/Til Death/Scripts/11 Wheel.lua create mode 100644 Themes/_fallback/docs/markdown/Actor-Commands.md create mode 100644 Themes/_fallback/docs/markdown/QuickStart.md diff --git a/Themes/Til Death/Graphics/asdaasd.png b/Themes/Til Death/Graphics/asdaasd.png new file mode 100644 index 0000000000000000000000000000000000000000..0e6029019212fd44dfa72477e443ce3a4f3e3c6d GIT binary patch literal 12324 zcmbW7c|4SD-~VUEh_Xu;35isbY+Yo@nym|W$MHSB=drv$pX0oB&e~jHm*g%G z2qbXkw23VU1O|SfTD%b8KYimwdEnR1pwmvFAQ0c~tsgKbCr<(d+GXQwY<%wAmB6sT z&?|vKvS*BqWrIQjFZ=%O4FW|C<=gq#+s*u;w=(+ulqCw8VHs$MF_+cyJ(aR4*Sdh+vgVP?bvN2z@>E$Q6vd0Vaf{YgzIl#XyEvQ%@Cx49&pE{Om(^ zpvO>0S^rfAvue803<1U=R3lI!Jc6H_8Nb0*j0$Wav} zcGtnm`|UkCMO3iT28rmb~was`ZT)}9N2%a#p`aY zEREwnA51(BPc(i4POaoNyrw@)vS9%V=#I9BEA42{n4lyW8`?5DM&-;wYcWEB@%_>VY?>p`y1B%DzL1otLvr*Ep?an_@3} z;k5KOy%30Yva4A``pLJT*KFA#yr=QykYha--o}#)N<1Pc%1to zWq1?m^DfJhSf+?J?^Ku$7-VR+_7RT2lVO zyP?1QU-D>Y9FtXidvh{>k~sP2T@9g77 z7oO(Wjy!*2FQSp=e5&FJ+P3O^^7Gy5;W^q}*Z(+USyb`Q!(PcN;#XFDtGSdx zvCjJ7(9=0%{w3=R*Y`+%fuudx+fhD8_U20PNcilHl&H!+TfDdT_TF}TRZTT|Htmtn zqreM}N6|-P_oR31dT8!m-##ov^RJb@5H{f!-;s7Xk+~B{Noz;iN-crzDs*wMIAffFHoKo zo~Y4ssHW>vY{XG)Hd`8dTd%D2iMH{d7JoXtvSnsmHsG1a4qnX*v))NNQj*1tPZ<@P zhkb_aD^@>?QS)~7FU!ozbSytze!kqC-gKgpQIcQWWQuiSB?=m~TO4*hZ0?iR&7DuP z`(!s#va93|D?Od1O64;DqJ2-WCXx7nlDX^xoEx&>Y+%V~bQ5h|Do%xM&ql15ESd8= z?s&z2a0i9ITSB*0BREi3TBV(`c-|OJG&C;qeCU})y^)UjsQa|v?5>&69p5(BiGve} zHbmRgLpu%~IAm${)oL!s)(TS$D?WMlG;ssA!0fgbw+c# z^X3fVTEAz`sQ5UNgh_*cPM~*p!diUu?Q(m~eZ+k*q1TzH+qW#Qbt-4+E9dTO8+qF_ zX%V&*45wc0S<26SmD|jCPN|wZG3Ps%JY4u*y%1L5^k?V?;#=eK^HU!U_zEAY`j5Sc zw=uR!^r@xEt6Wk^cc>s&*A+#Ut$5Ch>o4nv6i(<*=xUB0A9ZqnuSuwTTi0nr3@mWJ zIcA(7&-sgUmGco)f>Z$eaNSBYN_2s+R=ym>DE%fJU7&uP!w#CZP0H3zRrzT=s{Ev2-Tk5--t_!~F2 z!C)qT&i~9e5hI?h@)jNx{iM73`^}O+N|i;A>0}z7MOkZQEEowNeg4NCg>Snf6;gLa zH%mAB$f?0Qtj`rGNFR#)%OrZ;LtA8h@z=-3qI#^KU?jb{bUj^yeT{E-tO zi#V>Q)1-F&e)_%OQ)LIN9-w```b=Mr=zQUQ^W|o1!0kE}nTI^@{9oOB!R@593w^5i zi@oy^@=>0bKHd(O@m;q%v@^>K6uTJjUv*IKY39urau}k`qSX87q9jWPC27a$rWbzN zFLi^XDZ3{2a4RNV-0?!UJ_UUg(Qi}EaLB5RZ#s0<%0JQVO~mOE5s-)6i>yv5T)6OUtGdm8`BK6zp}hG3F^=x4zN4bP|Da=Nm%7LNgaYRqgu|#krkvZflZ_|4UBA_b zeS1ln+U-#9kW;1Oj`$k(Rd@42uT48P51UhoarMW{U2Uq3xx6y7uRybVY?peKHPVgf{ zK4yL#HecCs^EzoWeJM@Im^7wJ%e_~t*Got5H$ zsKl@K)5+Z*vp+t``j+(okBBW|eqW)BK`+kwdcoR7sDLwymOvq+3 zRyN@X=gL~mlHG?A)`Ptd9&n&s+02bge=1P`-juy`+SUpLx~c#IA+Li#YaHPB3sG-@BuKN>a=tDz{1kk&CPHC*7tD`DCLj6_! zmsgxGoO#r7XI$mPtn3+1=jfTeCY2gTPnP(J_R#j>W+-~>LJpg=qk0!-B7sdB zW4d>4+AcJe+MV6pwE#cQFq#F|@U+MX#~A+mkJX5;>e`iDWqPv9$U!bIA=Ll;v7skL z2KWCg_@5^>PiW{SasMyHt%m=*mNDz4S9;HXs~DxX5Lx=bA=t2XdmO?s<1UN3JAN-5 zdosR`=eH;l1Kai19uI8~7O0bv{l63}Ng87q{Z~7|Hu}G|GmqkX^}o&B#ola^Pn-i*+NcXRwu1f-5T@E z)y{U)b18;JOlv3NQ!$eb6(e^3Hnnrk%CO>Wv&bNV!;$v7OLJ{s30nP+P4f}EEw$DV*+nTtN>gZHS&YeD6 z%Ijr&?0)A@eXe$A)kf4I9?~@lSjaO}&NL@hn?H-zsc#y9(W{*+t%c|B1NUlKX(l*2 zn$F^#At5H#B5GE>YrRt&i&EMT_3PmD0_Qlt+Rk*ZhELoCXD?2_XwVq<9b(jakPaIN zW~dmw-;Yv@Mqpm?A;ViY%gqRJ;;MO7L{HRAwzD4v{T-sI(Jy9qM>8_|jgA+`6+cAV9i7 zwHzz$qCC0J5qqmjCKlT-9W4#;r}WR2_QPG`1*Me0)j5NB1az3h?Jh+2G?3biey>!A z$j3vz78i@EwQ2c62|)X|ZIElO3u0MW)JAnk$42OQtemXv*-K}ia)Sm$Snd?=JLH+~ zGqLMY7TOQHUPAleN=oK~+=Lu2PK5Zqp4cN_B4n!CF(UUUm9I+%A}Z#}z@Dp@Y7%a= zJUi{ZsU6fXo6KY?$b~3|%2zY|KJ~GX)n*{wfLcz)o^c!>%C{jFmzSV#p3*}OaG(fP zF#Kk|#u*MmK;Axh zs=gqQNEPPX8U9AUg?w3onauW*GRJ~i;t{qM?q*!e#3`nCp&2RMEWY1QBK}DS=na2wHdAh1w@<(k;qzhvKg= zN^7m)lHiHS6~l`%ta+yUB8!x$mY38?6}3A?yB1l&RxRW!nCJb#Ygp^yH^;OXHY0_ z%J`bcL6;Y~cXRtg7b-6WhD-@{)VS^rYZBOB1=Rb{o;6h9ykbvBPhXUi+mJ%};d|hQ z&N6}xuE`TYs}7Snbau{Tv{LD0wp`oCT|lq_+)**gtE#RAD(S$i%>q*|YAS>{>w}Mh zQS4p&z$?kuGr`m;*M%mL5B;Y_G`Eue(2_t2eY4-Dy>J>#WgR92Xp6tt>UXWkf{v`N zfz)e$UVH&BYN}Y(fJbhb9srGv)_NX`Io^oZgh=h0B;9SQ>WKWdM^yzpfzXZ9FO1hW z$EEGq`0y3o&DER+bJ;e(t(bH~jE!D>DRGF?B6uP2E81`&H%oew@h-MPh5g!=s%f@I<&SJ61bRtK`0g z`;Z+yqIS;DSE2bK)r({i2`+8Xm5s#?SGLoGQ~G*WGPIvX zG|~sR6aa(kSTDG4W@9a6eJw9!Jw$F?Use|bJ3H&NBC6`vHZc=#H;6{V83oQG1Fl)g z*YkFX#SGMeHoj3G6AjWj`I=W)*J#Pt+s?}y&N@vUHr)8eP3?K8av0L^LS%t)X`bs2 zzJqN-i2C;|Plc7dgmvBmR&ym%V6qd$KIS5Z@AOLOn~9|;-AxJ1^ppul!qc+xJH-an_`ZvSHKUn;GVQDG2pb4qWq69Uz;pOUFHEZ>NHT5Bo zo0NBa%?Vn|I!79rRY-5~YJ6THiOJWDsB`_p`Gi7|x>au&v&5F+6fE!I+Rbfl9j-5; zx&pzHXABdRYJ8e3w^oz1_KD=v(c0p=g?t?vrthDEH=VsmTN5etP01QJ^-=%^;TIz< zTo5Q+zordzVQkmdq-pgw$SYJypCcvD`HlQ*gAk4x!1L8x0VB7!-LAt|U*sGxH|HBf z#?R{eNA4G>hgT*~D8#26DGeA3Ida7%)M^Fn*)MaE%p0XA9;+uvW-Dy&!AxHbgyQxJ z7qrM+tmi{bQ6JYg@@J8n&UylIM@ichc9#^|q}ws*bSqEH$Ug9c zLE?G@Siuxn_Nv;ctH9FYTGuK6IsDaqGvpw#ssaT29B#O(%CC}zdfSOyc*%EKp;b%o zv#F<-5FRU{Y6a}MQ%r5Sj_Fa}!O?x-w9q3TjtFizOlC)d>pB@%aWV#Zwy6ymgT2)V zOi{L1&SyO#-ty%I^L=37Xss_-af0psXVd-4C~GE$O1U|fDX_N15$RNsnAP1n;L>B9 z#RfcoC(#IlnCEJav(heJY>I`T^foY9WJZWdOIWVEFwO*6RCN0rVwzM|U6jFILJ4c4 zLHpY1?Y%R`&!oaB)4Rdpc3EZwiGxBDLii3h#g1N!wp>1_5&>SvJ_w^igTTYlIBg*jrO~sn&ik#j#y~3 z{O7BUf~*5_A^GN9bDB4&vd08jmtw+dl6eNXP0kYI>vc(7&4HEt^Oh|M7!ld!g)4WF z^r&@U>PA^d2SDGe@Tzb%;}w@vCyDaPVBoc^=}09L)6y*~DPu0J7hFKx1Ey2b z*c!fLGpIV#26^z`^gVW%bP4JAlkOXR=H6}R>L^m)FV_H$OP6|z0l@elodEoUeLQ8m zPFN_oVE%18`Hrgj{CfRLM>|942MFullN6*~+a81aZ`VE-_V3@`pmgY=U#|7aAH@9H zLX~9q%KMw2wv+R`Q-Av}oo?UWX&DOv@ykCe^Ac+OB|f1d>)*ot zmi8=(_=_T#&&mz` z@gfqFKTrRbg>99MKhetL`w_(tvA6XHp>TWp#-G%m+P(c{=!I&D|L0mpcez)6D$f$8 z?F1Rep5rX0CA=PJsHC$h!{P6|Q?lDWK7l(TX60K|`DvYNYuXmDidx(}3s+t{l?PyL z+n~8g${Jrn%1o?&p>@gW^OlT;%6V2L-OnH9l~Wun$$satrzS!EUt&V*Zu`Vykk+#d z=W>J_*xA9)O5~{x$kA#xAspD>1GA{!98qoBfSUudSOk=|mo+9nm>2R4h3X8_E+iFR zI$9J4Cr8GSBP-Auz;2lu0bY39zezR#%K_vqSFDw9-9DjaT2}iSh#oh;?(F|8yX{?# zyW^SJgr(gcQY91AQQmA8D2^Nshba_Gl)#RGt5XLPYN3-;uSrW0(r!svS*4RN)gkMZ zwaO$c$P)D8&@%odAF7@|t9LC!PU$WZ=ReZJTg``DYS|RGG<>HZSL~}(keWPkz_hGF zxrtEO3#bKQ7M@X8mtkwcBqfqPCEVQHG7Gt|KvD*rVc}~UA4rJ{_5GWi0uD+di5h~@ zH83Dykxu^b?oXm1`Ym>#5}3wZi_$IrKE&%70ftTaN-`iG3N@To(Q_R=yg)CLi3ez| zmNV;9?MPdHlb2A!RWDAtC1ELI-!hAAW;nJIDlbd(5(g!yF3;mbZ~;(&{Z==;4eRL* z1J2#i4NMy`nc5*v=9=rcI=cfIM0YM%DpF7F{mW3|;%-&~2P)BC#dE`@?$h^*@S=>2 z9xXrUmblt#;wqM(#g69;@dA58kr)=_cwv?kC%#Z5B78n%W^Q+LEjq7P-D<~;weCy! zAxO4e3d&a!4{*1)zVHWN6;B@)OY*~yZj9{%Clfsr21_zBL*Ky1!YeX#TGj79@V_R^ z(ohC#x5nBH21zRuEgLiPTwEf+outIfEts`U$;ea~kJZNS6%H5~=6j)}u*J9xEYepp zt)$lz2Yb=a+VvsJc?%hr098t7s7fs-$5~_0L!>4`u?S(JeH4$uHwmCJG8Kt5FqK5I zgBAI&z>%SEo-daJ^s6Tus}r|Zcn%oD{-sPS&jqGwNFrk-op9^+^Tjy zB5}I_jXYEV$mwyG5L)I_?aK1@jDhvyEcS~C1 zgzOg%SjlbPqI?SjNJu;a>e@{UHR*F6iaP-?RW%&sg`ZXc#&_>btS+#BchaAXH1btL z7ievxE0Zi===)xyVC;w>D~oOUEYH~=PG9fZ2)ZYJ<2-|$$6@g`6T|CWfl+Glj?szn zP~nwd9%~m3!nsCRkR za~7C9h1U33qx#yR9GWo@4i>U8fDFow1iK0U5ra!p@YpLniXR5LWaSCKUBIs0F&97a zu1+Brn7Xo!-@(`cXAA9SqLCM=EDH(yTq|;pwi_ImU?BdtIIu9W4tF%}cpsQN(nblA z!142vcpwelIv=DDl@D@L>?_5aOFFZF5N79S|6%xPIU4X~FG|C=Zjup2g zFd|M$0a*l8M5RAm5i`h*(xZ=YALDAa%W!r^FcD8`{h%B0nicYt%L{PejvGKwGZL^S zX#qz`aJ-;B!-=*lh@<9_SKPZ8l}F;PJ7FMod`vvgR;JT1t`!l8)!=;XY0l^+|WV+cvbVE-Av?yuC$}Y zntmkMi?mY9m%R@xV%J?npT;)hux7~U7~Dzi5|o%)em8AmF~c^)b}kSVS=85$mwhqB zl%{b2q6*U~Ol=1!3xH3>I3vedYPrHVpxW1`avtBm=pDZu;Yd46p0lL1YnL;_YcVgi=UJ3xjt44J>~#yiQ1P&o}d$r zfIW#B_a=I;a6BjS#`EO`9vo!4g!uU?Rv;NzDvt~ClEk6!EeY)Ag)_6B;e{ZWY0f?{ z^A_?*C&jZf?v3`;N`%w%L1JM8)a0z)F(IBNLEaU(e??}Ft>oAnzGi@ismkLgfK7%P z1T2`&Sp2?k%hbn#HGIM`tJnxIneHvI%*x8M^ba59e!V`;O~w1~d>(Kp3BRZ)YieN! zbYdz@zxBB6a6@HaMb}|S@uEr~6o?b?&A^7ox;IQGKdt?eiC--m(5)7a0(Y?#GlA}} zyaep7I%<%X)Ux)}`n2l;K+_2qRnE;)rIkQy@$L)Z^=`^UpjKyKKOS)x-b~v{+6oT3 z5hMSY-f(rl@Fo`)#9Ut3bU=Emd*lG>G)zm%&bp#obB78kxjT!yY`OYW6<0Hvj*y5~ zlO1l6!2$kP)StjqSkO}jxP03C87;SATFIL0&CtI{_^e zJlbX)%cMld{6NU@C)+(`nUps!+ipoT{-iqq9ZS9&Zu6N(t8_5i@F_~xd0PO+r8?WL zpLfbXlpp&e_8&wKn9KMZ zzx4P2s^!PoK*FBubwAR%RsEx1>adsI7FYWJZ^)0Ve|q!_=iXC(;;&FEY+D0QuFNF< z5CB^cuCcwVdutFJ>~MIQ#54@%p;DR01iXV$+|qR;cnZWE8!bj7#uiqr(+wu;SpnLjV(6 zSHR3uP=oH)g`{?|kNpk)BX)IbPv%)YAr=z=#8iPCEobqw-|RYIrY#65gZ$L}X~}uE z?i4$+UU+Uv<-En2^Z)>oo*GEKIIvu0YjURanV1NXu}%$I3+C9`4x#5t$2LARAjoyD z#o2AXA#a6bRF*mT(k>V&e{&)z8k5Hnu~Q7EG?Y|wo-E}KSakP_O{hDA#?P0t1JA(v zGvom9&SEYyXN1$&Z6o0;#&w^<*~J4HJ?d7Pg&+WVIbRPG5DjrU()uzh+C{hs8#u?9 zJl{~Ms3F%DEU5wU1T1-$$UQq?zo4GjsK;;Ab6i75`~DTz5@p~5zGEZM>xv~=(-m>Ws2@aG5 zmsW*G8i)^Ps%On*FswhlZA#6sbOX(4Ccjhp!L_S~A!gIMgkV@JwL{jK7;90h*7>j^+ zDe&_WRlM-`;lU|+nY+R5^fhlS)0QR?)iJSwknUdf1TII&IR<$Oz=^XeRhl;+Hqh5g z2IkjsDodlhK~}*bfUg@cT#Sv_)8$}KO8_l<0N-VTxdxm& zycdD{GBM+D@={Tem?Zdx;&RF-ikaavRDCKrt({szw0swBN3o+v!twNmOo1)BU6FtM zOudj-%N;mudbC{Vo*+0JK7tNso_K=2p?M_1UpH?*U(*%`UE9qZw|2f9+kQy_}as)qWwOO|NAarizg~ z$G~_1)UCd}S+pS(33eY9JSjk=h7@>38%4?hA zFdCNo5D^u0|4vvN3~=HHtHQ&(mI^bHfFa$E|S~x_6r7;glqAU@YzD-bzx&hNP zp1h7A*G^Gow}Q#HB!rj~f+gIPX{akjvwkamD_Fop%qWKC@lC7TX-as7`y?8apmimu znASPdyLL}5ymoE~IC;pCyQ_BhsTrt@t+NlTAQvz}=WE7PA;=AYD@8gCG21fc6*qXJ zSl1Q+hr5>=9c@%kFKmc^r7JaAtlAP^WNEmz&P}a1kOC4t*q2Fz6Vz`i0Q3!)m+gPO zF%F~-nCT(UfKO-0dbMuA@dd|C5=>rPpHYpylXXADozly8T>ua*)LRQL9mBb-`%QFV z{n`RB@M#IAeR*|&b=rsUa|kJrGfU(7XQ(Pzym~`Qg0p;WA@;}>JO3P>8*yByCWAMC zYwqqQjMIc{X)D&X2Q!8>K1-H_AZ(m&V=M~DWVCoS0^S993XKPpmtTa4FI;tBn9%_a zrSQw=LqF95LlQfHaOpg=Tn<2rTH8j>B_i*tdb8Ue+bIUxA>eV69VrPi%8h|f02)7p4xVf|?_I0B1Shy17DBrEPs zT^gC4OvFvTE@eJ3+)74AB=~%$zF}Tv7Mo3dOs*rIsE`B%*2NLtw=h724G97B4`v${ zy`~*R4v(vVsY5nT&$2O5C^N(N6eQ*QdeFJA{*>Cy(r`+p3$Ud0CIS*_n7c8~C~9>^ zwM&SH(J)sUo;&a`kGK`vfWqTqF&IFcvFi>dis3GlN_t(zSYHnFCEo%~H0EL*aLQy9 zmB(`<)B+H86_kiL2R{qXox(8}hj{D9#3GvTvaUVHf&7kChA*)KpiyH5^WHn_hm$5Y zzg;rviUy7{DGdm^g+*^;jZ~&9{GzoWG&RG;iMR zUDefu$TbY1D;Sx%%^fKu?%R41Tl+#gbz*S=a5EAFUqs`KJoK;t!)jU@b~9fcpaC4K zbQm(7+dQNr3AUbjQ^kPD0mDYD*HcT+Jym3DKhqZ9c+1sXrnj+aMqsSPvcq&HGa3Nm zkEB%kW1eNmJl`^Y%_YIW?!KrKs}&D)J2DVDJkR$>j3ebRAqzN;5x*h-&(urbkyxv@ zfErZ>)Q(U>vuJf5U#f3{wq9YHNNM3dFtAcv%6kMrt-XZ&N4SUEC^Y60u&I{xWuf5( zLWqh!lmvc8!w7ivqo(2Hzm64TlnqS#fa92Xi1Qh3xq#m9nw-anmKRnS5HB3;Z!L4( zI#+ZB!UgXi=k9OqJI9@(_abnoW4vIV*HuiOLB372j6n8&K|kQcXhLO{3#Av!G9!db z8AzvfV#a$$N5!QUY3{oZE-xqpCl5uUD_|<11sW?5o6x9UUJ1^PL99RTC`As~y(H|U zl9+(YK2|8i7UH=9INR-fhLbs7o81Y~%xep|W`zBFfx#G+ao4b5;;M9DVJh(UfPDlV zj@1MPuMpi89O4`=qzebOkTtd9%#PylkqB1I=E|o+VVP+0dlnrU4`H8G^Wqa~$-UPf z9s}c<_|hR_r1|XcpT_{Ucc9(j>sxjsNxG%#RWqY8u;3cOYr_-=a91^NV=dmNwuk vAD+H;wK_&M8a4Y8T9RohY0-Z6nHmN-2aqa&Bs5bFf literal 0 HcmV?d00001 diff --git a/Themes/Til Death/Scripts/11 Wheel.lua b/Themes/Til Death/Scripts/11 Wheel.lua new file mode 100644 index 0000000000..8c8eb2fbd2 --- /dev/null +++ b/Themes/Til Death/Scripts/11 Wheel.lua @@ -0,0 +1,252 @@ +local Wheel = {} + +Wheel.mt = { + move = function(whee, num) + rebuildFrames(whee, whee.index + num) + --TODO: Animations? + end, + rebuildFrames = function(whee, newIndex) + whee.items = whee.itemsGetter() + whee.index = newIndex or whee.startIndex + for k, v in pairs(whee.items) do + -- TODO: Handle circular buffering logic? + whee.itemUpdater(v, whee.items[k]) + end + end +} + +Wheel.defaultParams = { + itemsGetter = function() + -- Should return an array table of elements for the wheel + -- This is a function so it can be delayed, and rebuilt + -- with different items using this function + return SONGMAN:GetAllSongs() + end, + count = 20, + itemBuilder = function() + -- Should return an actor def + --TODO + end, + frameUpdater = function(frame, item) -- Update an frame created with frameBuilder with an item + --TODO + end, + x = 0, + y = 0, + highlightBuilder = function() + end, + buildOnInit = true, -- Build wheel in InitCommand (Will be empty until rebuilt otherwise) + frameTransformer = function(frame, offsetFromCenter, index, total) -- Handle frame positioning + --TODO + end, + startIndex = 1 +} +function Wheel:new(params) + local whee = Def.ActorFrame {} + setmetatable(whee, Wheel.mt) + whee.itemsGetter = params.itemsGetter + whee.count = params.count + whee.startIndex = params.startIndex + whee.frameUpdater = params.frameUpdater + whee.buildOnInit = params.buildOnInit + whee.frameTransformer = params.frameTransformer + whee.index = whee.startIndex + whee.x = params.x + whee.y = params.y + whee.OnCommand = function() + whee:x(whee.x):y(whee.y) + if params.buildOnInit then + whee:rebuildFrames() + end + end + whee.frames = {} + for i = 1, (params.count) do + local frame = + params.frameBuilder() .. + { + InitCommand = function(self) + whee.frames[i] = self + local offset = math.floor(i - whee.count / 2 + 0.5) + whee.frameTransformer(self, offset, i, whee.count) + end + } + whee[#whee + 1] = frame + end + whee[#whee + 1] = + params.highlightBuilder() .. + { + InitCommand = function(self) + whee.highlight = self + end + } + return whee +end + +local function LegacyParams() + local params = {} + local function SelectMusicWheelMetric(key) + return GetMetric("ScreenSelectMusic", "MusicWheel" .. key) + end + params.x = SelectMusicWheelMetric("X") + params.y = SelectMusicWheelMetric("Y") + local function MusicWheelMetric(key) + return GetMetric("MusicWheel", key) + end + params.frameTransformer = MusicWheelMetric("ItemTransformFunction") + params.count = MusicWheelMetric("NumWheelItems") + local function MusicWheelItemMetric(key) + return GetMetric("MusicWheelItem", key) + end + local songNameX = MusicWheelItemMetric("SongNameX") + local songNameY = MusicWheelItemMetric("SongNameY") + local function wheelItemPartXY(type) + return { + x = MusicWheelItemMetric(type .. "X"), + y = MusicWheelItemMetric(type .. "Y") + } + end + local function wheelItemPart(type) + local part = wheelItemPartXY(type) + part.on = MusicWheelItemMetric(type .. "OnCommand") + return part + end + local wheelItemParts = { + "SectionExpanded", + "SectionCollapsed", + "SectionCount", + "Sort", + "WheelNotifyIcon", + "Roulette", + "SongName", + "Portal", + "Random", + "Custom", + "Mode" + } + params.parts = {} + for i = 1, #wheelItemParts do + local part = wheelItemParts[i] + params.parts[part] = wheelItemPart(part) + end + local wheelItemTypes = { + "Course", + "Custom", + "Mode", + "Portal", + "Random", + "Roulette", + "SectionExpanded", + "SectionCollaped", + "Song", + "Sort" + } + local function loadGraphicFile(filename) + --TODO + return loadfile(THEME:GetPathG(filename, "")) + end + local function loadMusicWheelItemPartLegacyActor(name) + return loadGraphicFile("MusicWheelItem " .. type) + end + local function loadMusicWheelItemTypeLegacyActor(type) + local parts = { + "Normal", + "Color", + "Over" + } + local item = Def.ActorFrame {} + for i = 1, #parts do + local part = parts[i] + local actor = loadMusicWheelItemPartLegacyActor(type .. " " .. part .. "Part") + item[#item + 1] = actor + end + return item + end + local function constF(x) + return function() + return x + end + end + params.actorBuilders = {} + for i = 1, #wheelItemTypes do + local type = wheelItemTypes[i] + params.actorBuilders[type] = constF(loadMusicWheelItemTypeLegacyActor(type)) + end + params.actorBuilders.grades = constF(loadMusicWheelItemPartLegacyActor("grades")) + params.actorBuilders.highlight = constF(loadGraphicFile("highlight")) +end + +local function example() + -- Pseudo code for a possible way of doing groups + -- Using polymorphism of items so both strings and songs are in there + local function allPacks() + --TODO + end + local function songActor() + --TODO + end + local function groupActor() + --TODO + end + local function split(table, element) + --TODO + end + local function concat(t1, t2, t3, t4, tn) + --TODO + end + local function getAllSongsFromPack(packname) + --TODO + end + local w + w = + Wheel:new { + contentGetter = allPacks, + frameBuilder = function() + local x + x = + Def.ActorFrame { + groupActor { + InitCommand = function(self) + x.g = self + end + }, + songActor { + InitCommand = function(self) + x.s = self + end + } + } + return x + end, + frameUpdater = function(frame, songOrPack) + if songOrPack.GetAllSteps then -- song + -- Update songActor and make group actor invis + local song = frame.s + local group = frame.g + group:visible(false) + song:visible(true) + else -- pack + --update group actor and make song actor invis + local song = frame.s + local group = frame.g + group:visible(true) + song:visible(false) + end + end, + onSelection = function(frame, songOrPack) + if songOrPack.GetAllSteps then -- song + -- TODO: Start song + else -- pack + local group = songOrPack + local groups = allPacks() + local g1, g2 = split(groups, group) + w.contentGetter = function() + return concat(g1, getAllSongsFromPack(group), g2) + end + w:rebuildFrames() + end + end + } +end + +function Wheel:LegacyWheel() + return Wheel.new(LegacyParams) +end diff --git a/Themes/_fallback/Scripts/02 ActorDef.lua b/Themes/_fallback/Scripts/02 ActorDef.lua index 79938a8b8d..a44f56ceed 100644 --- a/Themes/_fallback/Scripts/02 ActorDef.lua +++ b/Themes/_fallback/Scripts/02 ActorDef.lua @@ -87,6 +87,9 @@ setmetatable( ) --- Resolve a path (Returns resolved path string) +-- @string path +-- @number level integer, call stack level for error() +-- @boolean optional is this path required or optional function ResolveRelativePath(path, level, optional) if path:sub(1, 1) ~= "/" then -- "Working directory": @@ -101,6 +104,8 @@ function ResolveRelativePath(path, level, optional) end --- Load an actor template. +-- @string path +-- @number level integer, call stack level for error() function LoadActorFunc(path, level) level = level or 1 @@ -166,6 +171,7 @@ function LoadActorFunc(path, level) end --- Load and create an actor template. +-- @string path function LoadActor(path, ...) local t = LoadActorFunc(path, 2) assert(t) @@ -174,6 +180,8 @@ end --- Same as LoadActor but sets everything in params as -- "Thread Variables" accessed via Var("name") +-- @string path path to file without extension +-- @table params doing Var(key) in the file in path will index this table function LoadActorWithParams(path, params, ...) local t = LoadActorFunc(path, 2) assert(t) @@ -218,7 +226,7 @@ function LoadColorFont(a, b) } end ---- Returns an ActorFrame with the numeric table t as children +--- Returns an ActorFrame with the numeric table/array t as children function WrapInActorFrame(t) return Def.ActorFrame {children = t} end @@ -256,6 +264,7 @@ function ShowStandardDecoration(MetricsName) return THEME:GetMetric(Var "LoadingScreen", "Show" .. MetricsName) end +-- @table NullActor --blank actor because these come in handy from time to time NullActor = {Class = "Actor", _Source = "(null actor)"} diff --git a/Themes/_fallback/docs/markdown/Actor-Commands.md b/Themes/_fallback/docs/markdown/Actor-Commands.md new file mode 100644 index 0000000000..77c01ef96b --- /dev/null +++ b/Themes/_fallback/docs/markdown/Actor-Commands.md @@ -0,0 +1,187 @@ +#Actor Commands + +## Command + +A command is basically an `Actor` function defined by lua. These can be called instantly using playcommand(commandStringName) or queued for the next frame using queuecommand(commandStringName) on an actor. Usually, they identify certain events that happen, and are called accordingly. Parameters to Commands are '(self, params)' with params being an optional table of named parameters. Note that the command's name must be stripped of the suffix 'Command' when playing/queueing it. + + Def.ActorFrame { + InitCommand = function(self) + self:x(5) + end + } + +## MessageCommand + +A 'message' command is registered as XMessageCommand (Instead of XCommand), and the registered command will still be called X, but it will be flagged as a message command. This means that if someone broadcasts a message (Using `MSGMAN` a.k.a message manager) it will trigger/execute that command (Meaning, that function). Parameters to MessageCommands are '(self, params)' with params being an optional table of named parameters. + +## Universal Commands + +These are Commands which are usable for all actors, regardless of screen. + +### InitCommand + +Executed before the screen displays it's 'on' state. Useful to initialize actor state (Like position, sizes, storing the reference to the actor in a file-local variable) + +### OnCommand + +Executed as the screen is displayed (After all InitCommands). Useful, for example, to begin animations as the player enters a screen. + +### OffCommand + +Executed as the screen is being exited. + +### AnimationFinishedCommand + +Executed when an animation is finished (If one was executed on this actor) + +### CodeMessageCommand + +Executed when any button specified in metrics is pressed. You must have CodeNames set in the respective screen in metrics.ini for this to function correctly. + + params = { + PlayerNumber = PLAYER_1 or PLAYER_2 , + Name = the name of the code you specified. So if you have `Codeleft="Left"` in metrics.ini and you press left, params.Name would be "left" + } + +Example metrics: + + CodeNames="ResetJudge,PrevJudge,NextJudge,ToggleHands" + CodeResetJudge="MenuUp" + CodeNextJudge="EffectUp" + CodePrevJudge="EffectDown" + CodeToggleHands="MenuDown" + +# Screen Specific + +Note: In case something is missing in any particular screen, you can check the ScreenX.cpp files under /src/ in the github repository, checking what is broadcasted by MESSAGEMAN. + +## ScreenSelectMusic + +### SetMessageCommand + +Broadcast when a `MusicWheelItem`' is being set with new information, such as when scrolling up and down. Gets the `Song` currently selected in the `MusicWheel` + + params = { + Song = An instance of the `Song` that was just set to the `MusicWheelItem`, + Index = The index of the `MusicWheelItem` that was just set, + HasFocus = If the `MusicWheelItem` is focused or not, + Text = The name of the song group this `MusicWheelItem` is from, + } + +### CurrentStepsP1ChangedMessageCommand + +Triggered when the currently selected `Steps` (a.k.a chart within a `Song`) change, whether it be by changing the difficulty or selecting another song. + +### CurrentSongChangedMessageCommand + +Triggered when the `MusicWheel` current `Song` changes. + +### PreviousSongMessageCommand or NextSongMessageCommand + +Triggered when the player selects a different `Song` in the `MusicWheel` by tapping left or right. + +### ChangeStepsMessageCommand + +Triggered when `Steps` are changed. Need to check player & direction using ChangeStepsMessageCommand=function(self, params) then params.Player and params.Direction. + + params = { + Player =PLAYER_1 or PLAYER_2, + Direction = 1 or -1, + } + +## ScreenGameplay + +### LifeChangedMessageCommand + +Activated whenever a player's life changes. + +| Parameters | Description | +| ---------- | --------------------------------------- | +| Player | Either PLAYER_1 or PLAYER_2 | +| LifeMeter | Amount of life in a decimal from 0 to 1 | + +If the lifebar is type is battery it will also have LivesLeft and LostLife. + +### HealthStateChangedMessageCommand + +Activated whenever a player's health state changes... + +| Parameters | Description | +| -------------- | ------------------------------------------------------------------------------------------------------------------------ | +| PlayerNumber | Either PLAYER_1 or PLAYER_2 | +| HealthState | A HealthState Enum, which is either `HealthState_Hot`, `HealthState_Alive`, `HealthState_Danger`, or `HealthState_Dead`. | +| OldHealthState | self explanatory. | + +### PlayerFailedMessageCommand + +This one's obvious. + +| Parameters | Description | +| ------------ | --------------------------- | +| PlayerNumber | Either PLAYER_1 or PLAYER_2 | + +### ScoreChangedMessageCommand + +Activated whenever a player's score changes. Params include PlayerNumber and MultiPlayer, but can also include ToastyCombo in certain cases. + +| Parameters | Description | +| ------------ | --------------------------- | +| PlayerNumber | Either PLAYER_1 or PLAYER_2 | +| MultiPlayer | ??? | + +### JudgmentMessageCommand + +Triggered when a judgment happens, either because a player stepped on a note or they completely missed it. + +| Parameters | Description | +| ------------- | -------------------------------- | +| Player | Either PLAYER_1 or PLAYER_2 | +| MultiPlayer | If they're multiplayer, probably | +| TapNoteSccre | The TapNoteScore | +| Early | True if early, false if late | +| TapNoteOffset | Offset of the judgement | +| HoldNoteScore | The HoldNoteScore | + +### ComboChangedMessageCommand + +Activated whenever a combo changes. + +| Parameters | Description | +| ---------------- | ---------------------------------------------------------------- | +| Player | Either PLAYER_1 or PLAYER_2 | +| OldCombo | ??? | +| OldMissCombo | ??? | +| PlayerState | An instance of PlayerState. This may not always be present. | +| PlayerStageStats | An instance of PlayerStageStats. This may not always be present. | + +### ToastyAchievedMessageCommand + +| Parameters | Description | +| ------------ | --------------------------- | +| PlayerNumber | Either PLAYER_1 or PLAYER_2 | +| ToastyCombo | ??? | +| Level | ??? | + +### ToastyDroppedMessageCommand + +| Parameters | Description | +| ------------ | --------------------------- | +| PlayerNumber | Either PLAYER_1 or PLAYER_2 | + +### DoneLoadingNextSongMessageCommand + +Unknown, might be triggered during course mode + +## ActorScroller specific + +### GainFocusCommand + +Triggered when the ActorScroller is selected + +### LoseFocusCommand + +Triggered when the ActorScroller is deselected + +## Downloads + +### diff --git a/Themes/_fallback/docs/markdown/QuickStart.md b/Themes/_fallback/docs/markdown/QuickStart.md new file mode 100644 index 0000000000..e1d9826578 --- /dev/null +++ b/Themes/_fallback/docs/markdown/QuickStart.md @@ -0,0 +1,15 @@ +# QuickStart + +A lua file is plain text. To create and edit these you need a plain text editor such as notepad. + +You can use any text editor, but to make your life easier, we recommend that you use vscode. Extensions you may want to use with vscode would definitely be the vscode-lua generic lua extension and the ettlua extension. + +If you have no programming language experience whatsoever or you are not familiar with lua and don't think you would be comfortable infering the syntax, it is recommended that you read some lua book or material (Like https://www.lua.org/pil/contents.html , chapter 1 being optional, chapters 2 to 5 recommended and 13,19 and 20 also optional. You're free to read the whole book, but you will probably not get a lot of useful things for lua in this game from the rest). + +## Basic Structure + +The game defines a number of `Screen`s. It's possible to define custom `Screens`, but that's not inmediately relevant. Each `Screen` is a container for `Actor`s. Pretty much every Drawable thing is an `Actor`. A container for `Actor`s is actually called an `ActorFrame` (So, `Screen`s are `ActorFrame`s). Lua comes into play in the game when loading `Screen`s. Some lua code is executed when initializing `Screen`s, and it tells the game which `Actor`s it needs to create and add to it. It can also registers a number of `Command`s, which are just lua functions executed on certain events (Usually called by the game engine). Lua code is also executed when the game is executed, on startup, usually to initialize whatever global state it needs to use later, and to define functions globally so they can be available everywhere (Note: Usually it's recommended to "namespace" your global functions, putting them under a table, so as to not pollute the global namespace). A lua file executed at startup is called a `Script` within the context of this game. Sometimes, Screen lua files are called `BGAnimations`, or "BackGround Animations" (Sometimes abbreviated BGAnims). + +## Screens + +I mentioned lua code can be executed on `Screen` initialization. However, `Screen`s have a second component to them that is of relatively big importance to someone dealing with BGAnims: metrics.ini diff --git a/Utils/config.ld b/Utils/config.ld index 53f963890c..72e41496c4 100644 --- a/Utils/config.ld +++ b/Utils/config.ld @@ -1,8 +1,13 @@ +project = "Etterna" title = "Etterna lua docs" description = "Spread 4k focused rhythm game" -project = "Etterna" -file = {"../Themes/_fallback/Scripts"} +file = {"../Themes/_fallback/Scripts", "../Themes/_fallback/docs"} +topics = '../Themes/_fallback/docs/markdown' +use_markdown_titles = true +format = 'discount' +style = '!fixed' all = true pretty = true --prettify_files = true -not_luadoc = true \ No newline at end of file +not_luadoc = true +alias('ret',{'return',modifiers={type="$1"}}) \ No newline at end of file From 1e21ae049948b0c75da06d9b63946dfdd14fce06 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 15:16:25 -0500 Subject: [PATCH 007/320] fix theme errors due to typos --- .../BGAnimations/ScreenSelectMusic decorations/score.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index ac5c82fb02..abcc07938b 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -352,7 +352,8 @@ local l = local overall = score:GetSkillsetSSR("Overall") self:settextf("%.2f", overall):diffuse(byMSD(overall)) end - }, + end + }, LoadFont("Common Normal") .. { Name = "Score", @@ -380,7 +381,7 @@ local l = self:settext(getClearTypeFromScore(pn, score, 0)) self:diffuse(getClearTypeFromScore(pn, score, 2)) end - },rtLeaderboard callbacks + }, LoadFont("Common Normal") .. { Name = "Combo", From 8a5dbbaaaea86b3ae5cbeeece92973a93adc4807 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 15:17:27 -0500 Subject: [PATCH 008/320] fix scoretab not updating properly when tabs are swtiched --- .../BGAnimations/ScreenSelectMusic decorations/score.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index abcc07938b..c344eea749 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -225,7 +225,7 @@ local t = BeginCommand = function(self) SCREENMAN:GetTopScreen():AddInputCallback(input) end, - SetCommand = function(self) + OnCommand = function(self) if nestedTab == 1 and self:GetVisible() then if GAMESTATE:GetCurrentSong() ~= nil then rtTable = getRateTable() From 5f83ccd4c11a9e304c060c9086288c88dadf7f7c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 15:22:19 -0500 Subject: [PATCH 009/320] explicitly set chartpreview notefield visibility when toggling --- .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index b6b6168a3f..a3f26d7664 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -117,9 +117,11 @@ local function toggleNoteField() if song then if mcbootlarder:GetVisible() then mcbootlarder:visible(false) + mcbootlarder:GetChild("NoteField"):visible(false) MESSAGEMAN:Broadcast("ChartPreviewOff") else mcbootlarder:visible(true) + mcbootlarder:GetChild("NoteField"):visible(true) MESSAGEMAN:Broadcast("ChartPreviewOn") end end From f416a99907b862d6b01572726b4e5060c5b977e6 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 15:31:08 -0500 Subject: [PATCH 010/320] remove unnecessary and unanswered visibility set in cdgraphs --- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index 80fc8ab849..17da340203 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -43,7 +43,6 @@ local function updateGraphMultiVertex(parent, realgraph) -- reset everything if theres nothing to show realgraph:SetVertices({}) realgraph:SetDrawState( {Mode = "DrawMode_Quads", First = 0, Num = 0} ) - realgraph:visible(false) return end From 47ed239e3ca443012343971721491b76fe8b0432 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 15:49:22 -0500 Subject: [PATCH 011/320] properly center chartpreview notefields --- .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 3 +-- Themes/Til Death/BGAnimations/_chartpreview.lua | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index a3f26d7664..9a4ae14e4b 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -9,7 +9,6 @@ local noteField = false local heyiwasusingthat = false local mcbootlarder local prevX = capWideScale(get43size(98), 98) -local idkwhatimdoing = capWideScale(prevX+8, prevX/2+4) local usingreverse = GAMESTATE:GetPlayerState(PLAYER_1):GetCurrentPlayerOptions():UsingReverse() local prevY = 55 local prevrevY = 208 @@ -108,7 +107,7 @@ local function toggleNoteField() MESSAGEMAN:Broadcast("ChartPreviewOn") -- for banner reaction... lazy -mina mcbootlarder:playcommand("SetupNoteField") mcbootlarder:xy(prevX,prevY) - mcbootlarder:GetChild("NoteField"):xy(prevX+idkwhatimdoing, prevY*1.5) + mcbootlarder:GetChild("NoteField"):y(prevY*1.5) if usingreverse then mcbootlarder:GetChild("NoteField"):y(prevY*1.5 + prevrevY) end diff --git a/Themes/Til Death/BGAnimations/_chartpreview.lua b/Themes/Til Death/BGAnimations/_chartpreview.lua index 84db559800..01cabb5678 100644 --- a/Themes/Til Death/BGAnimations/_chartpreview.lua +++ b/Themes/Til Death/BGAnimations/_chartpreview.lua @@ -26,6 +26,7 @@ local function setUpPreviewNoteField() yeet:zoom(prevZoom):draworder(90) SCREENMAN:GetTopScreen():dootforkfive(memehamstermax) yeet = memehamstermax:GetChild("NoteField") + yeet:x(wodth/2) memehamstermax:SortByDrawOrder() MESSAGEMAN:Broadcast("NoteFieldVisible") end From bf195c03191c73ed17f84795031194c1991c208e Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 16:22:36 -0500 Subject: [PATCH 012/320] cleanup old stuff in songbg --- Themes/Til Death/BGAnimations/_songbg.lua | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Themes/Til Death/BGAnimations/_songbg.lua b/Themes/Til Death/BGAnimations/_songbg.lua index eaf12db8d2..93d7019199 100644 --- a/Themes/Til Death/BGAnimations/_songbg.lua +++ b/Themes/Til Death/BGAnimations/_songbg.lua @@ -1,7 +1,3 @@ -local magnitude = 0.03 -local maxDistX = SCREEN_WIDTH * magnitude -local maxDistY = SCREEN_HEIGHT * magnitude - local enabled = themeConfig:get_data().global.SongBGEnabled local brightness = 0.3 @@ -13,21 +9,12 @@ if enabled then CurrentSongChangedMessageCommand = function(self) self:finishtweening():smooth(0.5):diffusealpha(0):sleep(0.2):queuecommand("ModifySongBackground") end, - BeginCommand = function(self) - self:scaletocover(0, 0, SCREEN_WIDTH + maxDistX / 4, SCREEN_BOTTOM + maxDistY / 4):diffusealpha(0.3) - end, ModifySongBackgroundCommand = function(self) self:finishtweening() - collectgarbage() if GAMESTATE:GetCurrentSong() and GAMESTATE:GetCurrentSong():GetBackgroundPath() then self:finishtweening() self:visible(true) self:LoadBackground(GAMESTATE:GetCurrentSong():GetBackgroundPath()) - if moveBG then - self:scaletocover(0 - maxDistY / 8, 0 - maxDistY / 8, SCREEN_WIDTH + maxDistX / 8, SCREEN_BOTTOM + maxDistY / 8) - else - self:scaletocover(0, 0, SCREEN_WIDTH, SCREEN_BOTTOM) - end self:scaletocover(0, 0, SCREEN_WIDTH, SCREEN_BOTTOM) self:sleep(0.25) self:smooth(0.5) From c708453ea3e021c98a0f725eab4e1b1c6732f8b7 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 16:23:20 -0500 Subject: [PATCH 013/320] move lua collect garbage call to select music default --- .../BGAnimations/ScreenSelectMusic decorations/default.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua index 78b3f38f79..1c677736c0 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua @@ -90,4 +90,5 @@ t[#t + 1] = } t[#t + 1] = LoadActor("../_mousewheelscroll") +collectgarbage() return t From 0d3f2a731a6e0e49ca88dd0979c8b3ce3a8cca59 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 17:20:55 -0500 Subject: [PATCH 014/320] fix delayed online leaderboard load theme error --- Themes/Til Death/BGAnimations/superscoreboard.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index 8f5d89d137..af438eb684 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -106,9 +106,11 @@ local o = SCREENMAN:GetTopScreen():AddInputCallback(input) end, ChartLeaderboardUpdateMessageCommand = function(self) - scoretable = DLMAN:GetChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), currentCountry) - ind = 0 - self:playcommand("Update") + if GAMESTATE:GetCurrentSong() then + scoretable = DLMAN:GetChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), currentCountry) + ind = 0 + self:playcommand("Update") + end end, BortCommand = function(self) scoretable = {} From 7aaf002fcb08960d4927884a708a44f341ccb1b9 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 17:28:27 -0500 Subject: [PATCH 015/320] added possibly templateable mouse select for profile screen the whole screen should probably be rewritten though --- .../ScreenSelectProfile overlay.lua | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua b/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua index 5c8c0c10ab..190eb14252 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua @@ -1,4 +1,30 @@ ---Commenting out the Player 2 stuff so if someone is attempting to use this theme for versus or 2P side, it's not going to work. Go use Prim's original spawnhack theme for that. -Misterkister +local function selectprofile(self) + if isOver(self) then + SCREENMAN:GetTopScreen():SetProfileIndex(PLAYER_1, self:GetParent():GetName() + 1) + SCREENMAN:GetTopScreen():Finish() + end +end +local function genericHighlight(self, highlight, base, clickaction) + self:SetUpdateFunction(function(self) + self:RunCommandsOnChildren( + function(self) + if isOver(self) then + self:diffusealpha(highlight) + else + self:diffusealpha(base) + end + end + ) + end) + self:SetUpdateRate(0.5) + if clickaction then + self:RunCommandsOnChildren( + function(self) + self:addcommand("LeftClickMessage", clickaction) + end + ) + end +end function GetLocalProfiles() local t = {} @@ -8,11 +34,15 @@ function GetLocalProfiles() local profile = PROFILEMAN:GetLocalProfileFromIndex(p) local ProfileCard = Def.ActorFrame { + Name = p, + InitCommand = function(self) + genericHighlight(self, 0.75, 1, selectprofile) + end, LoadFont("Common Large") .. { Text = string.format("%s: %.2f", profile:GetDisplayName(), profile:GetPlayerRating()), InitCommand = function(self) - self:xy(34 / 2, -10):zoom(0.4):ztest(true, maxwidth, (200 - 34 - 4) / 0.4) + self:xy(34 / 2, -10):zoom(0.4):ztest(true, maxwidth, (200 - 34 - 4) / 0.4) end }, LoadFont("Common Normal") .. From a721e495076043a06180c04ec20c55d680f214b2 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 18:20:10 -0500 Subject: [PATCH 016/320] scale cd graph functions to rate --- src/Steps.cpp | 13 +++++++------ src/Steps.h | 6 ++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Steps.cpp b/src/Steps.cpp index 7cad3e6fe5..07583e6223 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -688,7 +688,7 @@ Steps::SetCachedRadarValues(const RadarValues& rv) } vector -Steps::GetNPSVector(NoteData& nd, vector nerv, vector etaner) +Steps::GetNPSVector(NoteData& nd, vector nerv, vector etaner, float rate) { vector doot(static_cast(etaner.back())); int notecounter = 0; @@ -696,7 +696,7 @@ Steps::GetNPSVector(NoteData& nd, vector nerv, vector etaner) int curinterval = 0; for (size_t i = 0; i < nerv.size(); ++i) { - curinterval = static_cast(etaner[i]); + curinterval = static_cast(etaner[i] / rate); if (curinterval > lastinterval) { doot[lastinterval] = notecounter; notecounter = 0; @@ -714,7 +714,7 @@ Steps::GetNPSVector(NoteData& nd, vector nerv, vector etaner) } vector -Steps::GetCNPSVector(NoteData& nd, vector nerv, vector etaner, int chordsize) +Steps::GetCNPSVector(NoteData& nd, vector nerv, vector etaner, int chordsize, float rate) { vector doot(static_cast(etaner.back())); int chordnotecounter = 0; // number of NOTES inside chords of this size, so 5 jumps = 10 notes, 3 hands = 9 notes, etc @@ -902,21 +902,22 @@ class LunaSteps : public Luna } static int GetCDGraphVectors(T* p, lua_State* L) { + float rate = FArg(1); auto nd = p->GetNoteData(); if (nd.IsEmpty()) return 0; const vector& nerv = nd.BuildAndGetNerv(); const vector& etaner = - p->GetTimingData()->BuildAndGetEtaner(nerv); + p->GetTimingData()->BuildAndGetEtaner(nerv); // directly using CreateTableFromArray(p->GetNPSVector(nd, nerv, etaner), L) produced tables full of 0 values for ???? reason -mina - vector scroot = p->GetNPSVector(nd, nerv, etaner); + vector scroot = p->GetNPSVector(nd, nerv, etaner, rate); lua_newtable(L); LuaHelpers::CreateTableFromArray(scroot, L); lua_rawseti(L, -2, 1); for (int i = 1; i < nd.GetNumTracks(); ++i) { - scroot = p->GetCNPSVector(nd, nerv, etaner, i + 1); // sort of confusing: the luatable pos/chordsize are i + 1 + scroot = p->GetCNPSVector(nd, nerv, etaner, i + 1, rate);// sort of confusing: the luatable pos/chordsize are i + 1 LuaHelpers::CreateTableFromArray(scroot, L); // but we're iterating over tracks which are 0 indexed lua_rawseti(L, -2, i + 1); // so jumps are position 2 and 2 notes each when i = 1 -mina } diff --git a/src/Steps.h b/src/Steps.h index 2a4d39aa0d..e4af8febfa 100644 --- a/src/Steps.h +++ b/src/Steps.h @@ -142,7 +142,8 @@ class Steps // self exaplanatory -mina vector GetNPSVector(NoteData& nd, vector nerv, - vector etaner); + vector etaner, + float rate); // takes size of chord and counts how many -NOTES- are in // chords of that exact size (this functionally means // multiplying chord counter by chord size) in a row -mina @@ -150,7 +151,8 @@ class Steps vector GetCNPSVector(NoteData& nd, vector nerv, vector etaner, - int chordsize); + int chordsize, + float rate); float PredictMeter() const { return 1.f; } unsigned GetHash() const; From 86e7401f79c9d5085329f6f5e851eab1b6e5479f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 18:20:55 -0500 Subject: [PATCH 017/320] give lua access to notedata numcols from steps objects --- src/Steps.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Steps.cpp b/src/Steps.cpp index 07583e6223..ed6e43566d 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -722,7 +722,7 @@ Steps::GetCNPSVector(NoteData& nd, vector nerv, vector etaner, int c int curinterval = 0; for (size_t i = 0; i < nerv.size(); ++i) { - curinterval = static_cast(etaner[i]); + curinterval = static_cast(etaner[i] / rate); if (curinterval > lastinterval) { doot[lastinterval] = chordnotecounter; chordnotecounter = 0; @@ -925,7 +925,11 @@ class LunaSteps : public Luna p->GetTimingData()->UnsetEtaner(); return 1; } - + static int GetNumColumns(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetNoteData().GetNumTracks()); + return 1; + } LunaSteps() { ADD_METHOD(GetAuthorCredit); @@ -955,6 +959,7 @@ class LunaSteps : public Luna ADD_METHOD(GetDisplayBPMType); ADD_METHOD(GetRelevantSkillsetsByMSDRank); ADD_METHOD(GetCDGraphVectors); + ADD_METHOD(GetNumColumns); } }; From 8b10acab090ddbc074c5d30094e95caa04e468f2 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 18:29:06 -0500 Subject: [PATCH 018/320] update cdgraph lua side to update with rates --- .../BGAnimations/_chorddensitygraph.lua | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index 17da340203..a3f5aaa5a8 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -23,22 +23,26 @@ local function makeABar(vertices, x, y, barWidth, barHeight, prettycolor) vertices[#vertices + 1] = {{x,y,0},prettycolor} end -local function getColorForDensity(density) +local function getColorForDensity(density, ncol) if density == 1 then return color(".75,.75,.75") -- nps color + elseif density == ncol then + return color(".1,.1,.1") -- biggest chord color elseif density == 2 then return color(".5,.5,.5") -- jumps color elseif density == 3 then return color(".25,.25,.25") -- hands color - else - return color(".1,.1,.1") -- quads color + --else + --local c = lerp(density / (ncol +1 ), .1, .75) -- im sure we can programmatically handle n columns but im too lazy + --return color(c..","..c..","..c..","..c) -- to make this look nice atm -mina end end local function updateGraphMultiVertex(parent, realgraph) local steps = GAMESTATE:GetCurrentSteps(PLAYER_1) if steps then - local graphVectors = steps:GetCDGraphVectors() + local ncol = steps:GetNumColumns() + local graphVectors = steps:GetCDGraphVectors(getCurRateValue()) if graphVectors == nil then -- reset everything if theres nothing to show realgraph:SetVertices({}) @@ -66,7 +70,7 @@ local function updateGraphMultiVertex(parent, realgraph) for density = 1,4 do for column = 1,numberOfColumns do if graphVectors[density][column] > 0 then - local barColor = getColorForDensity(density) + local barColor = getColorForDensity(density, ncol) makeABar(verts, column * columnWidth, yOffset, columnWidth, graphVectors[density][column] * 2 * hodth, barColor) end end @@ -86,6 +90,11 @@ local t = Def.ActorFrame { DelayedChartUpdateMessageCommand = function(self) self:queuecommand("GraphUpdate") end, + CurrentRateChangedMessageCommand = function(self) + if self:GetParent():GetVisible() then + self:queuecommand("GraphUpdate") + end + end, Def.Quad { Name = "cdbg", InitCommand = function(self) From 3539b08349b9ab939004868689f9ac8badad6429 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 19:27:39 -0500 Subject: [PATCH 019/320] clamp min rate to 1.0 in cdgraphs because it crashes below that --- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 5 +++-- src/Steps.cpp | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index a3f5aaa5a8..ee69d65f31 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -42,7 +42,8 @@ local function updateGraphMultiVertex(parent, realgraph) local steps = GAMESTATE:GetCurrentSteps(PLAYER_1) if steps then local ncol = steps:GetNumColumns() - local graphVectors = steps:GetCDGraphVectors(getCurRateValue()) + local rate = math.max(1, getCurRateValue()) + local graphVectors = steps:GetCDGraphVectors(rate) if graphVectors == nil then -- reset everything if theres nothing to show realgraph:SetVertices({}) @@ -52,7 +53,7 @@ local function updateGraphMultiVertex(parent, realgraph) local npsVector = graphVectors[1] -- refers to the cps vector for 1 (tap notes) local numberOfColumns = #npsVector - local columnWidth = wodth/numberOfColumns + local columnWidth = wodth/numberOfColumns * rate -- set height scale of graph relative to the max nps local hodth = 0 diff --git a/src/Steps.cpp b/src/Steps.cpp index ed6e43566d..d6bb4b65a4 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -903,6 +903,7 @@ class LunaSteps : public Luna static int GetCDGraphVectors(T* p, lua_State* L) { float rate = FArg(1); + CLAMP(rate, 1.f, 2.f); auto nd = p->GetNoteData(); if (nd.IsEmpty()) return 0; From c01495eb6209eb7117776fa53d0229f74e859538 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 19:39:13 -0500 Subject: [PATCH 020/320] add text indicator for song position on chartpreview when seeking --- Themes/Til Death/BGAnimations/_chartpreview.lua | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chartpreview.lua b/Themes/Til Death/BGAnimations/_chartpreview.lua index 01cabb5678..c9e290a94e 100644 --- a/Themes/Til Death/BGAnimations/_chartpreview.lua +++ b/Themes/Til Death/BGAnimations/_chartpreview.lua @@ -12,7 +12,7 @@ local cd local function UpdatePreviewPos(self) if noteField and yeet and SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" then local pos = SCREENMAN:GetTopScreen():GetPreviewNoteFieldMusicPosition() / musicratio - self:GetChild("Pos"):zoomto(math.min(pos,wodth), hidth) + self:GetChild("Pos"):zoomto(math.min(pos,wodth), hidth) self:queuecommand("Highlight") end end @@ -93,8 +93,13 @@ local t = Def.ActorFrame { HighlightCommand = function(self) -- use the bg for detection but move the seek pointer -mina if isOver(self) then self:GetParent():GetChild("Seek"):visible(true) + self:GetParent():GetChild("Seektext"):visible(true) self:GetParent():GetChild("Seek"):x(INPUTFILTER:GetMouseX() - self:GetParent():GetX()) + self:GetParent():GetChild("Seektext"):x(INPUTFILTER:GetMouseX() - self:GetParent():GetX() - 4) -- todo: refactor this lmao -mina + self:GetParent():GetChild("Seektext"):y(INPUTFILTER:GetMouseY() - self:GetParent():GetY()) + self:GetParent():GetChild("Seektext"):settextf("%0.2f", self:GetParent():GetChild("Seek"):GetX() * musicratio / getCurRateValue()) else + self:GetParent():GetChild("Seektext"):visible(false) self:GetParent():GetChild("Seek"):visible(false) end end @@ -110,6 +115,13 @@ local t = Def.ActorFrame { t[#t + 1] = LoadActor("_chorddensitygraph.lua") -- more draw order shenanigans +t[#t + 1] = LoadFont("Common Normal") .. { + Name = "Seektext", + InitCommand = function(self) + self:y(8):valign(1):halign(1):draworder(1100):diffuse(color("0.8,0,0")):zoom(0.4) + end +} + t[#t + 1] = Def.Quad { Name = "Seek", InitCommand = function(self) From 3f17b7c9a0348381d43ccaefcda80f53868c3d54 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 19:40:28 -0500 Subject: [PATCH 021/320] some bandaids to chartpreview * give some leeway for the end of the file so we don't begin fadeout before the file actually ends * if the previewpoint is after the last second of the chart, just start near the beginning --- src/ScreenSelectMusic.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 7b843fde2e..52708bb11c 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -370,7 +370,12 @@ ScreenSelectMusic::CheckBackgroundRequests(bool bForce) PlayParams.sFile = song->GetMusicPath(); PlayParams.fLengthSeconds = - song->GetLastSecond() - m_fSampleStartSeconds; + song->GetLastSecond() - m_fSampleStartSeconds + 2.f; + if (PlayParams.fLengthSeconds < 3.f) { // if the songpreview is after the last note + PlayParams.fStartSecond = 5.f; // chartpreview wont play, just set it near the start -mina + PlayParams.fLengthSeconds = song->GetLastSecond() + 2.f; + } + } SOUND->PlayMusic(PlayParams, FallbackMusic); @@ -1601,7 +1606,14 @@ ScreenSelectMusic::GeneratePreviewNoteField() SOUND->StopMusic(); m_sSampleMusicToPlay = song->GetMusicPath(); m_fSampleStartSeconds = max(song->GetFirstSecond() - 4.f, -1.f); - m_fSampleLengthSeconds = song->GetLastSecond(); + m_fSampleLengthSeconds = + song->GetLastSecond() - m_fSampleStartSeconds + 2.f; + if (m_fSampleLengthSeconds < + 3.f) { // if the songpreview is after the last note + m_fSampleStartSeconds = + 5.f; // chartpreview wont play, just set it near the start -mina + m_fSampleLengthSeconds = song->GetLastSecond() + 2.f; + } g_bSampleMusicWaiting = true; CheckBackgroundRequests(true); From 55ad8234a16ed47220339fbd82749fde96b1050f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 19:43:03 -0500 Subject: [PATCH 022/320] bandaid to make sure cd bars dont go outside of bounds --- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index ee69d65f31..29c2b7620a 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -72,7 +72,7 @@ local function updateGraphMultiVertex(parent, realgraph) for column = 1,numberOfColumns do if graphVectors[density][column] > 0 then local barColor = getColorForDensity(density, ncol) - makeABar(verts, column * columnWidth, yOffset, columnWidth, graphVectors[density][column] * 2 * hodth, barColor) + makeABar(verts, math.min(column * columnWidth, wodth), yOffset, columnWidth, graphVectors[density][column] * 2 * hodth, barColor) end end end From 4234038bcdbaa9835d3b8e8d52120d54d9d786a0 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 20:21:36 -0500 Subject: [PATCH 023/320] allow open ended cd graphs --- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index 29c2b7620a..8dce875656 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -68,7 +68,7 @@ local function updateGraphMultiVertex(parent, realgraph) hodth = hidth/hodth local verts = {} -- reset the vertices for the graph local yOffset = 0 -- completely unnecessary, just a Y offset from the graph - for density = 1,4 do + for density = 1,ncol do for column = 1,numberOfColumns do if graphVectors[density][column] > 0 then local barColor = getColorForDensity(density, ncol) From 7eb9a8ea109bac91db2b388448eef2e9b74dfb7a Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 20:24:11 -0500 Subject: [PATCH 024/320] stop preview notefield from regenerating when entering gameplay --- .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 9a4ae14e4b..f3c30f37c1 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -623,7 +623,7 @@ t[#t + 1] = --Chart Preview Button local yesiwantnotefield = false - +local oldstyle local function ihatestickinginputcallbackseverywhere(event) if event.type ~= "InputEventType_Release" and getTabIndex() == 0 then if event.DeviceInput.button == "DeviceButton_space" then @@ -649,11 +649,12 @@ t[#t + 1] = LoadFont("Common Normal") .. { end end, CurrentStyleChangedMessageCommand=function(self) -- need to regenerate the notefield when changing styles or crashman appears -mina - if noteField then + if noteField and oldstyle ~= GAMESTATE:GetCurrentStyle() then SCREENMAN:GetTopScreen():DeletePreviewNoteField(mcbootlarder) noteField = false toggleNoteField() end + oldstyle = GAMESTATE:GetCurrentStyle() end } From cdd6f5c32d22822eb82ef560bb80d11a2b868d03 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 22:44:13 -0300 Subject: [PATCH 025/320] Fix ettmulti selectmusic clicking --- .../default.lua | 169 +++++------------- src/ScreenNetSelectMusic.cpp | 2 +- 2 files changed, 41 insertions(+), 130 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua index 51d53e20d0..a4136b6b65 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua @@ -1,5 +1,12 @@ local t = Def.ActorFrame {} if NSMAN:IsETTP() then + t[#t + 1] = + Def.ActorFrame { + LeftClickMessageCommand = function() + SCREENMAN:SystemMessage("asdasdasd") + MESSAGEMAN:Broadcast("MouseLeftClick") + end + } t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/default") return t end @@ -96,18 +103,19 @@ g[#g + 1] = LoadActor("radaronline") g[#g + 1] = Def.ActorFrame { + Name = "StepsDisplay", InitCommand = function(self) - self:xy(capWideScale(get43size(384), 384) + 26, 70, halign, 0):valign(0):zoom(math.min(1, SCREEN_WIDTH / 854)) + self:xy(stepsdisplayx, 70):valign(0) end, OffCommand = function(self) - self:bouncebegin(0.2):xy(capWideScale(get43size(384), 384) + 26 - 500, 70) -- visible(false() + self:visible(false) end, OnCommand = function(self) - self:bouncebegin(0.2):xy(capWideScale(get43size(384), 384) + 26, 70) + self:visible(true) end, TabChangedMessageCommand = function(self) self:finishtweening() - if getTabIndex() == 0 then + if getTabIndex() < 3 and GAMESTATE:GetCurrentSong() then self:playcommand("On") else self:playcommand("Off") @@ -115,152 +123,55 @@ g[#g + 1] = end, CurrentSongChangedMessageCommand = function(self) local song = GAMESTATE:GetCurrentSong() - if song then - self:finishtweening() - self:playcommand("TweenOn") - elseif not song and self:GetZoomX() == 1 then - self:finishtweening() - self:playcommand("TweenOff") + if song and getTabIndex() < 3 then + self:playcommand("On") + elseif not song then + self:playcommand("Off") end end, + PlayingSampleMusicMessageCommand = function(self) + local leaderboardEnabled = + playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() + if leaderboardEnabled then + local chartkey = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() + DLMAN:RequestChartLeaderBoardFromOnline( + chartkey, + function(leaderboard) + end + ) + end + end, + ChartPreviewOnMessageCommand = function(self) + self:addx(capWideScale(12, 0)):addy(capWideScale(18, 0)) + end, + ChartPreviewOffMessageCommand = function(self) + self:addx(capWideScale(-12, 0)):addy(capWideScale(-18, 0)) + end, Def.StepsDisplayList { Name = "StepsDisplayListRow", CursorP1 = Def.ActorFrame { InitCommand = function(self) - self:x(55):player(PLAYER_1) - end, - PlayerJoinedMessageCommand = function(self, params) - if params.Player == PLAYER_1 then - self:visible(true) - self:zoom(0):bounceend(1):zoom(1) - end - end, - PlayerUnjoinedMessageCommand = function(self, params) - if params.Player == PLAYER_1 then - self:visible(true) - self:bouncebegin(1):zoom(0) - end - end, - Def.Quad { - InitCommand = function(self) - self:zoomto(6, 22):halign(1):valign(0.5) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if GAMESTATE:GetNumPlayersEnabled() >= 2 then - self:zoomy(11) - self:valign(1) - else - self:zoomy(22) - self:valign(0.5) - end - end, - PlayerJoinedMessageCommand = function(self) - self:playcommand("Set") - end, - PlayerUnjoinedMessageCommand = function(self) - self:playcommand("Set") - end - }, - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:x(-1):halign(1):valign(0.5):zoom(0.3):diffuse(color("#000000")) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - self:settext("1") - if GAMESTATE:GetNumPlayersEnabled() >= 2 then - self:y(-6) - else - self:y(0) - end - end, - PlayerJoinedMessageCommand = function(self) - self:playcommand("Set") - end, - PlayerUnjoinedMessageCommand = function(self) - self:playcommand("Set") - end - } - }, - CursorP2 = Def.ActorFrame { - InitCommand = function(self) - self:x(55):player(PLAYER_2) - end, - PlayerJoinedMessageCommand = function(self, params) - if params.Player == PLAYER_2 then - self:visible(true) - self:zoom(0):bounceend(1):zoom(1) - end - end, - PlayerUnjoinedMessageCommand = function(self, params) - if params.Player == PLAYER_2 then - self:visible(true) - self:bouncebegin(1):zoom(0) - end + self:player(PLAYER_1) end, Def.Quad { InitCommand = function(self) - self:zoomto(6, 22):halign(1):valign(0.5) + self:x(54):zoomto(6, 20):halign(1):valign(0.5) end, BeginCommand = function(self) self:queuecommand("Set") end, SetCommand = function(self) - if GAMESTATE:GetNumPlayersEnabled() >= 2 then - self:zoomy(11) - self:valign(0) - else - self:zoomy(22) - self:valign(0.5) - end - end, - PlayerJoinedMessageCommand = function(self) - self:playcommand("Set") - end, - PlayerUnjoinedMessageCommand = function(self) - self:playcommand("Set") + self:zoomy(20) end - }, - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:x(-1):halign(1):valign(0.5):zoom(0.3):diffuse(color("#000000")) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - self:settext("2") - if GAMESTATE:GetNumPlayersEnabled() >= 2 then - self:y(6) - else - self:y(0) - end - end, - PlayerJoinedMessageCommand = function(self) - self:playcommand("Set") - end, - PlayerUnjoinedMessageCommand = function(self) - self:playcommand("Set") - end - } + } }, + CursorP2 = Def.ActorFrame {}, CursorP1Frame = Def.Actor { ChangeCommand = function(self) self:stoptweening():decelerate(0.05) end }, - CursorP2Frame = Def.Actor { - ChangeCommand = function(self) - self:stoptweening():decelerate(0.05) - end - } + CursorP2Frame = Def.Actor {} } } t[#t + 1] = g diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index b2cb26a6eb..b94e07c3d8 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -99,7 +99,7 @@ ScreenNetSelectMusic::Init() NSMAN->OnMusicSelect(); m_bInitialSelect = false; - m_bAllowInput = false; + m_bAllowInput = NSMAN->IsETTP(); SAMPLE_MUSIC_FALLBACK_FADE_IN_SECONDS.Load( m_sName, "SampleMusicFallbackFadeInSeconds"); From f099fe7fdc41e5ad379e55c69eeec7687698d1bb Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 22:45:21 -0300 Subject: [PATCH 026/320] More lua docs stuff --- Themes/_fallback/docs/Actor.luadoc | 705 +++++++++++++++++++ Themes/_fallback/docs/ActorFrame.luadoc | 108 +++ Themes/_fallback/docs/BitmapText.luadoc | 74 ++ Themes/_fallback/docs/Sprite.luadoc | 112 +++ Themes/_fallback/docs/markdown/QuickStart.md | 8 +- 5 files changed, 1003 insertions(+), 4 deletions(-) create mode 100644 Themes/_fallback/docs/Actor.luadoc create mode 100644 Themes/_fallback/docs/ActorFrame.luadoc create mode 100644 Themes/_fallback/docs/BitmapText.luadoc create mode 100644 Themes/_fallback/docs/Sprite.luadoc diff --git a/Themes/_fallback/docs/Actor.luadoc b/Themes/_fallback/docs/Actor.luadoc new file mode 100644 index 0000000000..a3e2e5e1df --- /dev/null +++ b/Themes/_fallback/docs/Actor.luadoc @@ -0,0 +1,705 @@ +--- Basic Actor class +-- @classmod Actor + + +--- Get the name of this specific actor instance +-- Usually set as Def.Actor{Name = "string"} +-- @treturn Actor self +function Actor:name() end + +--- Inserts a linear tween of seconds time and then a 0 seconds empty tween +-- to force the future tweens to happen after seconds seconds elapse +-- @number seconds +-- @treturn Actor self +function Actor:sleep(seconds) end + +--- Inserts a linear tween of seconds time +-- @number seconds +-- @treturn Actor self +function Actor:linear(seconds) end + +--- Inserts an accelerate tween of seconds time +-- @number seconds +-- @treturn Actor self +function Actor:accelerate(seconds) end + +--- Inserts a decelerate tween of seconds time +-- @number seconds +-- @treturn Actor self +function Actor:decelerate(seconds) end + +--- Inserts a spring tween of seconds time +-- @number seconds +-- @treturn Actor self +function Actor:spring(seconds) end + +--- Inserts a tween of tweenType with seconds duration +-- @number seconds +-- @treturn Actor self +function Actor:tween(seconds, tweenType) end + +--- Immediately cancels/stops all tweens left for this actor +-- @treturn Actor self +function Actor:stoptweening() end + +--- Immediately finish all tweens left for this actor +-- This reaches the final state of the tweens in succession +-- @treturn Actor self +function Actor:finishtweening() end + +--- +-- @number factor the ratio for the new tween speedup (Or slowdown) +-- @treturn Actor self +function Actor:hurrytweening(factor) end + +--- +-- @treturn Actor self +function Actor:GetTweenTimeLeft() end + +--- Set this actors horizontal position +-- 0 is the left edge of the screen +-- @number x The new horizontal position to set +-- @treturn Actor self +function Actor:x(x) end + +--- Set this actors vertical position +-- 0 is the top edge of the screen +-- @number y The new vertical position to set +-- @treturn Actor self +function Actor:y(y) end + +--- Set this actors normal position +-- @number z The new position to set +-- @treturn Actor self +function Actor:z(z) end + +--- Set this actors x and y position easily in one method +-- Just for convenience +-- @number x The new horizontal position to set +-- @number y The new vertical position to set +-- @treturn Actor self +function Actor:xy(x, y) end + +--- +-- @treturn Actor self +function Actor:addx() end + +--- +-- @treturn Actor self +function Actor:addy() end + +--- +-- @treturn Actor self +function Actor:addz() end + +--- +-- @treturn Actor self +function Actor:zoom() end + +--- +-- @treturn Actor self +function Actor:zoomx() end + +--- +-- @treturn Actor self +function Actor:zoomy() end + +--- +-- @treturn Actor self +function Actor:zoomz() end + +--- +-- @treturn Actor self +function Actor:zoomto() end + +--- +-- @treturn Actor self +function Actor:zoomtowidth() end + +--- +-- @treturn Actor self +function Actor:zoomtoheight() end + +--- +-- @treturn Actor self +function Actor:setsize() end + +--- +-- @treturn Actor self +function Actor:SetWidth() end + +--- +-- @treturn Actor self +function Actor:SetHeight() end + +--- +-- @treturn Actor self +function Actor:basealpha() end + +--- +-- @treturn Actor self +function Actor:basezoom() end + +--- +-- @treturn Actor self +function Actor:basezoomx() end + +--- +-- @treturn Actor self +function Actor:basezoomy() end + +--- +-- @treturn Actor self +function Actor:basezoomz() end + +--- +-- @treturn Actor self +function Actor:stretchto() end + +--- +-- @treturn Actor self +function Actor:cropleft() end + +--- +-- @treturn Actor self +function Actor:croptop() end + +--- +-- @treturn Actor self +function Actor:cropright() end + +--- +-- @treturn Actor self +function Actor:cropbottom() end + +--- +-- @treturn Actor self +function Actor:fadeleft() end + +--- +-- @treturn Actor self +function Actor:fadetop() end + +--- +-- @treturn Actor self +function Actor:faderight() end + +--- +-- @treturn Actor self +function Actor:fadebottom() end + +--- +-- @treturn Actor self +function Actor:diffuse() end + +--- +-- @treturn Actor self +function Actor:diffuseupperleft() end + +--- +-- @treturn Actor self +function Actor:diffuseupperright() end + +--- +-- @treturn Actor self +function Actor:diffuselowerleft() end + +--- +-- @treturn Actor self +function Actor:diffuselowerright() end + +--- +-- @treturn Actor self +function Actor:diffuseleftedge() end + +--- +-- @treturn Actor self +function Actor:diffuserightedge() end + +--- +-- @treturn Actor self +function Actor:diffusetopedge() end + +--- +-- @treturn Actor self +function Actor:diffusebottomedge() end + +--- +-- @treturn Actor self +function Actor:diffusealpha() end + +--- +-- @treturn Actor self +function Actor:diffusecolor() end + +--- +-- @treturn Actor self +function Actor:glow() end + +--- +-- @treturn Actor self +function Actor:aux() end + +--- +-- @treturn Actor self +function Actor:getaux() end + +--- +-- @treturn Actor self +function Actor:rotationx() end + +--- +-- @treturn Actor self +function Actor:rotationy() end + +--- +-- @treturn Actor self +function Actor:rotationz() end + +--- +-- @treturn Actor self +function Actor:addrotationx() end + +--- +-- @treturn Actor self +function Actor:addrotationy() end + +--- +-- @treturn Actor self +function Actor:addrotationz() end + +--- +-- @treturn Actor self +function Actor:getrotation() end + +--- +-- @treturn Actor self +function Actor:baserotationx() end + +--- +-- @treturn Actor self +function Actor:baserotationy() end + +--- +-- @treturn Actor self +function Actor:baserotationz() end + +--- +-- @treturn Actor self +function Actor:skewx() end + +--- +-- @treturn Actor self +function Actor:skewy() end + +--- +-- @treturn Actor self +function Actor:heading() end + +--- +-- @treturn Actor self +function Actor:pitch() end + +--- +-- @treturn Actor self +function Actor:roll() end + +--- +-- @treturn Actor self +function Actor:shadowlength() end + +--- +-- @treturn Actor self +function Actor:shadowlengthx() end + +--- +-- @treturn Actor self +function Actor:shadowlengthy() end + +--- +-- @treturn Actor self +function Actor:shadowcolor() end + +--- +-- @treturn Actor self +function Actor:horizalign() end + +--- +-- @treturn Actor self +function Actor:vertalign() end + +--- +-- @treturn Actor self +function Actor:halign() end + +--- +-- @treturn Actor self +function Actor:valign() end + +--- +-- @treturn Actor self +function Actor:diffuseblink() end + +--- +-- @treturn Actor self +function Actor:diffuseshift() end + +--- +-- @treturn Actor self +function Actor:diffuseramp() end + +--- +-- @treturn Actor self +function Actor:glowblink() end + +--- +-- @treturn Actor self +function Actor:glowshift() end + +--- +-- @treturn Actor self +function Actor:glowramp() end + +--- +-- @treturn Actor self +function Actor:rainbow() end + +--- +-- @treturn Actor self +function Actor:wag() end + +--- +-- @treturn Actor self +function Actor:bounce() end + +--- +-- @treturn Actor self +function Actor:bob() end + +--- +-- @treturn Actor self +function Actor:pulse() end + +--- +-- @treturn Actor self +function Actor:spin() end + +--- +-- @treturn Actor self +function Actor:vibrate() end + +--- +-- @treturn Actor self +function Actor:stopeffect() end + +--- +-- @treturn Actor self +function Actor:effectcolor1() end + +--- +-- @treturn Actor self +function Actor:effectcolor2() end + +--- +-- @treturn Actor self +function Actor:effectperiod() end + +--- +-- @treturn Actor self +function Actor:effecttiming() end + +--- +-- @treturn Actor self +function Actor:effect_hold_at_full() end + +--- +-- @treturn Actor self +function Actor:effectoffset() end + +--- +-- @treturn Actor self +function Actor:effectclock() end + +--- +-- @treturn Actor self +function Actor:effectmagnitude() end + +--- +-- @treturn Actor self +function Actor:geteffectmagnitude() end + ADD_GET_SET_METHODS(tween_uses_effect_delta); + +--- +-- @treturn Actor self +function Actor:scaletocover() end + +--- +-- @treturn Actor self +function Actor:scaletofit() end + +--- +-- @treturn Actor self +function Actor:animate() end + +--- +-- @treturn Actor self +function Actor:play() end + +--- +-- @treturn Actor self +function Actor:pause() end + +--- +-- @treturn Actor self +function Actor:setstate() end + +--- +-- @treturn Actor self +function Actor:GetNumStates() end + +--- +-- @treturn Actor self +function Actor:texturetranslate() end + +--- +-- @treturn Actor self +function Actor:texturewrapping() end + +--- +-- @treturn Actor self +function Actor:SetTextureFiltering() end + +--- +-- @treturn Actor self +function Actor:blend() end + +--- +-- @treturn Actor self +function Actor:zbuffer() end + +--- +-- @treturn Actor self +function Actor:ztest() end + +--- +-- @treturn Actor self +function Actor:ztestmode() end + +--- +-- @treturn Actor self +function Actor:zwrite() end + +--- +-- @treturn Actor self +function Actor:zbias() end + +--- +-- @treturn Actor self +function Actor:clearzbuffer() end + +--- +-- @treturn Actor self +function Actor:backfacecull() end + +--- +-- @treturn Actor self +function Actor:cullmode() end + +--- +-- @treturn Actor self +function Actor:visible() end + +--- +-- @treturn Actor self +function Actor:hibernate() end + +--- +-- @treturn Actor self +function Actor:draworder() end + +--- +-- @treturn Actor self +function Actor:playcommand() end + +--- +-- @treturn Actor self +function Actor:queuecommand() end + +--- +-- @treturn Actor self +function Actor:queuemessage() end + +--- +-- @treturn Actor self +function Actor:addcommand() end + +--- +-- @treturn Actor self +function Actor:GetCommand() end + +--- +-- @treturn Actor self +function Actor:RunCommandsRecursively() end + +--- Get X position (horizontal) +-- 0 is leftmost +-- @treturn number the horizontal x position. +function Actor:GetX() end + + +--- Get Y position (vertical) +-- 0 is topmost +-- @treturn number the vertical y position. +function Actor:GetY() end + + +--- Get Z position +-- @treturn number the z position. +function Actor:GetZ() end + +--- +-- @treturn Actor self +function Actor:GetDestX() end + +--- +-- @treturn Actor self +function Actor:GetDestY() end + +--- +-- @treturn Actor self +function Actor:GetDestZ() end + +--- +-- @treturn Actor self +function Actor:GetWidth() end + +--- +-- @treturn Actor self +function Actor:GetHeight() end + +--- +-- @treturn Actor self +function Actor:GetZoomedWidth() end + +--- +-- @treturn Actor self +function Actor:GetZoomedHeight() end + +--- +-- @treturn Actor self +function Actor:GetZoom() end + +--- +-- @treturn Actor self +function Actor:GetZoomX() end + +--- +-- @treturn Actor self +function Actor:GetZoomY() end + +--- +-- @treturn Actor self +function Actor:GetZoomZ() end + +--- +-- @treturn Actor self +function Actor:GetRotationX() end + +--- +-- @treturn Actor self +function Actor:GetRotationY() end + +--- +-- @treturn Actor self +function Actor:GetRotationZ() end + +--- +-- @treturn Actor self +function Actor:GetBaseZoomX() end + +--- +-- @treturn Actor self +function Actor:GetBaseZoomY() end + +--- +-- @treturn Actor self +function Actor:GetBaseZoomZ() end + +--- +-- @treturn Actor self +function Actor:GetSecsIntoEffect() end + +--- +-- @treturn Actor self +function Actor:GetEffectDelta() end + +--- +-- @treturn Actor self +function Actor:GetDiffuse() end + +--- +-- @treturn Actor self +function Actor:GetDiffuseAlpha() end + +--- +-- @treturn Actor self +function Actor:GetGlow() end + +--- +-- @treturn Actor self +function Actor:GetVisible() end + +--- +-- @treturn Actor self +function Actor:GetHAlign() end + +--- +-- @treturn Actor self +function Actor:GetVAlign() end + + +--- +-- @treturn Actor self +function Actor:GetName() end + +--- +-- @treturn Actor self +function Actor:GetParent() end + +--- +-- @treturn Actor self +function Actor:GetFakeParent() end + +--- +-- @treturn Actor self +function Actor:SetFakeParent() end + +--- +-- @treturn Actor self +function Actor:AddWrapperState() end + +--- +-- @treturn Actor self +function Actor:RemoveWrapperState() end + +--- +-- @treturn Actor self +function Actor:GetNumWrapperStates() end + +--- +-- @treturn Actor self +function Actor:GetWrapperState() end + + +--- +-- @treturn Actor self +function Actor:Draw() end + + +--- +-- @treturn Actor self +function Actor:SaveXY() end + +--- +-- @treturn Actor self +function Actor:LoadXY() end \ No newline at end of file diff --git a/Themes/_fallback/docs/ActorFrame.luadoc b/Themes/_fallback/docs/ActorFrame.luadoc new file mode 100644 index 0000000000..eee51464f3 --- /dev/null +++ b/Themes/_fallback/docs/ActorFrame.luadoc @@ -0,0 +1,108 @@ +--- Actor container/composite +-- @classmod ActorFrame + + + +--- +-- @treturn ActorFrame self +function ActorFrame:playcommandonchildren() end + +--- +-- @treturn ActorFrame self +function ActorFrame:playcommandonleaves() end + +--- +-- @treturn ActorFrame self +function ActorFrame:runcommandsonleaves() end + +--- +-- @treturn ActorFrame self +function ActorFrame:RunCommandsOnChildren() end + +--- +-- @treturn ActorFrame self +function ActorFrame:propagate() end // deprecated + +--- +-- @treturn ActorFrame self +function ActorFrame:fov() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetUpdateRate() end + +--- +-- @treturn ActorFrame self +function ActorFrame:GetUpdateRate() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetFOV() end + +--- +-- @treturn ActorFrame self +function ActorFrame:vanishpoint() end + +--- +-- @treturn ActorFrame self +function ActorFrame:GetChild() end + +--- +-- @treturn ActorFrame self +function ActorFrame:GetChildren() end + +--- +-- @treturn ActorFrame self +function ActorFrame:GetNumChildren() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetDrawByZPosition() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetDrawFunction() end + +--- +-- @treturn ActorFrame self +function ActorFrame:GetDrawFunction() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetUpdateFunction() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SortByDrawOrder() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetAmbientLightColor() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetDiffuseLightColor() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetSpecularLightColor() end + +--- +-- @treturn ActorFrame self +function ActorFrame:SetLightDirection() end + +--- +-- @treturn ActorFrame self +function ActorFrame:AddChild() end + +--- +-- @treturn ActorFrame self +function ActorFrame:AddChildFromPath() end + +--- +-- @treturn ActorFrame self +function ActorFrame:RemoveChild() end + +--- +-- @treturn ActorFrame self +function ActorFrame:RemoveAllChildren() end \ No newline at end of file diff --git a/Themes/_fallback/docs/BitmapText.luadoc b/Themes/_fallback/docs/BitmapText.luadoc new file mode 100644 index 0000000000..0a88128e9b --- /dev/null +++ b/Themes/_fallback/docs/BitmapText.luadoc @@ -0,0 +1,74 @@ +--- Font actor +-- @classmod BitmapText + + +--- +-- @treturn BitmapText self +function BitmapText:wrapwidthpixels() end + +--- +-- @treturn BitmapText self +function BitmapText:maxwidth() end + +--- +-- @treturn BitmapText self +function BitmapText:maxheight() end + +--- +-- @treturn BitmapText self +function BitmapText:max_dimension_use_zoom() end + +--- +-- @treturn BitmapText self +function BitmapText:vertspacing() end + +--- +-- @treturn BitmapText self +function BitmapText:settext() end + +--- +-- @treturn BitmapText self +function BitmapText:rainbowscroll() end + +--- +-- @treturn BitmapText self +function BitmapText:jitter() end + +--- +-- @treturn BitmapText self +function BitmapText:distort() end + +--- +-- @treturn BitmapText self +function BitmapText:undistort() end + ADD_GET_SET_METHODS(mult_attrs_with_diffuse); + +--- +-- @treturn BitmapText self +function BitmapText:GetText() end + +--- +-- @treturn BitmapText self +function BitmapText:AddAttribute() end + +--- +-- @treturn BitmapText self +function BitmapText:ClearAttributes() end + +--- +-- @treturn BitmapText self +function BitmapText:strokecolor() end + +--- +-- @treturn BitmapText self +function BitmapText:getstrokecolor() end + +--- +-- @treturn BitmapText self +function BitmapText:uppercase() end + +--- +-- @treturn BitmapText self +function BitmapText:textglowmode() end + // ADD_METHOD( LoadFromFont ); +// ADD_METHOD( LoadFromTextureAndChars ); \ No newline at end of file diff --git a/Themes/_fallback/docs/Sprite.luadoc b/Themes/_fallback/docs/Sprite.luadoc new file mode 100644 index 0000000000..fba534fcc7 --- /dev/null +++ b/Themes/_fallback/docs/Sprite.luadoc @@ -0,0 +1,112 @@ +--- Sprite +-- @classmod Sprite + + + +--- +-- @treturn Sprite self +function Sprite:Load() end + +--- +-- @treturn Sprite self +function Sprite:LoadBanner() end + +--- +-- @treturn Sprite self +function Sprite:LoadBackground() end + +--- +-- @treturn Sprite self +function Sprite:LoadFromCached() end + +--- +-- @treturn Sprite self +function Sprite:customtexturerect() end + +--- +-- @treturn Sprite self +function Sprite:SetCustomImageRect() end + +--- +-- @treturn Sprite self +function Sprite:SetCustomPosCoords() end + +--- +-- @treturn Sprite self +function Sprite:StopUsingCustomPosCoords() end + +--- +-- @treturn Sprite self +function Sprite:texcoordvelocity() end + +--- +-- @treturn Sprite self +function Sprite:get_use_effect_clock_for_texcoords() end + +--- +-- @treturn Sprite self +function Sprite:set_use_effect_clock_for_texcoords() end + +--- +-- @treturn Sprite self +function Sprite:scaletoclipped() end + +--- +-- @treturn Sprite self +function Sprite:CropTo() end + +--- +-- @treturn Sprite self +function Sprite:stretchtexcoords() end + +--- +-- @treturn Sprite self +function Sprite:addimagecoords() end + +--- +-- @treturn Sprite self +function Sprite:setstate() end + +--- +-- @treturn Sprite self +function Sprite:GetState() end + +--- +-- @treturn Sprite self +function Sprite:SetStateProperties() end + +--- +-- @treturn Sprite self +function Sprite:GetAnimationLengthSeconds() end + +--- +-- @treturn Sprite self +function Sprite:SetSecondsIntoAnimation() end + +--- +-- @treturn Sprite self +function Sprite:SetTexture() end + +--- +-- @treturn Sprite self +function Sprite:GetTexture() end + +--- +-- @treturn Sprite self +function Sprite:SetEffectMode() end + +--- +-- @treturn Sprite self +function Sprite:GetNumStates() end + +--- +-- @treturn Sprite self +function Sprite:SetAllStateDelays() end + +--- +-- @treturn Sprite self +function Sprite:GetDecodeMovie() end + +--- +-- @treturn Sprite self +function Sprite:SetDecodeMovie() end \ No newline at end of file diff --git a/Themes/_fallback/docs/markdown/QuickStart.md b/Themes/_fallback/docs/markdown/QuickStart.md index e1d9826578..7f1eb042b8 100644 --- a/Themes/_fallback/docs/markdown/QuickStart.md +++ b/Themes/_fallback/docs/markdown/QuickStart.md @@ -2,14 +2,14 @@ A lua file is plain text. To create and edit these you need a plain text editor such as notepad. -You can use any text editor, but to make your life easier, we recommend that you use vscode. Extensions you may want to use with vscode would definitely be the vscode-lua generic lua extension and the ettlua extension. +You can use any text editor, but to make your life easier, we recommend that you use [vscode](https://code.visualstudio.com/Download). Extensions you may want to use with [vscode](https://code.visualstudio.com/Download) would definitely be the [vscode-lua](https://marketplace.visualstudio.com/items?itemName=trixnz.vscode-lua) generic lua extension and the [ettlua](https://marketplace.visualstudio.com/items?itemName=Nick12.ettlua-for-vscode) extension. -If you have no programming language experience whatsoever or you are not familiar with lua and don't think you would be comfortable infering the syntax, it is recommended that you read some lua book or material (Like https://www.lua.org/pil/contents.html , chapter 1 being optional, chapters 2 to 5 recommended and 13,19 and 20 also optional. You're free to read the whole book, but you will probably not get a lot of useful things for lua in this game from the rest). +If you have no programming language experience whatsoever or you are not familiar with lua and don't think you would be comfortable infering the syntax, it is recommended that you read some lua book or material (Like [Programming In Lua](https://www.lua.org/pil/contents.html), chapter 1 being optional, chapters 2 to 5 recommended and 13,19 and 20 also optional. You're free to read the whole book, but you will probably not get a lot of useful things for lua in this game from the rest). ## Basic Structure -The game defines a number of `Screen`s. It's possible to define custom `Screens`, but that's not inmediately relevant. Each `Screen` is a container for `Actor`s. Pretty much every Drawable thing is an `Actor`. A container for `Actor`s is actually called an `ActorFrame` (So, `Screen`s are `ActorFrame`s). Lua comes into play in the game when loading `Screen`s. Some lua code is executed when initializing `Screen`s, and it tells the game which `Actor`s it needs to create and add to it. It can also registers a number of `Command`s, which are just lua functions executed on certain events (Usually called by the game engine). Lua code is also executed when the game is executed, on startup, usually to initialize whatever global state it needs to use later, and to define functions globally so they can be available everywhere (Note: Usually it's recommended to "namespace" your global functions, putting them under a table, so as to not pollute the global namespace). A lua file executed at startup is called a `Script` within the context of this game. Sometimes, Screen lua files are called `BGAnimations`, or "BackGround Animations" (Sometimes abbreviated BGAnims). +The game defines a number of `Screens`. It's possible to define custom `Screens`, but that's not inmediately relevant. Each `Screen` is a container for `Actors`. Pretty much every Drawable thing is an `Actor`. A container for `Actors` is actually called an `ActorFrame` (So, `Screens` are `ActorFrames`). Lua comes into play in the game when loading `Screens`. Some lua code is executed when initializing `Screens`, and it tells the game which `Actors` it needs to create and add to it. It can also registers a number of `Commands`, which are just lua functions executed on certain events (Usually called by the game engine). Lua code is also executed when the game is executed, on startup, usually to initialize whatever global state it needs to use later, and to define functions globally so they can be available everywhere (Note: Usually it's recommended to "namespace" your global functions, putting them under a table, so as to not pollute the global namespace). A lua file executed at startup is called a `Script` within the context of this game. Sometimes, Screen lua files are called `BGAnimations`, or "BackGround Animations" (Sometimes abbreviated BGAnims). ## Screens -I mentioned lua code can be executed on `Screen` initialization. However, `Screen`s have a second component to them that is of relatively big importance to someone dealing with BGAnims: metrics.ini +I mentioned lua code can be executed on `Screen` initialization. However, `Screens` have a second component to them that is of relatively big importance to someone dealing with BGAnims: metrics.ini From 0c976a221c41693353a29218bc0c8fbac4b87777 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 20:56:37 -0500 Subject: [PATCH 027/320] allow song to play its own preview and give lua access (experimental) borp --- .../wifeTwirl.lua | 1 + src/Song.cpp | 27 ++++++++++++++++--- src/Song.h | 5 +++- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index f3c30f37c1..bd50bbc829 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -114,6 +114,7 @@ local function toggleNoteField() return end if song then + song:Borp() if mcbootlarder:GetVisible() then mcbootlarder:visible(false) mcbootlarder:GetChild("NoteField"):visible(false) diff --git a/src/Song.cpp b/src/Song.cpp index 0de1577cce..e524fb64e8 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -1,4 +1,4 @@ -#include "global.h" +#include "global.h" #include "FontCharAliases.h" #include "GameManager.h" #include "RageLog.h" @@ -34,6 +34,7 @@ #include "LyricsLoader.h" #include "ActorUtil.h" #include "CommonMetrics.h" +#include "GameSoundManager.h" #include "GameState.h" #include @@ -2047,6 +2048,21 @@ Song::IsMarathon() const return m_fMusicLengthSeconds >= g_fMarathonVerSongSeconds; } +void +Song::Borp() +{ + GameSoundManager::PlayMusicParams PlayParams; + PlayParams.sFile = m_sMusicFile; + PlayParams.pTiming = &this->m_SongTiming; + PlayParams.bForceLoop = true; + PlayParams.fStartSecond = m_fMusicSampleStartSeconds; + PlayParams.fLengthSeconds = GetLastSecond() + 2.f; + PlayParams.fFadeOutLengthSeconds = 1.f; + PlayParams.bAlignBeat = true; + PlayParams.bApplyMusicRate = true; + SOUND->PlayMusic(PlayParams); +} + // lua start #include "LuaBinding.h" @@ -2468,13 +2484,17 @@ class LunaSong : public Luna p->ReloadFromSongDir(); COMMON_RETURN_SELF; } - static int GetOrTryAtLeastToGetSimfileAuthor(T* p, lua_State* L) { lua_pushstring(L, p->GetOrTryAtLeastToGetSimfileAuthor()); return 1; } - + static int Borp(T* p, lua_State* L) + { + p->Borp(); + return 0; + } + LunaSong() { ADD_METHOD(GetDisplayFullTitle); @@ -2543,6 +2563,7 @@ class LunaSong : public Luna ADD_METHOD(GetPreviewVidPath); ADD_METHOD(GetPreviewMusicPath); ADD_METHOD(ReloadFromSongDir); + ADD_METHOD(Borp); } }; diff --git a/src/Song.h b/src/Song.h index f87ebfd402..f7205ece4c 100644 --- a/src/Song.h +++ b/src/Song.h @@ -1,4 +1,4 @@ -#ifndef SONG_H +#ifndef SONG_H #define SONG_H #include "Difficulty.h" @@ -438,6 +438,9 @@ class Song bool IsLong() const; bool IsMarathon() const; + // plays music for chart preview and is available to lua -mina + void Borp(); + bool SongCompleteForStyle(const Style* st) const; bool HasStepsType(StepsType st) const; bool HasStepsTypeAndDifficulty(StepsType st, Difficulty dc) const; From a47dc0a35b4aacf1b12ab03f44fb49a65806d990 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 24 Nov 2018 23:37:14 -0300 Subject: [PATCH 028/320] Fix ettmulti offsetplot --- Themes/Til Death/BGAnimations/offsetplot.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/offsetplot.lua b/Themes/Til Death/BGAnimations/offsetplot.lua index eb95cc6824..0d74f6015c 100644 --- a/Themes/Til Death/BGAnimations/offsetplot.lua +++ b/Themes/Til Death/BGAnimations/offsetplot.lua @@ -32,7 +32,9 @@ local handspecific = false local left = false local function fitX(x) -- Scale time values to fit within plot width. - if finalSecond == 0 then return 0 end + if finalSecond == 0 then + return 0 + end return x / finalSecond * plotWidth - plotWidth / 2 end @@ -46,16 +48,15 @@ local o = self:xy(plotX, plotY) -- being explicit about the logic since atm these are the only 2 cases we handle - if SCREENMAN:GetTopScreen():GetName() == "ScreenEvaluationNormal" then -- default case, all data is in pss and no disk load is required + local name = SCREENMAN:GetTopScreen():GetName() + if name == "ScreenEvaluationNormal" or name == "ScreenNetEvaluation" then -- default case, all data is in pss and no disk load is required local pss = STATSMAN:GetCurStageStats():GetPlayerStageStats(PLAYER_1) dvt = pss:GetOffsetVector() nrt = pss:GetNoteRowVector() ctt = pss:GetTrackVector() -- column information for each offset ntt = pss:GetTapNoteTypeVector() -- notetype information (we use this to handle mine hits differently- currently that means not displaying them) pss:UnloadReplayData() -- force unload replaydata in memory after loading it (not sure if i should allow this but i don't trust deconstructors) -mina - end - - if SCREENMAN:GetTopScreen():GetName() == "ScreenScoreTabOffsetPlot" then -- loaded from scoretab not eval so we need to read from disk and adjust plot display + elseif name == "ScreenScoreTabOffsetPlot" then -- loaded from scoretab not eval so we need to read from disk and adjust plot display plotWidth, plotHeight = SCREEN_WIDTH, SCREEN_WIDTH * 0.3 self:xy(SCREEN_CENTER_X, SCREEN_CENTER_Y) textzoom = 0.5 From 8921bff33621688023b5e6b2bf861364d9c0ca70 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 22:47:56 -0500 Subject: [PATCH 029/320] actually do what 0c976a221c41693353a29218bc0c8fbac4b87777 was meant to this alters the condition that ignores queued music if it's the same as the currently playing music, seeing as there's no way to access the params for playing without changing the currently playing music, waiting for the updates to finish setting properly, then changing the music back to what we originally wanted to play, and given that for whatever reason this breaks completely when using actual song timing, the condition now requires the songtiming for the queued musictoplay to be not null in order to ignore the playmusic request --- .../wifeTwirl.lua | 2 +- src/GameSoundManager.cpp | 3 ++- src/Song.cpp | 20 +++++++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index bd50bbc829..4b00bb169a 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -114,7 +114,6 @@ local function toggleNoteField() return end if song then - song:Borp() if mcbootlarder:GetVisible() then mcbootlarder:visible(false) mcbootlarder:GetChild("NoteField"):visible(false) @@ -122,6 +121,7 @@ local function toggleNoteField() else mcbootlarder:visible(true) mcbootlarder:GetChild("NoteField"):visible(true) + song:Borp() MESSAGEMAN:Broadcast("ChartPreviewOn") end end diff --git a/src/GameSoundManager.cpp b/src/GameSoundManager.cpp index 3a172b1c6d..975dc4a21b 100644 --- a/src/GameSoundManager.cpp +++ b/src/GameSoundManager.cpp @@ -104,7 +104,8 @@ StartMusic(MusicToPlay& ToPlay) { LockMutex L(*g_Mutex); if (g_Playing->m_Music->IsPlaying() && - g_Playing->m_Music->GetLoadedFilePath().EqualsNoCase(ToPlay.m_sFile)) + g_Playing->m_Music->GetLoadedFilePath().EqualsNoCase(ToPlay.m_sFile) && + ToPlay.HasTiming) return; /* We're changing or stopping the music. If we were dimming, reset. */ diff --git a/src/Song.cpp b/src/Song.cpp index e524fb64e8..d9f2753279 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -2052,15 +2052,27 @@ void Song::Borp() { GameSoundManager::PlayMusicParams PlayParams; - PlayParams.sFile = m_sMusicFile; - PlayParams.pTiming = &this->m_SongTiming; + PlayParams.sFile = GetMusicPath(); + PlayParams.pTiming = nullptr; PlayParams.bForceLoop = true; PlayParams.fStartSecond = m_fMusicSampleStartSeconds; - PlayParams.fLengthSeconds = GetLastSecond() + 2.f; + PlayParams.fLengthSeconds = GetLastSecond() - m_fMusicSampleStartSeconds + 2.f; PlayParams.fFadeOutLengthSeconds = 1.f; PlayParams.bAlignBeat = true; PlayParams.bApplyMusicRate = true; - SOUND->PlayMusic(PlayParams); + + GameSoundManager::PlayMusicParams FallbackMusic; + FallbackMusic.sFile = GetMusicPath(); + FallbackMusic.fFadeInLengthSeconds = 1.f; + FallbackMusic.bAlignBeat = true; + + if (PlayParams.fLengthSeconds < + 3.f) { // if the songpreview is after the last note + PlayParams.fStartSecond = + 5.f; // chartpreview wont play, just set it near the start -mina + PlayParams.fLengthSeconds = GetLastSecond() + 2.f; + } + SOUND->PlayMusic(PlayParams, FallbackMusic); } // lua start From e5dbf4a8ff38e0c82c3c5d36382eee3f6338155a Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 23:44:28 -0500 Subject: [PATCH 030/320] borp it --- .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 4b00bb169a..6c284fa9c6 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -37,6 +37,7 @@ local t = mcbootlarder:visible(true) mcbootlarder:GetChild("NoteField"):visible(true) MESSAGEMAN:Broadcast("ChartPreviewOn") + song:Borp() heyiwasusingthat = false end self:queuecommand("On") From f9a0e1f95ea1638eeeb1a875ca32b193a8c8d335 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 23:44:42 -0500 Subject: [PATCH 031/320] cd graph clamp should go to 3x --- src/Steps.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Steps.cpp b/src/Steps.cpp index d6bb4b65a4..f1c738e715 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -903,7 +903,7 @@ class LunaSteps : public Luna static int GetCDGraphVectors(T* p, lua_State* L) { float rate = FArg(1); - CLAMP(rate, 1.f, 2.f); + CLAMP(rate, 1.f, 3.f); auto nd = p->GetNoteData(); if (nd.IsEmpty()) return 0; From 584f2a8be5d9c83eea0d8f9844c980f717b5e3e7 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 24 Nov 2018 23:58:37 -0500 Subject: [PATCH 032/320] werwerwerwerwerwerwer's birthday --- src/NoteField.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index 6c852ad1c6..a5d9892dbd 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -361,6 +361,11 @@ NoteField::Update(float fDeltaTime) { if (!this->GetVisible()) return; + if (!GAMESTATE->m_pCurSong) { + this->DeleteAllChildren(); + return; + } + if (m_bFirstUpdate) { m_pCurDisplay->m_ReceptorArrowRow.PlayCommand("On"); } @@ -824,6 +829,11 @@ NoteField::CalcPixelsBeforeAndAfterTargets() void NoteField::DrawPrimitives() { + if (!GAMESTATE->m_pCurSong) { + this->DeleteAllChildren(); + return; + } + // LOG->Trace( "NoteField::DrawPrimitives()" ); // This should be filled in on the first update. From 7417ba5123adde140506124f4a477e8b349c8b3e Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 24 Nov 2018 23:12:20 -0600 Subject: [PATCH 033/320] Add replay data utility for calculating radar values --- src/PlayerAI.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ src/PlayerAI.h | 2 ++ 2 files changed, 89 insertions(+) diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index acc9a25557..8b3c2f925e 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -5,6 +5,7 @@ #include "PlayerAI.h" #include "PlayerState.h" #include "RageUtil.h" +#include "RadarValues.h" #define AI_PATH "Data/AI.ini" @@ -492,6 +493,92 @@ PlayerAI::GetTapNoteOffsetForReplay(TapNote* pTN, int noteRow, int col) return -1.f; // data missing or invalid, give them a miss } +void +PlayerAI::CalculateRadarValuesForReplay(RadarValues& rv, RadarValues& possibleRV) +{ + // We will do this thoroughly just in case someone decides to use the other + // categories we don't currently use + int tapsHit = 0; + int jumpsHit = 0; + int handsHit = 0; + int holdsHeld = possibleRV[RadarCategory_Holds]; + int rollsHeld = possibleRV[RadarCategory_Rolls]; + int liftsHit = 0; + int fakes = possibleRV[RadarCategory_Fakes]; + int totalNotesHit = 0; + int minesMissed = possibleRV[RadarCategory_Mines]; + + // For every row recorded... + for (auto& row : m_ReplayTapMap) + { + int tapsOnThisRow = 0; + // For every tap on these rows... + for (TapReplayResult& trr : row.second) + { + if (trr.type == TapNoteType_Fake) + { + fakes--; + continue; + } + if (trr.type == TapNoteType_Mine) + { + minesMissed--; + continue; + } + if (trr.type == TapNoteType_Lift) + { + liftsHit++; + continue; + } + tapsOnThisRow++; + if (trr.type == TapNoteType_Tap || trr.type == TapNoteType_HoldHead) + { + totalNotesHit++; + tapsHit++; + if (tapsOnThisRow == 2) + { + jumpsHit++; + } + else if (tapsOnThisRow >= 3) + { + handsHit++; + } + continue; + } + } + } + + // For every hold recorded... + for (auto& row : m_ReplayHoldMap) + { + // For every hold on this row... + for (HoldReplayResult& hrr : row.second) + { + if (hrr.subType == TapNoteSubType_Hold) + { + holdsHeld--; + continue; + } + else if (hrr.subType == TapNoteSubType_Roll) + { + rollsHeld--; + continue; + } + } + } + + // lol just set them + rv[RadarCategory_TapsAndHolds] = tapsHit; + rv[RadarCategory_Jumps] = jumpsHit; + rv[RadarCategory_Holds] = holdsHeld; + rv[RadarCategory_Mines] = minesMissed; + rv[RadarCategory_Hands] = handsHit; + rv[RadarCategory_Rolls] = rollsHeld; + rv[RadarCategory_Lifts] = liftsHit; + rv[RadarCategory_Fakes] = fakes; + rv[RadarCategory_Notes] = totalNotesHit; +} + /* * (c) 2003-2004 Chris Danford * All rights reserved. diff --git a/src/PlayerAI.h b/src/PlayerAI.h index 27d3ab384e..6299320f96 100644 --- a/src/PlayerAI.h +++ b/src/PlayerAI.h @@ -63,6 +63,8 @@ class PlayerAI static int GetAdjustedRowFromUnadjustedCoordinates(int row, int col); // Remove a given Tap from the fallback and Full replay data vectors static void RemoveTapFromVectors(int row, int col); + // Go through the replay data to fill out the radar values for the eval screen + static void CalculateRadarValuesForReplay(RadarValues& rv, RadarValues& possibleRV); }; #endif From 38481fc81c2cb1c9ebdfb30dfd09a1fded118074 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 24 Nov 2018 23:12:34 -0600 Subject: [PATCH 034/320] Fix unloaded hold replay vector --- src/HighScore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/HighScore.cpp b/src/HighScore.cpp index 14bdfe4939..226609e549 100644 --- a/src/HighScore.cpp +++ b/src/HighScore.cpp @@ -892,6 +892,7 @@ HighScore::LoadReplayDataFull() SetOffsetVector(vOffsetVector); SetTrackVector(vTrackVector); SetTapNoteTypeVector(vTapNoteTypeVector); + SetHoldReplayDataVector(vHoldReplayDataVector); m_Impl->ReplayType = 2; LOG->Trace("Loaded replay data at %s", path.c_str()); From f59b2caa1bb08eaa203c47646f8d66a5f6b05f32 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 24 Nov 2018 23:14:27 -0600 Subject: [PATCH 035/320] Fix inconsistent judge conversions in replay eval screen --- src/ScreenGameplay.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 4782c45c8d..699f799be9 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -2231,6 +2231,19 @@ ScreenGameplay::SaveStats() NoteDataWithScoring::GetActualRadarValues(nd, pss, fMusicLen, rv); pss.m_radarActual += rv; GAMESTATE->SetProcessedTimingData(NULL); + } + if (GamePreferences::m_AutoPlay.Get() == PC_REPLAY) { + // We need to replace the newly created replay data with the actual old + // data Because to keep consistently lazy practices, we can just hack + // things together instead of fixing the real issue -poco + // (doing this fixes a lot of issues in the eval screen) + PlayerStageStats* pss = m_vPlayerInfo[PLAYER_1].GetPlayerStageStats(); + HighScore* hs = PlayerAI::pScoreData; + pss->m_vHoldReplayData = hs->GetHoldReplayDataVector(); + pss->m_vNoteRowVector = hs->GetNoteRowVector(); + pss->m_vOffsetVector = hs->GetOffsetVector(); + pss->m_vTapNoteTypeVector = hs->GetTapNoteTypeVector(); + pss->m_vTrackVector = hs->GetTrackVector(); } } From 8c431f31b49fbd49ffadfa944bba1b693798a910 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 24 Nov 2018 23:15:00 -0600 Subject: [PATCH 036/320] Calculate radar values "properly" for eval screen viewer --- src/ScreenSelectMusic.cpp | 49 ++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 52708bb11c..0d6a33fb3c 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -42,7 +42,8 @@ #include "PlayerAI.h" #include "PlayerOptions.h" #include "NoteData.h" -#include "Player.h" +#include "Player.h" +#include "NoteDataUtil.h" static const char* SelectionStateNames[] = { "SelectingSong", "SelectingSteps", @@ -1819,21 +1820,37 @@ class LunaScreenSelectMusic : public Luna // construct the current stage stats and stuff to the best of our // ability - StageStats ss; - ss.Init(); - auto score = SCOREMAN->GetMostRecentScore(); - score->LoadReplayData(); - auto& pss = ss.m_player[0]; - pss.m_HighScore = *score; - pss.CurWifeScore = score->GetWifeScore(); - pss.m_fWifeScore = score->GetWifeScore(); - pss.m_vNoteRowVector = score->GetNoteRowVector(); - pss.m_vOffsetVector = score->GetOffsetVector(); - pss.m_vTapNoteTypeVector = score->GetTapNoteTypeVector(); - pss.m_vTrackVector = score->GetTrackVector(); - score->UnloadReplayData(); - pss.m_iSongsPassed = 1; - pss.m_iSongsPlayed = 1; + StageStats ss; + RadarValues rv; + NoteData nd; + Steps* steps = GAMESTATE->m_pCurSteps[PLAYER_1]; + steps->GetNoteData(nd); + float songlength = GAMESTATE->m_pCurSong->m_fMusicLengthSeconds; + ss.Init(); + auto score = SCOREMAN->GetMostRecentScore(); + score->LoadReplayData(); + PlayerAI::SetScoreData(score); + + auto& pss = ss.m_player[0]; + pss.m_HighScore = *score; + pss.CurWifeScore = score->GetWifeScore(); + pss.m_fWifeScore = score->GetWifeScore(); + pss.m_vNoteRowVector = score->GetNoteRowVector(); + pss.m_vOffsetVector = score->GetOffsetVector(); + pss.m_vTapNoteTypeVector = score->GetTapNoteTypeVector(); + pss.m_vTrackVector = score->GetTrackVector(); + // score->UnloadReplayData(); + pss.m_iSongsPassed = 1; + pss.m_iSongsPlayed = 1; + GAMESTATE->SetProcessedTimingData( + GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData()); + NoteDataUtil::CalculateRadarValues(nd, songlength, rv); + pss.m_radarPossible += rv; + RadarValues realRV; + PlayerAI::CalculateRadarValuesForReplay(realRV, rv); + score->SetRadarValues(realRV); + pss.m_radarActual += realRV; + GAMESTATE->SetProcessedTimingData(NULL); pss.everusedautoplay = true; for (int i = TNS_Miss; i < NUM_TapNoteScore; i++) { pss.m_iTapNoteScores[i] = score->GetTapNoteScore((TapNoteScore)i); From a19738c6575d949ba8c202e297b0d9da96b79c5a Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 01:45:52 -0500 Subject: [PATCH 037/320] screen mines out of offsetvector when grabbing from pss --- src/PlayerStageStats.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/PlayerStageStats.cpp b/src/PlayerStageStats.cpp index e0dbc34518..ec2028ae78 100644 --- a/src/PlayerStageStats.cpp +++ b/src/PlayerStageStats.cpp @@ -1037,9 +1037,12 @@ LuaFunction(GetGradeFromPercent, GetGradeFromPercent(FArg(1))) // Convert to MS so lua doesn't have to static int GetOffsetVector(T* p, lua_State* L) { - vector doot = p->m_vOffsetVector; - for (size_t i = 0; i < doot.size(); ++i) - doot[i] = doot[i] * 1000; + auto& offs = p->m_vOffsetVector; + auto& type = p->m_vTapNoteTypeVector; + vector doot; + for (size_t i = 0; i < offs.size(); ++i) + if (type[i] != TapNoteType_Mine) + doot.emplace_back(offs[i] * 1000); LuaHelpers::CreateTableFromArray(doot, L); return 1; } From a4a316bbf09e5a186de4b74e8a3120e314c9e8e7 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 01:46:10 -0500 Subject: [PATCH 038/320] only pop offsets during replays if cc is off --- src/PlayerAI.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index 8b3c2f925e..5cbe40faae 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -455,9 +455,12 @@ PlayerAI::GetTapNoteOffsetForReplay(TapNote* pTN, int noteRow, int col) // this is done to be able to judge simultaneous taps differently // due to CC Off this results in possibly incorrect precise per tap // judges, but the correct judgement ends up being made overall. - m_ReplayTapMap[noteRow].pop_back(); - if (m_ReplayTapMap[noteRow].empty()) { - m_ReplayTapMap.erase(noteRow); + + if (!pScoreData->GetChordCohesion()) { + m_ReplayTapMap[noteRow].pop_back(); + if (m_ReplayTapMap[noteRow].empty()) { + m_ReplayTapMap.erase(noteRow); + } } return -offset; From b6e8bae9e5ed75732df1fea041c350cb118adca5 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 02:05:47 -0500 Subject: [PATCH 039/320] compilerwarns --- src/PlayerAI.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index 5cbe40faae..d5b22f33c0 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -174,19 +174,16 @@ PlayerAI::SetScoreData(HighScore* pHighScore) // Generate TapReplayResults to put into a vector referenced by the song row // in a map - for (int i = 0; i < (int)replayNoteRowVector.size(); i++) { + for (size_t i = 0; i < replayNoteRowVector.size(); i++) { TapReplayResult trr; trr.row = replayNoteRowVector[i]; trr.offset = replayOffsetVector[i]; - trr.offsetAdjustedRow = replayOffsetVector[i]; + trr.offsetAdjustedRow = static_cast(replayOffsetVector[i]); if (pScoreData->GetReplayType() == 2) // 2 means that this is a Full Replay { trr.track = replayTrackVector[i]; trr.type = replayTapNoteTypeVector[i]; - - - } else // Anything else (and we got this far without crashing) means // it's not a Full Replay { From 54811f50841facbf6cace27900cb696f7865e893 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 02:29:22 -0500 Subject: [PATCH 040/320] properly gate updates on notefield and unload notedata used by it --- src/NoteField.cpp | 10 ++-------- src/ScreenSelectMusic.cpp | 9 ++++++++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/NoteField.cpp b/src/NoteField.cpp index a5d9892dbd..ded2d3b43c 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -359,12 +359,8 @@ NoteField::InitColumnRenderers() void NoteField::Update(float fDeltaTime) { - if (!this->GetVisible()) + if (!this->GetVisible() || !GAMESTATE->m_pCurSong) return; - if (!GAMESTATE->m_pCurSong) { - this->DeleteAllChildren(); - return; - } if (m_bFirstUpdate) { m_pCurDisplay->m_ReceptorArrowRow.PlayCommand("On"); @@ -829,10 +825,8 @@ NoteField::CalcPixelsBeforeAndAfterTargets() void NoteField::DrawPrimitives() { - if (!GAMESTATE->m_pCurSong) { - this->DeleteAllChildren(); + if (!this->GetVisible() || !GAMESTATE->m_pCurSong) return; - } // LOG->Trace( "NoteField::DrawPrimitives()" ); diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 0d6a33fb3c..be4b180b91 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1366,8 +1366,15 @@ ScreenSelectMusic::AfterMusicChange() GAMESTATE->m_pPreferredSong = pSong; else { GAMESTATE->m_pCurSteps[PLAYER_1].Set(nullptr); - if (m_pPreviewNoteField) + if (m_pPreviewNoteField) { m_pPreviewNoteField->SetVisible(false); + // if previewnotefield is active and we are moving out of a pack + // into the pack list (that's what this block of code is for + // handling) manually call songmans cleanup function (compresses all + // steps); we could optimize by only compressing the pack but this + // is pretty fast anyway -mina + SONGMAN->Cleanup(); + } } GAMESTATE->SetPaused(false); // hacky can see this being problematic From decdc6698cdf781e58cf765eb6e4e9f3c32d56a1 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 02:33:35 -0500 Subject: [PATCH 041/320] this chartpreview music set is now handled by lua --- src/ScreenSelectMusic.cpp | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index be4b180b91..a1902da0d6 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1603,36 +1603,13 @@ ScreenSelectMusic::GeneratePreviewNoteField() GAMESTATE->m_bIsChartPreviewActive = true; - // Restart the music from the beginning for a full chart preview - - // (Enabling this would restart the music at its current position, but would - // never go back to earlier sections) - /* - m_fSampleStartSeconds = - SOUND->GetRageSoundPlaying()->GetPositionSeconds(); - */ - SOUND->StopMusic(); - m_sSampleMusicToPlay = song->GetMusicPath(); - m_fSampleStartSeconds = max(song->GetFirstSecond() - 4.f, -1.f); - m_fSampleLengthSeconds = - song->GetLastSecond() - m_fSampleStartSeconds + 2.f; - if (m_fSampleLengthSeconds < - 3.f) { // if the songpreview is after the last note - m_fSampleStartSeconds = - 5.f; // chartpreview wont play, just set it near the start -mina - m_fSampleLengthSeconds = song->GetLastSecond() + 2.f; - } - g_bSampleMusicWaiting = true; - CheckBackgroundRequests(true); - // Create and Render the NoteField afterwards // It is done in this order so we don't see it before the music changes. m_pPreviewNoteField = new NoteField; m_pPreviewNoteField->SetName( "NoteField"); // Use this to get the ActorFrame from the Screen Children - m_pPreviewNoteField->Init(GAMESTATE->m_pPlayerState[PLAYER_1], - 100); + m_pPreviewNoteField->Init(GAMESTATE->m_pPlayerState[PLAYER_1], 100); m_pPreviewNoteField->Load(&m_PreviewNoteData, 0, 800); } From 23022b8613791885beac56eba46ba4ed03feca4b Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:01:30 -0500 Subject: [PATCH 042/320] hand over more chartpreview music control to lua --- .../wifeTwirl.lua | 3 ++ src/ScreenSelectMusic.cpp | 28 +++++++------------ 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 6c284fa9c6..b86b0c429d 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -31,6 +31,9 @@ local t = if song ~= bong then song = bong self:queuecommand("MortyFarts") + if noteField and mcbootlarder:GetChild("NoteField"):GetVisible() and song then + song:Borp() + end end if getTabIndex() == 0 then if heyiwasusingthat and GAMESTATE:GetCurrentSong() and noteField then -- these can prolly be wrapped better too -mina diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index a1902da0d6..81de78fb75 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -316,9 +316,9 @@ ScreenSelectMusic::CheckBackgroundRequests(bool bForce) // heavy duty chart specific operations can be delayed when scrolling (chord // density graph, possibly chart leaderboards, etc) -mina - // in theory the notedata load for chartpreviews could go here however a delay - // might make it weird when swapping between difficulties to compare sections - // for which you would want instantaneous action -mina + // in theory the notedata load for chartpreviews could go here however a + // delay might make it weird when swapping between difficulties to compare + // sections for which you would want instantaneous action -mina if (delayedchartupdatewaiting) { if (g_ScreenStartedLoadingAt .Ago() > // not sure if i need the "moving fast" check -mina @@ -365,18 +365,8 @@ ScreenSelectMusic::CheckBackgroundRequests(bool bForce) // the notefield is not visible when the // previewmusic starts i.e. when the general tab // is not active when a song is switched -mina - auto song = GAMESTATE->m_pCurSong; - if (song == nullptr) - return; - - PlayParams.sFile = song->GetMusicPath(); - PlayParams.fLengthSeconds = - song->GetLastSecond() - m_fSampleStartSeconds + 2.f; - if (PlayParams.fLengthSeconds < 3.f) { // if the songpreview is after the last note - PlayParams.fStartSecond = 5.f; // chartpreview wont play, just set it near the start -mina - PlayParams.fLengthSeconds = song->GetLastSecond() + 2.f; - } - + return; + MESSAGEMAN->Broadcast("PlayingSampleMusic"); } SOUND->PlayMusic(PlayParams, FallbackMusic); @@ -1003,7 +993,8 @@ ScreenSelectMusic::HandleMessage(const Message& msg) } m_iSelection[pn] = iSel; - Steps* pSteps = m_vpSteps.empty() ? nullptr : m_vpSteps[m_iSelection[pn]]; + Steps* pSteps = + m_vpSteps.empty() ? nullptr : m_vpSteps[m_iSelection[pn]]; GAMESTATE->m_pCurSteps[pn].Set(pSteps); } @@ -1287,10 +1278,11 @@ ScreenSelectMusic::AfterStepsOrTrailChange(const vector& vpns) CLAMP(m_iSelection[pn], 0, m_vpSteps.size() - 1); Song* pSong = GAMESTATE->m_pCurSong; - Steps* pSteps = m_vpSteps.empty() ? nullptr : m_vpSteps[m_iSelection[pn]]; + Steps* pSteps = + m_vpSteps.empty() ? nullptr : m_vpSteps[m_iSelection[pn]]; GAMESTATE->m_pCurSteps[pn].Set(pSteps); - if (pSteps != nullptr) + if (pSteps != nullptr) GAMESTATE->SetCompatibleStyle(pSteps->m_StepsType, pn); int iScore = 0; From 9d52f9992086f4aa3a62e39d05450d0e67c637a5 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:01:42 -0500 Subject: [PATCH 043/320] pretty sure this does nothing --- Themes/Til Death/BGAnimations/_chartpreview.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chartpreview.lua b/Themes/Til Death/BGAnimations/_chartpreview.lua index c9e290a94e..8c0b7419fe 100644 --- a/Themes/Til Death/BGAnimations/_chartpreview.lua +++ b/Themes/Til Death/BGAnimations/_chartpreview.lua @@ -65,7 +65,6 @@ local t = Def.ActorFrame { cd:visible(true):y(20) -- need to control this manually -mina cd:GetChild("cdbg"):diffusealpha(0) -- we want to use our position background for draw order stuff -mina cd:queuecommand("GraphUpdate") -- first graph will be empty if we dont force this on initial creation - self:queuecommand("PlayingSampleMusic") end, Def.Quad { Name = "BG", From 29eafa351e37e1a3188183807ddc53a7b596a876 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:02:11 -0500 Subject: [PATCH 044/320] "properly" gate visibility req for cdgraph updating --- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index 8dce875656..dfa66138a3 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -88,7 +88,11 @@ local t = Def.ActorFrame { self:SetUpdateFunction(textmover) cdg = self end, + CurrentSongChangedMessageCommand = function(self) + self:diffusealpha(0) + end, DelayedChartUpdateMessageCommand = function(self) + self:diffusealpha(1) self:queuecommand("GraphUpdate") end, CurrentRateChangedMessageCommand = function(self) @@ -108,7 +112,7 @@ t[#t+1] = Def.ActorMultiVertex { Name = "CDGraphDrawer", GraphUpdateCommand = function(self) - if self:GetVisible() then + if self:GetParent():GetVisible() then updateGraphMultiVertex(cdg, self) end end From 9036e6d52386d60adad079e17d8ab6f372a5851f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:11:02 -0500 Subject: [PATCH 045/320] only cool people could get this bug but now they will never know --- .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index b86b0c429d..0b2651b165 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -115,6 +115,7 @@ local function toggleNoteField() if usingreverse then mcbootlarder:GetChild("NoteField"):y(prevY*1.5 + prevrevY) end + song:Borp() -- catches a dumb bug that isn't worth explaining -mina return end if song then From d0f97769e87d181a493816ec7bd8625d622795e2 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:11:15 -0500 Subject: [PATCH 046/320] fix another missed update with scores... need to refactor --- .../BGAnimations/ScreenSelectMusic decorations/score.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index c344eea749..3704a25d86 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -179,6 +179,7 @@ local ret = end end, NestedTabChangedMessageCommand = function(self) + self:queuecommand("Set") updateLeaderBoardForCurrentChart() end, CurrentStepsP1ChangedMessageCommand = function(self) From c46ff5fed27f3c22c2d541f5c04bd0fcab5f126f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:17:35 -0500 Subject: [PATCH 047/320] cd graph can fade in to look slightly less weird --- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index dfa66138a3..87dfb16a36 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -92,7 +92,6 @@ local t = Def.ActorFrame { self:diffusealpha(0) end, DelayedChartUpdateMessageCommand = function(self) - self:diffusealpha(1) self:queuecommand("GraphUpdate") end, CurrentRateChangedMessageCommand = function(self) @@ -114,6 +113,8 @@ t[#t+1] = GraphUpdateCommand = function(self) if self:GetParent():GetVisible() then updateGraphMultiVertex(cdg, self) + self:GetParent():linear(0.3) + self:GetParent():diffusealpha(1) end end } From 343c13db72c3f7b9f93ad28ede5a82c8893d0a56 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:30:50 -0500 Subject: [PATCH 048/320] handled via lua now --- src/ScreenSelectMusic.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 81de78fb75..02b9940791 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -355,23 +355,8 @@ ScreenSelectMusic::CheckBackgroundRequests(bool bForce) FallbackMusic.fFadeInLengthSeconds = SAMPLE_MUSIC_FALLBACK_FADE_IN_SECONDS; FallbackMusic.bAlignBeat = ALIGN_MUSIC_BEATS; - - // update the chartpreview music when switching songs -mina - if (m_pPreviewNoteField != nullptr && - m_pPreviewNoteField->GetVisible() && - m_pPreviewNoteField->GetParent() - ->GetVisible()) { // this kinda makes a lot of assumptions atm and - // stops the full preview music from playing if - // the notefield is not visible when the - // previewmusic starts i.e. when the general tab - // is not active when a song is switched -mina - return; - MESSAGEMAN->Broadcast("PlayingSampleMusic"); - } - SOUND->PlayMusic(PlayParams, FallbackMusic); MESSAGEMAN->Broadcast("PlayingSampleMusic"); - // DLMAN->RequestChartLeaderBoard(GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); } } From a64ee8b1d0ad036957c55642f45f7a1f03f0849f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:31:03 -0500 Subject: [PATCH 049/320] move msd tab cdgraph initialization --- .../BGAnimations/ScreenSelectMusic decorations/msd.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/msd.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/msd.lua index af608f95af..ae4571bf0f 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/msd.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/msd.lua @@ -23,7 +23,6 @@ local t = Def.ActorFrame { BeginCommand = function(self) cd = self:GetChild("ChordDensityGraph") - cd:playcommand("GraphUpdate") -- force the first update before setting visible(false) (so it's not empty when switching to the tab) -mina cd:xy(frameX + offsetX, frameY + 140):visible(false) self:queuecommand("Set"):visible(false) end, @@ -55,6 +54,7 @@ local t = if song and steps then cd:visible(true) + cd:queuecommand("GraphUpdate") else cd:visible(false) end From f88caa2a67a9fac5181d94e1d5aa2c7fea67a060 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 03:37:24 -0500 Subject: [PATCH 050/320] only borp when you most must --- .../ScreenSelectMusic decorations/wifeTwirl.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 0b2651b165..25af56e8fb 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -12,6 +12,7 @@ local prevX = capWideScale(get43size(98), 98) local usingreverse = GAMESTATE:GetPlayerState(PLAYER_1):GetCurrentPlayerOptions():UsingReverse() local prevY = 55 local prevrevY = 208 +local boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone = false local update = false local t = @@ -22,6 +23,11 @@ local t = OnCommand = function(self) self:bouncebegin(0.2):xy(0, 0):diffusealpha(1) end, + CurrentSongChanged = function() + if getTabIndex() ~= 0 then + boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone = true + end + end, MintyFreshCommand = function(self) self:finishtweening() local bong = GAMESTATE:GetCurrentSong() @@ -40,7 +46,9 @@ local t = mcbootlarder:visible(true) mcbootlarder:GetChild("NoteField"):visible(true) MESSAGEMAN:Broadcast("ChartPreviewOn") - song:Borp() + if boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone then + song:Borp() + end heyiwasusingthat = false end self:queuecommand("On") From aad0c4ed9685175171dfdb93bf6f4ee9f9f676a8 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 04:37:59 -0500 Subject: [PATCH 051/320] uncollapsed online scores with current rate now respond to rate changes using a completely idiotic solution to remind me to refactor and streamline the scripts fallback function --- .../ScreenSelectMusic decorations/score.lua | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 3704a25d86..614eab9344 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -186,6 +186,33 @@ local ret = self:queuecommand("Set") updateLeaderBoardForCurrentChart() end, + CodeMessageCommand = function(self, params) -- this is intentionally bad to remind me to fix other things that are bad -mina + if ((getTabIndex() == 2 and nestedTab == 2) and not collapsed) and DLMAN:GetCurrentRateFilter() then + local rate = getCurRateValue() + if params.Name == "PrevScore" and rate < 2.95 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate + 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate + 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate + 0.1) + MESSAGEMAN:Broadcast("CurrentRateChanged") + elseif params.Name == "NextScore" and rate > 0.75 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate - 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate - 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate - 0.1) + MESSAGEMAN:Broadcast("CurrentRateChanged") + end + if params.Name == "PrevRate" and rate < 3 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate + 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate + 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate + 0.05) + MESSAGEMAN:Broadcast("CurrentRateChanged") + elseif params.Name == "NextRate" and rate > 0.7 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate - 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate - 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate - 0.05) + MESSAGEMAN:Broadcast("CurrentRateChanged") + end + end + end, CurrentRateChangedMessageCommand = function(self) if ((getTabIndex() == 2 and nestedTab == 2) or collapsed) and DLMAN:GetCurrentRateFilter() then moped:queuecommand("ChartLeaderboardUpdate") From 37ef602d5a6dfe2d4a071a53a1c8fb64f11ecc5e Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 18:19:04 -0500 Subject: [PATCH 052/320] put back gameplay percent display background --- .../ScreenGameplay overlay/WifeJudgmentSpotting.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua index a84b1481fe..6a0e392691 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua @@ -347,6 +347,11 @@ local cp = end self:zoom(MovableValues.DisplayPercentZoom):x(MovableValues.DisplayPercentX):y(MovableValues.DisplayPercentY) end, + Def.Quad { + InitCommand = function(self) + self:zoomto(60, 13):diffuse(color("0,0,0,0.4")):halign(1):valign(0) + end + }, -- Displays your current percentage score LoadFont("Common Large") .. { Name = "DisplayPercent", From 1a8089609cf3cfd612c0e97512756fbc4e7a7e39 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 18:24:14 -0500 Subject: [PATCH 053/320] remove commented out restart button code --- .../WifeJudgmentSpotting.lua | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua index 6a0e392691..f5ac00013c 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua @@ -135,15 +135,6 @@ local enabledJudgeCounter = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)). local leaderboardEnabled = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() local isReplay = GAMESTATE:GetPlayerState(PLAYER_1):GetPlayerController() == "PlayerController_Replay" --- restart button (MOVED OUT OF THEME IN FAVOR OF REMAPPING) ---[[ -local function froot(loop) - if loop.DeviceInput.button == "DeviceButton_`" then - SCREENMAN:GetTopScreen():SetPrevScreenName("ScreenStageInformation"):begin_backing_out() - end -end -]] - local function arbitraryErrorBarValue(value) errorBarFrameWidth = capWideScale(get43size(value), value) wscale = errorBarFrameWidth / 180 @@ -173,9 +164,6 @@ local t = local endTime = os.time() + GetPlayableTime() GAMESTATE:UpdateDiscordPresence(largeImageTooltip, detail, state, endTime) - --[[if SCREENMAN:GetTopScreen():GetName() == "ScreenGameplay" then - SCREENMAN:GetTopScreen():AddInputCallback(froot) - end]] screen = SCREENMAN:GetTopScreen() usingReverse = GAMESTATE:GetPlayerState(PLAYER_1):GetCurrentPlayerOptions():UsingReverse() Notefield = screen:GetChild("PlayerP1"):GetChild("NoteField") @@ -360,7 +348,7 @@ local cp = end, OnCommand = function(self) if allowedCustomization then - self:settextf("%05.2f%%", -10000) + self:settextf("%05.2f%%", -10000) setBorderAlignment(self:GetParent():GetChild("Border"), 1, 0) setBorderToText(self:GetParent():GetChild("Border"), self) end From aff1e92844be94f60bb2ea15bd7015873ec9a307 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 25 Nov 2018 22:59:05 -0300 Subject: [PATCH 054/320] Move vanilla SM docs to legacy folder and add building instructions --- Docs/Building-Docs.md | 12 + Docs/Building.md | 195 + Docs/Contributing.md | 53 + Docs/{ => legacy}/Changelog_SSCformat.txt | 0 Docs/{ => legacy}/Changelog_language.txt | 0 Docs/{ => legacy}/Changelog_sm-ssc.txt | 0 Docs/{ => legacy}/Changelog_sm5.txt | 5232 +++---- Docs/{ => legacy}/CommandLineArgs.txt | 0 Docs/{ => legacy}/Copying.MAD | 680 +- Docs/{ => legacy}/CourseFormat.txt | 0 Docs/{ => legacy}/CustomMissionReference.txt | 0 .../Devdocs/BuildingFfmpegOnMac.txt | 0 Docs/{ => legacy}/Devdocs/CodingStyle.txt | 0 Docs/{ => legacy}/Devdocs/CompileFlags.txt | 0 Docs/{ => legacy}/Devdocs/GoldenRules.txt | 0 .../{ => legacy}/Devdocs/NegBPMsTutorial.html | 258 +- Docs/{ => legacy}/Devdocs/SMLanProtocol.txt | 0 Docs/{ => legacy}/Devdocs/SMO_protocol-aj.txt | 0 Docs/{ => legacy}/Devdocs/SMXML.txt | 0 Docs/{ => legacy}/Devdocs/Sound Drivers.txt | 0 Docs/{ => legacy}/Devdocs/SplitTiming.txt | 192 +- Docs/{ => legacy}/Devdocs/TextEntry.txt | 0 Docs/{ => legacy}/Devdocs/WarpNotes.txt | 0 Docs/{ => legacy}/Devdocs/ezsockets.txt | 0 .../Devdocs/interesting_sm4_commit_logs.txt | 0 .../Devdocs/negbpmtut/screen00214.jpg | Bin .../Devdocs/negbpmtut/screen00215.jpg | Bin .../Devdocs/negbpmtut/screen00216.jpg | Bin .../Devdocs/negbpmtut/screen00217.jpg | Bin .../Devdocs/negbpmtut/screen00218.jpg | Bin .../Devdocs/negbpmtut/screen00221.jpg | Bin .../Devdocs/possible memory leaks.txt | 0 Docs/{ => legacy}/Devdocs/rivaldata.txt | 0 Docs/{ => legacy}/Devdocs/versioning.txt | 0 Docs/{ => legacy}/KnownIssues.txt | 106 +- Docs/{ => legacy}/Licenses.txt | 0 Docs/{ => legacy}/Luadoc/Lua.xml | 7106 +++++----- Docs/{ => legacy}/Luadoc/Lua.xsd | 376 +- Docs/{ => legacy}/Luadoc/Lua.xsl | 0 Docs/{ => legacy}/Luadoc/LuaDocumentation.xml | 11468 ++++++++-------- Docs/legacy/Luadoc/a.lua | 22 + Docs/{ => legacy}/Luadoc/bgline.png | Bin Docs/{ => legacy}/Luadoc/closed.gif | Bin Docs/{ => legacy}/Luadoc/favicon.ico | Bin Docs/{ => legacy}/Luadoc/open.gif | Bin .../Mapping_keys_for_edit_mode.txt | 0 Docs/{ => legacy}/README-GUIDELINES | 60 +- .../BMS/BM98Data_format_specification.html | 0 .../SimfileFormats/BMS/BM98FinalSecret.html | 0 .../BMS/BMS_Reading_Tutorial.rtf | 0 .../BMS/BMS_Reading_Tutorial.txt | 0 Docs/{ => legacy}/SimfileFormats/BMS/_src.txt | 0 Docs/{ => legacy}/SimfileFormats/BMS/tmp.txt | 0 Docs/{ => legacy}/SimfileFormats/DWI/DWI.txt | 0 .../SimfileFormats/DWI/readme.html | 2448 ++-- Docs/{ => legacy}/SimfileFormats/KSF/_src.txt | 0 .../SimfileFormats/KSF/ksf-format.txt | 0 .../SimfileFormats/KSF/sample.ksf | 42 +- Docs/{ => legacy}/SimfileFormats/README | 20 +- Docs/{ => legacy}/SimfileFormats/SDF/SDF.txt | 0 .../SimfileFormats/SDF/ssc-banner.png | Bin .../SimfileFormats/SDF/ssc-bg.png | Bin .../SimfileFormats/SDF/test-1bpm.sdf | Bin Docs/{ => legacy}/SimfileFormats/SDF/test.sdf | Bin Docs/{ => legacy}/SimfileFormats/SDF/test.sm | 0 .../SimfileFormats/dance-spec.txt | 0 Docs/{ => legacy}/SimfileFormats/misc.txt | 0 .../SimfileFormats/new format draft.txt | 0 Docs/{ => legacy}/SimfileFormats/ssc_msd5.txt | 148 +- Docs/{ => legacy}/Stats.xml | 0 .../Examples/Example_Actors/ActorFrame.lua | 0 .../Example_Actors/ActorFrameTexture.lua | 0 .../Examples/Example_Actors/ActorScroller.lua | 0 .../Examples/Example_Actors/BitmapText.lua | 0 .../Examples/Example_Actors/Quad.lua | 0 .../Example_Actors/RollingNumbers.lua | 0 .../Examples/Example_Actors/Toasty.lua | 0 .../Example_Screens/ScreenHeartEntry.lua | 0 .../Example_Screens/ScreenMapControllers.lua | 0 .../Example_Screens/ScreenOptionsExample.ini | 0 .../ScreenSimpleExample overlay.lua | 0 .../One_Screen_Example_Theme/ThemeInfo.ini | 0 .../One_Screen_Example_Theme/metrics.ini | 0 .../One_Screen_Example_Theme/readme.txt | 0 .../Examples/OptionRowHandlerLua.lua | 0 .../Examples/anatomy_of_an_actor.lua | 0 .../Noteskin elements Reference.txt | 0 .../Themerdocs/ScreenAMVTest overlay.lua | 0 .../Themerdocs/ScreenMessages.txt | 0 .../Themerdocs/ScreenTextEntry.txt | 0 Docs/{ => legacy}/Themerdocs/ThemePrefs.txt | 0 .../Themerdocs/ThemePrefsRows.txt | 0 Docs/{ => legacy}/Themerdocs/XmlToLua.txt | 0 Docs/{ => legacy}/Themerdocs/actordef.txt | 0 .../Themerdocs/announcer_files.txt | 0 Docs/{ => legacy}/Themerdocs/calories.txt | 0 .../Themerdocs/conditional_music.txt | 0 .../{ => legacy}/Themerdocs/effect_colors.txt | 0 Docs/{ => legacy}/Themerdocs/fontini.txt | 0 Docs/{ => legacy}/Themerdocs/gamecommands.txt | 0 Docs/{ => legacy}/Themerdocs/haste.txt | 0 .../Themerdocs/included_scripts.txt | 0 Docs/{ => legacy}/Themerdocs/modslevel.txt | 0 Docs/{ => legacy}/Themerdocs/moremsg.txt | 0 Docs/{ => legacy}/Themerdocs/pause_menu.md | 0 .../Themerdocs/recommended_practices.txt | 0 .../Themerdocs/sm-ssc_themeguide.txt | 0 .../Userdocs/Keymaps_ini_format.md | 0 .../Userdocs/bgchanges_format.txt | 0 Docs/{ => legacy}/Userdocs/sm5_beginner.txt | 0 Docs/{ => legacy}/credits.txt | 364 +- Docs/{ => legacy}/docpack.zip | Bin Docs/{ => legacy}/license-ext/Scoring-jp.txt | 0 Docs/{ => legacy}/license-ext/readme | 0 .../license-ext/theme_lang-ja.txt | 0 .../license-ext/vlgothic/Changelog | 0 .../{ => legacy}/license-ext/vlgothic/LICENSE | 0 .../license-ext/vlgothic/LICENSE.en | 0 .../license-ext/vlgothic/LICENSE_E.mplus | 0 .../license-ext/vlgothic/LICENSE_J.mplus | 0 Docs/{ => legacy}/license-ext/vlgothic/README | 0 .../license-ext/vlgothic/README.sazanami | 0 .../license-ext/vlgothic/README_J.mplus | 0 Docs/{ => legacy}/midiman.wishlist | 48 +- Docs/{ => legacy}/old_changelog.txt | 0 Docs/{ => legacy}/opensource_simulators.txt | 0 Docs/{ => legacy}/steps.lua | 0 Docs/{ => legacy}/versioning.txt | 0 README.md | 49 +- 129 files changed, 14587 insertions(+), 14292 deletions(-) create mode 100644 Docs/Building-Docs.md create mode 100644 Docs/Building.md create mode 100644 Docs/Contributing.md rename Docs/{ => legacy}/Changelog_SSCformat.txt (100%) rename Docs/{ => legacy}/Changelog_language.txt (100%) rename Docs/{ => legacy}/Changelog_sm-ssc.txt (100%) rename Docs/{ => legacy}/Changelog_sm5.txt (97%) rename Docs/{ => legacy}/CommandLineArgs.txt (100%) rename Docs/{ => legacy}/Copying.MAD (98%) rename Docs/{ => legacy}/CourseFormat.txt (100%) rename Docs/{ => legacy}/CustomMissionReference.txt (100%) rename Docs/{ => legacy}/Devdocs/BuildingFfmpegOnMac.txt (100%) rename Docs/{ => legacy}/Devdocs/CodingStyle.txt (100%) rename Docs/{ => legacy}/Devdocs/CompileFlags.txt (100%) rename Docs/{ => legacy}/Devdocs/GoldenRules.txt (100%) rename Docs/{ => legacy}/Devdocs/NegBPMsTutorial.html (98%) rename Docs/{ => legacy}/Devdocs/SMLanProtocol.txt (100%) rename Docs/{ => legacy}/Devdocs/SMO_protocol-aj.txt (100%) rename Docs/{ => legacy}/Devdocs/SMXML.txt (100%) rename Docs/{ => legacy}/Devdocs/Sound Drivers.txt (100%) rename Docs/{ => legacy}/Devdocs/SplitTiming.txt (98%) rename Docs/{ => legacy}/Devdocs/TextEntry.txt (100%) rename Docs/{ => legacy}/Devdocs/WarpNotes.txt (100%) rename Docs/{ => legacy}/Devdocs/ezsockets.txt (100%) rename Docs/{ => legacy}/Devdocs/interesting_sm4_commit_logs.txt (100%) rename Docs/{ => legacy}/Devdocs/negbpmtut/screen00214.jpg (100%) rename Docs/{ => legacy}/Devdocs/negbpmtut/screen00215.jpg (100%) rename Docs/{ => legacy}/Devdocs/negbpmtut/screen00216.jpg (100%) rename Docs/{ => legacy}/Devdocs/negbpmtut/screen00217.jpg (100%) rename Docs/{ => legacy}/Devdocs/negbpmtut/screen00218.jpg (100%) rename Docs/{ => legacy}/Devdocs/negbpmtut/screen00221.jpg (100%) rename Docs/{ => legacy}/Devdocs/possible memory leaks.txt (100%) rename Docs/{ => legacy}/Devdocs/rivaldata.txt (100%) rename Docs/{ => legacy}/Devdocs/versioning.txt (100%) rename Docs/{ => legacy}/KnownIssues.txt (97%) rename Docs/{ => legacy}/Licenses.txt (100%) rename Docs/{ => legacy}/Luadoc/Lua.xml (97%) rename Docs/{ => legacy}/Luadoc/Lua.xsd (97%) rename Docs/{ => legacy}/Luadoc/Lua.xsl (100%) rename Docs/{ => legacy}/Luadoc/LuaDocumentation.xml (98%) create mode 100644 Docs/legacy/Luadoc/a.lua rename Docs/{ => legacy}/Luadoc/bgline.png (100%) rename Docs/{ => legacy}/Luadoc/closed.gif (100%) rename Docs/{ => legacy}/Luadoc/favicon.ico (100%) rename Docs/{ => legacy}/Luadoc/open.gif (100%) rename Docs/{ => legacy}/Mapping_keys_for_edit_mode.txt (100%) rename Docs/{ => legacy}/README-GUIDELINES (97%) rename Docs/{ => legacy}/SimfileFormats/BMS/BM98Data_format_specification.html (100%) rename Docs/{ => legacy}/SimfileFormats/BMS/BM98FinalSecret.html (100%) rename Docs/{ => legacy}/SimfileFormats/BMS/BMS_Reading_Tutorial.rtf (100%) rename Docs/{ => legacy}/SimfileFormats/BMS/BMS_Reading_Tutorial.txt (100%) rename Docs/{ => legacy}/SimfileFormats/BMS/_src.txt (100%) rename Docs/{ => legacy}/SimfileFormats/BMS/tmp.txt (100%) rename Docs/{ => legacy}/SimfileFormats/DWI/DWI.txt (100%) rename Docs/{ => legacy}/SimfileFormats/DWI/readme.html (98%) rename Docs/{ => legacy}/SimfileFormats/KSF/_src.txt (100%) rename Docs/{ => legacy}/SimfileFormats/KSF/ksf-format.txt (100%) rename Docs/{ => legacy}/SimfileFormats/KSF/sample.ksf (93%) rename Docs/{ => legacy}/SimfileFormats/README (98%) rename Docs/{ => legacy}/SimfileFormats/SDF/SDF.txt (100%) rename Docs/{ => legacy}/SimfileFormats/SDF/ssc-banner.png (100%) rename Docs/{ => legacy}/SimfileFormats/SDF/ssc-bg.png (100%) rename Docs/{ => legacy}/SimfileFormats/SDF/test-1bpm.sdf (100%) rename Docs/{ => legacy}/SimfileFormats/SDF/test.sdf (100%) rename Docs/{ => legacy}/SimfileFormats/SDF/test.sm (100%) rename Docs/{ => legacy}/SimfileFormats/dance-spec.txt (100%) rename Docs/{ => legacy}/SimfileFormats/misc.txt (100%) rename Docs/{ => legacy}/SimfileFormats/new format draft.txt (100%) rename Docs/{ => legacy}/SimfileFormats/ssc_msd5.txt (93%) rename Docs/{ => legacy}/Stats.xml (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Actors/ActorFrame.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Actors/ActorFrameTexture.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Actors/ActorScroller.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Actors/BitmapText.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Actors/Quad.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Actors/RollingNumbers.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Actors/Toasty.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Screens/ScreenHeartEntry.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Screens/ScreenMapControllers.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Screens/ScreenOptionsExample.ini (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/BGAnimations/ScreenSimpleExample overlay.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/ThemeInfo.ini (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/metrics.ini (100%) rename Docs/{ => legacy}/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/readme.txt (100%) rename Docs/{ => legacy}/Themerdocs/Examples/OptionRowHandlerLua.lua (100%) rename Docs/{ => legacy}/Themerdocs/Examples/anatomy_of_an_actor.lua (100%) rename Docs/{ => legacy}/Themerdocs/Noteskin elements Reference.txt (100%) rename Docs/{ => legacy}/Themerdocs/ScreenAMVTest overlay.lua (100%) rename Docs/{ => legacy}/Themerdocs/ScreenMessages.txt (100%) rename Docs/{ => legacy}/Themerdocs/ScreenTextEntry.txt (100%) rename Docs/{ => legacy}/Themerdocs/ThemePrefs.txt (100%) rename Docs/{ => legacy}/Themerdocs/ThemePrefsRows.txt (100%) rename Docs/{ => legacy}/Themerdocs/XmlToLua.txt (100%) rename Docs/{ => legacy}/Themerdocs/actordef.txt (100%) rename Docs/{ => legacy}/Themerdocs/announcer_files.txt (100%) rename Docs/{ => legacy}/Themerdocs/calories.txt (100%) rename Docs/{ => legacy}/Themerdocs/conditional_music.txt (100%) rename Docs/{ => legacy}/Themerdocs/effect_colors.txt (100%) rename Docs/{ => legacy}/Themerdocs/fontini.txt (100%) rename Docs/{ => legacy}/Themerdocs/gamecommands.txt (100%) rename Docs/{ => legacy}/Themerdocs/haste.txt (100%) rename Docs/{ => legacy}/Themerdocs/included_scripts.txt (100%) rename Docs/{ => legacy}/Themerdocs/modslevel.txt (100%) rename Docs/{ => legacy}/Themerdocs/moremsg.txt (100%) rename Docs/{ => legacy}/Themerdocs/pause_menu.md (100%) rename Docs/{ => legacy}/Themerdocs/recommended_practices.txt (100%) rename Docs/{ => legacy}/Themerdocs/sm-ssc_themeguide.txt (100%) rename Docs/{ => legacy}/Userdocs/Keymaps_ini_format.md (100%) rename Docs/{ => legacy}/Userdocs/bgchanges_format.txt (100%) rename Docs/{ => legacy}/Userdocs/sm5_beginner.txt (100%) rename Docs/{ => legacy}/credits.txt (95%) rename Docs/{ => legacy}/docpack.zip (100%) rename Docs/{ => legacy}/license-ext/Scoring-jp.txt (100%) rename Docs/{ => legacy}/license-ext/readme (100%) rename Docs/{ => legacy}/license-ext/theme_lang-ja.txt (100%) rename Docs/{ => legacy}/license-ext/vlgothic/Changelog (100%) rename Docs/{ => legacy}/license-ext/vlgothic/LICENSE (100%) rename Docs/{ => legacy}/license-ext/vlgothic/LICENSE.en (100%) rename Docs/{ => legacy}/license-ext/vlgothic/LICENSE_E.mplus (100%) rename Docs/{ => legacy}/license-ext/vlgothic/LICENSE_J.mplus (100%) rename Docs/{ => legacy}/license-ext/vlgothic/README (100%) rename Docs/{ => legacy}/license-ext/vlgothic/README.sazanami (100%) rename Docs/{ => legacy}/license-ext/vlgothic/README_J.mplus (100%) rename Docs/{ => legacy}/midiman.wishlist (96%) rename Docs/{ => legacy}/old_changelog.txt (100%) rename Docs/{ => legacy}/opensource_simulators.txt (100%) rename Docs/{ => legacy}/steps.lua (100%) rename Docs/{ => legacy}/versioning.txt (100%) diff --git a/Docs/Building-Docs.md b/Docs/Building-Docs.md new file mode 100644 index 0000000000..f61a93976f --- /dev/null +++ b/Docs/Building-Docs.md @@ -0,0 +1,12 @@ +## Building Documentation + +## Lua + +We're using LDoc, you can find it's documentation here: https://stevedonovan.github.io/ldoc/manual/doc.md.html + +To generate the docs, just run /Utils/ldoc_run.bat (Which just runs "ldoc ."). The configuration file is Utils/config.ld . It's generating docs for Themes/\_fallback/Scripts and Themes/\_fallback/Docs , and topics for Themes/\_fallback/Docs/Markdown . + +## C++ + +We're using doxygen. +Just run Utils/doxygen_run.bat . The configuration file is /Utils/doxygen_config diff --git a/Docs/Building.md b/Docs/Building.md new file mode 100644 index 0000000000..293d3e3f76 --- /dev/null +++ b/Docs/Building.md @@ -0,0 +1,195 @@ +## Building + +It should be noted that building Etterna on your own from the lastest commit is more likely to behave strangely(Resulting in crashes, profile wipes, etc). Do it at your own risk. It is recommended to use the installers or source files provided with every release. + +1. Windows +1. Linux +1. Mac + + + +## Windows + +## Dependencies(Required libraries) + +You will need the following: + +1. Visual Studio(preferably 2015) with c++ packages. +1. CMake (You can CMake GUI if you're not comfortable with the command window) +1. DirectX End-User Runtimes (June 2010) +1. DirectX SDK +1. Microsoft Visual C++ x86 Redistributable for Visual Studio 2015(If on a 64 bit system grab both x86 and x64) +1. Windows 10 DK Is probably needed if you're on Windows 10 +1. Having Git is also necessary (For submodules), unless someone sent you a zip of the repo with submodules + +## Downloading and building + +Run this command in a cmd from the folder where you want to download etterna: + + git clone --depth=1 https://github.com/etternagame/etterna.git + +Make sure you're in the right branch(default is master). Find out which is the latest one by asking someone. As of 7/17 this is "develop". To change your branch to that one open a cmd in a folder inside the repo you cloned(Inside /etterna) and do + + git checkout develop + git submodule update --init + +Change develop to the branch you want (master is usually the stable branch and develop the playground, unstable one). Remember to run git submodule. + +Run cmake(from cmd or cmakeGUI) configured for VS 2015 and open the project files generated(/Build/Etterna.sln). If not using cmakeGUI, the command should look like this(Run from a cmd in /Build/, you might have to change the Visual Studio version to the one you have): + + cmake .. -G "Visual Studio 14 2015" --build + +Note that an error like this: + +![](https://cdn.discordapp.com/attachments/326225923240230923/337716512758562817/unknown.png) + +While compiling is completely normal. + +In order to build an installer first compile and then run stepmania.nsi(Right click+ run NSIS script) to make the installer. +To play without installing simply compile and open etterna/Program/Etterna.exe or run the Etterna project from VS. + +NOTE: You may need to make sure you're compiling as Release(Defaults to Debug) +![](https://cdn.discordapp.com/attachments/326225923240230923/337715335480475650/unknown.png) + +NOTE 2: If you get an error like this: +![](http://vivide.re/863GDX4n.png) +Try adding this to StepMania.cpp: + +``` +#include +#include +int (WINAPIV * __vsnprintf)(char *, size_t, const char*, va_list) = _vsnprintf; +``` + + + +## Linux + +### 1-a: Prepare dependencies(Debian Based systems) + +Open a terminal and: + +#### Debian Based systems + +``` +sudo apt-get install build-essential git cmake +sudo apt-get install libmad0 libcurl4-openssl-dev mesa-common-dev libglu1-mesa-dev libglew1.5-dev libxtst-dev libxrandr-dev libpng12-dev libjpeg-dev zlib1g-dev libbz2-dev libogg-dev libvorbis-dev libc6-dev yasm libasound-dev libpulse-dev binutils-dev libgtk2.0-dev libudev-dev libva-dev +``` + +#### Fedora Based systems + +``` +dnf install http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm +dnf install libXrandr-devel libXtst-devel libpng-devel libjpeg-devel zlib-devel libogg-devel libvorbis-devel yasm alsa-lib-devel pulseaudio-libs-devel bzip2-devel jack-audio-connection-kit-devel libva-devel pcre-devel gtk2-devel glew-devel libudev-devel +``` + +#### 2: Clone the etterna git and compile etterna + +Open a terminal and: + +``` +git clone --depth=1 https://github.com/etternagame/etterna.git +cd etterna +git submodule update --init +mkdir Build +cd Build +cmake .. -G 'Unix Makefiles' +make +``` + +Also note you probably want to do "git checkout" to the branch you want. Ask around to find out which one it is(develop is the development branch as of 2/2018) + +If it doesn't work you can look at how travis does it(https://travis-ci.org/etternagame/etterna) + +#### 3: Making a Launcher + +If you want to run etterna from a launch button like some desktop environments have, make a shell script like this and set the launch button to run the shell script. This assumes that the etterna folder is ~/etterna. If you don't know already, "~/" is shorthand for the home folder of the current user on Linux. + +Make a new emtpy text document and add the following: + +``` +#!/bin/bash +cd ~/etterna +./etterna +``` + +Save it as etternalauncher.sh or something similar + +right click it and make it executable in properties>permissions + +#### 4: Configuration + +Install songs in ~/.etterna/Songs/ + +Install themes in ~/.etterna/Themes/ + +Install noteskins in ~/.etterna/NoteSkins/ + +Preferences are in ~/.etterna/Save/Preferences.ini + +Profiles are in ~/.etterna/Save/LocalProfiles/ + +#### 5: Updating + +When you want to update your copy of SM5: + +cd into the etterna folder you cloned(usually ~/etterna), and run a git pull in terminal: + +``` +git checkout master +git pull origin master +``` + +Replacing master(twice) for the git branch you want to update to. Then build again(As instructed above). + + + +## Mac + +#### 1: Download + +First we download/clone the repository from github: + +``` +git clone https://github.com/etternagame/etterna.git +cd etterna +git submodule update --init +``` + +#### 2: Libraries + +Next we install the necessary libs: + +``` +brew install openssl +brew install --HEAD libuv --universal +brew install yasm +brew install nasm +brew uninstall libuv +brew install libuv --universal +brew uninstall openssl +brew install openssl --universal +brew uninstall zlib +brew install zlib --universal +``` + +#### 3: Final configuration + +We finish configuring the project: + +``` +mkdir build && cd build +export LIBRARY_SEARCH_PATHS=../Xcode/Libraries +export LIBRARY_PATH=../Xcode/Libraries +mv ../src/archutils/Darwin/Etterna.pch ../src/archutils/Darwin/StepMania.pch +cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl -G "Xcode" .. +mv ../src/archutils/Darwin/StepMania.pch ../src/archutils/Darwin/Etterna.pch +``` + +#### 4: Building + +Finally, we build the project: + +``` +xcodebuild ARCHS="x86_64" -project Etterna.xcodeproj -target Etterna -destination 'platform=OS X,arch=x86_64' -xcconfig ../Xcode/conf.cnf +``` diff --git a/Docs/Contributing.md b/Docs/Contributing.md new file mode 100644 index 0000000000..2e8552c4aa --- /dev/null +++ b/Docs/Contributing.md @@ -0,0 +1,53 @@ +## Contributing + +Anyone is welcome to contribute! These are the areas where help is needed the most. + + * [C++](#c) + * [Lua](#lua) + * [Documentation](#documentation) + * [Translating](#translating) + * [Packaging](#packaging) + * [Graphic Design](#graphic-Design) + * [Chart Making](#chart-making) + + +### C++ + +If you have *any* experience with C++ (Or even C and wanna learn a bit of C++) your help would be much appreciated! +There's **A LOT** of things that need doing. If you don't have any specific thing you want to work on, here are some ideas: + - [GitHub Issues](https://github.com/etternagame/etterna/issues) + - [Coverity Defects](https://scan.coverity.com/projects/etternagame-etterna) (Currently these are private, you can request access with an email, we might make this public in the future) + - Cleaning up the codebase in general (There's a lot of things that would be nice to see done, like replacing usage of RString with std::string) + - If you know how to use them and see a good place for them, some usage of modern C++ features like smart pointers might be good to see in the project :) + +### Lua + +Lua is a fairly simple language. If you have experience in any other programming language, you'll probably be able to get the basics of its syntax in under an hour. https://www.lua.org/pil/contents.html is probably a good place to learn a bit. + +Lua is used in Etterna for Themes and Noteskins. + +Noteskins control the way the notes are drawed (Most noteskins have very similar logic and only different images, but noteskins have the power to do a lot more, and some take advantage of that). + +You can think of themes as the front end of the game. The way each screen is drawn, how screen branching (Changing) happens, and other things are controlled by the theme. A theme can even create new screens from scratch, catch inputs (Both mouse and keyboard), and other things. They're fairly powerful. + +Currently, there's a lack of alternative themes (To the default one, Til Death) for Etterna. [Spawncamping-Wallhack](https://github.com/ca25nada/spawncamping-wallhack) is the only complete theme that supports Etterna as far as I know. + +### Documentation + +The project is sorely lacking in documentation. The current aim is to document the Lua stuff in https://etternagame.github.io/Lua-For-Etterna/API/Lua.xml (This is forked from http://dguzek.github.io/Lua-For-SM5/API/Lua.xml, a community-made reference for SM5 Lua). We intend to get the C++ documentation done in https://etternagame.github.io/wiki/ (At first we wanted to make this page have 3 "sections": General, Lua and C++, but gave up). Then there is a general wiki with information that can be useful to end users (https://wiki.etternaonline.com/). + +### Translating + +The Til Death theme (Default) only has one translation available. In order to make others, simply copy etterna/Themes/Til Death/Languages/en.ini and translate all the right-side words (After the `=`). Also, a list of the words/text/captions/things that aren't translate-able in the theme would be useful to make them(Some of the text is hard-coded so it's not possible to translate it). + +### Packaging + +A few people have complained about the lack of packages for Linux in general. If you'd like to, you can try working on a package for your favorite distro. I've already made a more-or-less functional debian package here: https://github.com/nico-abram/etterna/tree/debian/ + +### Graphic Design + +A lot of things in the game have been done in a hurry to simply provide a basic UI so things can be used. We usually mostly care about features working. Mockups for new designs, improved gfx (Images) and other ideas are incredibly welcome. This goes for both the default theme and the website, etternaonline. If you're interested, you could ask around in the etternaonline discord. Also, concepts for completely new themes would be interesting to see (In case someone who knows how to implement one decides to work on it). + +### Chart Making + +As the content in the game is completely community-driven, new charts and packs keep the game fresh. They make old time players come back for a day. Even if it doesnt seem like much, every chart makes the game as a whole more valuable. You can get started by clicking "Editor" within the client. diff --git a/Docs/Changelog_SSCformat.txt b/Docs/legacy/Changelog_SSCformat.txt similarity index 100% rename from Docs/Changelog_SSCformat.txt rename to Docs/legacy/Changelog_SSCformat.txt diff --git a/Docs/Changelog_language.txt b/Docs/legacy/Changelog_language.txt similarity index 100% rename from Docs/Changelog_language.txt rename to Docs/legacy/Changelog_language.txt diff --git a/Docs/Changelog_sm-ssc.txt b/Docs/legacy/Changelog_sm-ssc.txt similarity index 100% rename from Docs/Changelog_sm-ssc.txt rename to Docs/legacy/Changelog_sm-ssc.txt diff --git a/Docs/Changelog_sm5.txt b/Docs/legacy/Changelog_sm5.txt similarity index 97% rename from Docs/Changelog_sm5.txt rename to Docs/legacy/Changelog_sm5.txt index 191c4a7ff6..4ceee1322b 100644 --- a/Docs/Changelog_sm5.txt +++ b/Docs/legacy/Changelog_sm5.txt @@ -1,2616 +1,2616 @@ -StepMania 5 Changelog -________________________________________________________________________________ -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. -________________________________________________________________________________ - -2016/06/28 ----------- -* [Gameplay] Moved pause menu logic to a script in _fallback. Added - documentation to help other themes implement a pause menu. - -2016/06/24 ----------- -* [SelectMusic] Added AllowHoldForOptions preference to disable holding start - to go to the player options screen. [kyzentun] -* [General] Back button will only back out of the screen on a press, not when - it is still being held from the previous screen. [kyzentun] - -2016/06/12 ----------- -* [ScreenSyncOverlay] Moved actors to lua to make them themable. [kyzentun] - -2016/06/09 ----------- -* [Gameplay] Ready and Go announcer sounds no longer play simultaneously. If - the Ready animation doesn't exist and the Go animation exists, only the - Go announcer sound is played. If neither animation exists, only the Ready - announcer sound is played. [kyzentun] - -2016/06/07 ----------- -* [NotesWriterSM] Stops, delays, and warps that occur on the same row are now - summed correctly. Fixes bug that deleted warps that were on the same row - as a stop. [kyzentun] -* [Sound] Ignore invalid SoundDriver preference. [kyzentun] - -2016/06/06 ----------- -* [Language] Traditional Chinese translation added. [ddrtime] - -2016/05/25 ----------- -* [MemoryCards] Fixed bug that caused loading profiles from usb drives to - crash. [djpohly] - -2016/05/20 ----------- -* [Global] Removed UndocumentedFeature lua function because it was just a way - to crash with a message. [kyzentun] - - -2016/05/11 ----------- -* [Minimaid] Fixed crash that occurred when the minimaid lights driver was - selected, but no minimaid device was connected. [wolfman2000] - -================================================================================ -StepMania 5.0.11 | 20160401 --------------------------------------------------------------------------------- - -2016/03/22 ----------- -* [Prefs] Added DisableUploadDir preference to skip saving a score entry to - Save/Upload every time a song is played. Generating the unique filename - can take several seconds when there are years of scores accumulated, and it - clutters the disk. This preference defaults to false. [kyzentun] - -2016/03/17 ----------- -* [Actor] Added get and set_tween_uses_effect_delta lua functions to make an - Actor use the effect clock for tweening. [kyzentun] - -2016/03/15 ----------- -* [ProfileManager] Added GetStatsPrefix and SetStatsPrefix lua functions for - separating scores into different stats files. [kyzentun] - (this is kind of a stop gap, I'd really like to rewrite scoring to save - more data so that a score earned with one set of timing windows and weights - can be converted to the equivalent score with different timing windows) - -2016/03/14 ----------- -* [Online] Stepmania will force disconnection from the SMO server when - entering the jukebox or sync calibration screens to avoid crash. [kyzentun] - -2016/03/05 ----------- -* [global] get_sound_driver_list lua function added. [kyzentun] - -2016/03/02 ----------- -* [Gameplay] Fixed No Fakes mod to remove fakes inside warps. [kyzentun] -* [Keymaps] Added special name for colon key so it can be bound. [medmig] - -2016/02/20 ----------- -* [Language] Bahasa Indonesian translation added to default theme. [JOELwindows7] - -2016/02/15 ----------- -* [Input] Linux event devices now start at JOY10 instead of JOY1. Without - this change, if one dance pad is a joystick device, and the other is an - event device, they will both be JOY1, and stepmania will think they are the - same dance pad. If you use Linux, assume that you have to remap your dance - pad. [kyzentun] - -2016/02/13 ----------- -* [Lights] Minimaid driver added for Linux. This is practically identical to - the Windows minimaid driver that pkgingo wrote. -* [Gameplay] When checking for the first second in a song, AutoKeysound notes - are now ignored, being treated as if they were background music. This - allows the intro of BMS files to play as soon as ScreenGameplay is loaded, - while still having a delay before the real notes come in. [nixtrix] - -2016/02/04 ----------- -* [Course] In an Endless course, songs will only be repeated after all songs - in the group have been played. [blindbox] - -2016/02/03 ----------- -* [ScreenManager] Added PlayInvalidSound, PlayStartSound, PlayCoinSound, - PlayCancelSound, and PlayScreenshotSound lua bindings. [kyzentun] - Added get_input_redirected and set_input_redirected to allow the theme to - disable the normal input functions. (Example: a custom lua menu on - Select Music. When the menu is up, the theme doesn't want the player's - input to move the music wheel.) This is in SCREENMAN so that it will work - on all screens. [kyzentun] -* [ScreenSelectMusic] Added CanOpenOptionsList lua binding. OpenOptionsList - will do nothing if CanOpenOptionsList returns false. [kyzentun] - -2016/01/18 ----------- -* [Edit Mode] Added "Clear timing in region" to timing menu. [kyzentun] - Fixed crash that occurs when "Paste timing data" is used after copying a - region of timing data that only contains stops. [kyzentun] - -2016/01/14 ----------- -* [Gameplay] Added pause menu to default theme. Activated by pressing - Select, or Back twice without pressing something else. Has options for - restarting or forfeiting the current song in normal play. Course mode has - options for skipping the current song or ending the course or forfeiting. - [kyzentun] -* [Graphics] When fetching the list of resolutions, only 32bpp modes are - tested because less than 32bpp is not supported on Windows 8 and newer, and - because the bpp doesn't matter when fetching a list of resolutions. This - speeds up the load time of the Graphics/Sound option screen. [kyzentun] - -2016/01/10 ----------- -* [RageFile] Lua functions for RageFile should now emit an error when the - file was not opened correctly instead of crashing. [kyzentun] - -2016/01/05 ----------- -* [Linux] Disable DPMS on startup and restore setting on exit. [kyzentun] - -2015/12/27 ----------- -* [RageFileManager] Ignore OS X special files in GetDirListing. [kyzentun] - -2015/12/20 ----------- -* [Fonts] Fixed crash bug in Texture Font Generator. [drewbarbs] - -2015/12/16 ----------- -* [Player] ChangeLife and SetLife functions added. [kyzentun] - -2015/12/13 ----------- -* [popn] Judgment levels in popn game mode now use W1 to W5. [parashep] - -2015/12/05 ----------- -* [Player] Guitar mode cruft removed from Player. [tertu] - -2015/12/04 ----------- -* [NoteField] Changed DrawBeatBar to check the M-mod so that smaller beat - bars are drawn when M-mods are used in edit mode. [kyzentun] - -2015/11/09 ----------- -* [Gameplay] BG Brightness is no longer forced to 100% on songs that only - have a beginner chart. [kyzentun] - -2015/11/08 ----------- -* [ScreenSelectMusic] Using lua music files for the section music and similar - things works now. [kyzentun] - -2015/11/05 ----------- -* [PlayerOptions] Fixed bug that was clearing the noteskin back to default. - [kyzentun] - -================================================================================ -StepMania 5.0.10 | 20151031 --------------------------------------------------------------------------------- - -2015/10/29 ----------- -* [Language] French translation updated. [Arvaneth] - -2015/10/27 ----------- -* [Compiling] Link with /MT on windows instead of /MD. [wolfman2000] -* [Fonts] Put Texture Font Generator back in package. [wolfman2000] - Build Texture Font Generator when WITH_FULL_RELEASE or - WITH_TEXTURE_GENERATOR is enabled. [wolfman2000] - -2015/10/26 ----------- -* [Song] Added GetMainTitle lua function for bypassing ShowNativeLanguage - preference. [kyzentun] - -2015/10/25 ----------- -* [Compiling] Number of jobs used when building ffmpeg can be customized by - WITH_FFMPEG_JOBS. [wolfman2000] - Appveyor support added for automated windows building. [wolfman2000] - -2015/10/23 ----------- -* [BMS] Fixed crash when an unknown type chart was in a bms. [kyzentun] - -2015/10/21 ----------- -* [Actor] Changed PlayCommandNoRecurse so that setting a theme metric to a - function that doesn't exist doesn't emit an error. [kyzentun] -* [Compiling] Allow WITH_MP3=Off and WITH_WAV=Off to compile. [wolfman2000] -* [EditMode] Fixed crash on missing ScreenMiniMenuTimingDataChangeInformation - metrics. [kyzentun] -* [ScreenEvaluation] Changed assert that occurs when leaving ScreenGameplay - with SM_GoToNextScreen to give more info. [kyzentun] - -2015/10/20 ----------- -* [Compiling] Fixed cmake error when compiling with -DWITH_SSE2=off. [wallacoloo] - Don't define CPU_X86 on non-x86. [wallacoloo] -* [Noteskins] If the fallback for a noteskin is not found, that noteskin is - not loaded, to prevent picking it and crashing. [kyzentun] - -2015/10/18 ----------- -* [BitmapText] Added set_mult_attrs_with_diffuse lua function. [kyzentun] - -2015/10/17 ----------- -* [Course] Fixed loading of courses that use WORST entries. [wolfman2000] -* [SextetStream] SextetStream stuff is now in all platforms. [wolfman2000] - -2015/10/15 ----------- -* [BMS] Changed bms loading so that iidx bms files aren't loaded as kb7. - [zardoru] - -2015/10/12 ----------- -* [ActorMultiVertex] Fixed bug that *sometimes* caused diffuse to be applied - to verts wrong. [kyzentun] - -2015/10/11 ----------- -* [Song] Changed song loading to allow a song to have a blank MusicFile field - if the song has any keysounds. A blank MusicFile entry can result from - having '#' in the music file name, or be intended for bms files. Do not use - '#' in any fields, the .sm and .ssc file formats do not support it. The - engine has to detect that the field was loaded blank and look through the - song folder to figure out what was supposed to be there. [kyzentun] - -2015/10/09 ----------- -* [Edit Mode] Changed Current Second field to not have the global offset - added in. People were using one global offset for syncing to workaround - the problem and sync by comparing the Current Second in Edit Mode to the - current second in a music editor. The workaround of using a different - global offset for syncing should no longer be necessary. [kyzentun] -* [Input] Fixed input lockup caused by scrolling the mouse wheel. Why wasn't - this reported sooner? [kyzentun] - -2015/10/07 ----------- -* [ActorFrame] ActorFrame:SetDrawByZPosition now returns self. Missed a spot - when implementing function chaining. [kyzentun] -* [Gameplay] MaxRegenComboAfterMiss preference brought in. When a step is - missed in gameplay, the combo has to get back up to RegenComboAfterMiss - before the player starts regaining life. If MaxRegenComboAfterMiss is - greater than RegenComboAfterMiss, then each successive miss increases - RegenComboAfterMiss until it reaches RegenComboAfterMiss. - MaxRegenComboAfterMiss defaults to 5, the same as RegenComboAfterMiss, so - there should be no behavior change unless the preference is manually - changed. [dbk2] -* [Gameplay] When disqualification was turned on via Preferences, the old - logic exhibited two problems: - 1. charts with attacks were always disqualified from ranking - 2. charts without attacks could be disqualified from ranking if the attack - modifier was set to "Off" - So, this commit fixes those problems. If a chart has attacks, and the - attack modifier is used to turn them "Off", then disqualification is - enforced. - Additionally, disqualification is enforced if the attack modifier is set to - "Random Attacks." This part might not be necessary, but I acted on the - assumption that random attacks could theoretically make a chart easier. - [dbk2] - -2015/10/04 ----------- -* [FFmpeg] Upgrade FFmpeg to 2.1.3 for Windows. [wolfman2000] -* [FFmpeg] Fixed cmake WITH_SYSTEM_FFMPEG option. [lthls] - -2015/10/03 ----------- -* [FFmpeg] Upgrade FFmpeg to 2.1.3 for Mac OS X. [wolfman2000] -* [Gameplay] Fixed timing to apply the current music rate to the global - offset so that playing at different music rates doesn't make a chart off - sync. [Matt McCutchen] - -2015/10/02 ----------- -* [Edit Mode] .sm files will no longer be saved when split timing is used - because per-chart timing cannot be done in the .sm format. [kyzentun] -* [Scoring] Fixed bug that caused missed holds to be recorded as held in the - value returned by PlayerStageStats:GetRadarActual(). [kyzentun] - -2015/09/21 ----------- -* [Sprite] Added set_use_effect_clock_for_texcoords for toggling whether the - tex coord velocity uses the effect clock instead of the time. - -2015/09/10 ----------- -* [MusicWheel] Fixed SetItemPosition so that it actually passes the item - index and the number of items to the transform function. [kyzentun] - -2015/09/09 ----------- -* [Notefield] Fixed bug where the hold body doesn't scroll if it goes off the - top of the screen. [waiei] - -2015/09/08 ----------- -* [Compiling] Compiling stepmania on Windows with the locale set to Japanese should work now. [wolfman2000] - -2015/09/06 ----------- -* [Preferences] Fixed crash on Advanced Input Options on OS X caused by the - Axis Fix preference not existing on OS X. The preference does nothing on - OS X, but the game no longer crashes on that screen. [kyzentun] - -2015/09/03 ----------- -* [Fonts] Respliced large kanji sprite sheets from 32x106 and 32x61 to 63x54 - and 48x41 to bring them under 4096 pixels tall, which was causing a forced - resize and slowing down loading time. [kyzentun] -* [Gameplay] Fixed song position updating logic so that the - ScreenGameplay:PauseGame lua function actually pauses the game. Start, - Select, and Back are all used for different ways of giving up, so the - feature remains unused in the default theme. [kyzentun] - -2015/09/02 ----------- -* [Gameplay] Fixed Player logic that spammed TNS_AvoidMine repeatedly. [kyzentun] - -2015/08/29 ----------- -* [Edit Mode] Fixed crash on entering edit mode caused by entering edit mode - as Player 2. Edit Mode only works as Player 1. [kyzentun] - -2015/08/23 ----------- -* [BMS] Added myo2 channel layout and kb7 charts. Added preview point and - fixed offset support and linear solo bms layout. [zardoru] -* [Linux] Symbolic links will be followed to find the actual executable dir. [Wallacoloo] - -2015/08/20 ----------- -* [Minimaid] Minimaid support built in by default instead of off by default. [wolfman2000] -* [Options] Put AllowExtraStage on Advanced Options screen in default. [kyzentun] - -2015/08/19 ----------- -* [Gameplay] RandomBGEndsAtLastBeat metric defaults to true to be similar to - old behavior. [wolfy852] - -2015/08/08 ----------- -* [General] When the HighResolutionTextures preference is set to Auto, - StepMania checks whether the display height is greater than the theme - height instead of whether it's greater than 480. [shakesoda] - -2015/08/04 ----------- -* [PIUIO] Only send LightState changes to PIUIO when there is a change. [dbk2] - -2015/08/02 ----------- -* [NoteField] Fixed bottomcap when NoteDisplay is zoomed out. [hanubeki] - -2015/07/22 ----------- -* [Compiling] Fixed building on 32bit linux. [kyzentun] - -2015/07/19 ----------- -* [Pump] Added TimingWindowSecondsCheckpoint for the timing window that - checkpoint holds allow you to release for. [wolfman2000] - -2015/07/18 ----------- -* [General] Fixed bug that skipped notes on beat 0 in score. [kyzentun] - -2015/07/16 ----------- -* [ActorUtil] ActorUtil.ResolvePath and ResolveRelativePath now take a - boolean flag to tell if the thing is optional. [kyzentun] -* [CryptMan] Fixed bug that clipped hash strings with zeros. [kyzentun] - -2015/07/15 ----------- -* [Sprite] Sprite now executes the AnimationFinished command when it reaches - the end of its animation and starts over. [kyzentun] - -2015/07/11 ----------- -* [ScreenMapControllers] If the AutoDismissWarningSecs metric is less than - .25 seconds, the warning will not be shown (the TweenOn command for it will - not be played). Instead, the NeverShow command will be played. If the - NeverShow command does not exist for the warning actor, the warning actor - will be set to hibernate forever. [kyzentun] - -2015/07/02 ----------- -* [Gameplay] Random background video behavior is now controlled by these - three metrics in the Background section: - RandomBGStartBeat sets the beat of the music the first random bg occurs on. - RandomBGChangeMeasures sets the number of measures between changes. - RandomBGChangesWhenBPMChangesAtMeasureStart toggles the behavior in its name. - RandomBGEndsAtLastBeat toggles the behavior in its name. - -================================================================================ -StepMania 5.0.9 | 20150520 --------------------------------------------------------------------------------- - -2015/06/10 ----------- -* [global] get_music_file_length lua function added. [kyzentun] - multiapproach lua function now takes an optional 4th argument to multiply - the speeds by. [kyzentun] -* [NoteDisplay] 1px seam in hold cap rendering fixed. [A.C/waiei] -* [RageSound] get_length lua function added. [kyzentun] - -2015/06/06 ----------- -* [ScreenInitialScreenIsInvalid] Error screen for themes that set an invalid - initial screen. [kyzentun] - -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] -* [RageFile] Exposed Flush function to Lua. [kyzentun] - -2015/05/29 ----------- -* [OptionsList] The OptionsListQuickChange, OptionsListLeft, and - OptionsListRight messages now have a Selection parameter that has the id of - the selection the player moved to. [nixtrix] - -2015/05/24 ----------- -* [Gameplay] Autokeysounds are no longer twice as loud when playing - keysounded charts with two players. [nixtrix] - -2015/05/15 ----------- -* [BMS] .lua files defined in the #BMP tags now work as BG animations, and the - #difficulty tag is now supported. [nixtrix] -* [general] BackInEventMode code now works when called from either player. - [nixtrix] -* [cmake] JACK is now properly found by CMake. -* [theme] Preview music fadeout time is now adjustable by the metric - SampleMusicFadeoutSeconds. [nixtrix] -* [Song] Setting a sample length of 0 uses the length of the entire preview - file. [nixtrix] - -================================================================================ -StepMania 5.0.8 | 20150510 --------------------------------------------------------------------------------- - -2015/05/10 ----------- -* [General] Screenshots are not tagged with song title or screen name because - this causes problems when titles have UTF8 or slashes. [kyzentun] - -2015/05/09 ----------- -* [general] Workaround for the axis problem added. Set the Axis Fix - preference under Input Options to true if you have the axis problem. - [Fighter19] -* [general] Added XML to Lua converter. See Docs/Themerdocs/XmlToLua.txt for - details. [kyzentun] - -2015/05/08 ----------- -* [compiling] Added -DWITH_CRYSTALHD_DISABLED cmake options to allow more - users to build on Linux. [wolfman2000] - -2015/05/05 ----------- -* [Gameplay] Holding Select on gameplay now skips the current song in course - or endless mode. [kyzentun] - -2015/04/30 ----------- -* [beat] Default key configuration slightly tweaked, space is now the - default scratch key, key7 is now mapped to right instead of key3. - Backwards and shuffle chart mods now ignore the scratch column. [jobn] - -2015/04/27 ----------- -* [general] "Do not show again" button on missing texture dialog works now. - If the background or banner file for a song doesn't exist when the song is - cached, the cache file will have a blank path so Stepmania won't try to - load the nonexistent banner or background. - -2015/04/25 ----------- -* [General] Screenshot key now checks whether there is a current song, and - puts the song title and current screen name in the screenshot filename. [kyzentun] - -2015/04/24 ----------- -* [Gameplay] Toasty animation can now occur multiple times during gameplay. [kyzentun] - -2015/04/23 ----------- -* [ServiceMenu] Entries in service menu rearranged to hopefully organize them - better. ScreenOptionsInputSub and ScreenOptionsDisplaySub added. Updating - a theme to show the options for the new screens should be a simple matter of - changing the LineNames entry for ScreenOptionsService to include - "InputOptions" and "SoundGraphics". [tuxdude] - -2015/04/18 ----------- -* [EditMode] Fixed bug that made alter menu choices prompt for clearing. [kyzentun] -* [NoteColumnRenderer] Added handling for diffuse and glow to make rainbow - and related effects work. [kyzentun] - -2015/04/15 ----------- -* [compiling] -DWITH_LIBVA option added to cmake building to fix compiling - problems for some linux users. [wolfman2000] - -2015/04/14 ----------- -* [SelectMusic] Disabled late join on Extra Stage to prevent crash on - Evaluation Summary. [kyzentun] - -2015/04/13 ----------- -* [EditMode] Fixed Revert From Disk to actually work. [kyzentun] -* [japanese] Language update from hanubeki. [hanubeki] - -2015/04/11 ----------- -* [dev] cpack support for installing. [wolfman2000] -* [TimingData] Fixed bug that made steps on the same row as a stop and a bpm - change unhittable. [kyzentun] - -2015/04/10 ----------- -* [Profile] Kluged together a fix for scores on edit charts not being loaded - until after the chart is played. [kyzentun] - -2015/04/08 ----------- -* [ActorSound] IsAction attribute added. get/set_is_action functions added. - [kyzentun] -* [GameSoundManager] is_action arg added to PlayOnce. [kyzentun] - -2015/04/06 ----------- -* [global] rec_print_children and rec_print_table lua functions added to - _fallback. [kyzentun] -* [Language] Dutch translation updated. [Thumbsy] -* [RadarValues] Stream, Voltage, Air, Freeze, and Chaos are no longer capped - at 1. Stream and Voltage no longer count hold heads twice. - RadarCategory_Notes added, which counts all notes. - Scoring bug fixes related to radar calculation. [kyzentun] -* [ScreenSelectGame] Exit option returns to ScreenOptionsService unless the - game type actually changed. [Wallacoloo] - -2015/04/04 ----------- -* [EditMode] Added submenus to the timing edit menu to allow shifting, - copying, and pasting any or all timing segments in the selected region or - after the current cursor position. [kyzentun] - Shifting menus in edit mode now have choices for 1, 2, or 4 measures or 2 - beats. [kyzentun] -* [global] Fixed crash on OS X for certain dance pads when in Japanese - locale. [Wallacoloo] - -2015/04/03 ----------- -* [ScreenGameplay] The NoteField board is now underneath everything except - the backgound. This means underneath any custom actors on the underlay or - overlay or decoration layers, and also underneath the combo/judgment even - when the ComboUnderField metric is true. [kyzentun] - Fixed bug in screen filter in default theme that made it not appear under - the field when a solo file was played without Center1Player. [kyzentun] - -2015/04/02 ----------- -* [global] commify function exposed to lua. [kyzentun] - -================================================================================ -StepMania 5.0.7 | 20150401 --------------------------------------------------------------------------------- - -2015/03/30 ----------- -* [Select Music] Ctrl+Shift+R mapped to reload the current song. [kyzentun] -* [Song] ReloadFromSongDir lua function exposed. [kyzentun] -* [Preferences] NeverCacheList preference added. It's a comma separated - list of group names, if a song is in one of the named groups, it is never - cached. [kyzentun] - -2015/03/27 ----------- -* [Select Music] Ability to delete the current song by pressing Ctrl+Backspace added. [Wallacoloo] - -2015/03/24 ----------- -* [Sprite/RageTexture] GetTexturePath moved to RageTexture and renamed to - GetPath. [kyzentun] - -2015/03/22 ----------- -* [Dev] Primary build method of all platforms changed to CMake. People - building from source must install CMake (min 2.8.12) and read - Build/README.md for building instructions. [wolfman2000] - -2015/03/18 ----------- -* [OSX] Empty Stepmania directory created on desktop removed. [dguzek] - -2015/03/17 ----------- -* [ActorFrameTexture] Example added to Themerdocs/Examples/Example_Actors/. - Crash fixes for AFTs. [sigatrev] - -2015/03/15 ----------- -* [Sprite] GetTexturePath added. [kyzentun] - -2015/03/12 ----------- -* [Language] Docs/Changelog_language.txt added for tracking language changes. - -======= -================================================================================ -StepMania 5.0.7rc | 20150309 --------------------------------------------------------------------------------- - -2015/03/09 ----------- -* [EditMode] Autosave every 5 minutes added. [kyzentun] -* [General] NotesLoaderSM, NotesLoaderSSC, IniFile::ReadFile rewritten, - load times substantially faster. [kyzentun] -* [Preference] HarshHotLifePenalty preference added, for toggling whether - LifeMeterBar takes away .1 life when it's full. [kyzentun] - -2015/03/08 ----------- -* [EditMode] Clearing an area now prompts for confirmation if it contains - EditClearPromptThreshold notes or more. EditClearPromptThreshold is a - preference that can be set in the Advanced Options section, or in the - options in Edit Mode. [kyzentun] - -2015/03/05 ----------- -* [Graphics] DX9 support improved, giving a large speed boost and fixing the - problem that made people get stuck with 16bit color. [xwidghet] - -2015/03/04 ----------- -* [Loading] The song length from the cache is used now. This cut loading time - by 30% for kyz. [kyzentun] - -2015/03/02 ----------- -* [Song] Per-chart music feature added. Each chart can have a MUSIC tag. - [kyzentun] - -2015/03/01 ----------- -* [SelectMusic] Select Music now plays music file named by #PREVIEW tag if - it's not blank, instead of using the song file for the sample music. The - sample length is read from the preview file. The sample start is treated as - 0. [kyzentun] -* [Song] GetPreviewMusicPath added. [kyzentun] -* [foreach] foreach_ordered lua function now works on tables that have both - number and string keys. Number keys are iterated over first. [kyzentun] - -2015/02/28 ----------- -* [General] Pause/Break key now toggles "action" sounds off or on. There is - also a button in the F3 debug menu (press A, there are so many that it is - off the bottom) for people that don't have a Pause/Break key. [kyzentun] - -2015/02/27 ----------- -* [ActorFrame] Fixed RemoveChild and RemoveAllChildren lua functions to - delete the children instead of leaking memory. [kyzentun] -* [Font] Asserts and other things that caused Stepmania to crash on font - mistakes now emit non-fatal errors. [kyzentun] - -2015/02/26 ----------- -* [PaneDisplay] Changed to print an error when metrics or player number are - omitted instead of crashing. [kyzentun] -* [Screen] Fixed crash when AddInputCallback is passed nil. [kyzentun] - -2015/02/22 ----------- -* [BitmapText] Place characters of right-to-left alphabets correctly. - (untested) [roothorick] - -================================================================================ -StepMania 5.0.6 | 20150217 --------------------------------------------------------------------------------- - -2015/02/16 ----------- -* [EditMode] Fixed mistake in TimingData that broke editing bpms. [kyzentun] - Fixed crash when deleting steps. [kyzentun] -* [InputMapper] Backslash can be mapped now. [kyzentun] - -================================================================================ -StepMania 5.0.5 | 20150214 --------------------------------------------------------------------------------- - -2015/02/12 ----------- -* [InputMapper] Added D-Force Automappings [shakesoda] - -2015/02/04 ----------- -* [ActorFrame] GetUpdateRate added. [kyzentun] -* [Background] Using the wrong transition name no longer crashes. - Playback rate is applied to videos. - Checkerboard and other BackgroundEffects that use the same file twice no - longer play videos back at multiplied speed. [kyzentun] -* [Sprite] Get/SetDecodeMovie added. [kyzentun] - -2015/02/03 ----------- -* [MusicWheel] HideActiveSectionTitle metric added. [djpohly] - -2015/02/02 ----------- -* [ActorMultiVertex] ForceStateUpdate and Get/SetDecodeMovie added. [kyzentun] -* [RageTexture] GetWidth and Height functions added. - ( means Source, Texture, or Image) [kyzentun] -* [Scripts] find_missing_strings_in_theme_translations function added to - _fallback scripts to assist translators in finding what needs to be - translated. If you need/want to run it on your them, write a piece of lua - like this: - find_missing_strings_in_theme_translations("_fallback", "en.ini") - The first arg is the folder name of the theme to look at. - The second arg is the name of the language that is fully translated. All - other languages will be compared to it to decide what is missing or unused. - [kyzentun] -* [Song] GetBGChanges added. [kyzentun] - -2015/02/01 ----------- -* [ActorMultiVertex] Animation state system added. AMVs can now have - animated textures controlled by states written in lua. [kyzentun] - -2015/01/31 ----------- -* [EditMode] Want more lead in time before recording starts? - It's a preference. [kyzentun] - -2015/01/30 ----------- -* [Actor] Wrapper states added. This makes wrapping an Actor inside an - ActorFrame for any reason unnecessary, and makes it possible to do things - that were only possible by wrapping an Actor in an ActorFrame to Actors - that you couldn't put inside a frame before. [kyzentun] - -2015/01/20 ----------- -* [ScreenSelect] ChoiceNames can be a lua command that is evaluated to get a - list of the gamecommands. The main use of this is to get rid of the huge - list of metrics that ScreenSelectStyle requires. A single lua function - instead of a metric for every style for every game type. [kyzentun] -* [ScreenSelectMaster] IconChoicePosFunction metric added. This metric is - optional, if it's set, it must be set to a function that returns a table - of positions. Each position is a table of the form "{x, y, z}", where x, - y, and z are numbers and any that is not a number defaults to 0. - The function is passed the number of choices for the screen. - IconChoiceOnCommand and IconChoiceOffCommand metrics added so each choice - doesn't require its own On/OffCommand pair. These are also optional, but - if they are set, they will override the individual commands if they exist. - (If "IconChoiceCactusOnCommand" and "IconChoiceOnCommand" both exist, - "IconChoiceOnCommand" will be used.) [kyzentun] - Example: - # in metrics.ini - IconChoicePosFunction=choice_positions - -- In a file in Scripts/ - function choice_positions(count) - local ret= {} - for i= 1, ret do ret[i]= {i*24, i*48} end - return ret - end - -2015/01/16 ----------- -* [ScreenSelectMusic] HardCommentMeter metric added. Sets the meter that - will trigger the "select music comment hard" announcer sound. [kyzentun] - -2015/01/12 ----------- -* [ScreenOptions] GetNumRows function added. [kyzentun] - -2015/01/09 ----------- -* [Sprite] SetStateProperties function added. [kyzentun] - -2015/01/06 ----------- -* [ActorMultiVertex] GetSpline and SetVertsFromSplines functions added. - [kyzentun] -* [NoteColumnRenderer] Functions for fetching the spline handlers for the - column added. [kyzentun] -* [NCSplineHandler] New class for setting various parameters of a spline used - by a NoteColumnRenderer and containing the spline. [kyzentun] -* [CubicSplineN] New class that provides spline functionality. [kyzentun] - -2014/12/26 ----------- -* [NoteField] Columns turned into actors that can be fetched with - get_column_actors. [kyzentun] - Tiny boost in fps when there is a large number of notes on screen. -* [NoteColumnRenderer] New class for controlling one column. [kyzentun] - -2014/12/20 ----------- -* [Preferences] AllowMultipleHighScoreWithSameName, ComboContinuesBetweenSongs - Disqualification, FailOffForFirstStageEasy, FailOffInBeginner, - LockCourseDifficulties, InputDebounceTime, MaxHighScoresPerListForMachine, - and MaxHighScoresPerListForPlayer added to service options. - InputDebounceTime is in Input Options, the rest are in Arcade Options. - (might not show up in themes that customize the order and placement of the - preferences) [kyzentun] - -2014/12/18 ----------- -* [Profile] GetTotalDancePoints added. [kyzentun] - -2014/12/10 ----------- -* [EditMode] Play whole song and play from current beat will now play until - either the music or the notes end, whichever is greater. [kyzentun] - The screens used for setting the options used to play the screen and for - adding attacks can be set through the "OptionsScreen" and "SetModScreen" - metrics in the ScreenEdit section. -* [GameState] ApplyPreferredSongOptionsToOtherLevels function added. [kyzentun] -* [Player] "ComboBreakOnImmediateHoldLetGo" theme metric added. [sillybear] -* [PlayerState] ApplyPreferredOptionsToOtherLevels function added. [kyzentun] - -2014/12/07 ----------- -* [Game] GetSeparateStyles function added. Use this to detect whether a game - allows the players to play different styles. [kyzentun] (used by kickbox) -* [GameManager] Lua Scripts/ folders are now reloaded when the Game mode is - changed. [kyzentun] -* [GameState] CanSafelyEnterGameplay function added. [kyzentun] - In kickbox game mode, players can have different styles set, pass a - PlayerNumber when using SetCurrentStyle or GetCurrentStyle. -* [kickbox] New game mode with 4 styles. [kyzentun] -* [ScreenGameplay] Notefield positioning is handled a bit differently now. - See comments in _fallback/metrics.ini above the [ScreenGameplay] - MarginFunction metric. Basically, you can define a lua function that - returns the space you want at the edges and in the center instead of - setting position metrics. Do NOT use Style:GetWidth to calculate the - margins your function returns. - ScreenGameplay now handles zooming the notefield to fit in the space - instead of using the NeedsZoomOutWith2Players flag in the style. - If the notefield doesn't fit in the space between the margins, and there is - only one player, the player will be centered even if the Center1Player pref - is false. [kyzentun] -* [Style] NeedsZoomOutWith2Players decapitated. Always returns false now. - GetWidth added. [kyzentun] -* [techno] Techno game mode no longer has special column width for versus. - Techno was the only game mode that used the NeedsZoomOutWith2Players flag, - and the zoom factor it applied was 0.6, and the special versus column width - was 0.6*normal, so this should make no difference. [kyzentun] - -2014/12/03 ----------- -* [command line arg] --game command line arg added for setting the game type - when starting stepmania. [sillybear] -* [Announcer] "evaluation full combo W3" and "evaluation full combo W4" - responses added. [sillybear] - -2014/12/01 ----------- -* [ScreenMapControllers] Forced sanity checking of key mappings added. - Start, MenuLeft, MenuRight, and Operator keys must be mapped. - Reset key mappings option added to debug menu for recovering from an - unusuble keymap without needing to find and delete KeyMaps.ini. [kyzentun] - -2014/11/30 ----------- -* [NoteField] New functions added for controlling the receptor and ghost arrow - (explosion) flashes. [kyzentun] - -2014/11/28 ----------- -* [Profile] Guest and Test profile types added. All existing and new - profiles are Normal. If a profile is changed to Guest through the profile - management screen, it will always show at the top of the list. A profile - set to Test will always be at the bottom of the list. Profiles can be - moved around in the list. - GetType and GetPriority lua functions added to Profile. - Bug that caused a crash when a profile dir was renamed to a non-number and - a new profile was created fixed. [kyzentun] -* [Everything] Actor and singleton functions that formerly returned nothing now - return the actor or singleton. Example (set zoom, x, y, and diffuse in one): - self:zoom(.5):xy(_screen.cx, _screen.h-60):diffuse(color("#dc322f")) - This also works for PlayerOptions and SongOptions API functions. Pass true - as an extra arg, and they can be chained. - -2014/11/22 ----------- -* [Preferences] MinTNSToHideNotes preference added. [kyzentun] -* [PlayerOptions] MinTNSToHideNotes mod added. [kyzentun] - -2014/11/15 ----------- -* [Preferences] Default Fail Type preference mechanism changed internally again. - Set your Default Fail Type preference again. [kyzentun] - -2014/11/05 ----------- -* [ScreenPrompt] Answer OnCommand metrics fixed to actually work. [kyzentun] - -2014/11/01 ----------- -* [RollingNumbers] Cropping and color during tweens fixed. [kyzentun] - -2014/10/27 ----------- -* [Changelog] Vospi read the release notes. - -2014/10/23 ----------- -* [Global] approach, multiapproach, lerp, and lerp_color lua functions added. [kyzentun] - -2014/10/20 ----------- -* [StageStats] GetStepsSeconds function added. [kyzentun] -* [Steps] If an unrecognized step type is saved, preserve that step instead of - deleting it. A warning will be placed in the log file during song load. [kyzentun] - -================================================================================ -StepMania 5.0 beta 4a | 20141015 --------------------------------------------------------------------------------- - -2014/10/19 ----------- -* [BackgroundEffects] Fixed errors in StretchNoLoop and StretchRewind. - -2014/10/13 ----------- -* [NoteDisplay] Var Player and Var Controller work for non-receptor arrows. [hanubeki] -* [Mac OS X] Allow StepMania to be built and run in Yosemite. - -2014/10/11 ----------- -* [NoteDisplay] Add two noteskin metrics, {PartName}NoteColorType and - {PartName}NoteColorCount. View https://github.com/stepmania/stepmania/pull/328 - for more information. [hanubeki] - -================================================================================ -StepMania 5.0 beta 4 | 20140930 --------------------------------------------------------------------------------- - -To reduce the number of entries in this file, entries are dated to the Saturday after they occurred. - -2014/09/27 ----------- -* [Preferences] DebounceCoinInput time pref added for machines that need a - different debounce time for coin input. -* [Preferences] DefaultFailtype preference reinstated to resolve default fail - type problems. -* [TimingData] TimingData::GetReturnsNumbers metric added to make TimingData - functions return tables of numbers instead of strings. - -2014/09/20 ----------- -* [ScreenOptionsCustomizeProfile] New screen added for setting profile stats. - -2014/09/13 ----------- -* [Endless] Songs are repicked on each repeat of the course. -* [GameState] GetCurrentStage logic fixed to correctly return Stage_Final in - all cases where it should. -* [JudgmentMessage] Tracks parameter replaced with Notes and Holds parameters. -* [NumPadEntry] New customizable lua class for custom screens. -* [ScreenHeartEntry] New screen added to default. -* [TapNote] Class exposed to lua through JudgmentMessage with all data on the - TapNote. - -2014/09/06 ----------- -* Changed ES/OMES speed mod to 2x from 1.5x. -* [ActorMultiVertex] GetTexture lua function added. -* [BitmapText] max_dimension_use_zoom lua function added. -* [Edit Mode] Swap Up/Down and Arbitrary Remap added to Alter menu. -* [GameState] InsertCoin and InsertCredit lua functions added. -* [PrefsManager] FastNoteRendering preference added. -* [RageTexture] Reload lua function added. -* [RageTexture?] "__screen__" added as special screenshot texture name. - Causes a skip. -* [Screen] SetNextScreenName lua function added. -* [ScreenCredits] New ScreenCredits. Please update your theme if you applied - theme changes to this screen. -* [ScreenMapControllers] Massively changed to make it not suck. New elements, - new metrics, new actions. -* [WheelItemBase] IsLoaded lua function added. - -2014/08/30 ----------- -* [ActorScroller] wrap parameter added for controlling looping behavior better. -* Life difficulty matches StepMania 3.9's again. - -2014/08/16 ----------- -* [ActorFrame] Internal diffuse and glow now apply to BitmapText children. -* [GameState] SetCurrentPlayMode and SetCurrentStyle lua functions added. -* [PrefsManager] BackgroundFitMode preference added to settle all problems - with how backgrounds are stretched or fit. -* [ScreenSetBGFit] New screen for presenting the BackgroundFitMode preference. - See _fallback/BGAnimations/ScreenSetBGFitMode overlay.lua for documentation. -* [ThemeManager] HasMetric/String now return false when the group name or - metric name is an empty string. - -2014/08/09 ----------- -* [GameManager] GetStylesForGame lua function added. -* [LifeMeterBattery] CourseSongRewardLives metric added. -* [LifeMeter] LifeType, DrainType, and BatteryLives moved to PlayerOptions so - the players can have different settings. -* [ScreenGameplay] LifeMeterChangedP1 message is no longer broadcast for for - P2's lifemeter. Use LifeMeterChangedP2. "Life" and "StepsSecond" are passed - in the params table for the message. - -2014/08/02 ----------- -* [MusicWheel] Added GetSelectedSection lua function. - -2014/07/26 ----------- -* [ActorScroller] Accidental "permanent loop" bug fixed. -* [Common metrics] AfterThemeChangeScreen, AfterGameChangeScreen, and - AfterGameAndThemeChangeScreen optional metrics added to Common section. -* [GameManager] SetGame lua function added. -* [Globals] OldStyleStringToDifficulty lua function added. -* [PrefsManager] SavePreferences lua function added. - ThreeKeyNavigation preference added. -* [SoundManager] IsTimingDelayed lua function added. -* [ThemeManager] SetTheme lua function added. -* [ScreenHowToPlay] CharacterName metric works again. - -2014/07/18 ----------- -* [BitmapText] LoadFont is now obsolete. Set the Font attribute of the - BitmapText instead. -* [ErrorReporting] New system that reports theme errors through dialogs and - an on screen display. (Sorry guys, your themes are all full of errors, and - you should fix them) -* [LogDisplay] New actor class used by ErrorReporting, possibly useful more - widely. See _fallback/Scripts/04 LogDisplay.lua for docs. - -2014/07/05 ----------- -* [Actor] GetDestX/Y/Z lua functions added. -* [Profile] Lua functions for calculating calories based on heart rate added. - See ThemerDocs/calories.txt - -2014/06/28 ----------- -* [ArrowEffects] New namespace of lua functions. -* [Screen] AddInputCallback and RemoveInputCallback lua functions added. - -2014/06/21 ----------- -* [Gameplay] CMods and MMods now automatically compensate for music rate. -* [Globals] SaveScreenshot lua function added. -* [ScreenPlayerOptions] ArbitrarySpeedMods system added. -* [ScreenSelectMusic] Pad codes that set modifiers disabled. - -2014/06/07 ----------- -* [ScreenSelectMusic] SelectMenuInput message is now always sent when Select - is pressed. - -2014/05/17 ----------- -* [GameState] StoreRankingName lua function added. Ranking names now allow - lowercase. -* [Profile] SetLastUsedHighScoreName and GetHighScoreListIfExists lua - functions added. - -2014/05/10 ----------- -* [Player] Tracks param added to JudgmentMessageCommand. (will change before - beta 4) -* [ScreenGameplay] Themable haste system added. - GetTrueBPS lua function added. -* [ThemeManager] GetMetricNamesInGroup and GetStringNamesInGroup lua functions - added. - -2014/05/03 ----------- -* [ActorFrame] GetChild and GetChildren modified, see Lua.xml. -* [NoteSkinManager] GetMetric function added. -* [PlayerOptions] Entirely new API for setting player options. Superior - alternative to ApplyGameCommand. -* [SongOptions] Entirely new API for setting song options. Same design as new - PlayerOptions API. -* [NoteField] NoteField Board can now use any AutoActor class instead of just - Sprite/Sprite-derived ones. - -2014/04/26 ----------- -* [Style] GetColumnInfo and GetColumnDrawOrder lua functions added. - -2014/04/19 ----------- -* [ActorMultiVertex] New actor class added. -* [ScreenGameplay] GetHasteRate lua function added. GiveUpSeconds metric added. -* [SoundManager] StopMusic lua function added. - -2014/04/05 ----------- -* [GameState] HaveProfileToLoad/Save and Load/SaveProfiles lua functions added. -* [ScreenWithMenuElements] StartTransitioningScreen lua function added. - -2014/03/22 ----------- -* [Player] HoldNoteScore_MissedHold added. - -2014/03/05 ----------- -* [ScreenNetSelectBase] Fix colors when unicode characters are in chat box. - -2014/03/08 ----------- -* [ActorScroller] DrawByZPosition fixed for looping ActorScrollers. -* [Globals?] GetTimeSinceStart global lua function added. -* [Player] FirstTrack parameter added to JudgmentMessageCommand. (will change - before beta 4) - -================================================================================ -StepMania 5.0 beta 3 | 20140224 --------------------------------------------------------------------------------- - -2014/02/22 ----------- -* [Actor] texturetranslate lua function added. -* [BitmapText] distort lua function added. -* [ComboGraph] Added BodyHeight metric. -* [GameState] JoinInput lua function added. -* [PlayerOptions] "resetspeed" mod added. -* [PlayerStageStats] GetComboList and GetLifeRecord lua functions added. -* [Preferences] ComboContinuesBetweenSongs preference added. -* [ScreenWithMenuElements] SetAllowLateJoin lua function added. -* [SoundManager] loop and applyRate args added to PlayMusicPart lua function. -* [Sprite] SetCustomPosCoords lua function added. -* [Utils] XML backwards compatibility added. - -2014/02/08 ----------- -* [Actor] Added heading, pitch, and roll lua functions. - -2013/10/09 ----------- -* [CombinedLifeMeterTug] Added names and commands to Separator and Frame items. - [SSC] -* [MeterDisplay] Added names to Stream and Tip items. [SSC] - -2013/10/06 ----------- -* [ScreenOptions] Allow for the use of per-screen Start sounds instead of a forced - Common Start. [SSC] - -2013/10/03 ----------- -* [GameConstantsAndTypes] Declared RankingCategory as a type. [SSC] -* [Profile] Added GetCategoryHighScoreList(StepsType,RankingCategory) Lua - binding. [SSC] - -2013/09/23 ----------- -* PIUIO: Fix default mapping for lights on five-panel setups. - -2013/09/06 ----------- -* Re-implement CustomSpeedMods to use new Lua hooks. Fixes assertion when - loading SpeedMods.txt from unmounted card. -* Add Lua hooks for themes to load/save custom data to/from profiles. -* [Linux] Ignore comments in /etc/fstab. - -2013/08/30 ----------- -* Fix editor behavior when deleting/shifting timing changes. -* Re-enabled "convert to stop/delay" at beat 0. - -2013/08/29 ----------- -* Fix hack pertaining to ModIcons and Lua-based option rows. - -2013/08/22 ----------- -* [FFmpeg] Fix several video timing issues (delay, stutter, looping) with the - FFmpeg driver. - -2013/08/14 ----------- -* [ThemePrefs] Fix saving of ThemePrefs in default theme. - -2013/08/12 ----------- -* [ScreenEdit] Fix Undo for the Alter and Turn commands. Previously, trying - to undo one of these commands would erase the notes instead. Now it behaves - as expected. - -2013/08/08 ----------- -* [SoundDriver_JACK] New sound driver (experimental!). To use this, specify - JACK in your SoundDrivers preference, and set SoundDevice to a - comma-separated list of ports to connect to, for example: - "SoundDevice=system:playback_1,system:playback_2". - -2013/07/18 ----------- -* [ScreenEdit] Display scroll segments in editor and preview for both Song and - Steps Timing. - -2013/07/09 ----------- -* [MemoryCardDriver] Allow Unix fstab to specify memory card devices by alias - (e.g. /dev/disk/by-path/*) - -2013/06/29 ----------- -* [ArchHooks_Unix] Support the GoToUrl function. [phantom10111] - -2013/06/18 ----------- -* [InputHandler_DirectInput] Add support for all possible input device types - under new DirectX library. [Shenjoku] -* Add --enable-lto option for configure on Linux. [phantom10111] - -================================================================================ -StepMania 5.0 beta 2a | 20130616 --------------------------------------------------------------------------------- - -2013/06/15 ----------- -* Fix some minor DLL issues on Windows. [wolfman2000] -* Theme updates to make it faster. [Midiman] - -2013/06/09 ----------- -* [ScreenJukebox] Check for existing steps when starting jukebox. -* [ScreenEdit] Fix crash related to keysounds. [wolfman2000] - -2013/06/04 ----------- -* Fix theme glitches caused by the change to Home/Free modes. -* [UnlockManager] Allow entries to be explicitly locked by the theme. - [wolfman2000] - -================================================================================ -StepMania 5.0 beta 2 | 20130602 --------------------------------------------------------------------------------- - -2013/06/02 ----------- -* Add several video container formats that are supported by FFmpeg: mkv, mp4, - mov, flv, f4v. - -2013/05/31 ----------- -* [ArchHooks_MacOSX] Add per-user folders in ~/Application Support. - -2013/05/30 ----------- -* [ScreenSelectMusic] Fix crash when sorting in Oni mode. - -2013/05/28 ----------- -* [ActorFrame] Propagate glow and diffuse to children of ActorFrames. This - should fix any visual problems with layered noteskins and mods. - -2013/05/25 ----------- -* Remove the "random" part of the Random Vanish mod to prevent crashing. - [wolfman2000] - -2013/05/21 ----------- -* [MovieTexture_FFMpeg] Fix crashing with large videos. - -2013/05/20 ----------- -* [NotesLoaderSM] New algorithm for converting negative BPMs and stops to - warps, more closely matching the behavior of old StepManias. - -2013/03/24 ----------- -* [MusicWheel] Add the ChangeSort method to the Lua interface to allow the - theme to switch sorting methods. - -2013/02/04 ----------- -* [Player] Add a "Column" parameter to the StepMessage to allow the theme or - chart to discover which column is being triggered. -* [ArchHooks] Unix: Move UserPackages to Packages in the per-user directory, - and remove Data from the per-user directory. Users who have installed - packages to UserPackages will need to migrate them to Packages instead. - -2013/02/03 ----------- -* [Player] Fix a stutter that can take place when mines are skipped during - warp segments. [phantom, wolfman2000] - -2013/01/23 ----------- -* [TimingData, ScreenEdit] Fixed behavior in the editor whereby making changes - to Song Timing would unexpectedly change all charts to Steps Timing. - (Thanks to DJ OMiY for reporting and isolating the problem.) - -2013/01/11 ----------- -* [Screen] Allow overlay screens to accept codes. - -2013/01/06 ----------- -* [TimingChanges, ScreenEdit] Fix a bug in the editor where adding BPM changes - that differ by a very small amount from the previous BPM change were not - added at all. [vulture/wolfman2000] - -2013/01/03 ----------- -* [ScreenGameplayShared] Fix routine mode. [djpohly/FSX/shakesoda/wolfman2000] - -================================================================================ -StepMania 5.0 beta 1a | 20121228 --------------------------------------------------------------------------------- - -2012/12/28 ----------- -* [default] Improved autogen icon and Oni life display. [Midiman] -* [ScreenSelectMusic] Fix mouse events being eaten. [shakesoda] -* [ScreenEdit] Remove extra zeroes from editor text entry. [djpohly] -* [WheelBase] Add WheelBase.Move Lua binding. [shakesoda] - -2012/12/27 ----------- -* [default] Various theme improvements. [Midiman] -* [PlayerStageStats] Restore SetScore and SetCurMaxScore Lua bindings. [shakesoda] - -2012/12/26 ----------- -* Code restructuring. [djpohly/wolfman2000] - -================================================================================ -StepMania 5.0 beta 1 | 20121225 --------------------------------------------------------------------------------- - -2012/12/25 ----------- -* [PlayerStageStats] Remove SetScore and SetCurMaxScore Lua bindings. [FSX] - -2012/12/24 ----------- -* [ScreenDebugOverlay] Don't reset the gamestate when reloading screens. Reloading - ScreenSelectMusic or any other screen which relies on that works now. [shakesoda] -* [RageUtil] Fix math.random() never returning > 0.5. [vyhd] - -2012/12/18 ----------- -* [default] Fix Final Stage not appearing on StageInformation if a Long or Marathon song is - played as the last song. [FSX] -* [fallback] Add Song:GetStageCost() [FSX] - -2012/12/17 ----------- -* [Font] Fix a unicode-related crash which would sometimes happen on SMO. [shakesoda] -* [GameState] Fix arrow stuttering for cases where you get duplicated values between - updates. This helped significantly for PulseAudio on Ubuntu 12.04, for me. [shakesoda] - -2012/12/13 ----------- -* [RageDisplay_GLES2] Carry over a bunch of functionality from RageDisplay_OGL, still not - usable however. [shakesoda] - -2012/11/26 ----------- -* [ScreenSelectMusic] Only unchoose steps if there are more than 10 seconds on the timer - to prevent unchoosing steps for an infinite timer. [Marcio Barrientos] - -2012/11/22 ----------- -* [ProfileManager] Added SaveProfile, SaveLocalProfile, GetLocalProfileIDs, - ProfileFromMemoryCardIsNew, GetSongNumTimesPlayed, LocalProfileIDToDir, and - GetLocalProfileDisplayNames Lua bindings. [Alfred Sorenson] -* [Profile] Add GetGUID Lua binding. [Alfred Sorenson] - -2012/11/13 ----------- -* [RageDisplay_OGL] Try to fix the shader compilation crash once and for all. [shakesoda] - -2012/10/31 ----------- -* [RageDisplay_GLES2] Initial GLES2 commit. Not functional. [shakesoda] - -2012/10/20 ----------- -* [NotesLoaderSMA] Fix default speed length for SMA files. [Aldo MX] -* [NotesLoaderSMA] First segment required a zero. [Aldo MX] - - -2012/10/17 ----------- -* [ScreenEdit] Don't allow ratings of 0. [shakesoda] - -2012/08/10 ----------- -* [InputHandler_Linux_PIUIO] Add interface to PIUIO kernel module. [djpohly] - -2012/08/04 ----------- -* General theme updates: made things faster, title menu updated. [Midiman] - -2012/07/26 ----------- -* [ScreenDebugOverlay] Added BackgroundColor metric. [AJ] - -2012/07/19 ----------- -* [OptionRow] Set text after running OnCommand so commands like "uppercase,true" - actually have a chance to work. [AJ] - -2012/07/17 ----------- -* [SongManager] Fix a bug where DVNO wouldn't always be gold. [AJ] - -================================================================================ -StepMania 5.0 alpha 3 | 20120711 --------------------------------------------------------------------------------- - -2012/07/11 ----------- -* [ScreenEditMenu] Don't use "Blank" in the description for blank steps; - use a blank string instead. [AJ] - -2012/07/10 ----------- -* [ScreenSelectMusic] Fix an issue where Control+ wouldn't work. [AJ] - -2012/07/09 ----------- -* [InputMapper] Use "|" for separating entries instead of ",", since some - companies have names like "x Ltd., something". [Mordae, AJ] - -2012/07/06 ----------- -* [ScoreDisplayRave] Add FrameBase and FrameOver to the metrics. [AJ] -* [PlayerStageStats] Added GetSongsPassed and GetSongsPlayed Lua bindings. [AJ] - -2012/07/05 ----------- -* [ScreenRanking] Added "NextPage" command. "SwitchPage" command is - now "SwitchedPage". [AJ] -* [ScreenRanking] Don't clobber alpha values when applying colors in SetPage. [AJ] - -2012/07/03 ----------- -* [ScreenHowToPlay] Actually shows notes again. [AJ] -* [ScreenGameplay] When ShowLifeMeterForDisabledPlayers is true, don't fill up - life in the meter for the disabled player. (LifeMeterBar only) [AJ] - -2012/07/02 ----------- -* [ScreenHowToPlay] Run InitCommand on Characters if enabled. [AJ] -* [RageUtil] Add detection of ".hg" to StripCvsAndSvn. [AJ] - -2012/06/27 ----------- -* [SongManager] Ending a group's name in PreferredSongs with "/*" will now load - all songs from that group automatically. [AJ] - -2012/06/21 ----------- -* [ProfileManager] Added GetPlayerName(pn) Lua binding. [AJ] - -2012/06/05 ----------- -* [GrooveRadar] Added SetFromValues(pn,{f1,f2,f3,f4,f5}) Lua binding. [AJ] - -2012/06/02 ----------- -* [PrefsManager] Added StretchBackgrounds preference. [AJ] -* [BMSLoader] Add #banner support. [hanubeki] - Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=bf8b57b9a662af59de66b9d06ca282f38f9126d9 - -2012/05/31 ----------- -* [PaneDisplay] Added NullCountString metric. [AJ] -* [PlayerOptions] Fixes to Get/Set[C, M, X]Mod Lua bindings. [hanubeki] - Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=97761b5dc87b8c8a1b296985a09814337578c745 - -2012/05/27 ----------- -* [MusicWheel] Added EmptyColor metric. [AJ] -* [PlayerState] Enabled GetPlayerController Lua binding. - -2012/05/21 ----------- -* [NotesLoaderBMS] Support for #BMP based background changes. [theDtTvB] -* [SongManager] Add song to the list of songs before loading it, this fixes - crashes in some BMS files. [theDtTvB] -* [ScreenEdit] Allow a new way of creating and modifying attacks using the - Area Menu. Note: Using the C or V keys is no longer allowed for attacks. - It will simplify things for later. [Wolfman2000] -* [Steps] Modified HasSignificantTimingChanges; the following now disqualify - when using a CMod: Stops, Delays, Warps, Speed Changes, Scroll Changes. - Songs with a non-constant BPM will only disqualify if the High/Low difference - is greater than 3.00. [AJ] - -2012/05/19 ----------- -* [Actor] Made the xy command a source-code level command. [AJ] - -2012/05/17 ----------- -* [LoadingWindow_Gtk] Actually resolve the path to the Splash file. [djpohly] - -2012/05/16 ----------- -* [ScreenWithMenuElements] Added DelayMusicSeconds metric. [AJ] -* [ScreenOptionsMasterPrefs] Allow for FastLoadAdditionalSongs preference - to be called via the "conf" command. [AJ] - -2012/05/14 ----------- -* [Course] Added AllSongsAreFixed() Lua binding. [AJ] - -================================================================================ -StepMania 5.0 alpha 2 | 20120504 --------------------------------------------------------------------------------- - -2012/05/03 ----------- -* Add Var "Player" and Var "Controller" for NoteSkin. [hanubeki] - Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=824cff29912d1c29a667046ba463d195e81c524a -* [CustomSpeedMods] If a player decides to remove 1x from the machine profile's - custom speed mods, re-add it back in to avoid crashes. [AJ] - -2012/05/02 ----------- -* Make ReceptorArrowRow and GhostArrowRow respect the column draw order. [hanubeki] - Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=8ccf7449651eef51e8c42d031aa64da49a0b72ce - -2012/04/25 ----------- -* [Profile] Added GetLastPlayedSong and GetLastPlayedCourse Lua bindings. [AJ] - -2012/04/22 ----------- -* [LifeMeterBar] Reverted a change from 2010 that messed with how the life meter - subtracts life. The life difficulty should match StepMania 3.9 again. [AJ] - -2012/04/08 ----------- -* [ScreenNetworkOptions] Fixed a bug where localized text would not show up - properly. Fixes issue 759. [AJ] -* [Steps, Song] Replace Steps:UsesSplitTiming with - Song:IsStepsUsingDifferentTiming for both C++ and Lua. [wolfman2000] - -2012/04/06 ----------- -* Modify Jousway's planned noteskin to allow it to work with Technomotion - style gameplay. Expect minor bugs. [Jousway, Wolfman2000] - -2012/04/03 ----------- -* [PlayerOptions] Fix setting some effect mods that were always set to Drunk. - I wonder who had too much to drink. [TaroNuke] - -2012/03/31 ----------- -* [GameManager] Allow beat single7 and versus7 to be shown in Demonstration. [AJ] - -2012/03/28 ----------- -* [ScoreKeeperRave] Actually handle hold scores in HandleHoldScore(). - Players should please provide feedback on how this affects gameplay, as this - is a temporary feature. [AJ] -* [GameConstantsAndTypes] Made StageResult Lua-aware. [AJ] -* [GameState] Added GetStageResult(pn) Lua binding. [AJ] -* [Player] Keysounds now respect the volume settings. [hanubeki] - Sourced from hanubeki-modified-sm-ssc rev. 16fc5b714582 - -2012/03/27 ----------- -* [ScreenEditMenu] Don't hardcode stopping the music on pressing the back button. - This interferes with the StopMusicOnBack metric. [AJ] - -2012/03/20 ----------- -* [Background] Fix 3D noteskins and dancing characters from clashing with each other. [shakesoda, AJ] -* [NoteField] Fix 3D noteskins overlapping. [shakesoda, AJ] -* [ScreenEdit] Don't use Step timing by default. [Midiman] -* [ScreenEdit] Allow playback of course modifiers in Course Edit mode [Midiman] - -2012/03/15 ----------- -* [04 Scoring.lua] Added various 3.9 and 3.9+ scoring methods. [hanubeki] - -2012/03/12 ----------- -* Remove libtheora support since ffmpeg already supports theora videos. [cvpcs] - -2012/03/10 ----------- -* Update ffmpeg support to v0.10. [cvpcs] - -2012/03/09 ----------- -* [PlayerOptions] Don't display x-mods when using m-mods. - Sourced from hanubeki-modified-sm-ssc rev. bd08a58dd7cf and OpenITG. - -2012/03/08 ----------- -* [MusicWheel] Added RouletteStopped message, which is broadcast when Roulette - is finished and the wheel is locked. [AJ] -* [WheelBase] Made WheelState a Lua-enabled enum and added - GetWheelState() Lua binding. Deprecated IsLocked() Lua binding. [AJ] - -2012/03/07 ----------- -* [ScreenSelectMaster] Now updates choices on player join; it will move the - scroller to the correct location, but the GainFocus/LoseFocus commands don't - seem to work. [AJ] - -2012/03/05 ----------- -* [GameCommand] Added GetDifficulty(), GetCourseDifficulty(), GetPlayMode(), - GetSortOrder(), GetAnnouncer(), GetPreferredModifiers(), and - GetStageModifiers() Lua bindings. [AJ] - -2012/03/04 ----------- -* [Player] Changed default Hold window to 0.250f, like it was in 3.9. [AJ] - -2012/03/02 ----------- -* [NotesLoaderBMS] Fix calculating stops, Support for #LNOBJ, Don't use #BACKBMP - as song background if main StepsType is beat-*. [hanubeki] - These changes constitute revisions f26caccf103e, 2d114b38c6c9, and b60f021d2b67 - of hanubeki-modified-sm-ssc. (http://code.google.com/r/hanubeki-modified-sm-ssc/) - -2012/03/01 ----------- -* [MemoryCardManager] Disable Memory Cards by default. If you want to use them, -set MemoryCards=1 in Save/Preferences.ini (or Save/Static.ini). [AJ] -* [GameState] Set Premium to Premium_DoubleFor1Credit by default. [AJ] -* [ScreenSelectMusic] Added PlaySoundOnEnteringOptionsMenu metric. [AJ] -* [MusicWheel, WheelBase] Added collapse sound. [AJ] - -================================================================================ -StepMania 5.0 alpha 1a | 20120219 --------------------------------------------------------------------------------- - -2012/02/19 ----------- -* [Style] Added LockedDifficulty() Lua binding. [AJ] - -2012/02/15 ----------- -* [HighScore] Added Max Combo, Stage Award and Peak Award. New Lua bindings for - HighScore: GetMaxCombo(), GetStageAward(), GetPeakComboAward(). [AJ] - (the specifics of this are subject to change.) - -2012/02/10 ----------- -* [WheelBase, WheelItemBase] Turned WheelItemDataType into a Lua type, - made WheelBase:GetSelectedType() return the enum instead of a number. [AJ] - -2012/02/08 ----------- -* [ScreenEdit] Added support for editing keysounds. Use the Area Menu (Enter) - to either modify what sounds play on that row, or even remove a sound from - the list. Any sounds assigned to empty notes will automatically become - an AutoKeysound, and any AutoKeysounds that have their sound removed will - become empty notes. [Wolfman2000] - -2012/02/08 ----------- -* [ScreenOptionsMaster] Added StepsRowLayoutType metric. - (Valid values are "ShowAllInRow" or "ShowOneInRow".) [AJ] - -2012/01/23 ----------- -* [Player] Tap Note Scores (tns) can now be "AvoidMine" or "HitMine" in -JudgmentMessageCommand. [Saturn2888, shakesoda] - -2012/01/15 ----------- -* [WheelNotifyIcon] Add the NumIconsToShow metric. [Wolfman2000] -* [PlayerOptions] Fix a problem with m-mods where you would get m200 as - the default speed modifier. [AJ] - -2012/01/11 ----------- -* [ScreenEdit] Fix a floating point issue when dealing with speed segments. - [Wolfman2000] - -2012/01/09 ----------- -* [Song] Fix a bug introduced with "Only read certain tags during first load" - where song graphic files wouldn't load. [theDtTvB] - -================================================================================ -StepMania 5.0 alpha 1 | 20120108 --------------------------------------------------------------------------------- - -2012/01/08 ----------- -* [Song] Add HasPreviewVid and GetPreviewVidPath lua binding [cerbo] - -2012/01/08 ----------- -* [ScreenManager] Made AddScreenToTop take a second (optional) parameter for - posting a ScreenMessage on screen pop. [AJ] -* Only read certain tags during first load; makes song loading faster. [theDtTvB] - -2012/01/07 ----------- -* Fix Portable.ini not working on Mac OS X. [shakesoda] - -2012/01/05 ----------- -* [PercentageDisplay] Remove unused ApplyScoreDisplayOptions metric; - added PercentFormat and RemainderFormat metrics. [AJ] -* Fix Portable.ini not working in Linux. [FSX] - -2012/01/04 ----------- -* Fix a scoring/grading bug with Lifts. [FSX] - -2011/12/27 ----------- -* [MusicWheel] Add IsRouletting Lua binding. [AJ] -* [LuaManager] Remove GetOSName Lua binding; use GetArchName instead. [AJ] - -2011/12/26 ----------- -* [ArchHooks_OSX] Worked around a crash when language detection goes wrong. - Note: a real fix should be looked into. [shakesoda] - -2011/12/23 ----------- -* [Song] Fixed a bug where a sample start of 0 wouldn't work. [AJ] -* [Game] Added CountNotesSeparately and GetMapJudgmentTo(TapNoteScore) - Lua bindings. [AJ] -* [StepMania.cpp] Fix initial aspect ratio on first boot, hopefully. - (See issues 6 and 27) [AJ] - -2011/12/22 ----------- -* [LuaManager] Added ProductFamily() Lua binding. [AJ] - -2011/12/17 ----------- -* [Various] Allow loading of *.jpeg in addition to *.jpg. [AJ] - -2011/12/16 ----------- -* [StreamDisplay] Added VelocityMultiplier, VelocityMin, VelocityMax, - SpringMultiplier and ViscosityMultiplier metrics. [AJ] - -2011/12/12 ----------- -* [ScreenEdit] Add the GAMESTATE:InStepEditor Lua binding. [Wolfman2000] -* [Player, ScreenGameplay] Allow failing on Oni without crashing. This one - took awhile. [Wolfman2000] -* [LifeMeterBattery] Fixed various issues (lives not fully disappearing on fail, - P2 lose life animation having the wrong x zoom, hide the lives number if it - falls below 0). [AJ] - -2011/12/11 ----------- -* [ScreenEdit] Restore cycling the timing segments for jumping between. - The required line somehow never got replaced. [Wolfman2000] - -2011/11/30 ----------- -* [PlayerOptions] Added IsEasierForSongAndSteps(Song,Steps,PlayerNumber) and - IsEasierForCourseAndTrail(Course, Trail) Lua bindings. [AJ] -* [PlayerState] Added GetSuperMeterLevel() Lua binding. [AJ] - -2011/11/28 ----------- -* [ScreenGameplay] Add the SurvivalModOverride metric. Let the themer decide - if mods should be overridden on survival or not. Funny enough, this used - to be true for the old Oni style mode, but...well, we'll cross that bridge - later. [Wolfman2000] -* [LifeMeterBattery] Added MaxLives metric, which limits the maximum amount of - lives. Setting this to 0 will remove the limit. [AJ] - -2011/11/27 ----------- -* [PlayerOptions] Pretty large changes here, namely a bunch of new bindings. - Fixed the logic for GetReversePercentForColumn; It will now return nil for - invalid columns. Also fixed the logic for UsingReverse (now checks for 1.0f) - and SetPassmark (no longer allows values < 0.00f and > 1.0f). [AJ] -* [ScreenEdit] Allow inserting and removing beats and timing changes in - specific note increments instead of just quarter notes (a whole beat). - Those that prefer to keep using the shortcut keys will note that the - behavior has not changed for that: only by going into the Area menu can you - deal with more specific changes. [Wolfman2000] - -2011/11/26 ----------- -* [ScreenEdit] Restore using F9 and F10 to adjust stops by a fixed amount. - Sorry for the delay in this. [Wolfman2000] -* [ScreenEdit] Minor convenience. If you attempt to create a negative stop - segment from scratch, it does not create, and you are not requested to - save on exit, for there is nothing to save. [Wolfman2000] -* [ScreenEdit] Allow Shift + F9/F10 for adjusting delays. This works the same - way as adjusting stops. [Wolfman2000] - -2011/11/25 ----------- -* [PlayerStageStats] Hitting a mine no longer gives you full combo when - [Gameplay] MineHitIncrementsMissCombo=true. [AJ] - -2011/11/24 ----------- -* [PlayerStageStats] Added GetFailed and GetNumControllerSteps Lua bindings. [AJ] - -2011/11/15 ----------- -* [LifeMeterBar] Added the ForceLifeDifficultyOnExtraStage metric and - the ExtraStageLifeDifficulty metric. Let the themer decide if extra stages - should have their own life bar behavior. Note that this metric does NOT - change the lifebar to the battery style. [Wolfman2000/FSX] - -2011/11/14 ----------- -* [Mac OS X] Restore JPEG functionality. [Wolfman2000] - -2011/11/06 ----------- -* [GameState] Add the RefreshNoteSkinData lua binding. This will only - refresh the NS data for the present game, not all games. [Wolfman2000] -* [ScreenSelectMusic] Fixed Rave difficulties not being synced on late join. - Fixes issue 577. [AJ] -* [GameplayAssist] Don't play sounds if the player is dead. Fixes issue 621. [AJ] - -2011/11/04 ----------- -* [ScoreKeeperRave] Revert fix from 2011/10/28. [AJ] -* [ScoreKeeperRave] Fixed Miss and HitMine giving meter life. - (Fixes issue 622.) [AJ] - -2011/11/02 ----------- -* [ArchHooks] Add the GetArchName lua binding. To the themers that use - GetOSName, that function may be deprecated in the future. For now, - both options exist. [vyhd, Wolfman2000] - -2011/11/01 ----------- -* [ArrowEffects] Fix Expand, and possibly other mods, from breaking if - using a second player. [Wolfman2000] -* [ArchHooks] Add the AppHasFocus lua binding. [vyhd, Wolfman2000] - -2011/10/29 ----------- -* [GameState] Add the ResetPlayerOptions lua binding. [Wolfman2000] - -2011/10/28 ----------- -* [ScoreKeeperRave] Fix an issue where the super meter would not decrease back - to 1 after hitting the end of 3. (Fixes issue 314.) [AJ] - -2011/10/27 ----------- -* [Default theme] Fixed the pref controlling timing segments on song meter. [FSX] - -2011/10/18 ----------- -* [LightsManager] Use song beat for menu button lights, allow demonstration to - flash pad lights when BlinkGameplayButtonLightsOnNote is true, light custom - game buttons when pressed during attract mode, general optimizations. [vyhd] - -2011/10/17 ----------- -* [ScreenEdit/NoteField] Fix an editor crash when you exit without saving - after creating new steps. [Wolfman2000] - -2011/10/16 ----------- -* [NoteDataUtil] Add the Backwards mod for games where the intended - definition of Mirror is different. Regarding Pump gameplay, what was - called Mirror in Preview 4 is considered Backwards now, and the original - Mirror is back in its old position. [Wolfman2000] - -2011/10/12 ----------- -* [Steps] Fix a bug where e.g. ".SM" ".DWI" ".Sm" ".sM" files - wouldn't properly load since the code was expecting lowercase. [AJ] - -2011/10/10 ----------- -* [NotesLoaderBMS] Add the time signature segments. [theDtTvB] - -2011/10/09 ----------- -* [NotesLoaderBMS] Fix the bug where keysounds that points to nonexistant file - gets assigned a random one. [theDtTvB] -* [NotesLoaderBMS] Use BMSLoader to load PMS files. [theDtTvB] -* [RageSoundReader_WAV] Fix ADPCM support. [theDtTvB] - -2011/10/08 ----------- -* [GameSoundManager] Add the PlayMusicPart lua binding. [Wolfman2000] -* [ScreenEdit] Add the FadeInPreview and FadeOutPreview metrics. This controls - how long the fade in and fade outs are for playing the preview music. - The default values are 0 and 1.5 respectively. [Wolfman2000] - -2011/10/07 ----------- -* [RageDisplay] Add the GetFPS, GetVPF, and GetCumFPS bindings. [Wolfman2000] - -2011/10/06 ----------- -* Various scoring fixes sourced from http://www47.atwiki.jp/waiei/pages/21.html - [A.C/@waiei, 桜為å°é³©/@sakuraponila] - -================================================================================ -StepMania 5.0 Preview 4 | 20111005 --------------------------------------------------------------------------------- - -2011/10/04 ----------- -* [NoteDataUtil] More accurate Left, Right, and Mirror mods for Pump gameplay. - Major thanks to Hudson Felker and Bill Shillito here. [Wolfman2000] - -2011/10/01 ----------- -* [ScreenHighScores] Disable forced screen transition behavior when - ManualScrolling=true. [AJ] - -2011/09/30 ----------- -* [GameState] Added CurrentOptionsDisqualifyPlayer(player), - ApplyPreferredModifiers(player,string) and ApplyStageModifiers(player,string) - Lua bindings. [AJ] - -2011/09/29 ----------- -* [Fallback theme] Fix ImmediateHoldLetGo function. [Wolfman2000] -* [GameState] Add the EditAllowedForExtra metric. Use this if you want edit - steps to be allowed for accessing the extra stage. By default, this is - false. [Wolfman2000] - -2011/09/26 ----------- -* [Default theme] Added Song Timing Display user preference. [AJ] -* [ThemeManager] Add global Scripts dir. [shakesoda] - -2011/09/25 ----------- -* [WheelItemBase] Added GetColor and GetText Lua bindings. [AJ] - -2011/09/24 ----------- -* [ScreenEdit] Disable shifting timing changes down one beat if starting on - beat 0. Important information must stay on that beat. [Wolfman2000] -* [ScreenEdit] Disable converting rows to a stop or beat starting on beat 0. - There should be no reason for this at this time. [Wolfman2000] -* [MusicWheelItem] Add/reinstate MusicWheelItem Mode Normal/Color/OverPart. [AJ] -* [FadingBanner] Added LoadFromSortOrder(SortOrder) Lua binding. [AJ] - -2011/09/23 ----------- -* [ScreenEvaluation] Added RollingNumbersMaxComboClass metric. [AJ] -* [NotesLoaderSM] Fix loading .sm files with non standard difficulty names. - It should be Hard, not Heavy. [Wolfman2000] - -2011/09/22 ----------- -* [ScreenDebugOverlay] Replaced hardcoded toggle command with - ButtonTextToggledCommand metric. [AJ] -* [LoadingWindow_Win32] Make the StepMania window gain focus after the - loading window closes. Fixes issue 424. [AJ] - -2011/09/21 ----------- -* [FadingBanner] Added LoadRandom(), LoadRoulette(), LoadFallback(), - LoadCourseFallback(), and GetBanner(int) Lua bindings. [AJ] - -2011/09/18 ----------- -* [Song] Added GetSampleStart() and GetSampleLength() Lua bindings. [Wolfman2000] - -2011/09/16 ----------- -* [UnlockManager] Added GetNumLockedSongs() Lua binding. [Wolfman2000] -* [UnlockManager] Added IsSongLocked() Lua binding. [Wolfman2000] - -2011/09/12 ----------- -* [NotesLoaderSSC/WriterSSC] Allow all timing tags regardless of what timing - is used. [Wolfman2000] - -2011/09/11 ----------- -* [ScreenEvaluation] Added "evaluation full combo W1" and - "evaluation full combo W2" announcer cues. [AJ] -* [Banner] Added "Banner group fallback" graphic. [AJ] - -2011/09/09 ----------- -* [NotesLoaderBMS] Rewrite the BMS loader, should fix issues 430 and 500. [theDtTvB] - -2011/09/08 ----------- -* [GameManager] Fix shifting of 2P notes in beat mode. [1a2a3a2a1a] - -2011/09/07 ----------- -* [Model] Added GetDefaultAnimation() Lua binding. [AJ] -* [GameState] Added GetEarnedExtraStage() Lua binding. [AJ] - -2011/09/02 ----------- -* [MenuTimer] Added start(), disable() Lua bindings. Also renamed setseconds to - SetSeconds to match GetSeconds. [AJ] -* [GameManager] beat "versus" -> "versus5"; fix beat versus7 being "single7". [1a2a3a2a1a] - -2011/08/27 ----------- -* Updated libjpeg to 8c. -* [SongManager] Added GetCoursesInGroup(sCourseGroup,bIncludeAutogen), - GetSongGroupBannerPath(songGroup), GetCourseGroupBannerPath(courseGroup), - DoesSongGroupExist(songGroup), DoesCourseGroupExist(courseGroup) and - GetPopularSongs() Lua bindings. [AJ] -* [SongManager] Added GetPreferredSortSongs(), GetPreferredSortCourses(courseType,bIncludeAutogen), - and GetPopularCourses(courseType) Lua bindings. [AJ] -* [SongManager] Add SongToPreferredSortSectionName(song), WasLoadedFromAdditionalSongs(song), - and WasLoadedFromAdditionalCourses(course) Lua bindings. [AJ] -* [CryptManager] Add GenerateRandomUUID() Lua binding. [AJ] -* [ThemeManager] Added DoesThemeExist(sTheme), IsThemeSelectable(sTheme), - DoesLanguageExist(sLang), GetCurThemeName(), HasMetric(sGroup,sValue), and - HasString(sGroup,sValue) Lua bindings. [AJ] - -2011/08/23 ----------- -* [Makefile.am] Fixed version date and time handling. [AJ] - -2011/08/22 ----------- -* [PrefsManager, X11Helper] Added ShowMouseCursor preference. [AJ] -* [UnlockManager] Added GetStepOfAllTypes Lua binding. This gets the locked - Steps for all game types based on the difficulty specified. [Wolfman2000] -* [UnlockManager] Added requirepasschallengesteps Lua binding. This is more - self-explanitory: pass challenge to be able to play edits. [Wolfman2000] - -2011/08/21 ----------- -* [NotesLoaderSSC] Fix loading pre-split timing files that had blank timing - tags inside of them. Thanks to Vin.il for the catch. [Wolfman2000] -* [Song] Added Jacket, CD image (a la early DDR), and Disc (PIU-style) support. - Added GetJacketPath(), GetCDImagePath(), GetDiscPath(), HasJacket(), HasDisc(), - and HasCDImage() Lua bindings. [AJ] - -================================================================================ -StepMania 5.0 Preview 3 | 20110820 --------------------------------------------------------------------------------- - -2011/08/20 ----------- -* [PlayerOptions] Add GetMMod() Lua binding. [AJ] -* [Player] Make keysounds respect volume preference. Fixes issue 344. [AJ] - -2011/08/19 ----------- -* [Steps] Add PredictMeter() and GetDisplayBPMType() Lua bindings. [AJ] -* [Song] Add ShowInDemonstrationAndRanking() Lua binding. [AJ] -* Turn off Autogen by default. [shakesoda] -* Disable automatic aspect ratio guessing, default to 854x480 - (16:9 because most newer displays are wide). [shakesoda] -* Turn on FastLoad and FastLoadAdditionalSongs by default. [shakesoda] - -2011/08/18 ----------- -* [RageInput] Added "No input devices were loaded." string to languages. [AJ] -* [RageInputDevice] Added localized names for InputDeviceState. [AJ] -* [Course] Add IsPlayableIn(StepsType) and IsRanking() Lua bindings. [AJ] -* [Trail] Added GetTotalMeter(), GetLengthSeconds(), IsSecret() - and ContainsSong(song) Lua bindings. [AJ] - -2011/08/16 ----------- -* Added PrettyPercent(numerator,denominator) Lua binding. [AJ] - -2011/08/14 ----------- -* [Foreground] Restore Foreground Changes for use in gameplay. Note that it - is recommended to use lua for #FGCHANGES from now on: not all XML changes - will work. [infamouspat] - -2011/08/13 ----------- -* [Theme-side] Added Fancy UI Background preference to Theme Options. [AJ] -* [LowLevelWindow_X11] Don't force the window into the upper left corner. [ZipFile] - -2011/08/07 ----------- -* [LifeMeterBattery] Added LostLife param to LifeChanged message. [AJ] -* [LifeMeterBattery] Converted LifeMeterBattery lives to an AutoActor. [AJ] -* [TimingData] Add HasDelays() Lua binding; HasStops() now only checks stops. [AJ] -* [GameState, SongUtil] Fix Issue 263 by not charging 2x stages for doubles when - not using joint premium. [AJ] -* [BeginnerHelper] Made BeginnerHelper run the OnCommand. [AJ] -* [GameState] add GetExpandedSectionName() Lua binding. [AJ] -* [ScreenSelectMusic] Added IdleCommentSeconds metric and - "ScreenSelectMusic IdleComment" announcer sound. [AJ] -* [NotesLoaderBMS] "Send the actual song file to LoadFromBMSFile in - BMSLoader::LoadNoteDataFromSimfile instead of the dummy one... - This fixes the wrong sound issue [423]..." [theDtTvB] - -2011/08/06 ----------- -* [NoteSkins/beat/default] Fix Issue 425. [AJ] -* [ScoreDisplayRave] Allow (Meter/Level)(X/Y) metrics to work again. [AJ] - -2011/08/05 ----------- -* [NoteField] Added AreaHighlightColor metric. [AJ] - -2011/08/04 ----------- -* [NoteTypes, ScreenEdit] Removed artificial MAX_NOTES_PER_MEASURE limit. [AJ] - -2011/08/02 ----------- -* [NotesSSC] Only write timing/attack tags for the step if there is a - difference from the song. For timing tags, at this time it means that if even - one tag is different, all tags are written. [Wolfman2000] - -2011/08/01 ----------- -* [MusicWheel, RoomWheel] Moved the "- EMPTY -" string to the languages file. [AJ] - -2011/07/31 ----------- -* [ScreenGameplay, LyricDisplay] Stop lyrics from animating on failure. - Fixes issue 298. [AJ] - -2011/07/30 ----------- -* [ProfileManager] Fix an issue when deleting recently created profiles. [AJ] -* Start removing anything related to Guitar mode. This was rushed in, and it - is not worth us keeping at this time. [Wolfman2000] - -2011/07/26 ----------- -* [ScreenEdit] Add a semi working implementation of the often requested - copy/paste selected timing data feature. This should make it easier for - some charters. [Wolfman2000] - -2011/07/21 ----------- -* [BeginnerHelper] Removed DancePadAngle metric in favor of DancePadOnCommand. - The same goes for PlayerAngle, dancer rotation is now handled in - PlayerP1/2OnCommand. [AJ] -* [Course] Bumped up max edit course title length to 16 (still feels too short). - Also added #DESCRIPTION tag and Course:GetDescription() Lua binding. [AJ] - -2011/07/20 ----------- -* [Win32/CrashHandlerChild] Crashlog and log now open in the player's default - text editor. Also, the Show Log button works again, including for people using - Portable.ini. [AJ] - -2011/07/19 ----------- -* [LoadingWindow] Added the ability for themes to have custom splash banners. - (Currently Windows-only.) [AJ] - -2011/07/17 ----------- -* [Cache] No longer store #NOTES in the cache. This should speed things up - on the first load if there is not much to write. (General note: this was - taken from another branch, but results at that point were great.) - [Wolfman2000] - -2011/07/13 ----------- -* [Difficulty] Allow ALL StepsTypes to use CustomDifficulty properly. - There was some unfair targeting of Couple and Routine. [Wolfman2000] -* [Steps] Calculate accurate radar values for Couple charts. [Wolfman2000] -* [ScreenEdit] Display more accurate chart data for Couple and Routine charts - for the future. No more having (almost) every row as a jump! [Wolfman2000] - -2011/07/12 ----------- -* [OptionRowHandler] Add a new metric to ScreenOptionsMaster: - StepsUseChartName. Use this if you want your charts to have a unique name - in the options menu. If there is no #CHARTNAME or it is "Blank", it reverts - to the original behavior. This metric is false by default. [Wolfman2000] -* [ScreenEdit] Fixed a bug involving #ATTACKS. Now when you set an attack, - the mods are reverted back to how they were prior to the attack being set. - [Wolfman2000] - -2011/07/09 ----------- -* [NotesTheUsual] Update the #COMBOS tag to allow for a Miss Combo attribute. - Any files that only use the Combo attribute will have that value copied to - miss combo on next launch. [Wolfman2000] -* [ScoreKeeperNormal] Better match #COMBOS with eval. Scoring formulas should - not be affected, but it may require more testing. [Wolfman2000] -* [Metrics] Have Pump mode lump the checkpoint judgments with Flawless and - Miss judgments on eval. Of course, this goes down to Perfect and Miss if - that is disabled. [Wolfman2000] - -2011/07/07 ----------- -* [ScreenEdit] Fix the NoMines transformation bug, issue 363. [Wolfman2000] -* [CourseLoaderCRS] Don't load BEST# and WORST# where # is greater than the - number of songs installed. Fixes issue 373. [AJ] -* [NotesAllSSC] Add the #CHARTNAME tag to the Steps. #DESCRIPTION is now for - more detailed descriptions, or perhaps some short hand lingo. All files - that used #DESCRIPTION will have their values moved to #CHARTNAME on - load. [Wolfman2000] -* [ScreenEdit] Add a Steps Data menu for getting numerical step data on the - chart. This is a read only menu. Edit Steps Information contains writable - information. [Wolfman2000] -* [NotesAllSSC] Add the Steps version of #DISPLAYBPM. The Song version is - still there, so themes should not have to worry about breakage. - [Wolfman2000] - -2011/07/06 ----------- -* [ScreenEdit] Fix the bug where hitting Enter during playing wouldn't take - the user back to the editor. [Wolfman2000] -* [Gameplay] Fix Fail mods being dishonored. [Midiman] - -2011/07/05 ----------- -* [ScreenEdit] Restore dance-couple and pump-couple for editing purposes. - Saving should still work, but this was never tested yet. [Wolfman2000] -* [ScreenOptions] Mini is now ITG Mini, and Tiny is now Pump Pro Mini. - This will prevent many prior courses from breaking. [sharksoda, Wolfman2000] -* [CharacterManager] Add a lua function to check how many characters you have. - For an example of how this is used, check the default theme's scripts - folder, specifically 03 ThemePrefs.lua. [Wolfman2000] - -2011/07/04 ----------- -* [ScreenEdit] Add a function to switch the notes the routine players have to - hit. In simple terms, Player 1's notes are now Player 2's and vice~versa. - Check it out in the Alter Menu. [Wolfman2000] -* [ScreenEdit] Add two routine mirroring functions. Now you can build sections - of a chart for one player, and mirror the effect for the other player when - finished. For Pump players, it is not a straight mirror, but is more akin - to what is found via normal routine charts. In other words, you'll be happy. - Check it out in the Alter Menu. [Wolfman2000] - -2011/07/03 ----------- -* [ScreenEdit] Fix a crash if one tries to remove an attack that doesn't - exist at that time. [Wolfman2000] - -================================================================================ -StepMania 5.0 Preview 2 | 20110703 --------------------------------------------------------------------------------- - -2011/07/03 ----------- -* [Player] Bring mMods from OpenITG over. Also, a metric was added, - "MModHighCap", to cap the speed mod if required for playing songs like - Tsuhsuixamush. Set the metric to 0 or less to remove the cap. [AJ, sharksoda, - Wolfman2000] - -2011/07/02 ----------- -* [ScreenEdit] Fixed a crash when hitting Enter in the F1 help menu. [AJ] - -2011/06/30 ----------- -* [NotesAll] Use #FIRSTSECOND, #LASTSECOND, and #LASTSECONDHINT instead of the - former BEAT equivalents. Split Timing has made this a necessity thanks to - certain files that abuse Stops/Delays more than usual. [Wolfman2000] -* [ScreenEdit] Add a function in the Area Menu to designate the current beat - as the last second of the song. Please try to be smart and not use this too - early. [Wolfman2000] - -2011/06/28 ----------- -* [ScreenEdit] Add a function to copy/paste the TimingData of a player's - choice. Remember to be in the appropriate mode when copying and pasting. - By default, the song timing is already located in the clipboard, ready for - use. [Wolfman2000] - -2011/06/27 ----------- -* [Steps] Make sure #ATTACKS are copied when requested. [Wolfman2000] -* [ScreenEdit] Have Step Author up front instead of Chart Style. This is - probably going to be better overall. [Wolfman2000] -* [TimingData] Preserve the length of time for Speed Segment scaling when using - beats. [Wolfman2000] -* [NotesLoader/WriterSSC] #OFFSET is to be before #ATTACKS. This is required if - we pursue beat based attacks and not just second based. [Wolfman2000] - -2011/06/26 ----------- -* [UnlockManager] New metric: AutoLockEditSteps. Use this to hide bonus charts - until the Expert steps are beaten. No guarantee that this works with no - challenge steps in the song. This defaults to false. [Wolfman2000] -* [UnlockManager] New metric: SongsNotAdditional. Set to true to keep the - default behavior, false to have the AdditionalSongs folder contain - unlockable material. This is set to true to start. [Wolfman2000] -* [ScreenEdit] Allow jumping between all segments, not just Label segments. - You still use Ctrl + ,/. to jump, but now you use Ctrl + N/M to cycle the - segments. By default, it starts with Label. [Wolfman2000] -* [PlayerOptions] No longer display StepAttacks in the player's list. - Instead, show NoAttacks if attacks are disabled. [Wolfman2000] - -2011/06/24 ----------- -* [Actor] Implement compound(length,tweens) in _fallback/02 Actor.lua. [AJ] -* [UnlockManager] Add a new unlock reward: StepsType. This is similar to - unlocking Steps, but it is targeted for one step in one stepstype rather - than one step in all stepstypes. This needs testing. [Wolfman2000] -* [ScreenEdit] Add the option to convert delays to beats. Just find a better - song to use this on besides Uprock. [Wolfman2000] -* [ScreenEdit] Fix a crash if you don't save any steps on a new song. - [Wolfman2000] -* [NotesLoader/WriterSSC] Add support for Step #ATTACKS. Furthermore, Song - Attacks (or rather, Step Attacks as it should be called now) are turned on - by default instead of off. [Wolfman2000] - -2011/06/19 ----------- -* [EditMenu] Allow all songs to work in Practice Mode, regardless of folder - location. This fixes a crash if everyone had songs in AdditionalSongs. - [Wolfman2000] - -2011/06/17 ----------- -* [LifeMeterBattery] Fixed a bug where MinesSubtractLives was not being honored. - Also added LifeChanged message to changing of life on holds. [AJ] - -2011/06/15 ----------- -* [TimingData] Added many lua bindings for the other timing segments. GetWarps, - GetCombos, GetTimeSignatures, GetTickcounts, GetFakes, GetScrolls, GetSpeeds. - This should cover all of them now. [Wolfman2000] - -2011/06/13 ----------- -* [InputHandler_DirectInput] Fixed MouseWheel input not resetting. [AJ] -* [ScreenTextEntry] Make it so only the keyboard's Enter key can finish the - screen. Should fix issues with buttons whose secondary function is MenuStart. [AJ] -* [InputMapper] Modify default mappings. Use the Hyphen key instead of the - Numlock key for Player 2's GAME_BUTTON_BACK. This should address some - issues with Player 2 being unable to back out if they use a laptop. - [Wolfman2000] -* [NoteDisplay] Add two new metrics. - * DrawRollHeadForTapsOnSameRow: bool, similar to DrawHoldHeadForTapsOnSameRow - * TapHoldRollOnRowMeansHold: bool, true means hold and false means roll - * No noteskins should require updating, as these were placed in common/common - for ease of use. [Wolfman2000] -* [LifeMeterBattery] Added ChangeLives(int) Lua binding. [AJ] -* [LifeMeterBattery] Added DangerThreshold metric. [AJ] -* [LifeMeterBattery] Added some important metrics. [AJ] - * MinScoreToKeepLife='TapNoteScore_*' - any score below this = loss of life. - * SubtractLives=1 - how many lives are lost when going below MinScoreToKeepLife. - * MinesSubtractLives=1 - how many lives are lost when hitting a mine. - * HeldAddLives=0 - how many lives are gained when a hold is completed. - * LetGoSubtractLives=1 - how many lives are lost on a dropped hold. - -2011/06/12 ----------- -* [ScreenNetSelectMusic] Add PlayerOptionsScreen metric. [AJ] -* [ScreenEdit] Restore the old PageUp/PageDown behavior, added Control + - PageUp/PageDown to use recent time signature behavior. Laptop users, that - includes you guys too: semicolon and apostrophe are still good. [Wolfman2000] - -2011/06/11 ----------- -* [ScreenEdit] Allow setting the Music Preview via the Alter Menu. Just select - your area, enter the menu, and choose "Designate as Music Preview". No more - math calculations needed! [Wolfman2000] -* [SongUtil] Added GetPlayableSteps(Song) Lua binding. [AJ] -* [Steps] Allow 255 characters for all chart descriptions, including edits. - We are no longer bound by In The Groove I think. [Wolfman2000] -* [Player] Add GetPlayerTimingData() Lua binding. [Wolfman2000] - -2011/06/10 ----------- -* [ScreenEdit] Split the Area Menu into the Area Menu and Alter Menu. Use the - "A" key to enter the Alter Menu when a selection of notes/rows are - highlighted. Use the Enter key to enter the old Area Menu for the options that - do not depend on selecting NoteData. [Wolfman2000] -* [ScreenEdit] Allow converting selections to Delays, Warps, or Fakes as well - as Stops. Remember, use the Alter Menu for this. [Wolfman2000] - -2011/06/09 ----------- -* [ScreenSyncOverlay] Ensure that F11 / F12 work with all charts due to Split - Timing. [Wolfman2000] - -2011/06/08 ----------- -* Any notes in a fake segment or warp segment are completely ignored for - scoring purposes. Now you can get 100% on your warping goodness! - [Wolfman2000] - -2011/06/06 ----------- -* [PlayerOptions] Removed the ScoreDisplay mod choices. Use lua to make your - own scoring formulas that work in reverse instead. [Wolfman2000] -* [ScreenGameplay] Fix an assist tick bug if there was no Player 1. Note that - this changes the behavior slightly: it is the first enabled player, or - master player, that gets the ticks now. A better solution will be looked at - in the future. [Wolfman2000] -* [NoteDataUtil] Fix a radar issue involving hands. Unfortunately, this means - yet another cache reload for accuracy purposes. [Wolfman2000] - -2011/06/04 ----------- -* Changed default MusicWheelSwitchSpeed to 15 (was 10). [AJ] -* [AnnouncerManager] Fixed a bug where no announcers would be loaded. [AJ] -* Restored the UserPrefAutoSetStyle behavior. [Wolfman2000] -* [NotesLoaderSMA] Better way of identifying beats and seconds. [Wolfman2000] - -================================================================================ -StepMania 5.0 Preview 1a | 20110603 --------------------------------------------------------------------------------- - -2011/06/03 ----------- -* [LifeMeterBattery] Added LivesLeft param to LifeChanged message. [AJ] -* [Windows] Set up directories for pictures and app data in their proper - location. [Henke] -* [NotesLoaderSM] Fix an Offset load bug. [Wolfman2000] - -2011/06/02 ----------- -* [BPMDisplay] Added SetFromSteps Lua binding. [AJ] -* [ScreenDebugOverlay] Switch the R and T keys to be Volume Down and Up - respectively. I have to admit, it makes more sense to have volume up be - on the right instead of the left. [Wolfman2000] -* [SongManager] Make autogen courses have "Autogen" as the Scripter. [AJ] - -2011/06/01 ----------- -* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] -* [ScreenEdit] Fix Song Timing behaviors. [Wolfman2000] - -2011/05/31 ----------- -* [Player] Added the BattleRaveMirror metric. This determines if Battle and - Rave mode will have the two players with mirrored charts or not. By default, - this is set to true, preserving the ITG style behavior. [Wolfman2000] -* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] - -================================================================================ -StepMania 5.0 Preview 1 | 20110529 --------------------------------------------------------------------------------- - -2011/05/27 ----------- -* [ScreenEdit] Added the LoopOnChartEnd metric. Once you get to the end of - the chart while playing it in the editor, this controls whether it loops and - plays again, or simply stops. By default, this is true, replicating current - behavior. Set to false to replicate older StepMania behavior. [Wolfman2000] - -2011/05/26 ----------- -* [ScoreKeeperNormal] Added the MissComboIsPerRow metric. Similar to the - ComboIsPerRow metric, this determines how much miss combo is earned on missing - a row of notes. By default, this is true. Set to false to replicate Pump Pro - behavior. [Wolfman2000] - -2011/05/25 ----------- -* [NotesLoaderSSC/NotesWriterSSC] Added the ScrollSegments. Think BPM change, - but not. [theDtTvB] - -2011/05/23 ----------- -* [Steps] Added the UsesSplitTiming Lua binding. [Wolfman2000] - -2011/05/20 ----------- -* [CryptManager] Added SHA1File Lua binding. [AJ] - -2011/05/19 ----------- -* [BPMDisplay] Add CourseCycleSpeed metric. [AJ] - -2011/05/17 ----------- -* [NotesWriterSM] Write out OpenITG compatible SM files from here on out. - This includes turning Warps into Negative Stops. For those that wanted - negative BPMs specifically, my apologies, but stops are easier on math. - [Wolfman2000] - -2011/05/16 ----------- -* [ProfileManager] Added ProfileWasLoadedFromMemoryCard(PlayerNumber) - Lua binding. [AJ] -* Added #FAKES to the SSC format. Similar to the fake arrows, these blocks - prevent all judgments within the range. [Wolfman2000] -* Changed the syntax of #WARPS slightly. Now the second value is the relative - distance that is skipped, not the absolute value when you start hitting - arrows again. [Wolfman2000] - -2011/05/15 ----------- -* [ScreenGameplay] Removed hardcoded commands for Debug (give up text) and - replace them with DebugStartOnCommand, DebugBackOnCommand, and - DebugTweenOffCommand. [AJ] -* Added #SPEEDS to the SSC format. This multiplies your scrolling speed during - gameplay, not replaces it (see mod attacks for replacing). [Wolfman2000] - -2011/05/14 ----------- -* [ModIcon] Added StopWords metric. [AJ] -* [ScreenSelectMaster] Add "ScreenEmpty" param to MenuStartP# when the GameCommand - doesn't set a screen. [AJ] -* [StepsDisplay] Added MeterFormatString metric. [AJ] -* [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] -* [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] -* [Banner] Added ScrollMode and ScrollSortOrder metrics. [AJ] - -2011/05/13 ----------- -* Added Split Timing to .SSC files. All older .SSC files and other file - formats are converted to split timing on cache load. We are no longer bound - by Song Timing for everything. [theDtTvB, Wolfman2000, TeruFSX] - -2011/05/11 ----------- -* [GameSoundManager] Added PlayAnnouncer Lua binding. [AJ] -* [AnnouncerManager] Add support for "gameplay combo #" for announcer. [AJ] - -2011/05/10 ----------- -* [Sprite] Added SetSecondsIntoAnimation Lua binding. [AJ] -* [BPMDisplay] Added SetFromCourse Lua binding. [AJ] - -2011/05/03 ----------- -* [ScreenEdit] Allow changing the Beat 0 Offset, Music Sample Start, and - Music Sample Length via Edit Song Info menu. [Wolfman2000] - -2011/05/02 ----------- -* [ScreenSelectMusic] Added NullScoreString metric. [AJ] - -2011/04/17 --------- -* Use lua for all primary score keeping. Course modes right now still use the - old fashioned system. [TeruFSX, Wolfman2000] - -2011/04/09 --------- -* [Player] Force hold judgments to take place before setting the score. - [theDtTvB] - -2011/04/05 --------- -* [NotesLoaderSSC, NotesWriterSSC] Add the #LABELS tag. This is meant for step - editors to label different parts of their stepcharts. Use Control + , or . to - jump to different labels made. [Wolfman2000] - +StepMania 5 Changelog +________________________________________________________________________________ +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. +________________________________________________________________________________ + +2016/06/28 +---------- +* [Gameplay] Moved pause menu logic to a script in _fallback. Added + documentation to help other themes implement a pause menu. + +2016/06/24 +---------- +* [SelectMusic] Added AllowHoldForOptions preference to disable holding start + to go to the player options screen. [kyzentun] +* [General] Back button will only back out of the screen on a press, not when + it is still being held from the previous screen. [kyzentun] + +2016/06/12 +---------- +* [ScreenSyncOverlay] Moved actors to lua to make them themable. [kyzentun] + +2016/06/09 +---------- +* [Gameplay] Ready and Go announcer sounds no longer play simultaneously. If + the Ready animation doesn't exist and the Go animation exists, only the + Go announcer sound is played. If neither animation exists, only the Ready + announcer sound is played. [kyzentun] + +2016/06/07 +---------- +* [NotesWriterSM] Stops, delays, and warps that occur on the same row are now + summed correctly. Fixes bug that deleted warps that were on the same row + as a stop. [kyzentun] +* [Sound] Ignore invalid SoundDriver preference. [kyzentun] + +2016/06/06 +---------- +* [Language] Traditional Chinese translation added. [ddrtime] + +2016/05/25 +---------- +* [MemoryCards] Fixed bug that caused loading profiles from usb drives to + crash. [djpohly] + +2016/05/20 +---------- +* [Global] Removed UndocumentedFeature lua function because it was just a way + to crash with a message. [kyzentun] + + +2016/05/11 +---------- +* [Minimaid] Fixed crash that occurred when the minimaid lights driver was + selected, but no minimaid device was connected. [wolfman2000] + +================================================================================ +StepMania 5.0.11 | 20160401 +-------------------------------------------------------------------------------- + +2016/03/22 +---------- +* [Prefs] Added DisableUploadDir preference to skip saving a score entry to + Save/Upload every time a song is played. Generating the unique filename + can take several seconds when there are years of scores accumulated, and it + clutters the disk. This preference defaults to false. [kyzentun] + +2016/03/17 +---------- +* [Actor] Added get and set_tween_uses_effect_delta lua functions to make an + Actor use the effect clock for tweening. [kyzentun] + +2016/03/15 +---------- +* [ProfileManager] Added GetStatsPrefix and SetStatsPrefix lua functions for + separating scores into different stats files. [kyzentun] + (this is kind of a stop gap, I'd really like to rewrite scoring to save + more data so that a score earned with one set of timing windows and weights + can be converted to the equivalent score with different timing windows) + +2016/03/14 +---------- +* [Online] Stepmania will force disconnection from the SMO server when + entering the jukebox or sync calibration screens to avoid crash. [kyzentun] + +2016/03/05 +---------- +* [global] get_sound_driver_list lua function added. [kyzentun] + +2016/03/02 +---------- +* [Gameplay] Fixed No Fakes mod to remove fakes inside warps. [kyzentun] +* [Keymaps] Added special name for colon key so it can be bound. [medmig] + +2016/02/20 +---------- +* [Language] Bahasa Indonesian translation added to default theme. [JOELwindows7] + +2016/02/15 +---------- +* [Input] Linux event devices now start at JOY10 instead of JOY1. Without + this change, if one dance pad is a joystick device, and the other is an + event device, they will both be JOY1, and stepmania will think they are the + same dance pad. If you use Linux, assume that you have to remap your dance + pad. [kyzentun] + +2016/02/13 +---------- +* [Lights] Minimaid driver added for Linux. This is practically identical to + the Windows minimaid driver that pkgingo wrote. +* [Gameplay] When checking for the first second in a song, AutoKeysound notes + are now ignored, being treated as if they were background music. This + allows the intro of BMS files to play as soon as ScreenGameplay is loaded, + while still having a delay before the real notes come in. [nixtrix] + +2016/02/04 +---------- +* [Course] In an Endless course, songs will only be repeated after all songs + in the group have been played. [blindbox] + +2016/02/03 +---------- +* [ScreenManager] Added PlayInvalidSound, PlayStartSound, PlayCoinSound, + PlayCancelSound, and PlayScreenshotSound lua bindings. [kyzentun] + Added get_input_redirected and set_input_redirected to allow the theme to + disable the normal input functions. (Example: a custom lua menu on + Select Music. When the menu is up, the theme doesn't want the player's + input to move the music wheel.) This is in SCREENMAN so that it will work + on all screens. [kyzentun] +* [ScreenSelectMusic] Added CanOpenOptionsList lua binding. OpenOptionsList + will do nothing if CanOpenOptionsList returns false. [kyzentun] + +2016/01/18 +---------- +* [Edit Mode] Added "Clear timing in region" to timing menu. [kyzentun] + Fixed crash that occurs when "Paste timing data" is used after copying a + region of timing data that only contains stops. [kyzentun] + +2016/01/14 +---------- +* [Gameplay] Added pause menu to default theme. Activated by pressing + Select, or Back twice without pressing something else. Has options for + restarting or forfeiting the current song in normal play. Course mode has + options for skipping the current song or ending the course or forfeiting. + [kyzentun] +* [Graphics] When fetching the list of resolutions, only 32bpp modes are + tested because less than 32bpp is not supported on Windows 8 and newer, and + because the bpp doesn't matter when fetching a list of resolutions. This + speeds up the load time of the Graphics/Sound option screen. [kyzentun] + +2016/01/10 +---------- +* [RageFile] Lua functions for RageFile should now emit an error when the + file was not opened correctly instead of crashing. [kyzentun] + +2016/01/05 +---------- +* [Linux] Disable DPMS on startup and restore setting on exit. [kyzentun] + +2015/12/27 +---------- +* [RageFileManager] Ignore OS X special files in GetDirListing. [kyzentun] + +2015/12/20 +---------- +* [Fonts] Fixed crash bug in Texture Font Generator. [drewbarbs] + +2015/12/16 +---------- +* [Player] ChangeLife and SetLife functions added. [kyzentun] + +2015/12/13 +---------- +* [popn] Judgment levels in popn game mode now use W1 to W5. [parashep] + +2015/12/05 +---------- +* [Player] Guitar mode cruft removed from Player. [tertu] + +2015/12/04 +---------- +* [NoteField] Changed DrawBeatBar to check the M-mod so that smaller beat + bars are drawn when M-mods are used in edit mode. [kyzentun] + +2015/11/09 +---------- +* [Gameplay] BG Brightness is no longer forced to 100% on songs that only + have a beginner chart. [kyzentun] + +2015/11/08 +---------- +* [ScreenSelectMusic] Using lua music files for the section music and similar + things works now. [kyzentun] + +2015/11/05 +---------- +* [PlayerOptions] Fixed bug that was clearing the noteskin back to default. + [kyzentun] + +================================================================================ +StepMania 5.0.10 | 20151031 +-------------------------------------------------------------------------------- + +2015/10/29 +---------- +* [Language] French translation updated. [Arvaneth] + +2015/10/27 +---------- +* [Compiling] Link with /MT on windows instead of /MD. [wolfman2000] +* [Fonts] Put Texture Font Generator back in package. [wolfman2000] + Build Texture Font Generator when WITH_FULL_RELEASE or + WITH_TEXTURE_GENERATOR is enabled. [wolfman2000] + +2015/10/26 +---------- +* [Song] Added GetMainTitle lua function for bypassing ShowNativeLanguage + preference. [kyzentun] + +2015/10/25 +---------- +* [Compiling] Number of jobs used when building ffmpeg can be customized by + WITH_FFMPEG_JOBS. [wolfman2000] + Appveyor support added for automated windows building. [wolfman2000] + +2015/10/23 +---------- +* [BMS] Fixed crash when an unknown type chart was in a bms. [kyzentun] + +2015/10/21 +---------- +* [Actor] Changed PlayCommandNoRecurse so that setting a theme metric to a + function that doesn't exist doesn't emit an error. [kyzentun] +* [Compiling] Allow WITH_MP3=Off and WITH_WAV=Off to compile. [wolfman2000] +* [EditMode] Fixed crash on missing ScreenMiniMenuTimingDataChangeInformation + metrics. [kyzentun] +* [ScreenEvaluation] Changed assert that occurs when leaving ScreenGameplay + with SM_GoToNextScreen to give more info. [kyzentun] + +2015/10/20 +---------- +* [Compiling] Fixed cmake error when compiling with -DWITH_SSE2=off. [wallacoloo] + Don't define CPU_X86 on non-x86. [wallacoloo] +* [Noteskins] If the fallback for a noteskin is not found, that noteskin is + not loaded, to prevent picking it and crashing. [kyzentun] + +2015/10/18 +---------- +* [BitmapText] Added set_mult_attrs_with_diffuse lua function. [kyzentun] + +2015/10/17 +---------- +* [Course] Fixed loading of courses that use WORST entries. [wolfman2000] +* [SextetStream] SextetStream stuff is now in all platforms. [wolfman2000] + +2015/10/15 +---------- +* [BMS] Changed bms loading so that iidx bms files aren't loaded as kb7. + [zardoru] + +2015/10/12 +---------- +* [ActorMultiVertex] Fixed bug that *sometimes* caused diffuse to be applied + to verts wrong. [kyzentun] + +2015/10/11 +---------- +* [Song] Changed song loading to allow a song to have a blank MusicFile field + if the song has any keysounds. A blank MusicFile entry can result from + having '#' in the music file name, or be intended for bms files. Do not use + '#' in any fields, the .sm and .ssc file formats do not support it. The + engine has to detect that the field was loaded blank and look through the + song folder to figure out what was supposed to be there. [kyzentun] + +2015/10/09 +---------- +* [Edit Mode] Changed Current Second field to not have the global offset + added in. People were using one global offset for syncing to workaround + the problem and sync by comparing the Current Second in Edit Mode to the + current second in a music editor. The workaround of using a different + global offset for syncing should no longer be necessary. [kyzentun] +* [Input] Fixed input lockup caused by scrolling the mouse wheel. Why wasn't + this reported sooner? [kyzentun] + +2015/10/07 +---------- +* [ActorFrame] ActorFrame:SetDrawByZPosition now returns self. Missed a spot + when implementing function chaining. [kyzentun] +* [Gameplay] MaxRegenComboAfterMiss preference brought in. When a step is + missed in gameplay, the combo has to get back up to RegenComboAfterMiss + before the player starts regaining life. If MaxRegenComboAfterMiss is + greater than RegenComboAfterMiss, then each successive miss increases + RegenComboAfterMiss until it reaches RegenComboAfterMiss. + MaxRegenComboAfterMiss defaults to 5, the same as RegenComboAfterMiss, so + there should be no behavior change unless the preference is manually + changed. [dbk2] +* [Gameplay] When disqualification was turned on via Preferences, the old + logic exhibited two problems: + 1. charts with attacks were always disqualified from ranking + 2. charts without attacks could be disqualified from ranking if the attack + modifier was set to "Off" + So, this commit fixes those problems. If a chart has attacks, and the + attack modifier is used to turn them "Off", then disqualification is + enforced. + Additionally, disqualification is enforced if the attack modifier is set to + "Random Attacks." This part might not be necessary, but I acted on the + assumption that random attacks could theoretically make a chart easier. + [dbk2] + +2015/10/04 +---------- +* [FFmpeg] Upgrade FFmpeg to 2.1.3 for Windows. [wolfman2000] +* [FFmpeg] Fixed cmake WITH_SYSTEM_FFMPEG option. [lthls] + +2015/10/03 +---------- +* [FFmpeg] Upgrade FFmpeg to 2.1.3 for Mac OS X. [wolfman2000] +* [Gameplay] Fixed timing to apply the current music rate to the global + offset so that playing at different music rates doesn't make a chart off + sync. [Matt McCutchen] + +2015/10/02 +---------- +* [Edit Mode] .sm files will no longer be saved when split timing is used + because per-chart timing cannot be done in the .sm format. [kyzentun] +* [Scoring] Fixed bug that caused missed holds to be recorded as held in the + value returned by PlayerStageStats:GetRadarActual(). [kyzentun] + +2015/09/21 +---------- +* [Sprite] Added set_use_effect_clock_for_texcoords for toggling whether the + tex coord velocity uses the effect clock instead of the time. + +2015/09/10 +---------- +* [MusicWheel] Fixed SetItemPosition so that it actually passes the item + index and the number of items to the transform function. [kyzentun] + +2015/09/09 +---------- +* [Notefield] Fixed bug where the hold body doesn't scroll if it goes off the + top of the screen. [waiei] + +2015/09/08 +---------- +* [Compiling] Compiling stepmania on Windows with the locale set to Japanese should work now. [wolfman2000] + +2015/09/06 +---------- +* [Preferences] Fixed crash on Advanced Input Options on OS X caused by the + Axis Fix preference not existing on OS X. The preference does nothing on + OS X, but the game no longer crashes on that screen. [kyzentun] + +2015/09/03 +---------- +* [Fonts] Respliced large kanji sprite sheets from 32x106 and 32x61 to 63x54 + and 48x41 to bring them under 4096 pixels tall, which was causing a forced + resize and slowing down loading time. [kyzentun] +* [Gameplay] Fixed song position updating logic so that the + ScreenGameplay:PauseGame lua function actually pauses the game. Start, + Select, and Back are all used for different ways of giving up, so the + feature remains unused in the default theme. [kyzentun] + +2015/09/02 +---------- +* [Gameplay] Fixed Player logic that spammed TNS_AvoidMine repeatedly. [kyzentun] + +2015/08/29 +---------- +* [Edit Mode] Fixed crash on entering edit mode caused by entering edit mode + as Player 2. Edit Mode only works as Player 1. [kyzentun] + +2015/08/23 +---------- +* [BMS] Added myo2 channel layout and kb7 charts. Added preview point and + fixed offset support and linear solo bms layout. [zardoru] +* [Linux] Symbolic links will be followed to find the actual executable dir. [Wallacoloo] + +2015/08/20 +---------- +* [Minimaid] Minimaid support built in by default instead of off by default. [wolfman2000] +* [Options] Put AllowExtraStage on Advanced Options screen in default. [kyzentun] + +2015/08/19 +---------- +* [Gameplay] RandomBGEndsAtLastBeat metric defaults to true to be similar to + old behavior. [wolfy852] + +2015/08/08 +---------- +* [General] When the HighResolutionTextures preference is set to Auto, + StepMania checks whether the display height is greater than the theme + height instead of whether it's greater than 480. [shakesoda] + +2015/08/04 +---------- +* [PIUIO] Only send LightState changes to PIUIO when there is a change. [dbk2] + +2015/08/02 +---------- +* [NoteField] Fixed bottomcap when NoteDisplay is zoomed out. [hanubeki] + +2015/07/22 +---------- +* [Compiling] Fixed building on 32bit linux. [kyzentun] + +2015/07/19 +---------- +* [Pump] Added TimingWindowSecondsCheckpoint for the timing window that + checkpoint holds allow you to release for. [wolfman2000] + +2015/07/18 +---------- +* [General] Fixed bug that skipped notes on beat 0 in score. [kyzentun] + +2015/07/16 +---------- +* [ActorUtil] ActorUtil.ResolvePath and ResolveRelativePath now take a + boolean flag to tell if the thing is optional. [kyzentun] +* [CryptMan] Fixed bug that clipped hash strings with zeros. [kyzentun] + +2015/07/15 +---------- +* [Sprite] Sprite now executes the AnimationFinished command when it reaches + the end of its animation and starts over. [kyzentun] + +2015/07/11 +---------- +* [ScreenMapControllers] If the AutoDismissWarningSecs metric is less than + .25 seconds, the warning will not be shown (the TweenOn command for it will + not be played). Instead, the NeverShow command will be played. If the + NeverShow command does not exist for the warning actor, the warning actor + will be set to hibernate forever. [kyzentun] + +2015/07/02 +---------- +* [Gameplay] Random background video behavior is now controlled by these + three metrics in the Background section: + RandomBGStartBeat sets the beat of the music the first random bg occurs on. + RandomBGChangeMeasures sets the number of measures between changes. + RandomBGChangesWhenBPMChangesAtMeasureStart toggles the behavior in its name. + RandomBGEndsAtLastBeat toggles the behavior in its name. + +================================================================================ +StepMania 5.0.9 | 20150520 +-------------------------------------------------------------------------------- + +2015/06/10 +---------- +* [global] get_music_file_length lua function added. [kyzentun] + multiapproach lua function now takes an optional 4th argument to multiply + the speeds by. [kyzentun] +* [NoteDisplay] 1px seam in hold cap rendering fixed. [A.C/waiei] +* [RageSound] get_length lua function added. [kyzentun] + +2015/06/06 +---------- +* [ScreenInitialScreenIsInvalid] Error screen for themes that set an invalid + initial screen. [kyzentun] + +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] +* [RageFile] Exposed Flush function to Lua. [kyzentun] + +2015/05/29 +---------- +* [OptionsList] The OptionsListQuickChange, OptionsListLeft, and + OptionsListRight messages now have a Selection parameter that has the id of + the selection the player moved to. [nixtrix] + +2015/05/24 +---------- +* [Gameplay] Autokeysounds are no longer twice as loud when playing + keysounded charts with two players. [nixtrix] + +2015/05/15 +---------- +* [BMS] .lua files defined in the #BMP tags now work as BG animations, and the + #difficulty tag is now supported. [nixtrix] +* [general] BackInEventMode code now works when called from either player. + [nixtrix] +* [cmake] JACK is now properly found by CMake. +* [theme] Preview music fadeout time is now adjustable by the metric + SampleMusicFadeoutSeconds. [nixtrix] +* [Song] Setting a sample length of 0 uses the length of the entire preview + file. [nixtrix] + +================================================================================ +StepMania 5.0.8 | 20150510 +-------------------------------------------------------------------------------- + +2015/05/10 +---------- +* [General] Screenshots are not tagged with song title or screen name because + this causes problems when titles have UTF8 or slashes. [kyzentun] + +2015/05/09 +---------- +* [general] Workaround for the axis problem added. Set the Axis Fix + preference under Input Options to true if you have the axis problem. + [Fighter19] +* [general] Added XML to Lua converter. See Docs/Themerdocs/XmlToLua.txt for + details. [kyzentun] + +2015/05/08 +---------- +* [compiling] Added -DWITH_CRYSTALHD_DISABLED cmake options to allow more + users to build on Linux. [wolfman2000] + +2015/05/05 +---------- +* [Gameplay] Holding Select on gameplay now skips the current song in course + or endless mode. [kyzentun] + +2015/04/30 +---------- +* [beat] Default key configuration slightly tweaked, space is now the + default scratch key, key7 is now mapped to right instead of key3. + Backwards and shuffle chart mods now ignore the scratch column. [jobn] + +2015/04/27 +---------- +* [general] "Do not show again" button on missing texture dialog works now. + If the background or banner file for a song doesn't exist when the song is + cached, the cache file will have a blank path so Stepmania won't try to + load the nonexistent banner or background. + +2015/04/25 +---------- +* [General] Screenshot key now checks whether there is a current song, and + puts the song title and current screen name in the screenshot filename. [kyzentun] + +2015/04/24 +---------- +* [Gameplay] Toasty animation can now occur multiple times during gameplay. [kyzentun] + +2015/04/23 +---------- +* [ServiceMenu] Entries in service menu rearranged to hopefully organize them + better. ScreenOptionsInputSub and ScreenOptionsDisplaySub added. Updating + a theme to show the options for the new screens should be a simple matter of + changing the LineNames entry for ScreenOptionsService to include + "InputOptions" and "SoundGraphics". [tuxdude] + +2015/04/18 +---------- +* [EditMode] Fixed bug that made alter menu choices prompt for clearing. [kyzentun] +* [NoteColumnRenderer] Added handling for diffuse and glow to make rainbow + and related effects work. [kyzentun] + +2015/04/15 +---------- +* [compiling] -DWITH_LIBVA option added to cmake building to fix compiling + problems for some linux users. [wolfman2000] + +2015/04/14 +---------- +* [SelectMusic] Disabled late join on Extra Stage to prevent crash on + Evaluation Summary. [kyzentun] + +2015/04/13 +---------- +* [EditMode] Fixed Revert From Disk to actually work. [kyzentun] +* [japanese] Language update from hanubeki. [hanubeki] + +2015/04/11 +---------- +* [dev] cpack support for installing. [wolfman2000] +* [TimingData] Fixed bug that made steps on the same row as a stop and a bpm + change unhittable. [kyzentun] + +2015/04/10 +---------- +* [Profile] Kluged together a fix for scores on edit charts not being loaded + until after the chart is played. [kyzentun] + +2015/04/08 +---------- +* [ActorSound] IsAction attribute added. get/set_is_action functions added. + [kyzentun] +* [GameSoundManager] is_action arg added to PlayOnce. [kyzentun] + +2015/04/06 +---------- +* [global] rec_print_children and rec_print_table lua functions added to + _fallback. [kyzentun] +* [Language] Dutch translation updated. [Thumbsy] +* [RadarValues] Stream, Voltage, Air, Freeze, and Chaos are no longer capped + at 1. Stream and Voltage no longer count hold heads twice. + RadarCategory_Notes added, which counts all notes. + Scoring bug fixes related to radar calculation. [kyzentun] +* [ScreenSelectGame] Exit option returns to ScreenOptionsService unless the + game type actually changed. [Wallacoloo] + +2015/04/04 +---------- +* [EditMode] Added submenus to the timing edit menu to allow shifting, + copying, and pasting any or all timing segments in the selected region or + after the current cursor position. [kyzentun] + Shifting menus in edit mode now have choices for 1, 2, or 4 measures or 2 + beats. [kyzentun] +* [global] Fixed crash on OS X for certain dance pads when in Japanese + locale. [Wallacoloo] + +2015/04/03 +---------- +* [ScreenGameplay] The NoteField board is now underneath everything except + the backgound. This means underneath any custom actors on the underlay or + overlay or decoration layers, and also underneath the combo/judgment even + when the ComboUnderField metric is true. [kyzentun] + Fixed bug in screen filter in default theme that made it not appear under + the field when a solo file was played without Center1Player. [kyzentun] + +2015/04/02 +---------- +* [global] commify function exposed to lua. [kyzentun] + +================================================================================ +StepMania 5.0.7 | 20150401 +-------------------------------------------------------------------------------- + +2015/03/30 +---------- +* [Select Music] Ctrl+Shift+R mapped to reload the current song. [kyzentun] +* [Song] ReloadFromSongDir lua function exposed. [kyzentun] +* [Preferences] NeverCacheList preference added. It's a comma separated + list of group names, if a song is in one of the named groups, it is never + cached. [kyzentun] + +2015/03/27 +---------- +* [Select Music] Ability to delete the current song by pressing Ctrl+Backspace added. [Wallacoloo] + +2015/03/24 +---------- +* [Sprite/RageTexture] GetTexturePath moved to RageTexture and renamed to + GetPath. [kyzentun] + +2015/03/22 +---------- +* [Dev] Primary build method of all platforms changed to CMake. People + building from source must install CMake (min 2.8.12) and read + Build/README.md for building instructions. [wolfman2000] + +2015/03/18 +---------- +* [OSX] Empty Stepmania directory created on desktop removed. [dguzek] + +2015/03/17 +---------- +* [ActorFrameTexture] Example added to Themerdocs/Examples/Example_Actors/. + Crash fixes for AFTs. [sigatrev] + +2015/03/15 +---------- +* [Sprite] GetTexturePath added. [kyzentun] + +2015/03/12 +---------- +* [Language] Docs/Changelog_language.txt added for tracking language changes. + +======= +================================================================================ +StepMania 5.0.7rc | 20150309 +-------------------------------------------------------------------------------- + +2015/03/09 +---------- +* [EditMode] Autosave every 5 minutes added. [kyzentun] +* [General] NotesLoaderSM, NotesLoaderSSC, IniFile::ReadFile rewritten, + load times substantially faster. [kyzentun] +* [Preference] HarshHotLifePenalty preference added, for toggling whether + LifeMeterBar takes away .1 life when it's full. [kyzentun] + +2015/03/08 +---------- +* [EditMode] Clearing an area now prompts for confirmation if it contains + EditClearPromptThreshold notes or more. EditClearPromptThreshold is a + preference that can be set in the Advanced Options section, or in the + options in Edit Mode. [kyzentun] + +2015/03/05 +---------- +* [Graphics] DX9 support improved, giving a large speed boost and fixing the + problem that made people get stuck with 16bit color. [xwidghet] + +2015/03/04 +---------- +* [Loading] The song length from the cache is used now. This cut loading time + by 30% for kyz. [kyzentun] + +2015/03/02 +---------- +* [Song] Per-chart music feature added. Each chart can have a MUSIC tag. + [kyzentun] + +2015/03/01 +---------- +* [SelectMusic] Select Music now plays music file named by #PREVIEW tag if + it's not blank, instead of using the song file for the sample music. The + sample length is read from the preview file. The sample start is treated as + 0. [kyzentun] +* [Song] GetPreviewMusicPath added. [kyzentun] +* [foreach] foreach_ordered lua function now works on tables that have both + number and string keys. Number keys are iterated over first. [kyzentun] + +2015/02/28 +---------- +* [General] Pause/Break key now toggles "action" sounds off or on. There is + also a button in the F3 debug menu (press A, there are so many that it is + off the bottom) for people that don't have a Pause/Break key. [kyzentun] + +2015/02/27 +---------- +* [ActorFrame] Fixed RemoveChild and RemoveAllChildren lua functions to + delete the children instead of leaking memory. [kyzentun] +* [Font] Asserts and other things that caused Stepmania to crash on font + mistakes now emit non-fatal errors. [kyzentun] + +2015/02/26 +---------- +* [PaneDisplay] Changed to print an error when metrics or player number are + omitted instead of crashing. [kyzentun] +* [Screen] Fixed crash when AddInputCallback is passed nil. [kyzentun] + +2015/02/22 +---------- +* [BitmapText] Place characters of right-to-left alphabets correctly. + (untested) [roothorick] + +================================================================================ +StepMania 5.0.6 | 20150217 +-------------------------------------------------------------------------------- + +2015/02/16 +---------- +* [EditMode] Fixed mistake in TimingData that broke editing bpms. [kyzentun] + Fixed crash when deleting steps. [kyzentun] +* [InputMapper] Backslash can be mapped now. [kyzentun] + +================================================================================ +StepMania 5.0.5 | 20150214 +-------------------------------------------------------------------------------- + +2015/02/12 +---------- +* [InputMapper] Added D-Force Automappings [shakesoda] + +2015/02/04 +---------- +* [ActorFrame] GetUpdateRate added. [kyzentun] +* [Background] Using the wrong transition name no longer crashes. + Playback rate is applied to videos. + Checkerboard and other BackgroundEffects that use the same file twice no + longer play videos back at multiplied speed. [kyzentun] +* [Sprite] Get/SetDecodeMovie added. [kyzentun] + +2015/02/03 +---------- +* [MusicWheel] HideActiveSectionTitle metric added. [djpohly] + +2015/02/02 +---------- +* [ActorMultiVertex] ForceStateUpdate and Get/SetDecodeMovie added. [kyzentun] +* [RageTexture] GetWidth and Height functions added. + ( means Source, Texture, or Image) [kyzentun] +* [Scripts] find_missing_strings_in_theme_translations function added to + _fallback scripts to assist translators in finding what needs to be + translated. If you need/want to run it on your them, write a piece of lua + like this: + find_missing_strings_in_theme_translations("_fallback", "en.ini") + The first arg is the folder name of the theme to look at. + The second arg is the name of the language that is fully translated. All + other languages will be compared to it to decide what is missing or unused. + [kyzentun] +* [Song] GetBGChanges added. [kyzentun] + +2015/02/01 +---------- +* [ActorMultiVertex] Animation state system added. AMVs can now have + animated textures controlled by states written in lua. [kyzentun] + +2015/01/31 +---------- +* [EditMode] Want more lead in time before recording starts? + It's a preference. [kyzentun] + +2015/01/30 +---------- +* [Actor] Wrapper states added. This makes wrapping an Actor inside an + ActorFrame for any reason unnecessary, and makes it possible to do things + that were only possible by wrapping an Actor in an ActorFrame to Actors + that you couldn't put inside a frame before. [kyzentun] + +2015/01/20 +---------- +* [ScreenSelect] ChoiceNames can be a lua command that is evaluated to get a + list of the gamecommands. The main use of this is to get rid of the huge + list of metrics that ScreenSelectStyle requires. A single lua function + instead of a metric for every style for every game type. [kyzentun] +* [ScreenSelectMaster] IconChoicePosFunction metric added. This metric is + optional, if it's set, it must be set to a function that returns a table + of positions. Each position is a table of the form "{x, y, z}", where x, + y, and z are numbers and any that is not a number defaults to 0. + The function is passed the number of choices for the screen. + IconChoiceOnCommand and IconChoiceOffCommand metrics added so each choice + doesn't require its own On/OffCommand pair. These are also optional, but + if they are set, they will override the individual commands if they exist. + (If "IconChoiceCactusOnCommand" and "IconChoiceOnCommand" both exist, + "IconChoiceOnCommand" will be used.) [kyzentun] + Example: + # in metrics.ini + IconChoicePosFunction=choice_positions + -- In a file in Scripts/ + function choice_positions(count) + local ret= {} + for i= 1, ret do ret[i]= {i*24, i*48} end + return ret + end + +2015/01/16 +---------- +* [ScreenSelectMusic] HardCommentMeter metric added. Sets the meter that + will trigger the "select music comment hard" announcer sound. [kyzentun] + +2015/01/12 +---------- +* [ScreenOptions] GetNumRows function added. [kyzentun] + +2015/01/09 +---------- +* [Sprite] SetStateProperties function added. [kyzentun] + +2015/01/06 +---------- +* [ActorMultiVertex] GetSpline and SetVertsFromSplines functions added. + [kyzentun] +* [NoteColumnRenderer] Functions for fetching the spline handlers for the + column added. [kyzentun] +* [NCSplineHandler] New class for setting various parameters of a spline used + by a NoteColumnRenderer and containing the spline. [kyzentun] +* [CubicSplineN] New class that provides spline functionality. [kyzentun] + +2014/12/26 +---------- +* [NoteField] Columns turned into actors that can be fetched with + get_column_actors. [kyzentun] + Tiny boost in fps when there is a large number of notes on screen. +* [NoteColumnRenderer] New class for controlling one column. [kyzentun] + +2014/12/20 +---------- +* [Preferences] AllowMultipleHighScoreWithSameName, ComboContinuesBetweenSongs + Disqualification, FailOffForFirstStageEasy, FailOffInBeginner, + LockCourseDifficulties, InputDebounceTime, MaxHighScoresPerListForMachine, + and MaxHighScoresPerListForPlayer added to service options. + InputDebounceTime is in Input Options, the rest are in Arcade Options. + (might not show up in themes that customize the order and placement of the + preferences) [kyzentun] + +2014/12/18 +---------- +* [Profile] GetTotalDancePoints added. [kyzentun] + +2014/12/10 +---------- +* [EditMode] Play whole song and play from current beat will now play until + either the music or the notes end, whichever is greater. [kyzentun] + The screens used for setting the options used to play the screen and for + adding attacks can be set through the "OptionsScreen" and "SetModScreen" + metrics in the ScreenEdit section. +* [GameState] ApplyPreferredSongOptionsToOtherLevels function added. [kyzentun] +* [Player] "ComboBreakOnImmediateHoldLetGo" theme metric added. [sillybear] +* [PlayerState] ApplyPreferredOptionsToOtherLevels function added. [kyzentun] + +2014/12/07 +---------- +* [Game] GetSeparateStyles function added. Use this to detect whether a game + allows the players to play different styles. [kyzentun] (used by kickbox) +* [GameManager] Lua Scripts/ folders are now reloaded when the Game mode is + changed. [kyzentun] +* [GameState] CanSafelyEnterGameplay function added. [kyzentun] + In kickbox game mode, players can have different styles set, pass a + PlayerNumber when using SetCurrentStyle or GetCurrentStyle. +* [kickbox] New game mode with 4 styles. [kyzentun] +* [ScreenGameplay] Notefield positioning is handled a bit differently now. + See comments in _fallback/metrics.ini above the [ScreenGameplay] + MarginFunction metric. Basically, you can define a lua function that + returns the space you want at the edges and in the center instead of + setting position metrics. Do NOT use Style:GetWidth to calculate the + margins your function returns. + ScreenGameplay now handles zooming the notefield to fit in the space + instead of using the NeedsZoomOutWith2Players flag in the style. + If the notefield doesn't fit in the space between the margins, and there is + only one player, the player will be centered even if the Center1Player pref + is false. [kyzentun] +* [Style] NeedsZoomOutWith2Players decapitated. Always returns false now. + GetWidth added. [kyzentun] +* [techno] Techno game mode no longer has special column width for versus. + Techno was the only game mode that used the NeedsZoomOutWith2Players flag, + and the zoom factor it applied was 0.6, and the special versus column width + was 0.6*normal, so this should make no difference. [kyzentun] + +2014/12/03 +---------- +* [command line arg] --game command line arg added for setting the game type + when starting stepmania. [sillybear] +* [Announcer] "evaluation full combo W3" and "evaluation full combo W4" + responses added. [sillybear] + +2014/12/01 +---------- +* [ScreenMapControllers] Forced sanity checking of key mappings added. + Start, MenuLeft, MenuRight, and Operator keys must be mapped. + Reset key mappings option added to debug menu for recovering from an + unusuble keymap without needing to find and delete KeyMaps.ini. [kyzentun] + +2014/11/30 +---------- +* [NoteField] New functions added for controlling the receptor and ghost arrow + (explosion) flashes. [kyzentun] + +2014/11/28 +---------- +* [Profile] Guest and Test profile types added. All existing and new + profiles are Normal. If a profile is changed to Guest through the profile + management screen, it will always show at the top of the list. A profile + set to Test will always be at the bottom of the list. Profiles can be + moved around in the list. + GetType and GetPriority lua functions added to Profile. + Bug that caused a crash when a profile dir was renamed to a non-number and + a new profile was created fixed. [kyzentun] +* [Everything] Actor and singleton functions that formerly returned nothing now + return the actor or singleton. Example (set zoom, x, y, and diffuse in one): + self:zoom(.5):xy(_screen.cx, _screen.h-60):diffuse(color("#dc322f")) + This also works for PlayerOptions and SongOptions API functions. Pass true + as an extra arg, and they can be chained. + +2014/11/22 +---------- +* [Preferences] MinTNSToHideNotes preference added. [kyzentun] +* [PlayerOptions] MinTNSToHideNotes mod added. [kyzentun] + +2014/11/15 +---------- +* [Preferences] Default Fail Type preference mechanism changed internally again. + Set your Default Fail Type preference again. [kyzentun] + +2014/11/05 +---------- +* [ScreenPrompt] Answer OnCommand metrics fixed to actually work. [kyzentun] + +2014/11/01 +---------- +* [RollingNumbers] Cropping and color during tweens fixed. [kyzentun] + +2014/10/27 +---------- +* [Changelog] Vospi read the release notes. + +2014/10/23 +---------- +* [Global] approach, multiapproach, lerp, and lerp_color lua functions added. [kyzentun] + +2014/10/20 +---------- +* [StageStats] GetStepsSeconds function added. [kyzentun] +* [Steps] If an unrecognized step type is saved, preserve that step instead of + deleting it. A warning will be placed in the log file during song load. [kyzentun] + +================================================================================ +StepMania 5.0 beta 4a | 20141015 +-------------------------------------------------------------------------------- + +2014/10/19 +---------- +* [BackgroundEffects] Fixed errors in StretchNoLoop and StretchRewind. + +2014/10/13 +---------- +* [NoteDisplay] Var Player and Var Controller work for non-receptor arrows. [hanubeki] +* [Mac OS X] Allow StepMania to be built and run in Yosemite. + +2014/10/11 +---------- +* [NoteDisplay] Add two noteskin metrics, {PartName}NoteColorType and + {PartName}NoteColorCount. View https://github.com/stepmania/stepmania/pull/328 + for more information. [hanubeki] + +================================================================================ +StepMania 5.0 beta 4 | 20140930 +-------------------------------------------------------------------------------- + +To reduce the number of entries in this file, entries are dated to the Saturday after they occurred. + +2014/09/27 +---------- +* [Preferences] DebounceCoinInput time pref added for machines that need a + different debounce time for coin input. +* [Preferences] DefaultFailtype preference reinstated to resolve default fail + type problems. +* [TimingData] TimingData::GetReturnsNumbers metric added to make TimingData + functions return tables of numbers instead of strings. + +2014/09/20 +---------- +* [ScreenOptionsCustomizeProfile] New screen added for setting profile stats. + +2014/09/13 +---------- +* [Endless] Songs are repicked on each repeat of the course. +* [GameState] GetCurrentStage logic fixed to correctly return Stage_Final in + all cases where it should. +* [JudgmentMessage] Tracks parameter replaced with Notes and Holds parameters. +* [NumPadEntry] New customizable lua class for custom screens. +* [ScreenHeartEntry] New screen added to default. +* [TapNote] Class exposed to lua through JudgmentMessage with all data on the + TapNote. + +2014/09/06 +---------- +* Changed ES/OMES speed mod to 2x from 1.5x. +* [ActorMultiVertex] GetTexture lua function added. +* [BitmapText] max_dimension_use_zoom lua function added. +* [Edit Mode] Swap Up/Down and Arbitrary Remap added to Alter menu. +* [GameState] InsertCoin and InsertCredit lua functions added. +* [PrefsManager] FastNoteRendering preference added. +* [RageTexture] Reload lua function added. +* [RageTexture?] "__screen__" added as special screenshot texture name. + Causes a skip. +* [Screen] SetNextScreenName lua function added. +* [ScreenCredits] New ScreenCredits. Please update your theme if you applied + theme changes to this screen. +* [ScreenMapControllers] Massively changed to make it not suck. New elements, + new metrics, new actions. +* [WheelItemBase] IsLoaded lua function added. + +2014/08/30 +---------- +* [ActorScroller] wrap parameter added for controlling looping behavior better. +* Life difficulty matches StepMania 3.9's again. + +2014/08/16 +---------- +* [ActorFrame] Internal diffuse and glow now apply to BitmapText children. +* [GameState] SetCurrentPlayMode and SetCurrentStyle lua functions added. +* [PrefsManager] BackgroundFitMode preference added to settle all problems + with how backgrounds are stretched or fit. +* [ScreenSetBGFit] New screen for presenting the BackgroundFitMode preference. + See _fallback/BGAnimations/ScreenSetBGFitMode overlay.lua for documentation. +* [ThemeManager] HasMetric/String now return false when the group name or + metric name is an empty string. + +2014/08/09 +---------- +* [GameManager] GetStylesForGame lua function added. +* [LifeMeterBattery] CourseSongRewardLives metric added. +* [LifeMeter] LifeType, DrainType, and BatteryLives moved to PlayerOptions so + the players can have different settings. +* [ScreenGameplay] LifeMeterChangedP1 message is no longer broadcast for for + P2's lifemeter. Use LifeMeterChangedP2. "Life" and "StepsSecond" are passed + in the params table for the message. + +2014/08/02 +---------- +* [MusicWheel] Added GetSelectedSection lua function. + +2014/07/26 +---------- +* [ActorScroller] Accidental "permanent loop" bug fixed. +* [Common metrics] AfterThemeChangeScreen, AfterGameChangeScreen, and + AfterGameAndThemeChangeScreen optional metrics added to Common section. +* [GameManager] SetGame lua function added. +* [Globals] OldStyleStringToDifficulty lua function added. +* [PrefsManager] SavePreferences lua function added. + ThreeKeyNavigation preference added. +* [SoundManager] IsTimingDelayed lua function added. +* [ThemeManager] SetTheme lua function added. +* [ScreenHowToPlay] CharacterName metric works again. + +2014/07/18 +---------- +* [BitmapText] LoadFont is now obsolete. Set the Font attribute of the + BitmapText instead. +* [ErrorReporting] New system that reports theme errors through dialogs and + an on screen display. (Sorry guys, your themes are all full of errors, and + you should fix them) +* [LogDisplay] New actor class used by ErrorReporting, possibly useful more + widely. See _fallback/Scripts/04 LogDisplay.lua for docs. + +2014/07/05 +---------- +* [Actor] GetDestX/Y/Z lua functions added. +* [Profile] Lua functions for calculating calories based on heart rate added. + See ThemerDocs/calories.txt + +2014/06/28 +---------- +* [ArrowEffects] New namespace of lua functions. +* [Screen] AddInputCallback and RemoveInputCallback lua functions added. + +2014/06/21 +---------- +* [Gameplay] CMods and MMods now automatically compensate for music rate. +* [Globals] SaveScreenshot lua function added. +* [ScreenPlayerOptions] ArbitrarySpeedMods system added. +* [ScreenSelectMusic] Pad codes that set modifiers disabled. + +2014/06/07 +---------- +* [ScreenSelectMusic] SelectMenuInput message is now always sent when Select + is pressed. + +2014/05/17 +---------- +* [GameState] StoreRankingName lua function added. Ranking names now allow + lowercase. +* [Profile] SetLastUsedHighScoreName and GetHighScoreListIfExists lua + functions added. + +2014/05/10 +---------- +* [Player] Tracks param added to JudgmentMessageCommand. (will change before + beta 4) +* [ScreenGameplay] Themable haste system added. + GetTrueBPS lua function added. +* [ThemeManager] GetMetricNamesInGroup and GetStringNamesInGroup lua functions + added. + +2014/05/03 +---------- +* [ActorFrame] GetChild and GetChildren modified, see Lua.xml. +* [NoteSkinManager] GetMetric function added. +* [PlayerOptions] Entirely new API for setting player options. Superior + alternative to ApplyGameCommand. +* [SongOptions] Entirely new API for setting song options. Same design as new + PlayerOptions API. +* [NoteField] NoteField Board can now use any AutoActor class instead of just + Sprite/Sprite-derived ones. + +2014/04/26 +---------- +* [Style] GetColumnInfo and GetColumnDrawOrder lua functions added. + +2014/04/19 +---------- +* [ActorMultiVertex] New actor class added. +* [ScreenGameplay] GetHasteRate lua function added. GiveUpSeconds metric added. +* [SoundManager] StopMusic lua function added. + +2014/04/05 +---------- +* [GameState] HaveProfileToLoad/Save and Load/SaveProfiles lua functions added. +* [ScreenWithMenuElements] StartTransitioningScreen lua function added. + +2014/03/22 +---------- +* [Player] HoldNoteScore_MissedHold added. + +2014/03/05 +---------- +* [ScreenNetSelectBase] Fix colors when unicode characters are in chat box. + +2014/03/08 +---------- +* [ActorScroller] DrawByZPosition fixed for looping ActorScrollers. +* [Globals?] GetTimeSinceStart global lua function added. +* [Player] FirstTrack parameter added to JudgmentMessageCommand. (will change + before beta 4) + +================================================================================ +StepMania 5.0 beta 3 | 20140224 +-------------------------------------------------------------------------------- + +2014/02/22 +---------- +* [Actor] texturetranslate lua function added. +* [BitmapText] distort lua function added. +* [ComboGraph] Added BodyHeight metric. +* [GameState] JoinInput lua function added. +* [PlayerOptions] "resetspeed" mod added. +* [PlayerStageStats] GetComboList and GetLifeRecord lua functions added. +* [Preferences] ComboContinuesBetweenSongs preference added. +* [ScreenWithMenuElements] SetAllowLateJoin lua function added. +* [SoundManager] loop and applyRate args added to PlayMusicPart lua function. +* [Sprite] SetCustomPosCoords lua function added. +* [Utils] XML backwards compatibility added. + +2014/02/08 +---------- +* [Actor] Added heading, pitch, and roll lua functions. + +2013/10/09 +---------- +* [CombinedLifeMeterTug] Added names and commands to Separator and Frame items. + [SSC] +* [MeterDisplay] Added names to Stream and Tip items. [SSC] + +2013/10/06 +---------- +* [ScreenOptions] Allow for the use of per-screen Start sounds instead of a forced + Common Start. [SSC] + +2013/10/03 +---------- +* [GameConstantsAndTypes] Declared RankingCategory as a type. [SSC] +* [Profile] Added GetCategoryHighScoreList(StepsType,RankingCategory) Lua + binding. [SSC] + +2013/09/23 +---------- +* PIUIO: Fix default mapping for lights on five-panel setups. + +2013/09/06 +---------- +* Re-implement CustomSpeedMods to use new Lua hooks. Fixes assertion when + loading SpeedMods.txt from unmounted card. +* Add Lua hooks for themes to load/save custom data to/from profiles. +* [Linux] Ignore comments in /etc/fstab. + +2013/08/30 +---------- +* Fix editor behavior when deleting/shifting timing changes. +* Re-enabled "convert to stop/delay" at beat 0. + +2013/08/29 +---------- +* Fix hack pertaining to ModIcons and Lua-based option rows. + +2013/08/22 +---------- +* [FFmpeg] Fix several video timing issues (delay, stutter, looping) with the + FFmpeg driver. + +2013/08/14 +---------- +* [ThemePrefs] Fix saving of ThemePrefs in default theme. + +2013/08/12 +---------- +* [ScreenEdit] Fix Undo for the Alter and Turn commands. Previously, trying + to undo one of these commands would erase the notes instead. Now it behaves + as expected. + +2013/08/08 +---------- +* [SoundDriver_JACK] New sound driver (experimental!). To use this, specify + JACK in your SoundDrivers preference, and set SoundDevice to a + comma-separated list of ports to connect to, for example: + "SoundDevice=system:playback_1,system:playback_2". + +2013/07/18 +---------- +* [ScreenEdit] Display scroll segments in editor and preview for both Song and + Steps Timing. + +2013/07/09 +---------- +* [MemoryCardDriver] Allow Unix fstab to specify memory card devices by alias + (e.g. /dev/disk/by-path/*) + +2013/06/29 +---------- +* [ArchHooks_Unix] Support the GoToUrl function. [phantom10111] + +2013/06/18 +---------- +* [InputHandler_DirectInput] Add support for all possible input device types + under new DirectX library. [Shenjoku] +* Add --enable-lto option for configure on Linux. [phantom10111] + +================================================================================ +StepMania 5.0 beta 2a | 20130616 +-------------------------------------------------------------------------------- + +2013/06/15 +---------- +* Fix some minor DLL issues on Windows. [wolfman2000] +* Theme updates to make it faster. [Midiman] + +2013/06/09 +---------- +* [ScreenJukebox] Check for existing steps when starting jukebox. +* [ScreenEdit] Fix crash related to keysounds. [wolfman2000] + +2013/06/04 +---------- +* Fix theme glitches caused by the change to Home/Free modes. +* [UnlockManager] Allow entries to be explicitly locked by the theme. + [wolfman2000] + +================================================================================ +StepMania 5.0 beta 2 | 20130602 +-------------------------------------------------------------------------------- + +2013/06/02 +---------- +* Add several video container formats that are supported by FFmpeg: mkv, mp4, + mov, flv, f4v. + +2013/05/31 +---------- +* [ArchHooks_MacOSX] Add per-user folders in ~/Application Support. + +2013/05/30 +---------- +* [ScreenSelectMusic] Fix crash when sorting in Oni mode. + +2013/05/28 +---------- +* [ActorFrame] Propagate glow and diffuse to children of ActorFrames. This + should fix any visual problems with layered noteskins and mods. + +2013/05/25 +---------- +* Remove the "random" part of the Random Vanish mod to prevent crashing. + [wolfman2000] + +2013/05/21 +---------- +* [MovieTexture_FFMpeg] Fix crashing with large videos. + +2013/05/20 +---------- +* [NotesLoaderSM] New algorithm for converting negative BPMs and stops to + warps, more closely matching the behavior of old StepManias. + +2013/03/24 +---------- +* [MusicWheel] Add the ChangeSort method to the Lua interface to allow the + theme to switch sorting methods. + +2013/02/04 +---------- +* [Player] Add a "Column" parameter to the StepMessage to allow the theme or + chart to discover which column is being triggered. +* [ArchHooks] Unix: Move UserPackages to Packages in the per-user directory, + and remove Data from the per-user directory. Users who have installed + packages to UserPackages will need to migrate them to Packages instead. + +2013/02/03 +---------- +* [Player] Fix a stutter that can take place when mines are skipped during + warp segments. [phantom, wolfman2000] + +2013/01/23 +---------- +* [TimingData, ScreenEdit] Fixed behavior in the editor whereby making changes + to Song Timing would unexpectedly change all charts to Steps Timing. + (Thanks to DJ OMiY for reporting and isolating the problem.) + +2013/01/11 +---------- +* [Screen] Allow overlay screens to accept codes. + +2013/01/06 +---------- +* [TimingChanges, ScreenEdit] Fix a bug in the editor where adding BPM changes + that differ by a very small amount from the previous BPM change were not + added at all. [vulture/wolfman2000] + +2013/01/03 +---------- +* [ScreenGameplayShared] Fix routine mode. [djpohly/FSX/shakesoda/wolfman2000] + +================================================================================ +StepMania 5.0 beta 1a | 20121228 +-------------------------------------------------------------------------------- + +2012/12/28 +---------- +* [default] Improved autogen icon and Oni life display. [Midiman] +* [ScreenSelectMusic] Fix mouse events being eaten. [shakesoda] +* [ScreenEdit] Remove extra zeroes from editor text entry. [djpohly] +* [WheelBase] Add WheelBase.Move Lua binding. [shakesoda] + +2012/12/27 +---------- +* [default] Various theme improvements. [Midiman] +* [PlayerStageStats] Restore SetScore and SetCurMaxScore Lua bindings. [shakesoda] + +2012/12/26 +---------- +* Code restructuring. [djpohly/wolfman2000] + +================================================================================ +StepMania 5.0 beta 1 | 20121225 +-------------------------------------------------------------------------------- + +2012/12/25 +---------- +* [PlayerStageStats] Remove SetScore and SetCurMaxScore Lua bindings. [FSX] + +2012/12/24 +---------- +* [ScreenDebugOverlay] Don't reset the gamestate when reloading screens. Reloading + ScreenSelectMusic or any other screen which relies on that works now. [shakesoda] +* [RageUtil] Fix math.random() never returning > 0.5. [vyhd] + +2012/12/18 +---------- +* [default] Fix Final Stage not appearing on StageInformation if a Long or Marathon song is + played as the last song. [FSX] +* [fallback] Add Song:GetStageCost() [FSX] + +2012/12/17 +---------- +* [Font] Fix a unicode-related crash which would sometimes happen on SMO. [shakesoda] +* [GameState] Fix arrow stuttering for cases where you get duplicated values between + updates. This helped significantly for PulseAudio on Ubuntu 12.04, for me. [shakesoda] + +2012/12/13 +---------- +* [RageDisplay_GLES2] Carry over a bunch of functionality from RageDisplay_OGL, still not + usable however. [shakesoda] + +2012/11/26 +---------- +* [ScreenSelectMusic] Only unchoose steps if there are more than 10 seconds on the timer + to prevent unchoosing steps for an infinite timer. [Marcio Barrientos] + +2012/11/22 +---------- +* [ProfileManager] Added SaveProfile, SaveLocalProfile, GetLocalProfileIDs, + ProfileFromMemoryCardIsNew, GetSongNumTimesPlayed, LocalProfileIDToDir, and + GetLocalProfileDisplayNames Lua bindings. [Alfred Sorenson] +* [Profile] Add GetGUID Lua binding. [Alfred Sorenson] + +2012/11/13 +---------- +* [RageDisplay_OGL] Try to fix the shader compilation crash once and for all. [shakesoda] + +2012/10/31 +---------- +* [RageDisplay_GLES2] Initial GLES2 commit. Not functional. [shakesoda] + +2012/10/20 +---------- +* [NotesLoaderSMA] Fix default speed length for SMA files. [Aldo MX] +* [NotesLoaderSMA] First segment required a zero. [Aldo MX] + + +2012/10/17 +---------- +* [ScreenEdit] Don't allow ratings of 0. [shakesoda] + +2012/08/10 +---------- +* [InputHandler_Linux_PIUIO] Add interface to PIUIO kernel module. [djpohly] + +2012/08/04 +---------- +* General theme updates: made things faster, title menu updated. [Midiman] + +2012/07/26 +---------- +* [ScreenDebugOverlay] Added BackgroundColor metric. [AJ] + +2012/07/19 +---------- +* [OptionRow] Set text after running OnCommand so commands like "uppercase,true" + actually have a chance to work. [AJ] + +2012/07/17 +---------- +* [SongManager] Fix a bug where DVNO wouldn't always be gold. [AJ] + +================================================================================ +StepMania 5.0 alpha 3 | 20120711 +-------------------------------------------------------------------------------- + +2012/07/11 +---------- +* [ScreenEditMenu] Don't use "Blank" in the description for blank steps; + use a blank string instead. [AJ] + +2012/07/10 +---------- +* [ScreenSelectMusic] Fix an issue where Control+ wouldn't work. [AJ] + +2012/07/09 +---------- +* [InputMapper] Use "|" for separating entries instead of ",", since some + companies have names like "x Ltd., something". [Mordae, AJ] + +2012/07/06 +---------- +* [ScoreDisplayRave] Add FrameBase and FrameOver to the metrics. [AJ] +* [PlayerStageStats] Added GetSongsPassed and GetSongsPlayed Lua bindings. [AJ] + +2012/07/05 +---------- +* [ScreenRanking] Added "NextPage" command. "SwitchPage" command is + now "SwitchedPage". [AJ] +* [ScreenRanking] Don't clobber alpha values when applying colors in SetPage. [AJ] + +2012/07/03 +---------- +* [ScreenHowToPlay] Actually shows notes again. [AJ] +* [ScreenGameplay] When ShowLifeMeterForDisabledPlayers is true, don't fill up + life in the meter for the disabled player. (LifeMeterBar only) [AJ] + +2012/07/02 +---------- +* [ScreenHowToPlay] Run InitCommand on Characters if enabled. [AJ] +* [RageUtil] Add detection of ".hg" to StripCvsAndSvn. [AJ] + +2012/06/27 +---------- +* [SongManager] Ending a group's name in PreferredSongs with "/*" will now load + all songs from that group automatically. [AJ] + +2012/06/21 +---------- +* [ProfileManager] Added GetPlayerName(pn) Lua binding. [AJ] + +2012/06/05 +---------- +* [GrooveRadar] Added SetFromValues(pn,{f1,f2,f3,f4,f5}) Lua binding. [AJ] + +2012/06/02 +---------- +* [PrefsManager] Added StretchBackgrounds preference. [AJ] +* [BMSLoader] Add #banner support. [hanubeki] + Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=bf8b57b9a662af59de66b9d06ca282f38f9126d9 + +2012/05/31 +---------- +* [PaneDisplay] Added NullCountString metric. [AJ] +* [PlayerOptions] Fixes to Get/Set[C, M, X]Mod Lua bindings. [hanubeki] + Source: http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=97761b5dc87b8c8a1b296985a09814337578c745 + +2012/05/27 +---------- +* [MusicWheel] Added EmptyColor metric. [AJ] +* [PlayerState] Enabled GetPlayerController Lua binding. + +2012/05/21 +---------- +* [NotesLoaderBMS] Support for #BMP based background changes. [theDtTvB] +* [SongManager] Add song to the list of songs before loading it, this fixes + crashes in some BMS files. [theDtTvB] +* [ScreenEdit] Allow a new way of creating and modifying attacks using the + Area Menu. Note: Using the C or V keys is no longer allowed for attacks. + It will simplify things for later. [Wolfman2000] +* [Steps] Modified HasSignificantTimingChanges; the following now disqualify + when using a CMod: Stops, Delays, Warps, Speed Changes, Scroll Changes. + Songs with a non-constant BPM will only disqualify if the High/Low difference + is greater than 3.00. [AJ] + +2012/05/19 +---------- +* [Actor] Made the xy command a source-code level command. [AJ] + +2012/05/17 +---------- +* [LoadingWindow_Gtk] Actually resolve the path to the Splash file. [djpohly] + +2012/05/16 +---------- +* [ScreenWithMenuElements] Added DelayMusicSeconds metric. [AJ] +* [ScreenOptionsMasterPrefs] Allow for FastLoadAdditionalSongs preference + to be called via the "conf" command. [AJ] + +2012/05/14 +---------- +* [Course] Added AllSongsAreFixed() Lua binding. [AJ] + +================================================================================ +StepMania 5.0 alpha 2 | 20120504 +-------------------------------------------------------------------------------- + +2012/05/03 +---------- +* Add Var "Player" and Var "Controller" for NoteSkin. [hanubeki] + Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=824cff29912d1c29a667046ba463d195e81c524a +* [CustomSpeedMods] If a player decides to remove 1x from the machine profile's + custom speed mods, re-add it back in to avoid crashes. [AJ] + +2012/05/02 +---------- +* Make ReceptorArrowRow and GhostArrowRow respect the column draw order. [hanubeki] + Sourced from http://code.google.com/r/hanubeki-modified-sm-ssc/source/detail?r=8ccf7449651eef51e8c42d031aa64da49a0b72ce + +2012/04/25 +---------- +* [Profile] Added GetLastPlayedSong and GetLastPlayedCourse Lua bindings. [AJ] + +2012/04/22 +---------- +* [LifeMeterBar] Reverted a change from 2010 that messed with how the life meter + subtracts life. The life difficulty should match StepMania 3.9 again. [AJ] + +2012/04/08 +---------- +* [ScreenNetworkOptions] Fixed a bug where localized text would not show up + properly. Fixes issue 759. [AJ] +* [Steps, Song] Replace Steps:UsesSplitTiming with + Song:IsStepsUsingDifferentTiming for both C++ and Lua. [wolfman2000] + +2012/04/06 +---------- +* Modify Jousway's planned noteskin to allow it to work with Technomotion + style gameplay. Expect minor bugs. [Jousway, Wolfman2000] + +2012/04/03 +---------- +* [PlayerOptions] Fix setting some effect mods that were always set to Drunk. + I wonder who had too much to drink. [TaroNuke] + +2012/03/31 +---------- +* [GameManager] Allow beat single7 and versus7 to be shown in Demonstration. [AJ] + +2012/03/28 +---------- +* [ScoreKeeperRave] Actually handle hold scores in HandleHoldScore(). + Players should please provide feedback on how this affects gameplay, as this + is a temporary feature. [AJ] +* [GameConstantsAndTypes] Made StageResult Lua-aware. [AJ] +* [GameState] Added GetStageResult(pn) Lua binding. [AJ] +* [Player] Keysounds now respect the volume settings. [hanubeki] + Sourced from hanubeki-modified-sm-ssc rev. 16fc5b714582 + +2012/03/27 +---------- +* [ScreenEditMenu] Don't hardcode stopping the music on pressing the back button. + This interferes with the StopMusicOnBack metric. [AJ] + +2012/03/20 +---------- +* [Background] Fix 3D noteskins and dancing characters from clashing with each other. [shakesoda, AJ] +* [NoteField] Fix 3D noteskins overlapping. [shakesoda, AJ] +* [ScreenEdit] Don't use Step timing by default. [Midiman] +* [ScreenEdit] Allow playback of course modifiers in Course Edit mode [Midiman] + +2012/03/15 +---------- +* [04 Scoring.lua] Added various 3.9 and 3.9+ scoring methods. [hanubeki] + +2012/03/12 +---------- +* Remove libtheora support since ffmpeg already supports theora videos. [cvpcs] + +2012/03/10 +---------- +* Update ffmpeg support to v0.10. [cvpcs] + +2012/03/09 +---------- +* [PlayerOptions] Don't display x-mods when using m-mods. + Sourced from hanubeki-modified-sm-ssc rev. bd08a58dd7cf and OpenITG. + +2012/03/08 +---------- +* [MusicWheel] Added RouletteStopped message, which is broadcast when Roulette + is finished and the wheel is locked. [AJ] +* [WheelBase] Made WheelState a Lua-enabled enum and added + GetWheelState() Lua binding. Deprecated IsLocked() Lua binding. [AJ] + +2012/03/07 +---------- +* [ScreenSelectMaster] Now updates choices on player join; it will move the + scroller to the correct location, but the GainFocus/LoseFocus commands don't + seem to work. [AJ] + +2012/03/05 +---------- +* [GameCommand] Added GetDifficulty(), GetCourseDifficulty(), GetPlayMode(), + GetSortOrder(), GetAnnouncer(), GetPreferredModifiers(), and + GetStageModifiers() Lua bindings. [AJ] + +2012/03/04 +---------- +* [Player] Changed default Hold window to 0.250f, like it was in 3.9. [AJ] + +2012/03/02 +---------- +* [NotesLoaderBMS] Fix calculating stops, Support for #LNOBJ, Don't use #BACKBMP + as song background if main StepsType is beat-*. [hanubeki] + These changes constitute revisions f26caccf103e, 2d114b38c6c9, and b60f021d2b67 + of hanubeki-modified-sm-ssc. (http://code.google.com/r/hanubeki-modified-sm-ssc/) + +2012/03/01 +---------- +* [MemoryCardManager] Disable Memory Cards by default. If you want to use them, +set MemoryCards=1 in Save/Preferences.ini (or Save/Static.ini). [AJ] +* [GameState] Set Premium to Premium_DoubleFor1Credit by default. [AJ] +* [ScreenSelectMusic] Added PlaySoundOnEnteringOptionsMenu metric. [AJ] +* [MusicWheel, WheelBase] Added collapse sound. [AJ] + +================================================================================ +StepMania 5.0 alpha 1a | 20120219 +-------------------------------------------------------------------------------- + +2012/02/19 +---------- +* [Style] Added LockedDifficulty() Lua binding. [AJ] + +2012/02/15 +---------- +* [HighScore] Added Max Combo, Stage Award and Peak Award. New Lua bindings for + HighScore: GetMaxCombo(), GetStageAward(), GetPeakComboAward(). [AJ] + (the specifics of this are subject to change.) + +2012/02/10 +---------- +* [WheelBase, WheelItemBase] Turned WheelItemDataType into a Lua type, + made WheelBase:GetSelectedType() return the enum instead of a number. [AJ] + +2012/02/08 +---------- +* [ScreenEdit] Added support for editing keysounds. Use the Area Menu (Enter) + to either modify what sounds play on that row, or even remove a sound from + the list. Any sounds assigned to empty notes will automatically become + an AutoKeysound, and any AutoKeysounds that have their sound removed will + become empty notes. [Wolfman2000] + +2012/02/08 +---------- +* [ScreenOptionsMaster] Added StepsRowLayoutType metric. + (Valid values are "ShowAllInRow" or "ShowOneInRow".) [AJ] + +2012/01/23 +---------- +* [Player] Tap Note Scores (tns) can now be "AvoidMine" or "HitMine" in +JudgmentMessageCommand. [Saturn2888, shakesoda] + +2012/01/15 +---------- +* [WheelNotifyIcon] Add the NumIconsToShow metric. [Wolfman2000] +* [PlayerOptions] Fix a problem with m-mods where you would get m200 as + the default speed modifier. [AJ] + +2012/01/11 +---------- +* [ScreenEdit] Fix a floating point issue when dealing with speed segments. + [Wolfman2000] + +2012/01/09 +---------- +* [Song] Fix a bug introduced with "Only read certain tags during first load" + where song graphic files wouldn't load. [theDtTvB] + +================================================================================ +StepMania 5.0 alpha 1 | 20120108 +-------------------------------------------------------------------------------- + +2012/01/08 +---------- +* [Song] Add HasPreviewVid and GetPreviewVidPath lua binding [cerbo] + +2012/01/08 +---------- +* [ScreenManager] Made AddScreenToTop take a second (optional) parameter for + posting a ScreenMessage on screen pop. [AJ] +* Only read certain tags during first load; makes song loading faster. [theDtTvB] + +2012/01/07 +---------- +* Fix Portable.ini not working on Mac OS X. [shakesoda] + +2012/01/05 +---------- +* [PercentageDisplay] Remove unused ApplyScoreDisplayOptions metric; + added PercentFormat and RemainderFormat metrics. [AJ] +* Fix Portable.ini not working in Linux. [FSX] + +2012/01/04 +---------- +* Fix a scoring/grading bug with Lifts. [FSX] + +2011/12/27 +---------- +* [MusicWheel] Add IsRouletting Lua binding. [AJ] +* [LuaManager] Remove GetOSName Lua binding; use GetArchName instead. [AJ] + +2011/12/26 +---------- +* [ArchHooks_OSX] Worked around a crash when language detection goes wrong. + Note: a real fix should be looked into. [shakesoda] + +2011/12/23 +---------- +* [Song] Fixed a bug where a sample start of 0 wouldn't work. [AJ] +* [Game] Added CountNotesSeparately and GetMapJudgmentTo(TapNoteScore) + Lua bindings. [AJ] +* [StepMania.cpp] Fix initial aspect ratio on first boot, hopefully. + (See issues 6 and 27) [AJ] + +2011/12/22 +---------- +* [LuaManager] Added ProductFamily() Lua binding. [AJ] + +2011/12/17 +---------- +* [Various] Allow loading of *.jpeg in addition to *.jpg. [AJ] + +2011/12/16 +---------- +* [StreamDisplay] Added VelocityMultiplier, VelocityMin, VelocityMax, + SpringMultiplier and ViscosityMultiplier metrics. [AJ] + +2011/12/12 +---------- +* [ScreenEdit] Add the GAMESTATE:InStepEditor Lua binding. [Wolfman2000] +* [Player, ScreenGameplay] Allow failing on Oni without crashing. This one + took awhile. [Wolfman2000] +* [LifeMeterBattery] Fixed various issues (lives not fully disappearing on fail, + P2 lose life animation having the wrong x zoom, hide the lives number if it + falls below 0). [AJ] + +2011/12/11 +---------- +* [ScreenEdit] Restore cycling the timing segments for jumping between. + The required line somehow never got replaced. [Wolfman2000] + +2011/11/30 +---------- +* [PlayerOptions] Added IsEasierForSongAndSteps(Song,Steps,PlayerNumber) and + IsEasierForCourseAndTrail(Course, Trail) Lua bindings. [AJ] +* [PlayerState] Added GetSuperMeterLevel() Lua binding. [AJ] + +2011/11/28 +---------- +* [ScreenGameplay] Add the SurvivalModOverride metric. Let the themer decide + if mods should be overridden on survival or not. Funny enough, this used + to be true for the old Oni style mode, but...well, we'll cross that bridge + later. [Wolfman2000] +* [LifeMeterBattery] Added MaxLives metric, which limits the maximum amount of + lives. Setting this to 0 will remove the limit. [AJ] + +2011/11/27 +---------- +* [PlayerOptions] Pretty large changes here, namely a bunch of new bindings. + Fixed the logic for GetReversePercentForColumn; It will now return nil for + invalid columns. Also fixed the logic for UsingReverse (now checks for 1.0f) + and SetPassmark (no longer allows values < 0.00f and > 1.0f). [AJ] +* [ScreenEdit] Allow inserting and removing beats and timing changes in + specific note increments instead of just quarter notes (a whole beat). + Those that prefer to keep using the shortcut keys will note that the + behavior has not changed for that: only by going into the Area menu can you + deal with more specific changes. [Wolfman2000] + +2011/11/26 +---------- +* [ScreenEdit] Restore using F9 and F10 to adjust stops by a fixed amount. + Sorry for the delay in this. [Wolfman2000] +* [ScreenEdit] Minor convenience. If you attempt to create a negative stop + segment from scratch, it does not create, and you are not requested to + save on exit, for there is nothing to save. [Wolfman2000] +* [ScreenEdit] Allow Shift + F9/F10 for adjusting delays. This works the same + way as adjusting stops. [Wolfman2000] + +2011/11/25 +---------- +* [PlayerStageStats] Hitting a mine no longer gives you full combo when + [Gameplay] MineHitIncrementsMissCombo=true. [AJ] + +2011/11/24 +---------- +* [PlayerStageStats] Added GetFailed and GetNumControllerSteps Lua bindings. [AJ] + +2011/11/15 +---------- +* [LifeMeterBar] Added the ForceLifeDifficultyOnExtraStage metric and + the ExtraStageLifeDifficulty metric. Let the themer decide if extra stages + should have their own life bar behavior. Note that this metric does NOT + change the lifebar to the battery style. [Wolfman2000/FSX] + +2011/11/14 +---------- +* [Mac OS X] Restore JPEG functionality. [Wolfman2000] + +2011/11/06 +---------- +* [GameState] Add the RefreshNoteSkinData lua binding. This will only + refresh the NS data for the present game, not all games. [Wolfman2000] +* [ScreenSelectMusic] Fixed Rave difficulties not being synced on late join. + Fixes issue 577. [AJ] +* [GameplayAssist] Don't play sounds if the player is dead. Fixes issue 621. [AJ] + +2011/11/04 +---------- +* [ScoreKeeperRave] Revert fix from 2011/10/28. [AJ] +* [ScoreKeeperRave] Fixed Miss and HitMine giving meter life. + (Fixes issue 622.) [AJ] + +2011/11/02 +---------- +* [ArchHooks] Add the GetArchName lua binding. To the themers that use + GetOSName, that function may be deprecated in the future. For now, + both options exist. [vyhd, Wolfman2000] + +2011/11/01 +---------- +* [ArrowEffects] Fix Expand, and possibly other mods, from breaking if + using a second player. [Wolfman2000] +* [ArchHooks] Add the AppHasFocus lua binding. [vyhd, Wolfman2000] + +2011/10/29 +---------- +* [GameState] Add the ResetPlayerOptions lua binding. [Wolfman2000] + +2011/10/28 +---------- +* [ScoreKeeperRave] Fix an issue where the super meter would not decrease back + to 1 after hitting the end of 3. (Fixes issue 314.) [AJ] + +2011/10/27 +---------- +* [Default theme] Fixed the pref controlling timing segments on song meter. [FSX] + +2011/10/18 +---------- +* [LightsManager] Use song beat for menu button lights, allow demonstration to + flash pad lights when BlinkGameplayButtonLightsOnNote is true, light custom + game buttons when pressed during attract mode, general optimizations. [vyhd] + +2011/10/17 +---------- +* [ScreenEdit/NoteField] Fix an editor crash when you exit without saving + after creating new steps. [Wolfman2000] + +2011/10/16 +---------- +* [NoteDataUtil] Add the Backwards mod for games where the intended + definition of Mirror is different. Regarding Pump gameplay, what was + called Mirror in Preview 4 is considered Backwards now, and the original + Mirror is back in its old position. [Wolfman2000] + +2011/10/12 +---------- +* [Steps] Fix a bug where e.g. ".SM" ".DWI" ".Sm" ".sM" files + wouldn't properly load since the code was expecting lowercase. [AJ] + +2011/10/10 +---------- +* [NotesLoaderBMS] Add the time signature segments. [theDtTvB] + +2011/10/09 +---------- +* [NotesLoaderBMS] Fix the bug where keysounds that points to nonexistant file + gets assigned a random one. [theDtTvB] +* [NotesLoaderBMS] Use BMSLoader to load PMS files. [theDtTvB] +* [RageSoundReader_WAV] Fix ADPCM support. [theDtTvB] + +2011/10/08 +---------- +* [GameSoundManager] Add the PlayMusicPart lua binding. [Wolfman2000] +* [ScreenEdit] Add the FadeInPreview and FadeOutPreview metrics. This controls + how long the fade in and fade outs are for playing the preview music. + The default values are 0 and 1.5 respectively. [Wolfman2000] + +2011/10/07 +---------- +* [RageDisplay] Add the GetFPS, GetVPF, and GetCumFPS bindings. [Wolfman2000] + +2011/10/06 +---------- +* Various scoring fixes sourced from http://www47.atwiki.jp/waiei/pages/21.html + [A.C/@waiei, 桜為å°é³©/@sakuraponila] + +================================================================================ +StepMania 5.0 Preview 4 | 20111005 +-------------------------------------------------------------------------------- + +2011/10/04 +---------- +* [NoteDataUtil] More accurate Left, Right, and Mirror mods for Pump gameplay. + Major thanks to Hudson Felker and Bill Shillito here. [Wolfman2000] + +2011/10/01 +---------- +* [ScreenHighScores] Disable forced screen transition behavior when + ManualScrolling=true. [AJ] + +2011/09/30 +---------- +* [GameState] Added CurrentOptionsDisqualifyPlayer(player), + ApplyPreferredModifiers(player,string) and ApplyStageModifiers(player,string) + Lua bindings. [AJ] + +2011/09/29 +---------- +* [Fallback theme] Fix ImmediateHoldLetGo function. [Wolfman2000] +* [GameState] Add the EditAllowedForExtra metric. Use this if you want edit + steps to be allowed for accessing the extra stage. By default, this is + false. [Wolfman2000] + +2011/09/26 +---------- +* [Default theme] Added Song Timing Display user preference. [AJ] +* [ThemeManager] Add global Scripts dir. [shakesoda] + +2011/09/25 +---------- +* [WheelItemBase] Added GetColor and GetText Lua bindings. [AJ] + +2011/09/24 +---------- +* [ScreenEdit] Disable shifting timing changes down one beat if starting on + beat 0. Important information must stay on that beat. [Wolfman2000] +* [ScreenEdit] Disable converting rows to a stop or beat starting on beat 0. + There should be no reason for this at this time. [Wolfman2000] +* [MusicWheelItem] Add/reinstate MusicWheelItem Mode Normal/Color/OverPart. [AJ] +* [FadingBanner] Added LoadFromSortOrder(SortOrder) Lua binding. [AJ] + +2011/09/23 +---------- +* [ScreenEvaluation] Added RollingNumbersMaxComboClass metric. [AJ] +* [NotesLoaderSM] Fix loading .sm files with non standard difficulty names. + It should be Hard, not Heavy. [Wolfman2000] + +2011/09/22 +---------- +* [ScreenDebugOverlay] Replaced hardcoded toggle command with + ButtonTextToggledCommand metric. [AJ] +* [LoadingWindow_Win32] Make the StepMania window gain focus after the + loading window closes. Fixes issue 424. [AJ] + +2011/09/21 +---------- +* [FadingBanner] Added LoadRandom(), LoadRoulette(), LoadFallback(), + LoadCourseFallback(), and GetBanner(int) Lua bindings. [AJ] + +2011/09/18 +---------- +* [Song] Added GetSampleStart() and GetSampleLength() Lua bindings. [Wolfman2000] + +2011/09/16 +---------- +* [UnlockManager] Added GetNumLockedSongs() Lua binding. [Wolfman2000] +* [UnlockManager] Added IsSongLocked() Lua binding. [Wolfman2000] + +2011/09/12 +---------- +* [NotesLoaderSSC/WriterSSC] Allow all timing tags regardless of what timing + is used. [Wolfman2000] + +2011/09/11 +---------- +* [ScreenEvaluation] Added "evaluation full combo W1" and + "evaluation full combo W2" announcer cues. [AJ] +* [Banner] Added "Banner group fallback" graphic. [AJ] + +2011/09/09 +---------- +* [NotesLoaderBMS] Rewrite the BMS loader, should fix issues 430 and 500. [theDtTvB] + +2011/09/08 +---------- +* [GameManager] Fix shifting of 2P notes in beat mode. [1a2a3a2a1a] + +2011/09/07 +---------- +* [Model] Added GetDefaultAnimation() Lua binding. [AJ] +* [GameState] Added GetEarnedExtraStage() Lua binding. [AJ] + +2011/09/02 +---------- +* [MenuTimer] Added start(), disable() Lua bindings. Also renamed setseconds to + SetSeconds to match GetSeconds. [AJ] +* [GameManager] beat "versus" -> "versus5"; fix beat versus7 being "single7". [1a2a3a2a1a] + +2011/08/27 +---------- +* Updated libjpeg to 8c. +* [SongManager] Added GetCoursesInGroup(sCourseGroup,bIncludeAutogen), + GetSongGroupBannerPath(songGroup), GetCourseGroupBannerPath(courseGroup), + DoesSongGroupExist(songGroup), DoesCourseGroupExist(courseGroup) and + GetPopularSongs() Lua bindings. [AJ] +* [SongManager] Added GetPreferredSortSongs(), GetPreferredSortCourses(courseType,bIncludeAutogen), + and GetPopularCourses(courseType) Lua bindings. [AJ] +* [SongManager] Add SongToPreferredSortSectionName(song), WasLoadedFromAdditionalSongs(song), + and WasLoadedFromAdditionalCourses(course) Lua bindings. [AJ] +* [CryptManager] Add GenerateRandomUUID() Lua binding. [AJ] +* [ThemeManager] Added DoesThemeExist(sTheme), IsThemeSelectable(sTheme), + DoesLanguageExist(sLang), GetCurThemeName(), HasMetric(sGroup,sValue), and + HasString(sGroup,sValue) Lua bindings. [AJ] + +2011/08/23 +---------- +* [Makefile.am] Fixed version date and time handling. [AJ] + +2011/08/22 +---------- +* [PrefsManager, X11Helper] Added ShowMouseCursor preference. [AJ] +* [UnlockManager] Added GetStepOfAllTypes Lua binding. This gets the locked + Steps for all game types based on the difficulty specified. [Wolfman2000] +* [UnlockManager] Added requirepasschallengesteps Lua binding. This is more + self-explanitory: pass challenge to be able to play edits. [Wolfman2000] + +2011/08/21 +---------- +* [NotesLoaderSSC] Fix loading pre-split timing files that had blank timing + tags inside of them. Thanks to Vin.il for the catch. [Wolfman2000] +* [Song] Added Jacket, CD image (a la early DDR), and Disc (PIU-style) support. + Added GetJacketPath(), GetCDImagePath(), GetDiscPath(), HasJacket(), HasDisc(), + and HasCDImage() Lua bindings. [AJ] + +================================================================================ +StepMania 5.0 Preview 3 | 20110820 +-------------------------------------------------------------------------------- + +2011/08/20 +---------- +* [PlayerOptions] Add GetMMod() Lua binding. [AJ] +* [Player] Make keysounds respect volume preference. Fixes issue 344. [AJ] + +2011/08/19 +---------- +* [Steps] Add PredictMeter() and GetDisplayBPMType() Lua bindings. [AJ] +* [Song] Add ShowInDemonstrationAndRanking() Lua binding. [AJ] +* Turn off Autogen by default. [shakesoda] +* Disable automatic aspect ratio guessing, default to 854x480 + (16:9 because most newer displays are wide). [shakesoda] +* Turn on FastLoad and FastLoadAdditionalSongs by default. [shakesoda] + +2011/08/18 +---------- +* [RageInput] Added "No input devices were loaded." string to languages. [AJ] +* [RageInputDevice] Added localized names for InputDeviceState. [AJ] +* [Course] Add IsPlayableIn(StepsType) and IsRanking() Lua bindings. [AJ] +* [Trail] Added GetTotalMeter(), GetLengthSeconds(), IsSecret() + and ContainsSong(song) Lua bindings. [AJ] + +2011/08/16 +---------- +* Added PrettyPercent(numerator,denominator) Lua binding. [AJ] + +2011/08/14 +---------- +* [Foreground] Restore Foreground Changes for use in gameplay. Note that it + is recommended to use lua for #FGCHANGES from now on: not all XML changes + will work. [infamouspat] + +2011/08/13 +---------- +* [Theme-side] Added Fancy UI Background preference to Theme Options. [AJ] +* [LowLevelWindow_X11] Don't force the window into the upper left corner. [ZipFile] + +2011/08/07 +---------- +* [LifeMeterBattery] Added LostLife param to LifeChanged message. [AJ] +* [LifeMeterBattery] Converted LifeMeterBattery lives to an AutoActor. [AJ] +* [TimingData] Add HasDelays() Lua binding; HasStops() now only checks stops. [AJ] +* [GameState, SongUtil] Fix Issue 263 by not charging 2x stages for doubles when + not using joint premium. [AJ] +* [BeginnerHelper] Made BeginnerHelper run the OnCommand. [AJ] +* [GameState] add GetExpandedSectionName() Lua binding. [AJ] +* [ScreenSelectMusic] Added IdleCommentSeconds metric and + "ScreenSelectMusic IdleComment" announcer sound. [AJ] +* [NotesLoaderBMS] "Send the actual song file to LoadFromBMSFile in + BMSLoader::LoadNoteDataFromSimfile instead of the dummy one... + This fixes the wrong sound issue [423]..." [theDtTvB] + +2011/08/06 +---------- +* [NoteSkins/beat/default] Fix Issue 425. [AJ] +* [ScoreDisplayRave] Allow (Meter/Level)(X/Y) metrics to work again. [AJ] + +2011/08/05 +---------- +* [NoteField] Added AreaHighlightColor metric. [AJ] + +2011/08/04 +---------- +* [NoteTypes, ScreenEdit] Removed artificial MAX_NOTES_PER_MEASURE limit. [AJ] + +2011/08/02 +---------- +* [NotesSSC] Only write timing/attack tags for the step if there is a + difference from the song. For timing tags, at this time it means that if even + one tag is different, all tags are written. [Wolfman2000] + +2011/08/01 +---------- +* [MusicWheel, RoomWheel] Moved the "- EMPTY -" string to the languages file. [AJ] + +2011/07/31 +---------- +* [ScreenGameplay, LyricDisplay] Stop lyrics from animating on failure. + Fixes issue 298. [AJ] + +2011/07/30 +---------- +* [ProfileManager] Fix an issue when deleting recently created profiles. [AJ] +* Start removing anything related to Guitar mode. This was rushed in, and it + is not worth us keeping at this time. [Wolfman2000] + +2011/07/26 +---------- +* [ScreenEdit] Add a semi working implementation of the often requested + copy/paste selected timing data feature. This should make it easier for + some charters. [Wolfman2000] + +2011/07/21 +---------- +* [BeginnerHelper] Removed DancePadAngle metric in favor of DancePadOnCommand. + The same goes for PlayerAngle, dancer rotation is now handled in + PlayerP1/2OnCommand. [AJ] +* [Course] Bumped up max edit course title length to 16 (still feels too short). + Also added #DESCRIPTION tag and Course:GetDescription() Lua binding. [AJ] + +2011/07/20 +---------- +* [Win32/CrashHandlerChild] Crashlog and log now open in the player's default + text editor. Also, the Show Log button works again, including for people using + Portable.ini. [AJ] + +2011/07/19 +---------- +* [LoadingWindow] Added the ability for themes to have custom splash banners. + (Currently Windows-only.) [AJ] + +2011/07/17 +---------- +* [Cache] No longer store #NOTES in the cache. This should speed things up + on the first load if there is not much to write. (General note: this was + taken from another branch, but results at that point were great.) + [Wolfman2000] + +2011/07/13 +---------- +* [Difficulty] Allow ALL StepsTypes to use CustomDifficulty properly. + There was some unfair targeting of Couple and Routine. [Wolfman2000] +* [Steps] Calculate accurate radar values for Couple charts. [Wolfman2000] +* [ScreenEdit] Display more accurate chart data for Couple and Routine charts + for the future. No more having (almost) every row as a jump! [Wolfman2000] + +2011/07/12 +---------- +* [OptionRowHandler] Add a new metric to ScreenOptionsMaster: + StepsUseChartName. Use this if you want your charts to have a unique name + in the options menu. If there is no #CHARTNAME or it is "Blank", it reverts + to the original behavior. This metric is false by default. [Wolfman2000] +* [ScreenEdit] Fixed a bug involving #ATTACKS. Now when you set an attack, + the mods are reverted back to how they were prior to the attack being set. + [Wolfman2000] + +2011/07/09 +---------- +* [NotesTheUsual] Update the #COMBOS tag to allow for a Miss Combo attribute. + Any files that only use the Combo attribute will have that value copied to + miss combo on next launch. [Wolfman2000] +* [ScoreKeeperNormal] Better match #COMBOS with eval. Scoring formulas should + not be affected, but it may require more testing. [Wolfman2000] +* [Metrics] Have Pump mode lump the checkpoint judgments with Flawless and + Miss judgments on eval. Of course, this goes down to Perfect and Miss if + that is disabled. [Wolfman2000] + +2011/07/07 +---------- +* [ScreenEdit] Fix the NoMines transformation bug, issue 363. [Wolfman2000] +* [CourseLoaderCRS] Don't load BEST# and WORST# where # is greater than the + number of songs installed. Fixes issue 373. [AJ] +* [NotesAllSSC] Add the #CHARTNAME tag to the Steps. #DESCRIPTION is now for + more detailed descriptions, or perhaps some short hand lingo. All files + that used #DESCRIPTION will have their values moved to #CHARTNAME on + load. [Wolfman2000] +* [ScreenEdit] Add a Steps Data menu for getting numerical step data on the + chart. This is a read only menu. Edit Steps Information contains writable + information. [Wolfman2000] +* [NotesAllSSC] Add the Steps version of #DISPLAYBPM. The Song version is + still there, so themes should not have to worry about breakage. + [Wolfman2000] + +2011/07/06 +---------- +* [ScreenEdit] Fix the bug where hitting Enter during playing wouldn't take + the user back to the editor. [Wolfman2000] +* [Gameplay] Fix Fail mods being dishonored. [Midiman] + +2011/07/05 +---------- +* [ScreenEdit] Restore dance-couple and pump-couple for editing purposes. + Saving should still work, but this was never tested yet. [Wolfman2000] +* [ScreenOptions] Mini is now ITG Mini, and Tiny is now Pump Pro Mini. + This will prevent many prior courses from breaking. [sharksoda, Wolfman2000] +* [CharacterManager] Add a lua function to check how many characters you have. + For an example of how this is used, check the default theme's scripts + folder, specifically 03 ThemePrefs.lua. [Wolfman2000] + +2011/07/04 +---------- +* [ScreenEdit] Add a function to switch the notes the routine players have to + hit. In simple terms, Player 1's notes are now Player 2's and vice~versa. + Check it out in the Alter Menu. [Wolfman2000] +* [ScreenEdit] Add two routine mirroring functions. Now you can build sections + of a chart for one player, and mirror the effect for the other player when + finished. For Pump players, it is not a straight mirror, but is more akin + to what is found via normal routine charts. In other words, you'll be happy. + Check it out in the Alter Menu. [Wolfman2000] + +2011/07/03 +---------- +* [ScreenEdit] Fix a crash if one tries to remove an attack that doesn't + exist at that time. [Wolfman2000] + +================================================================================ +StepMania 5.0 Preview 2 | 20110703 +-------------------------------------------------------------------------------- + +2011/07/03 +---------- +* [Player] Bring mMods from OpenITG over. Also, a metric was added, + "MModHighCap", to cap the speed mod if required for playing songs like + Tsuhsuixamush. Set the metric to 0 or less to remove the cap. [AJ, sharksoda, + Wolfman2000] + +2011/07/02 +---------- +* [ScreenEdit] Fixed a crash when hitting Enter in the F1 help menu. [AJ] + +2011/06/30 +---------- +* [NotesAll] Use #FIRSTSECOND, #LASTSECOND, and #LASTSECONDHINT instead of the + former BEAT equivalents. Split Timing has made this a necessity thanks to + certain files that abuse Stops/Delays more than usual. [Wolfman2000] +* [ScreenEdit] Add a function in the Area Menu to designate the current beat + as the last second of the song. Please try to be smart and not use this too + early. [Wolfman2000] + +2011/06/28 +---------- +* [ScreenEdit] Add a function to copy/paste the TimingData of a player's + choice. Remember to be in the appropriate mode when copying and pasting. + By default, the song timing is already located in the clipboard, ready for + use. [Wolfman2000] + +2011/06/27 +---------- +* [Steps] Make sure #ATTACKS are copied when requested. [Wolfman2000] +* [ScreenEdit] Have Step Author up front instead of Chart Style. This is + probably going to be better overall. [Wolfman2000] +* [TimingData] Preserve the length of time for Speed Segment scaling when using + beats. [Wolfman2000] +* [NotesLoader/WriterSSC] #OFFSET is to be before #ATTACKS. This is required if + we pursue beat based attacks and not just second based. [Wolfman2000] + +2011/06/26 +---------- +* [UnlockManager] New metric: AutoLockEditSteps. Use this to hide bonus charts + until the Expert steps are beaten. No guarantee that this works with no + challenge steps in the song. This defaults to false. [Wolfman2000] +* [UnlockManager] New metric: SongsNotAdditional. Set to true to keep the + default behavior, false to have the AdditionalSongs folder contain + unlockable material. This is set to true to start. [Wolfman2000] +* [ScreenEdit] Allow jumping between all segments, not just Label segments. + You still use Ctrl + ,/. to jump, but now you use Ctrl + N/M to cycle the + segments. By default, it starts with Label. [Wolfman2000] +* [PlayerOptions] No longer display StepAttacks in the player's list. + Instead, show NoAttacks if attacks are disabled. [Wolfman2000] + +2011/06/24 +---------- +* [Actor] Implement compound(length,tweens) in _fallback/02 Actor.lua. [AJ] +* [UnlockManager] Add a new unlock reward: StepsType. This is similar to + unlocking Steps, but it is targeted for one step in one stepstype rather + than one step in all stepstypes. This needs testing. [Wolfman2000] +* [ScreenEdit] Add the option to convert delays to beats. Just find a better + song to use this on besides Uprock. [Wolfman2000] +* [ScreenEdit] Fix a crash if you don't save any steps on a new song. + [Wolfman2000] +* [NotesLoader/WriterSSC] Add support for Step #ATTACKS. Furthermore, Song + Attacks (or rather, Step Attacks as it should be called now) are turned on + by default instead of off. [Wolfman2000] + +2011/06/19 +---------- +* [EditMenu] Allow all songs to work in Practice Mode, regardless of folder + location. This fixes a crash if everyone had songs in AdditionalSongs. + [Wolfman2000] + +2011/06/17 +---------- +* [LifeMeterBattery] Fixed a bug where MinesSubtractLives was not being honored. + Also added LifeChanged message to changing of life on holds. [AJ] + +2011/06/15 +---------- +* [TimingData] Added many lua bindings for the other timing segments. GetWarps, + GetCombos, GetTimeSignatures, GetTickcounts, GetFakes, GetScrolls, GetSpeeds. + This should cover all of them now. [Wolfman2000] + +2011/06/13 +---------- +* [InputHandler_DirectInput] Fixed MouseWheel input not resetting. [AJ] +* [ScreenTextEntry] Make it so only the keyboard's Enter key can finish the + screen. Should fix issues with buttons whose secondary function is MenuStart. [AJ] +* [InputMapper] Modify default mappings. Use the Hyphen key instead of the + Numlock key for Player 2's GAME_BUTTON_BACK. This should address some + issues with Player 2 being unable to back out if they use a laptop. + [Wolfman2000] +* [NoteDisplay] Add two new metrics. + * DrawRollHeadForTapsOnSameRow: bool, similar to DrawHoldHeadForTapsOnSameRow + * TapHoldRollOnRowMeansHold: bool, true means hold and false means roll + * No noteskins should require updating, as these were placed in common/common + for ease of use. [Wolfman2000] +* [LifeMeterBattery] Added ChangeLives(int) Lua binding. [AJ] +* [LifeMeterBattery] Added DangerThreshold metric. [AJ] +* [LifeMeterBattery] Added some important metrics. [AJ] + * MinScoreToKeepLife='TapNoteScore_*' - any score below this = loss of life. + * SubtractLives=1 - how many lives are lost when going below MinScoreToKeepLife. + * MinesSubtractLives=1 - how many lives are lost when hitting a mine. + * HeldAddLives=0 - how many lives are gained when a hold is completed. + * LetGoSubtractLives=1 - how many lives are lost on a dropped hold. + +2011/06/12 +---------- +* [ScreenNetSelectMusic] Add PlayerOptionsScreen metric. [AJ] +* [ScreenEdit] Restore the old PageUp/PageDown behavior, added Control + + PageUp/PageDown to use recent time signature behavior. Laptop users, that + includes you guys too: semicolon and apostrophe are still good. [Wolfman2000] + +2011/06/11 +---------- +* [ScreenEdit] Allow setting the Music Preview via the Alter Menu. Just select + your area, enter the menu, and choose "Designate as Music Preview". No more + math calculations needed! [Wolfman2000] +* [SongUtil] Added GetPlayableSteps(Song) Lua binding. [AJ] +* [Steps] Allow 255 characters for all chart descriptions, including edits. + We are no longer bound by In The Groove I think. [Wolfman2000] +* [Player] Add GetPlayerTimingData() Lua binding. [Wolfman2000] + +2011/06/10 +---------- +* [ScreenEdit] Split the Area Menu into the Area Menu and Alter Menu. Use the + "A" key to enter the Alter Menu when a selection of notes/rows are + highlighted. Use the Enter key to enter the old Area Menu for the options that + do not depend on selecting NoteData. [Wolfman2000] +* [ScreenEdit] Allow converting selections to Delays, Warps, or Fakes as well + as Stops. Remember, use the Alter Menu for this. [Wolfman2000] + +2011/06/09 +---------- +* [ScreenSyncOverlay] Ensure that F11 / F12 work with all charts due to Split + Timing. [Wolfman2000] + +2011/06/08 +---------- +* Any notes in a fake segment or warp segment are completely ignored for + scoring purposes. Now you can get 100% on your warping goodness! + [Wolfman2000] + +2011/06/06 +---------- +* [PlayerOptions] Removed the ScoreDisplay mod choices. Use lua to make your + own scoring formulas that work in reverse instead. [Wolfman2000] +* [ScreenGameplay] Fix an assist tick bug if there was no Player 1. Note that + this changes the behavior slightly: it is the first enabled player, or + master player, that gets the ticks now. A better solution will be looked at + in the future. [Wolfman2000] +* [NoteDataUtil] Fix a radar issue involving hands. Unfortunately, this means + yet another cache reload for accuracy purposes. [Wolfman2000] + +2011/06/04 +---------- +* Changed default MusicWheelSwitchSpeed to 15 (was 10). [AJ] +* [AnnouncerManager] Fixed a bug where no announcers would be loaded. [AJ] +* Restored the UserPrefAutoSetStyle behavior. [Wolfman2000] +* [NotesLoaderSMA] Better way of identifying beats and seconds. [Wolfman2000] + +================================================================================ +StepMania 5.0 Preview 1a | 20110603 +-------------------------------------------------------------------------------- + +2011/06/03 +---------- +* [LifeMeterBattery] Added LivesLeft param to LifeChanged message. [AJ] +* [Windows] Set up directories for pictures and app data in their proper + location. [Henke] +* [NotesLoaderSM] Fix an Offset load bug. [Wolfman2000] + +2011/06/02 +---------- +* [BPMDisplay] Added SetFromSteps Lua binding. [AJ] +* [ScreenDebugOverlay] Switch the R and T keys to be Volume Down and Up + respectively. I have to admit, it makes more sense to have volume up be + on the right instead of the left. [Wolfman2000] +* [SongManager] Make autogen courses have "Autogen" as the Scripter. [AJ] + +2011/06/01 +---------- +* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] +* [ScreenEdit] Fix Song Timing behaviors. [Wolfman2000] + +2011/05/31 +---------- +* [Player] Added the BattleRaveMirror metric. This determines if Battle and + Rave mode will have the two players with mirrored charts or not. By default, + this is set to true, preserving the ITG style behavior. [Wolfman2000] +* [TimingData] Added the HasScrollChanges lua binding. [Wolfman2000] + +================================================================================ +StepMania 5.0 Preview 1 | 20110529 +-------------------------------------------------------------------------------- + +2011/05/27 +---------- +* [ScreenEdit] Added the LoopOnChartEnd metric. Once you get to the end of + the chart while playing it in the editor, this controls whether it loops and + plays again, or simply stops. By default, this is true, replicating current + behavior. Set to false to replicate older StepMania behavior. [Wolfman2000] + +2011/05/26 +---------- +* [ScoreKeeperNormal] Added the MissComboIsPerRow metric. Similar to the + ComboIsPerRow metric, this determines how much miss combo is earned on missing + a row of notes. By default, this is true. Set to false to replicate Pump Pro + behavior. [Wolfman2000] + +2011/05/25 +---------- +* [NotesLoaderSSC/NotesWriterSSC] Added the ScrollSegments. Think BPM change, + but not. [theDtTvB] + +2011/05/23 +---------- +* [Steps] Added the UsesSplitTiming Lua binding. [Wolfman2000] + +2011/05/20 +---------- +* [CryptManager] Added SHA1File Lua binding. [AJ] + +2011/05/19 +---------- +* [BPMDisplay] Add CourseCycleSpeed metric. [AJ] + +2011/05/17 +---------- +* [NotesWriterSM] Write out OpenITG compatible SM files from here on out. + This includes turning Warps into Negative Stops. For those that wanted + negative BPMs specifically, my apologies, but stops are easier on math. + [Wolfman2000] + +2011/05/16 +---------- +* [ProfileManager] Added ProfileWasLoadedFromMemoryCard(PlayerNumber) + Lua binding. [AJ] +* Added #FAKES to the SSC format. Similar to the fake arrows, these blocks + prevent all judgments within the range. [Wolfman2000] +* Changed the syntax of #WARPS slightly. Now the second value is the relative + distance that is skipped, not the absolute value when you start hitting + arrows again. [Wolfman2000] + +2011/05/15 +---------- +* [ScreenGameplay] Removed hardcoded commands for Debug (give up text) and + replace them with DebugStartOnCommand, DebugBackOnCommand, and + DebugTweenOffCommand. [AJ] +* Added #SPEEDS to the SSC format. This multiplies your scrolling speed during + gameplay, not replaces it (see mod attacks for replacing). [Wolfman2000] + +2011/05/14 +---------- +* [ModIcon] Added StopWords metric. [AJ] +* [ScreenSelectMaster] Add "ScreenEmpty" param to MenuStartP# when the GameCommand + doesn't set a screen. [AJ] +* [StepsDisplay] Added MeterFormatString metric. [AJ] +* [MusicWheel] Added ShowSectionsInBPMSort and ShowSectionsInLengthSort metrics. [AJ] +* [ScreenEvaluation] Stop the Bonus bars from overflowing in course modes. [AJ] +* [Banner] Added ScrollMode and ScrollSortOrder metrics. [AJ] + +2011/05/13 +---------- +* Added Split Timing to .SSC files. All older .SSC files and other file + formats are converted to split timing on cache load. We are no longer bound + by Song Timing for everything. [theDtTvB, Wolfman2000, TeruFSX] + +2011/05/11 +---------- +* [GameSoundManager] Added PlayAnnouncer Lua binding. [AJ] +* [AnnouncerManager] Add support for "gameplay combo #" for announcer. [AJ] + +2011/05/10 +---------- +* [Sprite] Added SetSecondsIntoAnimation Lua binding. [AJ] +* [BPMDisplay] Added SetFromCourse Lua binding. [AJ] + +2011/05/03 +---------- +* [ScreenEdit] Allow changing the Beat 0 Offset, Music Sample Start, and + Music Sample Length via Edit Song Info menu. [Wolfman2000] + +2011/05/02 +---------- +* [ScreenSelectMusic] Added NullScoreString metric. [AJ] + +2011/04/17 +-------- +* Use lua for all primary score keeping. Course modes right now still use the + old fashioned system. [TeruFSX, Wolfman2000] + +2011/04/09 +-------- +* [Player] Force hold judgments to take place before setting the score. + [theDtTvB] + +2011/04/05 +-------- +* [NotesLoaderSSC, NotesWriterSSC] Add the #LABELS tag. This is meant for step + editors to label different parts of their stepcharts. Use Control + , or . to + jump to different labels made. [Wolfman2000] + diff --git a/Docs/CommandLineArgs.txt b/Docs/legacy/CommandLineArgs.txt similarity index 100% rename from Docs/CommandLineArgs.txt rename to Docs/legacy/CommandLineArgs.txt diff --git a/Docs/Copying.MAD b/Docs/legacy/Copying.MAD similarity index 98% rename from Docs/Copying.MAD rename to Docs/legacy/Copying.MAD index fbdd65f6f8..d60c31a97a 100644 --- a/Docs/Copying.MAD +++ b/Docs/legacy/Copying.MAD @@ -1,340 +1,340 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Docs/CourseFormat.txt b/Docs/legacy/CourseFormat.txt similarity index 100% rename from Docs/CourseFormat.txt rename to Docs/legacy/CourseFormat.txt diff --git a/Docs/CustomMissionReference.txt b/Docs/legacy/CustomMissionReference.txt similarity index 100% rename from Docs/CustomMissionReference.txt rename to Docs/legacy/CustomMissionReference.txt diff --git a/Docs/Devdocs/BuildingFfmpegOnMac.txt b/Docs/legacy/Devdocs/BuildingFfmpegOnMac.txt similarity index 100% rename from Docs/Devdocs/BuildingFfmpegOnMac.txt rename to Docs/legacy/Devdocs/BuildingFfmpegOnMac.txt diff --git a/Docs/Devdocs/CodingStyle.txt b/Docs/legacy/Devdocs/CodingStyle.txt similarity index 100% rename from Docs/Devdocs/CodingStyle.txt rename to Docs/legacy/Devdocs/CodingStyle.txt diff --git a/Docs/Devdocs/CompileFlags.txt b/Docs/legacy/Devdocs/CompileFlags.txt similarity index 100% rename from Docs/Devdocs/CompileFlags.txt rename to Docs/legacy/Devdocs/CompileFlags.txt diff --git a/Docs/Devdocs/GoldenRules.txt b/Docs/legacy/Devdocs/GoldenRules.txt similarity index 100% rename from Docs/Devdocs/GoldenRules.txt rename to Docs/legacy/Devdocs/GoldenRules.txt diff --git a/Docs/Devdocs/NegBPMsTutorial.html b/Docs/legacy/Devdocs/NegBPMsTutorial.html similarity index 98% rename from Docs/Devdocs/NegBPMsTutorial.html rename to Docs/legacy/Devdocs/NegBPMsTutorial.html index ee9d34f0c7..932f9986e1 100644 --- a/Docs/Devdocs/NegBPMsTutorial.html +++ b/Docs/legacy/Devdocs/NegBPMsTutorial.html @@ -1,130 +1,130 @@ - - -Negative BPM/Stop Tutorial by WinDEU - - - -Hello everyone, and welcome to WinDEU's Negative BPM tutorial! Making negative -BPMs is pretty complex, so hopefully this guide will help you guys out.
-
-NOTE: I am using -SM 3.95 for this tutorial. 3.9 works as well, and is probably better to use -for playback purposes. When a negative BPM hits in edit mode, 3.95 jumps very -quickly (but not instantly) to the next point in the chart, whereas 3.9 does -do it instantly.
-
-What are negative BPMs? -Negative BPMs are the act of "warping" to a -later place in the chart, skipping multiple lines of the chart and -ignoring anything within those areas.
-
-Once you understand how negative BPMs work, it shouldn't be too hard to -figure out.
-
-So, let's start out with a screenshot.
-
- -
-We start off on measure 1, with a current second of 0.055, and a BPM of 150. -Take note of the current second (upper right), this is very important in -dealing with negative BPMs.
-
- -
-We are now on measure 2, with a BPM of -150, the exact opposite of the normal -BPM. Look at the current second again. It took 1.600 seconds to scroll 1 -whole measure at 150 BPM. Right now the current second is 1.655. Also of -note, the BPM goes back to 150 starting on measure 3. Now, here's where the -magic happens.
-
-
-We are on measure 3, back into positive BPM territory, but take a look at the -current second again. It is 0.055 on measure 3, the same value as the current -second from measure 1. This makes sense, because it took -1.600 seconds to -scroll from measure 2 to measure 3, because the BPM was negative during that -measure.
-
-
-As you can see from the current second on measure 4, it is the same value as measure 2.
-
-This is how the warping happens. When the chart first reaches the negative BPM, -it will search for the next positive BPM value. -NOTE: if there is no -positive BPM after the last negative BPM, I believe that the song ends -instantly, because it has reached the highest time possible within the chart. -Once the negative BPM hits, the current second will start counting backwards -forever.
-
-So, once the negative BPM hits, the game attempts to find the next place in -the chart that matches the current second of -the exact moment the negative BPM hit. At measure 2, the current second -was 1.655, and from the picture above, we can see that the next place that the -current second is 1.655 would be measure 4. So, you've effectively created a -warp going from measure 2 to measure 4, skipping everything in between.
-
- -
-So basically, it comes down to this: When making negative BPMs, make sure that -the space between the negative BPM and the next positive BPM is -doubled (assuming that you're using -the same BPM, which would be the easiest method anyway).
-
-Negative Stops -

-Negative stops work about the same way as negative BPMs, without the mess -of having to change around the BPMs. There is a little math involved, though.
-
-Let's say that you want to do a 2-measure warp, like the negative BPM example -above. You need to simulate going backwards by two measures. Normal stops keep -the current second going, even though the chart is at a standstill. Negative -stops keep the current second going as well, only backwards.
-
-First, find the time it would take to progress two measures. You can do this -by either checking the current second, going down two measures, check the -current second again, and take the difference. Or, you can calculate it like this:
-
-60/[BPM] = [quarter note value, in seconds]
-[quarter note] x 8 = [2 measures, in seconds]
-
-So that translates to:
-
-60/150 = 0.400
-0.400 x 8 = 3.200 seconds = two measures
-
-Now that we've got that out of the way, it's time to make the negative stop. -You might have noticed something though. StepMania doesn't let you input -negative stops. F9 to decrease the stop values in edit mode doesn't let you -go below 0.00, and adding a negative stop through Add Stop from the menu -doesn't work either.
-
-Unfortunately, you'll have to manually insert the negative stop into the .sm -file. NOTE: Before you -manually insert any negative stops, make sure to save your chart, otherwise -any unsaved data will be lost!
-
-This time, take note of the current beat -(again, upper right). Now, open up the .sm file and look for the #STOPS tag. -If you want to add a -3.200 long stop in at measure 2, it will look like this:
-
-#STOPS:4.000=-3.200;
-
-After you're done, save the .sm, and go back to StepMania (which should still -be open). Press ESC, and go to the menu option "Revert From Disk." It will -warn you that any unsaved changes will be lost (which is why I gave the warning -before explaining all of this). Choose yes, and you should see the negative -stop value appear on measure 2.
-
-
-
-If you scroll to measure 2, and then to measure 4, you will see that the -current second values are the same, meaning that you've successfully created -a warp with negative stops!
-
-NOTE: Using a lot of -negative stops in a short period of time tends to lag ITG machines a lot, -so be wary of this.
-
-That covers the basics of negative BPMs and negative stops. Hopefully this guide helps! - + + +Negative BPM/Stop Tutorial by WinDEU + + + +Hello everyone, and welcome to WinDEU's Negative BPM tutorial! Making negative +BPMs is pretty complex, so hopefully this guide will help you guys out.
+
+NOTE: I am using +SM 3.95 for this tutorial. 3.9 works as well, and is probably better to use +for playback purposes. When a negative BPM hits in edit mode, 3.95 jumps very +quickly (but not instantly) to the next point in the chart, whereas 3.9 does +do it instantly.
+
+What are negative BPMs? +Negative BPMs are the act of "warping" to a +later place in the chart, skipping multiple lines of the chart and +ignoring anything within those areas.
+
+Once you understand how negative BPMs work, it shouldn't be too hard to +figure out.
+
+So, let's start out with a screenshot.
+
+ +
+We start off on measure 1, with a current second of 0.055, and a BPM of 150. +Take note of the current second (upper right), this is very important in +dealing with negative BPMs.
+
+ +
+We are now on measure 2, with a BPM of -150, the exact opposite of the normal +BPM. Look at the current second again. It took 1.600 seconds to scroll 1 +whole measure at 150 BPM. Right now the current second is 1.655. Also of +note, the BPM goes back to 150 starting on measure 3. Now, here's where the +magic happens.
+
+
+We are on measure 3, back into positive BPM territory, but take a look at the +current second again. It is 0.055 on measure 3, the same value as the current +second from measure 1. This makes sense, because it took -1.600 seconds to +scroll from measure 2 to measure 3, because the BPM was negative during that +measure.
+
+
+As you can see from the current second on measure 4, it is the same value as measure 2.
+
+This is how the warping happens. When the chart first reaches the negative BPM, +it will search for the next positive BPM value. +NOTE: if there is no +positive BPM after the last negative BPM, I believe that the song ends +instantly, because it has reached the highest time possible within the chart. +Once the negative BPM hits, the current second will start counting backwards +forever.
+
+So, once the negative BPM hits, the game attempts to find the next place in +the chart that matches the current second of +the exact moment the negative BPM hit. At measure 2, the current second +was 1.655, and from the picture above, we can see that the next place that the +current second is 1.655 would be measure 4. So, you've effectively created a +warp going from measure 2 to measure 4, skipping everything in between.
+
+ +
+So basically, it comes down to this: When making negative BPMs, make sure that +the space between the negative BPM and the next positive BPM is +doubled (assuming that you're using +the same BPM, which would be the easiest method anyway).
+
+Negative Stops +

+Negative stops work about the same way as negative BPMs, without the mess +of having to change around the BPMs. There is a little math involved, though.
+
+Let's say that you want to do a 2-measure warp, like the negative BPM example +above. You need to simulate going backwards by two measures. Normal stops keep +the current second going, even though the chart is at a standstill. Negative +stops keep the current second going as well, only backwards.
+
+First, find the time it would take to progress two measures. You can do this +by either checking the current second, going down two measures, check the +current second again, and take the difference. Or, you can calculate it like this:
+
+60/[BPM] = [quarter note value, in seconds]
+[quarter note] x 8 = [2 measures, in seconds]
+
+So that translates to:
+
+60/150 = 0.400
+0.400 x 8 = 3.200 seconds = two measures
+
+Now that we've got that out of the way, it's time to make the negative stop. +You might have noticed something though. StepMania doesn't let you input +negative stops. F9 to decrease the stop values in edit mode doesn't let you +go below 0.00, and adding a negative stop through Add Stop from the menu +doesn't work either.
+
+Unfortunately, you'll have to manually insert the negative stop into the .sm +file. NOTE: Before you +manually insert any negative stops, make sure to save your chart, otherwise +any unsaved data will be lost!
+
+This time, take note of the current beat +(again, upper right). Now, open up the .sm file and look for the #STOPS tag. +If you want to add a -3.200 long stop in at measure 2, it will look like this:
+
+#STOPS:4.000=-3.200;
+
+After you're done, save the .sm, and go back to StepMania (which should still +be open). Press ESC, and go to the menu option "Revert From Disk." It will +warn you that any unsaved changes will be lost (which is why I gave the warning +before explaining all of this). Choose yes, and you should see the negative +stop value appear on measure 2.
+
+
+
+If you scroll to measure 2, and then to measure 4, you will see that the +current second values are the same, meaning that you've successfully created +a warp with negative stops!
+
+NOTE: Using a lot of +negative stops in a short period of time tends to lag ITG machines a lot, +so be wary of this.
+
+That covers the basics of negative BPMs and negative stops. Hopefully this guide helps! + \ No newline at end of file diff --git a/Docs/Devdocs/SMLanProtocol.txt b/Docs/legacy/Devdocs/SMLanProtocol.txt similarity index 100% rename from Docs/Devdocs/SMLanProtocol.txt rename to Docs/legacy/Devdocs/SMLanProtocol.txt diff --git a/Docs/Devdocs/SMO_protocol-aj.txt b/Docs/legacy/Devdocs/SMO_protocol-aj.txt similarity index 100% rename from Docs/Devdocs/SMO_protocol-aj.txt rename to Docs/legacy/Devdocs/SMO_protocol-aj.txt diff --git a/Docs/Devdocs/SMXML.txt b/Docs/legacy/Devdocs/SMXML.txt similarity index 100% rename from Docs/Devdocs/SMXML.txt rename to Docs/legacy/Devdocs/SMXML.txt diff --git a/Docs/Devdocs/Sound Drivers.txt b/Docs/legacy/Devdocs/Sound Drivers.txt similarity index 100% rename from Docs/Devdocs/Sound Drivers.txt rename to Docs/legacy/Devdocs/Sound Drivers.txt diff --git a/Docs/Devdocs/SplitTiming.txt b/Docs/legacy/Devdocs/SplitTiming.txt similarity index 98% rename from Docs/Devdocs/SplitTiming.txt rename to Docs/legacy/Devdocs/SplitTiming.txt index 26470f103f..cc7ad676e4 100644 --- a/Docs/Devdocs/SplitTiming.txt +++ b/Docs/legacy/Devdocs/SplitTiming.txt @@ -1,96 +1,96 @@ -This document describes the implementation of TimingData in StepMania, as of -shortly after version 5.0 beta 1a. - - -== What is TimingData? == - -TimingData refers to the information in a chart (a "Steps") or a song which -maps real time to beats and vice versa. This includes all BPMs and the -initial offset, as well as time gimmicks like stops, warps, and delays. The -TimingData object itself only has a few members: -* the name of the file that specified the data (for display only) -* the beat 0 offset -* a vector of TimingSegments for each type (BPM, warp, label, etc.) - -Each TimingSegment specifies a starting point in the chart, as well as any -parameters which are specific to that segment type. For a list of the -different types of TimingSegments, see TimingSegments.h. - - -== Split Timing == - -TimingData is primarily used for charts and songs, to specify the BPM and -offset and to implement gimmicks, as well as to synchronize effects with -background music. (It also provides features such as labels and time -signatures which can be useful when editing a chart.) - -Prior to StepMania 5, each song had a single TimingData structure which was -then used by all of the charts associated with that song. StepMania 5 -introduces a feature known as Split Timing, wherein a chart can have -individual TimingData ("Steps Timing") which is independent of the song's -TimingData ("Song Timing"). This allows for Pump-style gimmicks which can -differ between difficulties on the same song. - - -== Implementation == - -In the code, Song Timing is contained in the m_SongTiming field of a Song -object. Song Timing is used by default for any chart which does not specify -its own timing information. - -If a chart has its own timing information, this is contained in the m_Timing -field of the Steps object. If the chart does not have separate timing -information, the m_Timing structure will be empty (i.e. none of the vectors -will contain any TimingSegments). The TimingData::empty() function provides a -simply way to determine this. - -The most common way to get the TimingData for a chart is to use the -GetTimingData() function of the Steps object. This function will perform the -appropriate fallback to Song Timing if the chart's timing is empty. If, as in -the editor or sync implementations, it is necessary to access the Steps Timing -or Song Timing individually, the corresponding fields can be used instead. - -=== Editing === - -The editor has a "timing mode" setting which can be toggled between Song -Timing and Steps Timing (in the code, GAMESTATE->m_bIsUsingStepTiming). This -mode determines which set of TimingData will be updated when changes are made -with hotkeys or the Timing menu. It defaults to Steps Timing if the chart -being loaded has individual TimingData, and Song Timing otherwise. -Considering that we also want this to behave according to whether a chart has -individual timing, there are four possibilities when making a change: - -1. Song Timing mode, chart DOES NOT HAVE individual timings: changes will be - made to the Song Timing, and the chart will not have individual timings - added to it. Because of this, the changes to Song Timing will "show - through" to this chart. -2. Song Timing mode, chart HAS individual timings: changes will be made to the - Song Timing only. The timings in the chart will be left untouched. Because - of this, the changes to Song Timing will not affect this chart. -3. Steps Timing mode, chart HAS individual timings: changes will be made to the - Steps Timing only and will affect only this chart. -4. Steps Timing mode, chart DOES NOT HAVE individual timings: first, the Song - Timing will be copied into this chart. The changes are then made to the - Steps Timing only and will affect only this chart. - -Case #4 describes how Steps Timing is added to a chart: simply select Steps -Timing mode and start making changes. To remove Steps Timing, use the -corresponding item in the Timing menu. - - -== File formats == - -A quick note is in order about Split Timing support in the different file -formats supported by StepMania: - -* SSC files support Split Timing natively. Timing tags such as #BPMS in the - file header apply to the song, whereas the same tags inside a #NOTEDATA - section apply only to the current chart. -* SM files do not support Split Timing, since there is no way to specify - individual timing for a chart. -* SMA files support Split Timing in a similar fashion to SSC files. -* The KSF and BMS formats use one file for each chart, and therefore already - have per-chart timing information. When reading these formats, *every - chart* has Steps Timing. -* The DWI format does not support Split Timing, so Steps Timing is not written - to DWI files. +This document describes the implementation of TimingData in StepMania, as of +shortly after version 5.0 beta 1a. + + +== What is TimingData? == + +TimingData refers to the information in a chart (a "Steps") or a song which +maps real time to beats and vice versa. This includes all BPMs and the +initial offset, as well as time gimmicks like stops, warps, and delays. The +TimingData object itself only has a few members: +* the name of the file that specified the data (for display only) +* the beat 0 offset +* a vector of TimingSegments for each type (BPM, warp, label, etc.) + +Each TimingSegment specifies a starting point in the chart, as well as any +parameters which are specific to that segment type. For a list of the +different types of TimingSegments, see TimingSegments.h. + + +== Split Timing == + +TimingData is primarily used for charts and songs, to specify the BPM and +offset and to implement gimmicks, as well as to synchronize effects with +background music. (It also provides features such as labels and time +signatures which can be useful when editing a chart.) + +Prior to StepMania 5, each song had a single TimingData structure which was +then used by all of the charts associated with that song. StepMania 5 +introduces a feature known as Split Timing, wherein a chart can have +individual TimingData ("Steps Timing") which is independent of the song's +TimingData ("Song Timing"). This allows for Pump-style gimmicks which can +differ between difficulties on the same song. + + +== Implementation == + +In the code, Song Timing is contained in the m_SongTiming field of a Song +object. Song Timing is used by default for any chart which does not specify +its own timing information. + +If a chart has its own timing information, this is contained in the m_Timing +field of the Steps object. If the chart does not have separate timing +information, the m_Timing structure will be empty (i.e. none of the vectors +will contain any TimingSegments). The TimingData::empty() function provides a +simply way to determine this. + +The most common way to get the TimingData for a chart is to use the +GetTimingData() function of the Steps object. This function will perform the +appropriate fallback to Song Timing if the chart's timing is empty. If, as in +the editor or sync implementations, it is necessary to access the Steps Timing +or Song Timing individually, the corresponding fields can be used instead. + +=== Editing === + +The editor has a "timing mode" setting which can be toggled between Song +Timing and Steps Timing (in the code, GAMESTATE->m_bIsUsingStepTiming). This +mode determines which set of TimingData will be updated when changes are made +with hotkeys or the Timing menu. It defaults to Steps Timing if the chart +being loaded has individual TimingData, and Song Timing otherwise. +Considering that we also want this to behave according to whether a chart has +individual timing, there are four possibilities when making a change: + +1. Song Timing mode, chart DOES NOT HAVE individual timings: changes will be + made to the Song Timing, and the chart will not have individual timings + added to it. Because of this, the changes to Song Timing will "show + through" to this chart. +2. Song Timing mode, chart HAS individual timings: changes will be made to the + Song Timing only. The timings in the chart will be left untouched. Because + of this, the changes to Song Timing will not affect this chart. +3. Steps Timing mode, chart HAS individual timings: changes will be made to the + Steps Timing only and will affect only this chart. +4. Steps Timing mode, chart DOES NOT HAVE individual timings: first, the Song + Timing will be copied into this chart. The changes are then made to the + Steps Timing only and will affect only this chart. + +Case #4 describes how Steps Timing is added to a chart: simply select Steps +Timing mode and start making changes. To remove Steps Timing, use the +corresponding item in the Timing menu. + + +== File formats == + +A quick note is in order about Split Timing support in the different file +formats supported by StepMania: + +* SSC files support Split Timing natively. Timing tags such as #BPMS in the + file header apply to the song, whereas the same tags inside a #NOTEDATA + section apply only to the current chart. +* SM files do not support Split Timing, since there is no way to specify + individual timing for a chart. +* SMA files support Split Timing in a similar fashion to SSC files. +* The KSF and BMS formats use one file for each chart, and therefore already + have per-chart timing information. When reading these formats, *every + chart* has Steps Timing. +* The DWI format does not support Split Timing, so Steps Timing is not written + to DWI files. diff --git a/Docs/Devdocs/TextEntry.txt b/Docs/legacy/Devdocs/TextEntry.txt similarity index 100% rename from Docs/Devdocs/TextEntry.txt rename to Docs/legacy/Devdocs/TextEntry.txt diff --git a/Docs/Devdocs/WarpNotes.txt b/Docs/legacy/Devdocs/WarpNotes.txt similarity index 100% rename from Docs/Devdocs/WarpNotes.txt rename to Docs/legacy/Devdocs/WarpNotes.txt diff --git a/Docs/Devdocs/ezsockets.txt b/Docs/legacy/Devdocs/ezsockets.txt similarity index 100% rename from Docs/Devdocs/ezsockets.txt rename to Docs/legacy/Devdocs/ezsockets.txt diff --git a/Docs/Devdocs/interesting_sm4_commit_logs.txt b/Docs/legacy/Devdocs/interesting_sm4_commit_logs.txt similarity index 100% rename from Docs/Devdocs/interesting_sm4_commit_logs.txt rename to Docs/legacy/Devdocs/interesting_sm4_commit_logs.txt diff --git a/Docs/Devdocs/negbpmtut/screen00214.jpg b/Docs/legacy/Devdocs/negbpmtut/screen00214.jpg similarity index 100% rename from Docs/Devdocs/negbpmtut/screen00214.jpg rename to Docs/legacy/Devdocs/negbpmtut/screen00214.jpg diff --git a/Docs/Devdocs/negbpmtut/screen00215.jpg b/Docs/legacy/Devdocs/negbpmtut/screen00215.jpg similarity index 100% rename from Docs/Devdocs/negbpmtut/screen00215.jpg rename to Docs/legacy/Devdocs/negbpmtut/screen00215.jpg diff --git a/Docs/Devdocs/negbpmtut/screen00216.jpg b/Docs/legacy/Devdocs/negbpmtut/screen00216.jpg similarity index 100% rename from Docs/Devdocs/negbpmtut/screen00216.jpg rename to Docs/legacy/Devdocs/negbpmtut/screen00216.jpg diff --git a/Docs/Devdocs/negbpmtut/screen00217.jpg b/Docs/legacy/Devdocs/negbpmtut/screen00217.jpg similarity index 100% rename from Docs/Devdocs/negbpmtut/screen00217.jpg rename to Docs/legacy/Devdocs/negbpmtut/screen00217.jpg diff --git a/Docs/Devdocs/negbpmtut/screen00218.jpg b/Docs/legacy/Devdocs/negbpmtut/screen00218.jpg similarity index 100% rename from Docs/Devdocs/negbpmtut/screen00218.jpg rename to Docs/legacy/Devdocs/negbpmtut/screen00218.jpg diff --git a/Docs/Devdocs/negbpmtut/screen00221.jpg b/Docs/legacy/Devdocs/negbpmtut/screen00221.jpg similarity index 100% rename from Docs/Devdocs/negbpmtut/screen00221.jpg rename to Docs/legacy/Devdocs/negbpmtut/screen00221.jpg diff --git a/Docs/Devdocs/possible memory leaks.txt b/Docs/legacy/Devdocs/possible memory leaks.txt similarity index 100% rename from Docs/Devdocs/possible memory leaks.txt rename to Docs/legacy/Devdocs/possible memory leaks.txt diff --git a/Docs/Devdocs/rivaldata.txt b/Docs/legacy/Devdocs/rivaldata.txt similarity index 100% rename from Docs/Devdocs/rivaldata.txt rename to Docs/legacy/Devdocs/rivaldata.txt diff --git a/Docs/Devdocs/versioning.txt b/Docs/legacy/Devdocs/versioning.txt similarity index 100% rename from Docs/Devdocs/versioning.txt rename to Docs/legacy/Devdocs/versioning.txt diff --git a/Docs/KnownIssues.txt b/Docs/legacy/KnownIssues.txt similarity index 97% rename from Docs/KnownIssues.txt rename to Docs/legacy/KnownIssues.txt index 04ff7449f6..d84d3763fa 100644 --- a/Docs/KnownIssues.txt +++ b/Docs/legacy/KnownIssues.txt @@ -1,53 +1,53 @@ -The following is a list of known issues with StepMania 5. - -* The course editor is not working. (It could stand to be rewritten.) - -* The scoring system needs to be made global for the game instead - of tying it to the theme. The current arrangement causes multiple problems - (themes not supporting scoring unless they explicitly add it to gameplay - decorations, the last note not being scored, and so on). - -* The C and V keys in the editor (related to attacks) still has - work to go. Crashes should hopefully be minimal if not otherwise - nonexistant. - -* Attacks involving noteskins do not work. They may never work again unless - some internal coding issues are figured out. - -* Routine mode (dance or pump) isn't perfect yet. - * Attempting to use the Jukebox to show Routine steps will lead to an infinite - loop that is not escapable short of killing the program. - * Attempting to select routine mode in the Practice menu causes a crash. - -* The attempted unlock code written around Previews 2-4 (?) does not seem to - work at this time. Assistance may be needed here. - -* Hold/Roll heads seem to be draw under preceding taps when they - shouldn't be all the time. - -* C-Mods have not been fully tested with all of the new segments yet. - Warp segments are ignored when C-Mods are used. - -* Split Timing needs adjustments with only one chart in place. - * Either that, or all tags must be allowable in song timing. - -* Language detection fails for Czech and possibly other things on OS X - (non-fatally, now) - -* Japanese font maps are too large and get resized on load to something - manageable. They should be cut into thirds vertically. - * This makes debug builds in particular load very slowly, and reduces quality. - -* The editor sometimes keeps playing music and won't scroll. - -* VBR MP3's don't seek correctly in the editor, which botches sync. - -* There is no make install target for linux systems - this is important for - packaging purposes in particular (it would be great to release .debs!) - -* LuaDriver works well, but without threading it has latency issues. - -* Survival courses crash if you set a noteskin in the player options - just before starting the course. - -* On some graphics cards, 3D models may cause crashes. +The following is a list of known issues with StepMania 5. + +* The course editor is not working. (It could stand to be rewritten.) + +* The scoring system needs to be made global for the game instead + of tying it to the theme. The current arrangement causes multiple problems + (themes not supporting scoring unless they explicitly add it to gameplay + decorations, the last note not being scored, and so on). + +* The C and V keys in the editor (related to attacks) still has + work to go. Crashes should hopefully be minimal if not otherwise + nonexistant. + +* Attacks involving noteskins do not work. They may never work again unless + some internal coding issues are figured out. + +* Routine mode (dance or pump) isn't perfect yet. + * Attempting to use the Jukebox to show Routine steps will lead to an infinite + loop that is not escapable short of killing the program. + * Attempting to select routine mode in the Practice menu causes a crash. + +* The attempted unlock code written around Previews 2-4 (?) does not seem to + work at this time. Assistance may be needed here. + +* Hold/Roll heads seem to be draw under preceding taps when they + shouldn't be all the time. + +* C-Mods have not been fully tested with all of the new segments yet. + Warp segments are ignored when C-Mods are used. + +* Split Timing needs adjustments with only one chart in place. + * Either that, or all tags must be allowable in song timing. + +* Language detection fails for Czech and possibly other things on OS X + (non-fatally, now) + +* Japanese font maps are too large and get resized on load to something + manageable. They should be cut into thirds vertically. + * This makes debug builds in particular load very slowly, and reduces quality. + +* The editor sometimes keeps playing music and won't scroll. + +* VBR MP3's don't seek correctly in the editor, which botches sync. + +* There is no make install target for linux systems - this is important for + packaging purposes in particular (it would be great to release .debs!) + +* LuaDriver works well, but without threading it has latency issues. + +* Survival courses crash if you set a noteskin in the player options + just before starting the course. + +* On some graphics cards, 3D models may cause crashes. diff --git a/Docs/Licenses.txt b/Docs/legacy/Licenses.txt similarity index 100% rename from Docs/Licenses.txt rename to Docs/legacy/Licenses.txt diff --git a/Docs/Luadoc/Lua.xml b/Docs/legacy/Luadoc/Lua.xml similarity index 97% rename from Docs/Luadoc/Lua.xml rename to Docs/legacy/Luadoc/Lua.xml index 8ac6b3a44d..25a18d2a7c 100644 --- a/Docs/Luadoc/Lua.xml +++ b/Docs/legacy/Luadoc/Lua.xml @@ -1,3553 +1,3553 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Etterna0.60-git-0e213f9bf1 - 2018-08-20 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Etterna0.60-git-0e213f9bf1 + 2018-08-20 + diff --git a/Docs/Luadoc/Lua.xsd b/Docs/legacy/Luadoc/Lua.xsd similarity index 97% rename from Docs/Luadoc/Lua.xsd rename to Docs/legacy/Luadoc/Lua.xsd index 3edd27c34f..9d680cad2e 100644 --- a/Docs/Luadoc/Lua.xsd +++ b/Docs/legacy/Luadoc/Lua.xsd @@ -1,188 +1,188 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Docs/Luadoc/Lua.xsl b/Docs/legacy/Luadoc/Lua.xsl similarity index 100% rename from Docs/Luadoc/Lua.xsl rename to Docs/legacy/Luadoc/Lua.xsl diff --git a/Docs/Luadoc/LuaDocumentation.xml b/Docs/legacy/Luadoc/LuaDocumentation.xml similarity index 98% rename from Docs/Luadoc/LuaDocumentation.xml rename to Docs/legacy/Luadoc/LuaDocumentation.xml index c203e47a07..71b17f993c 100644 --- a/Docs/Luadoc/LuaDocumentation.xml +++ b/Docs/legacy/Luadoc/LuaDocumentation.xml @@ -1,5734 +1,5734 @@ - - - - - - - - - - - [02 Colors.lua] Returns a color with the specified alpha. - - - Use this to make a current value approach a goal value at the given speed. Speed must not be negative. The value will not overshoot the goal.
- Note: When you see the error "approach: speed 1 is negative." it means that the speed value passed was negative. The 1 is there because approach and multiapproach use the same internal function and can be ignored when using approach. -
- - [03 CustomSpeedMods.lua] - - - [02 StageMods.lua] - - - [02 StageMods.lua] - - - Issues an error when v is false (or nil). Returns all arguments otherwise. sAssertMessage is an optional error message (the default is "assertion failed!"). - - - Returns the base name of file path. - - - [02 Colors.lua] Boosts the specified color by multiplying its values by fBoost. - - - [02 Colors.lua] Modifies the brightness of the specified color. - - - [02 Utilities.lua] Returns true if Center 1P is being used. - - - [03 Gameplay.lua] Returns true if checkpoint judgments and tap judgments - are considered separate, or false otherwise. - - - CLAMP is an all-female Japanese mangaka group that formed in the mid 1980s. - Erm, I mean... Clamps fValue between fLow and fHigh. - - - [04 KeymapGuard.lua] - - - Closes any connection to an online server. - - - A generic interface to Lua's garbage collector. Performs different functions based on the value of opt. - - - Returns a color from a string. color can be in hex ("#FFFFFFFF") or 0..1 values ("1.0,1.0,1.0,1.0"), in RGBA order. - - - [02 Colors.lua] Returns a darker tone of the color. (Specifically c[1]/2, c[2]/2, c[3]/2, c[4]) - - - [02 Colors.lua] Returns a lighter tone of the color. (Specifically c[1]+(c[1]/2), c[2]+(c[2]/2), c[3]+(c[3]/2), c[4]) - - - [02 Colors.lua] Returns a midtone of the color. (Specifically c[1]/1.5, c[2]/1.5, c[3]/1.5, c[4]) - - - [02 Colors.lua] Returns a hex representation for the specified color. - - - [02 Colors.lua] Takes in a color and returns a table with the HSV values. - - - [03 Gameplay.lua] Determines what TapNoteScore allows for continuing the combo. - - - [03 Gameplay.lua] Determines what TapNoteScore allows for maintaining the combo. - - - [03 Gameplay.lua] Determines if combo should be per row (Jump = 1) or per column (Jump = 2). - - - [02 Other.lua] The combo trasform command. - - - [03 Gameplay.lua] Returns the UserPrefComboUnderField user preference value. - - - This will take the number and insert a comma every three digits, as normal in English for writing large numbers.
- number can be a string, an integer, or a float.
- comma is an optional argument that is used instead of a comma.
- "commify(1234, 'cat')" will result in "1cat234".
- dot is an optional argument that is used instead of a dot to find the end of the part that should be commified.
- "commify('1234cat5678', ',', 'cat')" will result in "1,234cat5678", but "commify('1234cat5678')" will result in "12,34c,at5,678".
- The comma and dot arguments are provided to ease compliance with locales or languages that do not use comma and dot in numbers the way English does. -
- - Tries to connect to the server at sAddress. - - - Recursively searches dir for xml files of actors and - converts them to equivalent lua files. See Docs/Themerdocs/XmlToLua.txt - for details. - - - Creates a RageBezier2D for you to use. Make sure you destroy the RageBezier2D when you're done with it, or you will have a memory leak. - - - Creates a CubicSplineN for you to use. Make sure you destroy the CubicSplineN when you're done with it, or you will have a memory leak. - - - [02 Colors.lua] - - - [02 Colors.lua] - - - [02 Colors.lua] - - - Returns the current day of the month. - - - Returns the current day of the year. - - - [02 Serialize] Recursively deep-copy a table. - - - [01 base.lua] "Override Lua's dofile to use our loadfile." - - - [03 Gameplay.lua] - - - [03 Gameplay.lua] - - - [02 Utilities.lua] Old name for approach. - - - This function creates files in the theme's Languages folder listing all the strings that have no translation and all the strings that are unused.
- Strings that do not have an entry in the master language are considered unused.
- master_lang_name is the name of the ini file that contains the language with all strings used by the theme.
- Example: find_missing_strings_in_theme_translations("my_best_theme", "en.ini") -
- - [02 Utilities.lua] Return the index of a true value in list. - - - [02 Utilities.lua] Find a key in tab with the given value. - - - func takes a key and a value. - - - Returns the number passed to the function followed by its suffix ("th", "nd", and so on). - - - - Returns fPercentDancePoints formatted as a percentage. - - - [03 Gameplay.lua] Returns a list of valid styles for the current gametype. - - - [03 Gameplay.lua] - - - Returns the corresponding CustomDifficulty string for a StepsType/Difficulty (/optional CourseType) combination. - - - [04 Scoring.lua] "Get the radar values directly. The individual steps aren't used much." - - - [02 Other.lua] Returns a string with the Edit Mode SubScreens. - - - [03 EnvUtils2.lua] Returns the value of name from the Env table. - - - [03 Gameplay.lua] Returns the number at which the Extra color should be used. - - - Returns a corresponding for the given percentage. - - - Returns the current Life Difficulty. - - - Returns the length of the music file found at path.
- If you are loading the sound into an ActorSound, ActorSound:get to get its RageSound then use RageSound's get_length function instead to avoid loading the file twice. -
- - Returns a table of the names of the sound drivers available. If the SoundDriver preference is set to something that is not in this list, StepMania WILL NOT START UP. Changes to the SoundDriver preference do not take effect until the next time StepMania starts up. - - - Returns a string representing the name of the operating system being used. (e.g. "Windows", "Linux", "Mac, "Unknown") - - - [02 Utilities.lua] "This returns a profile, preferably a player one. If there isn't one, [it falls] back on the machine profile." - - - [03 ThemePrefs.lua] Returns true if player pn is using ProTiming. - - - [02 Utilities.lua] Returns a path to a random song background. - - - [02 Actor.lua] - - - [02 Actor.lua] - - - Returns the display aspect ratio. - - - Returns the name of the currently connected server. - - - [02 Utilities.lua] Returns a path to the current songs background. - - - [03 Gameplay.lua] - - - Returns the theme's aspect ratio. - - - [03 ThemePrefs.lua] (Alias for .) - - - Returns the current Timing difficulty. - - - Returns the current time since the program was started. Includes time that was spent loading songs. - - - [01 alias.lua] - - - [01 alias.lua] - - - [04 Scoring.lua] "Retrieve the amount of taps/holds/rolls involved." Used in some scoring formulas. - - - [03 UserPreferences2.lua] Themer-facing function for getting a user preference. - - - [03 UserPreferences2.lua] Themer-facing function for getting a user preference as a boolean. - - - [03 UserPreferences2.lua] Themer-facing function for getting a user preference as a color. - - - [03 UserPreferences2.lua] Themer-facing function for getting a user preference as a number. - - - [02 Colors.lua] Returns the color's alpha if it has any, otherwise returns 1. - - - [03 Gameplay.lua] Returns the value to start showing the combo at. - - - [03 Gameplay.lua] Returns true if you need to step on hold heads to activate them. - - - [03 Gameplay.lua] Returns 0 in pump mode, TimingWindowSecondsHold preference value in any other game mode. - - - Returns the current hour. - - - [02 Colors.lua] Converts a color from HSV values to something StepMania can understand. - hue is from 0-360, saturation and value are 0..1 - - - [02 Colors.lua] Converts a color from HSV values with alpha to something StepMania can understand. - hue is from 0-360, saturation, value, and alpha are 0..1 - - - [02 Colors.lua] "Converts a set of HSV values to a color." - - - [02 Colors.lua] "Takes in a normal color and returns the hex representation. (Adapted from code in LuaBit)" - - - [02 Colors.lua] Changes the hue of the input color. - - - [03 ThemePrefs.lua] Initializes various user preferences. - - - [01 base.lua] "Like ipairs(), but returns only values." - - - [02 Utilities.lua] Returns true if the coin mode is not set to CoinMode_Home. - - - Returns true if Event Mode is turned on. - - - [02 Utilities.lua] Returns true if Arcade and the coin mode is CoinMode_Free. - - - [03 Gameplay.lua] Returns true if the current game is sGame. - - - [02 Utilities.lua] Returns true if the coin mode is set to CoinMode_Home. - - - Returns true if connected to the Internet. - - - Returns true if connected to StepMania Online. - - - Returns true if Player pn is logged on to a SMOnline server. - - - [04 Scoring.lua] Returns true if W1 is allowed (and tns == 'TapNoteScore_W2') - - - [02 Branches.lua] Returns true if Routine mode is being played. - - - [04 WidescreenHelpers.lua] Returns true if the aspect ratio is 16:10 (1.6) or higher. - - - [01 base.lua] "Like ipairs(), but returns only values." - - - [02 Utilities.lua] Joins a table, splitting each item with delimiter, returning a string of the results. - - - [02 Colors.lua] - - - [02 Colors.lua] - - - Returns a number linearly interpolated between start and end by percent. - - - Same as lerp, but for colors. All channels will reach the end of the interpolation at the same time. - - - Returns an Actor definition for the actor at sPath. If sPath points to a Lua file, any additional arguments will be passed to that script. - - - [02 ActorDef.lua] Loads an actor template. This is the actual core of LoadActor. - - - [02 ActorDef.lua] Loads an actor with params. - - - [01 base.lua] "Override Lua's loadfile to use lua.ReadFile." - - - [02 ActorDef.lua] Load the fallback BGA for the element that is currently being loaded. - - - [02 ActorDef.lua] Loads a font. - - - [02 Sprite.lua] Returns a Sprite with the current song's background. - - - Returns the length of the multi-byte character string sString. - - - Returns the current Minute. - - - [03 Gameplay.lua] Returns the value to start showing the miss combo at. - - - Creates a module. See the Lua manual for more details. - - - Returns the current month of the year (0-11). - - - Returns Month m as a localized string. - - - Returns Month m as a string. - - - Similar to approach, but operates on tables of values instead of single values. This will modify the contents of currents in place, as well as returning currents.
- currents, goals, and speeds must all be the same size and contain only numbers.
- multiplier is optional. The speeds in the speeds table will be multiplied by multiplier. This makes it more convenient to use multiapproach in a per-frame update: pass in the frame delta and the speeds will be scaled to the time that passed.
- Note: When you see the error "approach: speed 1 is negative." it means that a speed value passed was negative. The 1 tells you which entry in the table was invalid. -
- - "Allows a program to traverse all fields of a table. Its first argument is a - table and its second argument is an index in this table. - next returns the next index of the table and its associated value." - See the Lua manual for more details. - - - Converts a string such as 'oni' or 'expert' or 'trick' to the appropriate difficulty. - - - [03 ThemePrefs.lua] Returns a Lua option row for ProTiming. - - - "Returns three values: the function, the table t, and nil, - so that the construction for k,v in pairs(t) do body end - will iterate over all key–value pairs of table t." - - - [02 Colors.lua] - - - [02 Colors.lua] - - - [02 Utilities.lua] Converts a PlayerNumber into a short string (e.g. "P1", "P2"). - - - [02 Actor.lua] Returns either p1val or p2val depending on pn. - - - Returns a formatted percent with the specified numerator and denominator. - - - [00 init.lua] - - - [03 ThemePrefs.lua] Prints a table's contents to the log. - - - Returns the product family. (e.g. "StepMania") - - - Returns the product ID. (e.g. "StepMania 5") - - - Returns the product version. - - - "Checks whether v1 is equal to v2, without invoking any metamethod." - - - "Gets the real value of t[index], without invoking any metamethod." - - - "Sets the real value of t[index] to value, without invoking any metamethod." - The modified t is then returned. - - - [02 ActorDef.lua] Used internally by LoadActor to resolve a path. If optional is true, then a nil path is returned instead of emitting an error if no file is found. - - - [04 FileUtils.lua] Reads the file at path and returns its contents. - - - [03 UserPreferences2.lua] (internal) Reads the specified user preference from its config file. - - - Recursively prints all the children of the actor frame to the log file. This can be useful for finding out what actors are on a screen or just seeing what the structure of the actor tree looks like.
- indent is an optional argument that will be prepended to every line. -
- - Recursively prints all values in the table to the log file in the form "(key_type) key: (value_type) value" so that you know the type of the key and the value. Useful if you're not sure exactly what is in a table passed as a parameter.
- indent is an optional argument that will be prepended to every line. -
- - Sends the current style to the server. - - - Loads the specified module. See the Lua manual for more information. - - - [02 Utilities.lua] Round a number. - - - [03 Gameplay.lua] Returns the routine noteskin for player . - - - [03 Gameplay.lua] Returns the routine noteskin for player 2. - - - [02 Colors.lua] Modifies the saturation of the specified color - - - Saves a screenshot. If pn is nil, saves to the machine's Screenshots dir, otherwise saves to the profile's Screenshots dir. Saves as jpg if compress is true, or png if compress is false. The screenshot is signed if sign is true. prefix and suffix are optional strings to add to the beginning and end of the filename.
- Returns success and full path of the resulting screenshot. -
- - Scales x, originally within low1 and high1, to fall between low2 and high2. - - - [03 Gameplay.lua] Returns the primary ScoreKeeper class to use. - - - [00 alias.lua, 02 Other.lua] alias for . - - - [00 alias.lua, 02 Other.lua] alias for . - - - Returns the current second. - - - Converts fSecs to Minutes:Seconds:Milliseconds format using two digits for each section. - - - Converts fSecs to Minutes:Seconds.Milliseconds format using two digits for each section except Minutes (uses 1). - - - Converts fSecs to Minutes:Seconds format. - - - Converts fSecs to Minutes:Seconds.Milliseconds format. - - - Converts fSecs to Minutes:Seconds.Milliseconds format using two digits for each section. - - - Converts fSecs to Minutes:Seconds.Milliseconds format using two digits for each section except Milliseconds (uses 3). - - - "If index is a number, returns all arguments after argument - number index. Otherwise, index must be the string - "#", and [it] returns the total number of extra arguments it received." - - - [02 Branches.lua] Determines the correct music/course selection screen to use and returns it. - - - [03 Gameplay.lua] (soon to be deprecated) Returns a list of codes to use on ScreenSelectProfile. - - - [02 Serialize.lua] Serialize the table t. - - - [03 EnvUtils2.lua] Sets the value of name to value in the Env table. - - - [03 UserPreferences2.lua] Themer-facing function for setting a user preference. - - - [03 Gameplay.lua] - - - [02 ActorDef.lua] Returns true if a decoration should be shown on the current screen or not. - - - [03 CustomSpeedMods.lua] Returns a Lua option row with the custom speed mods defined in SpeedMods.txt. - - - [02 Utilities.lua] Splits a string at every occurence of delimiter, returning a table of the results. - - - [02 Colors.lua] - - - [02 Colors.lua] - - - [02 ActorDef.lua] - - - [02 ActorDef.lua] - - - [02 ActorDef.lua] - - - [02 Utilities.lua] Returns a shuffled version of t. - - - [02 Utilities.lua] Returns a slice of the specified table of size num. - - - [02 Utilities.lua] Look up each value in a table, returning a table with the resulting strings. - - - [02 TextBanner.lua] This function defines how the TextBanner is laid out. - - - [02 Utilities.lua] Converts a string or number to a bool. - - - Tries to convert e to a number. Returns nil if - it can't convert the input to a number. (base is optional.) - - - Converts e to a string. - - - [02 Enum.lua] Returns a string representing an enum starting from '_'. For example, passing PlayerNumber_P1 to this function will return P1. - - - [00 init.lua] Alias for . - - - Returns the type of the object as a string. See the Lua manual for valid return values. - - - "Returns the elements from the given table. - This function is equivalent to return list[i], list[i+1], ···, list[j]" - (i and j are optional; "by default, i is 1 and j is the length of the list.") - - - 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. - - - Returns the current version's build date. - - - Returns the current version's build time. - - - [00 init.lua] Alias for . - - - [04 WidescreenHelpers.lua] Depending on the screen width, scales between ar43 (4:3; 640px) and ar169 (16:9; 854px). - - - [02 Utilities.lua] - - - [02 ActorDef.lua] Wraps the children in an ActorFrame. - - - [04 FileUtils.lua] Writes buf to the file at path. - - - [03 GamePreferences.lua] - - - [03 UserPreferences2.lua] (internal) Writes user preference prefName to its config file with value being tostring'd. - - - Returns the current year. - - - - [03 ThemePrefs.lua] Returns a Lua option row for toggling AutoSetStyle. - - - [03 ThemePrefs.lua] Returns a Lua option row for displaying the score on ScreenGameplay. - - - [03 ThemePrefs.lua] Returns a Lua option row for displaying the StepsDisplay on ScreenGameplay. - - - [03 ThemePrefs.lua] Returns a Lua option row for determining the fail length. - - - [03 ThemePrefs.lua] Returns a Lua option row for determining the receptor arrow position. - - - [03 ThemePrefs.lua] Returns a Lua option row determining how deep the player options menu should go. - -
- - - - - - Returns the for the file at sPath. - - - Returns true if sClassName is a registered Class. - - - Loads all commands and sets X and Y for the specified Actor. - - - Used internally by LoadActor to resolve a path. If optional is true, then a nil path is returned instead of emitting an error if no file is found. - - - - - Updates ArrowEffects, which sets current values for Tornado, Invert, and Beat. - - - Returns the Y Offset of a note in column iCol at beat fNoteBeat for the provided PlayerState. Y Offset is affected by Speed mods and Accel mods, and impacts most other arrow effects. - - - Returns the Y position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState.
- fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player] -
- - Returns the Y offset of a note in column iCol with a Y position of fYPos for the provided PlayerState.
- fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player] -
- - Returns the X position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. - - - Returns the Z position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. - - - Returns the X rotation of a note with a Y offset of fYOffset for the provided PlayerState. - - - Returns the Y rotation of a note with a Y offset of fYOffset for the provided PlayerState. - - - Returns the Z rotation of a note at beat fNoteBeat for the provided PlayerState.
- bIsHoldHead is an optional argument which defaults to false. If true, this function will return 0 if the [ArrowEffects] metric DizzyHoldHeads is false. -
- - Returns the Z rotation of the receptors for the provided PlayerState. - - - Returns the Alpha of a note in column iCol with a Y offset of fYOffset for the provided PlayerState.
- fPercentFadeToFail is optional and defaults to -1.
- fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player]
- fDrawDistanceBeforeTargetsPixels is optional and will pull defaults from the [Player] metric DrawDistanceBeforeTargetsPixels
- fFadeInPercentOfDrawFar is optional and will pull defaults from the [NoteField] metric FadeBeforeTargetsPercent
-
- - Returns the Glow of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. The arguments are the same as for GetAlpha. - - - Returns the brightness of a note at beat fNoteBeat for the provided PlayerState. - - - Returns true if any arrow effects for the provided PlayerState require the z buffer. - - - Returns the zoom of a note for the provided PlayerState. - - - Returns the FrameWidthScale of a hold part with a Y offset of fYOffset for the provided PlayerState.
fOverlappedTime is optional and will default to 0. -
-
- - - Enumerated types are lookup tables associating a string to each numerical - value for each Enum. For example, - [1] would be the - string 'PlayerNumber_P1'.
- The functions defined in the Enum namespace are valid member - functions of every Enum where the first argument is - omitted and the name of the Enum is used in place - of Enum. Instead of - Enum.GetName( - ) or - Enum.Reverse( - ), one can use - :GetName() or - :Reverse(), respectively. -
- - Both x and y need to be elements of the enumerated - type e. Returns a value less than/greater than/equal to - 0 corresponding to the numerical value of x being - less than/greater than/equal to the numerical value of y as - determined by - Enum.Reverse( e ). - - - Returns the type of e. For example, - Enum.GetName( ) - will return the string 'PlayerNumber'. - - - Returns a reverse lookup table for the enumerated type e. For - example:
local r = - Enum.Reverse( );
- local n = r['PlayerNumber_P2'];

- The value of n in this case would be 1 corresponding - to the 0-based indexing using in C++ and not 2 as might be - expected for the 1-based indexing used in Lua. -
-
- - - Returns true if the type of v is sType. - - - Flushes log files to disk. - - - - Tries to read the file at sPath. If successful, it returns the file's contents. - If unsuccessful, it returns two values: nil and "error". - - - Reports the error through the error reporting system. error_type is the type used for the dialog that is presented, a dialog will not appear for a type the user has chosen to ignore.
- error is optional an defaults to "Script error occurred.". error_type is optional and defaults to "LUA_ERROR". -
- - Calls func(...) with two LuaThreadVariables set, and returns the return values of func(). - - - Writes sString to log.txt. Aliased by - . - - - Writes sString to info.txt and log.txt as - a warning. Aliased by . - -
- - - Returns a random number. Without arguments, the number is in the range 0..1. With a single argument (n), the number is in the range of 1..n. With two arguments (lower, upper), the number is in the range of l..u. - - - Sets the seed of the random number generator to seed. - - - - - Creates a RageFile handle with which one can use the commands in . - - - - - Gets the credits message for Player pn. - - - - - Returns a table with the playable Steps for the present Song based on the present Game. - - - Returns true if the song's steps (st) are playable. - - - Returns true if the song's StepsType (st) are playable. - - - - - Returns the number of songs in a Trail. - - - Returns the Trail's total length in seconds. - - -
- - - - - - This adds a wrapper state around the Actor, which is like wrapping the Actor in an ActorFrame, except that you can use it on any actor, and add or remove wrapper states in response to things that happen while the screen is being used. (wrapping an Actor in an ActorFrame normally requires setting it up before the screen starts)
- The ActorFrame that is returned is the wrapper state, for convenience.
- An Actor can have any number of wrapper states. Use GetWrapperState to access wrapper states for the actor. -
- - Returns the number of wrapper states the actor has. - - - Returns the wrapper state at index i. Think of wrapper states with a higher index as being "further out". Actor is inside Wrapper 1, Wrapper 1 is inside Wrapper 2, Wrapper 2 is inside Wrapper 3, and so on. - - - Removes the wrapper state at index i. - - - Returns the Actor's parent, or nil if it doesn't have one. - - - Returns the Actor's fake parent, or nil if it doesn't have one. - - - Sets the Actor's fake parent to p, or clears it if p is nil. - - - Returns the Actor's visibility. - - - Returns the Actor's x position. - - - Returns the Actor's y position. - - - Returns the Actor's z position. - - - Returns what the Actor's x position will be when it reaches its destination tween state. - - - Returns what the Actor's y position will be when it reaches its destination tween state. - - - Returns what the Actor's z position will be when it reaches its destination tween state. - - - Returns the Actor's zoom. - - - Returns the Actor's X zoom. - - - Returns the Actor's Y zoom. - - - Returns the Actor's Z zoom. - - - Sets Texture Filtering for an Actor to b. - - - Plays the commands that follow at an accelerated rate (fRate * fRate), where fRate is in seconds. - - - Adds a command to the Actor. - - - Adds rot to the Actor's current x rotation. - - - Adds rot to the Actor's current y rotation. - - - Adds rot to the Actor's current z rotation. - - - Adds xPos to the Actor's current x position. - - - Adds yPos to the Actor's current y position. - - - Adds zPos to the Actor's current z position. - - - [02 Actor.lua] Sets the alignment of an Actor, where h and v are in the range 0..1. - - - Sets whether or not the Actor should animate. - - - Sets the Actor's aux value. (This can be a solution for coupling data with an Actor.) - - - If true, cull the Actor's back faces. See also: . - - - Sets the Actor's base alpha to fAlpha, where fAlpha is in the range 0..1. - - - Sets the Actor's base X rotation to rot. - - - Sets the Actor's base Y rotation to rot. - - - Sets the Actor's base Z rotation to rot. - - - Sets the Actor's base zoom to zoom. - - - Sets the Actor's base X zoom to zoom. - - - Sets the Actor's base Y zoom to zoom. - - - Sets the Actor's base Z zoom to zoom. - - - Sets the Actor to use the specified blend mode. - - - Makes the Actor bob up and down. Can use to define different bobbing behavior. - - - Makes the Actor bounce, similar to bob but with one point acting as the ground. Can use to define different bouncing behavior (with effectmagnitude values relating to x, y, and z movement). - - - [02 Actor.lua] - - - [02 Actor.lua] - - - [02 Actor.lua] Centers an Actor on the screen. (equivalent to x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y) - - - [02 Actor.lua] Centers an Actor on the X axis. (equivalent to x,SCREEN_CENTER_X) - - - [02 Actor.lua] Centers an Actor on the y axis. (equivalent to y,SCREEN_CENTER_Y) - - - Determines if the z-buffer should be cleared or not. - - - [02 Actor.lua] Combines multiple interpolators for complex tweens. tweens - can either be a string like "linear,0.25,accelerate,0.75" or - a table with tween information { {Type="linear", Percent=0.25, Bezier=nil}, {Type="accelerate", Percent=0.75, Bezier=nil} } - - - Crops percent of the Actor from the bottom, where percent is in the range 0..1. - - - Crops percent of the Actor from the left, where percent is in the range 0..1. - - - Crops percent of the Actor from the right, where percent is in the range 0..1. - - - Crops percent of the Actor from the top, where percent is in the range 0..1. - - - Sets the Actor's cull mode to mode. - - - Plays the commands that follow at an decelerated rate (1 - (1-fRate) * (1-fRate)), where fRate is in seconds. - - - Set the Actor's diffuse color to c. - - - Sets the Actor's alpha level to fAlpha, where fAlpha is in the range 0..1. - - - Makes the Actor switch between two colors immediately. See Themerdocs/effect_colors.txt for an example. - - - Sets the Actor's bottom edge color to c. - - - Set the Actor's diffuse color to c, ignoring any alpha value in c. - - - Sets the Actor's left edge color to c. - - - Sets the Actor's lower left corner color to c. - - - Sets the Actor's lower right corner color to c. - - - Makes the Actor switch between two colors, jumping back to the first after reaching the second. See Themerdocs/effect_colors.txt for an example. - - - Sets the Actor's right edge color to c. - - - Makes the Actor shift between two colors smoothly. See Themerdocs/effect_colors.txt for an example. - - - Sets the Actor's top edge color to c. - - - Sets the Actor's upper left corner color to c. - - - Sets the Actor's upper right corner color to c. - - - Tells the Actor to draw itself. - - - Sets the Actor's draworder to iOrder, where larger values display first. - - - [02 Actor.lua] (Added in sm-ssc) - - - [02 Actor.lua] - - - Set the Actor's effect clock to s. - - - Sets the first effect color to c. - - - Sets the second effect color to c. - - - Set the Actor's effect magnitude in each direction to the given values. - - - Set the Actor's effect offset to fTime. The offset is added to the time into the effect before calculating percent_through_effect. - - - Set the Actor's effect period to fTime. - - - Set the Actor's effect timing.
- hold_at_zero is before hold_at_full in the argument list for compatibility. A future version will probably swap them because it makes more sense to have hold_at_full come before hold_at_zero.
- All effect timings must be greater than or equal to zero, at least one of them must be greater than zero.
- The effect timing controls how long it takes an effect to cycle and how long it spends in each phase.
- Depending on the effect clock, the actor's time into effect is updated every frame. That time is then translated into a percent_through_effect using the parameters to this function.
-
- ramp_to_half is the amount of time for percent_through_effect to reach 0.5.
- hold_at_half is the amount of time percent_through_effect will stay at 0.5.
- ramp_to_full is the amount of time percent_through_effect will take to go from 0.5 to 1.0.
- hold_at_full is the amount of time percent_through_effect will stay at 1.0.
- After reaching the end of hold_at_full, percent_through_effect stays at 0 until hold_at_zero is over.
-
- The different effects use percent_through_effect in different ways. Some use it to calculate percent_between_colors with this sine wave: sin((percent_through_effect + 0.25f) * 2 * PI ) / 2 + 0.5f
- Some effects check the internal bool blink_on. blink_on is true if percent_through_effect is greater than 0.5 and false if percent_through_effect is less than or equal to 0.5.
- Check the effect functions for individual explanations: diffuseblink, diffuseshift, glowblink, glowshift, glowramp, rainbow, wag, bounce, bob, pulse, spin, vibrate. -
- - Set the hold_at_full part of the effect timing while leaving the others unchanged. - - - Fades percent of the Actor from the bottom where percent is in the range 0..1. - - - Fades percent of the Actor from the left where percent is in the range 0..1. - - - Fades percent of the Actor from the right where percent is in the range 0..1. - - - Fades percent of the Actor from the top where percent is in the range 0..1. - - - Finishes up an Actor's tween immediately. - - - [02 Actor.lua] Stretches an Actor to fill the entire screen. - - - Returns the Actor's aux value. - - - Returns the Actor's base X zoom value. - - - Returns the Actor's base Y zoom value. - - - Returns the Actor's base Z zoom value. - - - Returns true if the Actor has a command named sCmdName. - - - Returns the Actor's current diffuse color. - - - Returns the Actor's current diffusealpha. - - - Returns the Actor's current effect delta. - - - Returns the Actor's current effect magnitude as three floats (not one; I hate Lua.xsd). - - - Returns the Actor's current glow color. - - - Returns the Actor's horizontal alignment as a number in the range 0..1. - - - Returns the Actor's name. - - - Returns the number of states the Actor has. - - - Returns the Actor's current height. - - - - Returns the Actor's current X rotation. - - - Returns the Actor's current Y rotation. - - - Returns the Actor's current Z rotation. - - - Returns the number of seconds into the currently running effect (e.g. diffuseshift, bob). - - - Returns how much time is remaining for the current tween. - - - Returns the Actor's vertical alignment as a number in the range 0..1. - - - Returns the Actor's current width. - - - Returns the zoomed height of an Actor. - - - Returns the zoomed width of an Actor. - - - Returns true if this actor is currently set to use the effect delta for tweening. - - - Sets the Actor's glow color. - - - Makes the Actor glow between two colors immediately. See Themerdocs/effect_colors.txt for an example. - - - Makes the Actor glow between two colors smoothly, jumping back to the first at the end. See Themerdocs/effect_colors.txt for an example. - - - Makes the Actor glow between two colors smoothly. See Themerdocs/effect_colors.txt for an example. - - - Set the fractional horizontal alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is left aligned while an alignment of 1 is right aligned. See for the common case. - - - Sets the heading of this Actor to fHeading. - - - Hides the Actor for the specified amount of time. - - - [Deprecated] Compatibility alias for the hidden command, which was removed in sm-ssc. Use instead. - - - [02 Actor.lua] "Hide if b is true, but don't unhide if b is false." - - - Set the horizontal alignment of the Actor according to align. See for fractional alignment. - - - Hurries up an Actor's tweening by factor. - - - Plays the commands that follow at a normal rate, where fRate is in seconds. - - - [02 Lyrics.lua] Plays the lyric command for the specified side ("Back" or "Front"). - - - Sets the Actor's name to sName. - - - Stops the Actor's movement. (Usually used for Sprites or Models.) - - - Sets the pitch of this Actor to fPitch. - - - Starts the Actor's movement. (Usually used for Sprites or Models.) - - - Plays a command named sCommandName. params is passed to the command as an argument if it is a table. - - - [02 Actor.lua] Sets the visibility of the Actor based on p being a human player. - - - Makes the Actor grow and shrink. Can use to define different pulsing behavior. - - - Queues a command named sCommandName to be played. - - - Basically creates a command named !sMessageName (Note the ! at the beginning. The source code says this: "Hack: use "!" as a marker to broadcast a command, instead of playing a command, so we don't have to add yet another element to every tween state for this rarely-used command.") - - - Makes the Actor change colors continually using colors of the rainbow. Each channel follows a cosine wave, red starts at 0, green starts at 2pi/3, and blue starts at 4pi/3. - - - Sets the roll of this Actor to fRoll. - - - Set the Actor's rotation on the X axis to fAlign. - - - Set the Actor's rotation on the Y axis to fAlign. - - - Set the Actor's rotation on the Z axis to fAlign. - - - - [02 Actor.lua] An alternative version of . - - - [02 Actor.lua] - - - Scales the Actor to cover a rectangle defined by the four float arguments. - - - Scales the Actor to fit inside a rectangle defined by the four float arguments. - - - Sets the height of the Actor. - - - Sets the size of the Actor. - - - [01 alias.lua] Alias for setsize. - - - Sets a multi-framed Actor's state to iNewState. - - - Sets the width of the Actor. - - - Use this to make the actor use the effect clock to tween instead of using the global frame delta. - - - Sets the shadow's color to c. - - - Sets the Actor's shadow length to fLength. - - - Sets the Actor's horizontal shadow length to fLength. - - - Sets the Actor's vertical shadow length to fLength. - - - Skews the Actor on the x axis by fAmount. - - - Skews the Actor on the y axis by fAmount. - - - Waits fSeconds before executing the next command. - - - [02 Actor.lua] - - - Tells the Actor to spin. Can use to define different spinning behavior. - - - - Stops any effect the Actor has. - - - Stops any tweening. - - - Stretches the Actor to a rectangle of a specific size. - - - Translates the texture of the actor by x and y. - - - Determines if the Actor should use texture wrapping or not. - - - Uses type to determine the tween to use. The type must be one of the TweenType enum values. If the type is note TweenType_Bezier, the params table is ignored. If the type is TweenType_Bezier, then the params table must have 4 or 8 numbers. 4 numbers in the params creates a 1 dimensional bezier curve, 8 numbers creates a 2 dimensional bezier curve.
- It's usually more convenient to use Actor:linear, Actor:accelerate, and so on, rather than using Actor:tween directly. -
- - Set the fractional vertical alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is top aligned while an alignment of 1 is bottom aligned. See for the common case. - - - Set the vertical alignment of the Actor according to align. See for fractional alignment. - - - Makes the Actor vibrate violently. Can use to define different vibration behavior. - - - Sets an Actor's visibility to b. - - - Makes the Actor wag. Use to define different wag behavior. - - - Set the x position of the Actor to xPos. - - - Set the y position of the Actor to yPos. - - - Set the z position of the Actor to zPos. - - - Sets the z bias to fBias. - - - Enables/disables z-buffer depending on bUse. - - - Zooms the Actor to zoom scale. - - - Zooms the Actor on both the X and Y axis using zoomX and zoomY. - - - Zooms the Actor to zoom height. See also: . - - - Zooms the Actor to zoom width. See also: . - - - Zooms the Actor to zoom scale on the X axis. - - - Zooms the Actor to zoom scale on the Y axis. - - - Zooms the Actor to zoom scale on the Z axis. - - - Sets the z testing mode to write on pass if true, turns it off if false - - - Sets the z testing mode to testMode. - - - Sets z writing to true or false based on bWrite. - - - - [02 Actor.lua] Plays the commands that follow using a bezier curve to determine the rate. The curve must have 4 or 8 elements. This is a convenience wrapper around calling Actor:tween with TweenType_Bezier. - - - [02 Actor.lua] Stretches an Actor to cover the screen. (equivalent to stretchto,0,0,SCREEN_WIDTH,SCREEN_HEIGHT) - - - [02 Actor.lua] A customized version of pulse that is more appealing for on-beat effects. - - - [02 Actor.lua] Sets and Actor as a mask destination. - - - [02 Actor.lua] Sets an Actor as a mask source. (Also clears zbuffer; other mask sources need to not clear the zbuffer) - - - [02 Actor.lua] Make graphics their true size at any resolution. - - - [02 Actor.lua] Scale things back up after they have already been scaled down. - - - [02 Actor.lua] A customized version of pulse that is more appealing for on-beat effects. - - - Sets the x and y location of the Actor in one command. - -
- - - Adds a child to the ActorFrame from the specified path. - - - Sets the field of view for the ActorFrame. - - - Returns the child with a name of sName.
- If there are multiple children with that name, returns an array of those children.
- The table also acts as a pass through layer, function calls pass through to the last child of that name. -
- - Returns a table of all the children in the ActorFrame.
- The table is indexed by the names of the children.
- If there are multiple children with the same name, the entry for that name is an array of those children.
- The table also acts as a pass through layer, function calls pass through to the last child of that name. -
- - Gets the ActorFrame's Draw function. - - - Returns the number of children in the ActorFrame. - - - Gets the update function's rate. - - - Plays the sCommandName command on the ActorFrame's children. - - - Plays the sCommandName command on the ActorFrame's leaves. - - - Sets if the Actorframe should propagate commands to its children. - - - [02 Actor.lua] Propagates a command to the ActorFrame's children. - - - Removes all the children from the ActorFrame. - - - Removes the specified child from the ActorFrame. - - - Runs the commands in cmds on the ActorFrame's children. - - - Runs the commands in cmds on the ActorFrame's leaves. - - - Sets the ActorFrame's ambient light color to c. - - - Sets the ActorFrame's diffuse light color to c. - - - Sets if the ActorFrame should draw by Z position. - - - Sets the ActorFrame's Draw function to the specified Lua function. - - - Sets the field of view for the ActorFrame. - - - Currently unimplemented since it does not handle errors correctly. Arguments must be passed in as a table. - - - Sets the ActorFrame's specular light color to c. - - - Sets the ActorFrame's update function to the specified Lua function. - - - Sets the update function's rate to fRate. - - - Tells the ActorFrame to sort by draw order. - - - Sets the vanishing point for the ActorFrame. - -
- - - Creates the ActorFrameTexture. - - - Enables/disables the Alpha Buffer. - - - Enables/disables the Depth Buffer. - - - Enables/disables - - - Enables/disables the Preserve Texture option. - - - Returns the texture. - - - Sets the Texture's name to sName. - - - - - Adds a texture to the ActorMultiTexture. Returns the number of texture units. - - - Clears all the textures from the ActorMultiTexture. - - - Sets the EffectMode on the ActorMultiTexture. - - - Sets the size of the ActorMultiTexture from the specified texture. - - - Sets the coordinates of the ActorMultiTexture. - - - Sets a TextureMode on the specified index. - - - - - The list of quad states is used to determine which animation state is used for each quad. The offset is added to the AMV's current state, and the resulting state is used. - - - Adds an animation state to the ActorMultiVertex. The state_data table must be like this:
- {{left, top, right, bottom}, delay}
- left, top, right, and bottom are pixel coordinates, starting at 0. If delay is 0 or negative, the state will last forever. -
- - Forces the AMV to update the texture coordinates on all its quads, even if the current state has not changed. - - - Returns whether the AMV uses the animation state. - - - Sets whether the AMV uses the animation state.
- This works best when using DrawMode_Quads.
- AMV's can have animated textures like sprites. Each state tells the AMV what part of the texture to use, and how long the state lasts.
- Use AddState to add a state onto the end, or SetStateProperties to set all the states at once, or SetState to set a single state.
- Each quad has its own offset that is added to the current state. Use AddQuadState to add to the list of quad states, or SetQuadState to set an existing quad state. -
- - Returns the number of states the AMV has. - - - Returns the number of quad states in the destination tween state for the AMV. - - - Returns the id of the current state. - - - Gets whether the AMV should call the decode function for its texture during updates. - - - Sets whether the AMV should call the decode function for its texture during updates. - - - Sets the current state. - - - Returns the offset of the requested quad state. - - - Sets the offset of the requested quad state. - - - Returns a table containing the data for the requested state. - - - Sets the requested state to the data in state_data. Similar to AddState, but SetStateData only works on states that have already been added. - - - Each element of the table must be a state_data table, and is used to construct one state. The table as a whole is the entire list of all states for the AMV. - - - Removes the requested state from the state list. - - - Removes the requested quad state from the quad state list. - - - Sets the delay for every state to delay. - - - Sets how far into its animation the AMV is. - - - Sets vertex number index with the properties provided. The tables of properties are each optional and can be provided in any order. - - - Sets multiple vertices at once. The elements of vertices should themselves be tables, of the form provided to SetVertex. If vertices is the first argument it will start from vertex 1. If an integer is provided before vertices it will start from that vertex. It will add vertices as necessary. - Example: self:SetVertices( { { { x1, y1, z1 } , { r1,g1,b1,a1 } , { tcx1,tcy1 } }; { { x2, y2, z2 } , { r2,g2,b2,a2 } , { tcx2,tcy2 } } } ) - - - Sets all the drawn verts of the ActorMultiVertex by evaluating the splines.
- ("all the drawn verts" means all the verts between FirstToDraw and NumToDraw, the verts that are set to draw in the current tween state.)
- The parts of the ActorMultiVertex are evenly spaced along the spline in terms of t value.
- The exact behavior depends on the draw mode.
- DrawMode_Quads uses all 4 splines, one for each corner.
- DrawMode_QuadStrip and DrawMode_Strip use 2 splines, one for each edge of the strip.
- DrawMode_Fan uses one spline, for the edge verts of the fan. The first vert is not touched because it is the center.
- DrawMode_Triangles uses 3 splines, one for each corner.
- DrawMode_SymmetricQuadStrip uses 3 splines, one on each edge and one in the center.
- DrawMode_LineStrip uses 1 spline.
-
- - Returns the requested spline. Spline indices range from 1 to 4.
- ActorMultiVertex splines are not inside the tween state, and will not change the verts until you call SetVertsFromSplines. -
- - Sets the number of vertices. - - - Returns the number of vertices - - - Sets the draw state variables to the values in the table.
- Mode must be a DrawMode.
- First is the index of the first vertex to draw.
- Num is the number of vertices to draw. -1 for Num means draw all verts after First.
- Any value not in the table defaults to the already set value.
- Examples:
- -- Sets all three parts of the draw state.
- self:SetDrawState{Mode="DrawMode_Quads", First= 1, Num= -1}
- -- Set only the draw mode. First and Num remain unchanged from previous.
- self:SetDrawState{Mode="DrawMode_Quads"}
- -- Set the first and number to draw. Draw mode remains unchanged.
- self:SetDrawState{First= 3, Num= 4}
-
- - Get the DrawMode of the destination tween state. - - - Get the FirstToDraw of the destination tween state. - - - Get the NumToDraw of the destination tween state. - - - Get the DrawMode of the current tween state. - - - Get the FirstToDraw of the current tween state. - - - Get the NumToDraw of the current tween state. - - - Returns the ActorMultiVertex's texture. - - - Sets the EffectMode of the ActorMultiVertex. - - - Sets the TextureMode of the ActorMultiVertex. - - - Sets the width of the line for DrawMode_LineStrip. - - - Sets the texture to texture - - - Sets the texture at from the file path path. - -
- - - Returns the target of the ActorProxy. - - - Sets the ActorProxy target to a. - - - - - Returns the scroller's current item. - - - Returns the item the scroller's going to. - - - Returns how long it will take for the scroller to completely scroll through all its items. - - - Returns the number of items in the ActorScroller. - - - Returns the number of seconds the scroller pauses between items. - - - Returns the number of seconds until the scroller reaches its destination. - - - Compatibility alias for . - - - Positions the scroller items. - - - Scrolls through all the items in the scroller. - - - Compatibility alias for . - - - Scrolls through all the items in the scroller with padding at the beginning and end. - - - Compatibility alias for . - - - Sets the item the scroller should scroll to next and makes it the current item. - - - Sets the item the scroller should scroll to next. - - - Sets if the scroller should catch up fast. - - - Compatibility alias for . - - - Specifies if the scroller should loop or not. - - - Sets the scroller's mask to a Quad that is fWidth by fHeight pixels. - - - Sets the scroller to draw fNumItems items. - - - Sets the number of subdivisions in the scroller. - - - Compatibility alias for . - - - Sets the scroller's pause countdown to fSecs. - - - Sets the scroller's pause between items to fSeconds. - - - Sets how many seconds the scroller should spend on each item.
- A value of 0 means the scroller will not scroll. -
- - Compatibility alias for . - - - Sets the scroller's transform function to the specified Lua function. - - - Sets the scroller's transform function from fItemHeight. - - - Sets the scroller's transform function from fItemWidth. - -
- - - This Actor represents a playable sound. There are two attributes that can be set on load.
- * SupportPan - Let the sound pan from side to side.
- * SupportRateChanging - Let the sound change rate and pitch.
- * IsAction - If true, the sound is an action sound, and will be muted if the MuteActions preference is turned on. -
- - Returns the that can be played by this Actor. - - - Returns whether the sound is an action. - - - Loads the sound at sPath. - - - Pauses or unpauses the sound based on bPause. - - - Plays the sound. - - - [02 Sound.lua] Plays the sound on the given player's side. You must set SupportPan = true on load. - - - Sets whether the sound is an action. - - - Stops the sound. - -
- - - Returns true if Announcer sAnnouncer exists. - - - Returns a table of installed announcers. - - - Returns the current announcer's name. - - - Sets the announcer to sNewAnnouncer. - - - - - Returns true if the application presently has focus. - - - Returns the name of the architecture in use. - - - - - Returns true if the Banner is currently scrolling. - - - - - - Loads the background from an UnlockEntry. - - - Loads the banner from an UnlockEntry. - - - Loads the card image from the specified Character. - - - Loads the banner from the cache based on sPath (typically or ). - - - Loads a Banner from a specified Course. - - - Loads a Banner from a specified Song. - - - Loads a Banner from a specified Song Group. - - - Loads a Banner from a specified SortOrder. - - - Loads an icon from the specified Character. - - - See . - - - See . - - - - - - - - Add the attribute attr to the string at position - iPos.
- The attribute is a table that must contain Length - which specifies how many (multi-byte) characters the attribute - is to apply. If Length=-1, then the attribute applies - until another attribute overrides it.
- If the table contains Diffuse, then the color value - is applied to the range of text.
- If the table contains Diffuses, then it should be - an array of 4 colors which specify the diffuse color for the - top left, top right, bottom left, and bottom right.
- If the table contains Glow, then the color value - is applied as a glow to the range of text.
- Example:
- attr = { Length = 10; Diffuse = color("#AABBCC"); } -
- - Clear all attributes associated with the BitmapText. - - - [02 Actor.lua] Sets the diffuse and stroke color of text in one command. - - - Returns the text that is currently set. - - - Causes each character of text to be randomly distorted by - distortion_percentage of its size when the text is set. The distortion - only changes when the text changes. - - - Turns off distortion. - - - Returns whether the diffuse colors in the attributes are multiplied by the general diffuse colors of the BitmapText. - - - If mult_attrs_with_diffuse is set to true, then the diffuse colors in the attributes are multiplied by the general diffuse colors of the BitmapText. - - - If bJitter is true, move each character of the string around by a small random amount. - - - If use_zoom is true, this BitmapText will use the zoom that has been applied to it when calculating to change its base zoom from maxheight or maxwidth. - - - Set the maximum height of the unzoomed text to fHeight. If fHeight is 0, then there is no maximum height. - - - Set the maximum width of the unzoomed text to fWidth. If fWidth is 0, then there is no maximum width. - - - [02 Actor.lua] Remove any stroke color. - - - [02 Actor.lua] Alias for setting to false. - - - If true, set each character of the text in turn to the rainbow colors in the metrics BitmapText::RainbowColor#. - - - Set the text to sText. This clears all attributes. - - - [02 Actor.lua] Sets text using string.format(sFormat, ...). - - - [02 Actor.lua] Alias for . - - - Sets the stroke color to c. - - - If the text is glowing, specify if just the stroke layer, just the inner layer, or both are affected by the glow. - - - If true, make all text uppercase. - - - Add iSpacing pixels of padding between lines of text. - - - Wrap the unzoomed text at iWidth pixels. If you or by x and you want the text wrapped at width, then you should use wrapwidthpixels(width/x). - -
- - - Returns the text that is currently set at the exact moment you call it. This is likely only going to be useful in an Update command. - - - Sets the BPMDisplay from the specified Course. - - - Sets the BPMDisplay from the GameState. - - - Sets the BPMDisplay from the specified Song. - - - Sets the BPMDisplay from the specified Steps. - - - - - Returns the path to the character's card graphic. - - - Returns this character's directory. - - - Returns this character's ID. - - - Returns the path of the dancing animation of this character. - - - Returns the character's display name. - - - Returns the path to the character's icon. - - - Returns the path of the model of this character. - - - Returns the path of the rest animation of this character. - - - Returns the path to the character's ScreenSelectMode icon. - - - Returns the path to the character's ScreenStage icon. - - - Returns the path of the warm-up animation of this character. - - - - - Returns a table of all characters installed. - - - Return the corresponding to sID. - - - Returns a random character. - - - Returns the number of characters available. - - - - - Loads the ComboGraph commands from the Metrics in group sMetricsGroup. - - - Sets the values of the ComboGraph using the specified StageStats and PlayerStageStats. - - - - - Loads the ControllerStateDisplay from the specified GameController. - - - Loads the ControllerStateDisplay from the specified MultiPlayer. - - - - - Returns true if all of the songs in the course have been defined (as opposed to random songs). - - - Returns a table of all the Trails in the Course. - - - Returns the path to the Course's background. - - - Returns the path to the Course's banner. - - - Returns the Course's directory. - - - Returns a table of CourseEntry items. - - - Gets the CourseEntry at iIndex from the Course. - - - Returns the Course's . (Returns CourseType in SM5; integer in SM4) - - - Returns the description for this Course. - - - Returns the full display title of the Course. - - - Returns the estimated number of stages for the Course. - - - Returns the goal seconds for the Course. - - - Returns the Course's group name. - - - Returns the Course's . (Returns PlayMode in SM5; integer in SM4) - - - Returns the name of the person who scripted the Course. - - - Returns the total length of the Course in seconds. - - - Returns the full transliterated title of the Course. - - - Returns true if the Course has a background. - - - Returns true if the Course has a banner. - - - Returns true if the Course has modifiers. - - - Returns true if the Course has timed modifiers. - - - Returns true if the Course is an edit. - - - Returns true if the Course was automatically generated. - - - Returns true if the Course is Endless. - - - Returns true if the Course is Nonstop. - - - Returns true if the Course is Oni. - - - Returns true if the Course is playable in StepsType st. - - - Returns true if the Course is a ranking course. - - - - - Sets the CourseContentsList from the GameState. - - - - - Returns the Song that this CourseEntry corresponds to. - - - - Returns the number of lives gained after completing the song. - - - Returns the number of seconds gained after completing the song. - - - Returns any stage (non-timed) modifiers. - - - Returns the number of modifier changes in this CourseEntry. - - - Returns a comma-delimited string representing various facts about the CourseEntry. - - - Returns true if this CourseEntry is a fixed song. - - - Returns true if this CourseEntry is secret. - - - - - Generates a random UUID (version 4). - - - Returns the MD5 hash for the file at sPath. - - - Returns the MD5 hash for s. - - - Returns the SHA-1 hash for the file at sPath. - - - Returns the SHA-1 hash for s. - - - - - All functions in this class have camel case equivalents, use whichever naming style you prefer.
- This spline implementation is a cubic spline.
- A spline is a line calculated from a small set of points with mathematical smooting applied.
- Splines can have any number of dimensions, but splines owned by actors (the ones inside NCSplineHandler and ActorMultiVertex) always have 3 dimensions.
-
- - Solves the spline, setting the coefficients. - - - Evaluates the spline at the given t value, returning a table of the results for each dimension of the spline.
- t can range from 0 to the value returned by get_max_t().
- A normal spline will return its starting point for any t value less than 0 and its end point for any t value greater than the max.
- A looped spline adjust the t value to be within the its range by adding or subtracting the max t as needed. (so if the max t is 4 and you evaluate at 5, it will return the same as if you evaluated at 1.) -
- - Evaluates the derivative at t. - - - Evaluates the second derivative at t. - - - Evaluates the third derivative at t.
- Second and third derivative functions exist because they're possible, not because they're expected to be useful. The fourth derivative would be 0 because the equation for evaluating the spline is "a + (b*t) + (c*t^2) + (d*t^3)". -
- - Sets point i of the spline to the position specified by the table p. - - - Sets the coefficients of the spline at point i.
- Each table must contain a value for each dimension of the spline.
- Solving the spline normally should cover all normal usage, this is for people that want a spline with an abnormal behavior, so if you set the coefficients directly, expect to end up with an unsmooth shape. -
- - Returns a table containing the tables of coefficients for the point i. - - - Sets the spatial extent of dimension d of the spline to e.
- The spatial extent exists to handle numbers that exist in a finite looped space, instead of the flat infinite space.
- To put it more concretely, spatial extent exists to allow a spline to control rotation with wrapping behavior at 0.0 and 2pi, instead of suddenly jerking from 2pi to 0.0. -
- - Returns the spatial extent of dimension d of the spline. - - - Returns the max t value the spline extends to. For a normal spline, this will be size()-1. For a looped spline, this will be size(). - - - Sets the number of points in the spline. You must set the number of points before trying to set the position of any point. - - - Returns the number of points in the spline. - - - Sets the number of dimensions the spline has.
- Splines that are owned by actors (the ones inside ActorMultiVertex and NCSplineHandler) cannot have their number of dimensions changed because the actors require them to have 3 dimensions. -
- - Returns the number of dimensions the spline has. - - - Returns true of the spline has zero points, or false if it has more than zero points. - - - Sets whether the spline is looped. A looped spline is one where the end point is connected to the start point. - - - Returns whether the spline is looped. - - - Sets whether the spline is polygonal. If the spline is polygonal, then it will have straight lines between the points instead of curves. - - - Returns whether the spline is polygonal. - - - Sets whether the spline is dirty. A dirty spline is one that has been changed in some way that affects its shape. When solve() is called, the spline will only be solved if it is dirty. The dirty flag is automatically set by everything, so you should never have to call this function. - - - Returns whether the spline is currently dirty. - - - Destroys the spline, freeing the memory allocated for it. This can only be called on splines created with create_spline(). - -
- - - Sets the DifficultyIcon's state from the difficulty passed in. - - - Sets the DifficultyIcon's Player to pn, - then sets the DifficultyIcon's state from the difficulty of Steps pSteps - - - Sets the DifficultyIcon's Player to pn, - then sets the DifficultyIcon's state from the difficulty of Trail pTrail - - - Sets the DifficultyIcon's Player to pn. - - - Blanks the DifficultyIcon. - - - - - Returns the index of the last banner loaded. - - - Loads the fallback course banner. - - - Loads the fallback banner. - - - Loads the card image from the specified Character. - - - Loads a Banner from a specified Course. - - - Loads a Banner from a specified Song. - - - Loads a Banner from a specified Song Group. - - - Loads a Banner from a specified SortOrder. - - - Loads an icon from the specified Character. - - - Loads the Random banner. - - - Loads the Roulette banner. - - - See . - - - See . - - - - - Sets the StepsDisplayList from the GameState. - - - - - Returns true if notes are counted separately in this game. - - - Returns the mapped judgment for tns. - - - Returns the name of the game such as "dance" or "pump". - - - Returns whether this game allows the players to have separate styles. - - - - - Returns any announcer that may have been set. - - - Returns any Character associated with this item (or nil if there isn't one). - - - Returns any Course that may have been set. - - - Returns a course difficulty, if one is set in the GameCommand. - - - Returns a difficulty, if one is set in the GameCommand. - - - Returns the index of this item. - - - Returns any MultiPlayer that may have been set. - - - Returns the choice name. - - - Returns the PlayMode associated with this GameCommand. - - - Returns any preferred modifiers that may have been set. - - - Returns any Profile ID that may have been set. - - - Returns any screen that may have been set as a string. - - - Returns any Song that may have been set. - - - Returns the name of any song group that may have been set. - - - Returns the sort order, if the GameCommand has set one. - - - Returns any stage modifiers that may have been set. - - - Returns any Steps that may have been set. - - - Returns any Style that may have been set. - - - Returns the display text. - - - Returns any Trail that may have been set. - - - Returns any Url that may have been set. - - - - - Return the first for the specified game. - - - Returns true if any noteskins exist for the specified Game s. - - - Return the localized string representation of st. - - - Returns a table of all selectable games. - - - Returns a table of all the styles for the that exist for game. - - - Sets the current game to Game. The second argument is optional, and if provided will determine which theme is loaded when the game changes. If the second argument is not provided, the default theme from the preferences for the new game type will be loaded.
- If only the game changes, the screen specified by the Common::AfterGameChangeScreen metric will be loaded.
- If the game and the theme both change, the screen specified by the Common::AfterGameAndThemeChangeScreen metric will be loaded.
- The Common::InitialScreen metric will be used if the appropriate metric for the change is blank or invalid. -
-
- - - Set the music volume to fVolume for fDuration seconds. - - - - Return the sound balance for pn. - - - Plays a sound from the current announcer. - - - Play the sound at musicPath starting from musicStart for - musicLength seconds one time. Both fadeIn and - fadeOut can be customized as required. loop - tells the sound manager to loop the music part. applyRate - tells the sound manager to apply the current music rate. If alignBeat - is true or nil, the length is automatically adjusted to cover an integer number of beats. - - - Play the sound at sPath one time. is_action is optional, if it is true, the sound is an action sound, and will be muted if the MuteActions preference is turned on. - - - Stops the music. - - - When music is requested to change, the new music does not start immediately due to latency and buffering. This will return true if the newest music has not yet actually begun. - - - - - Adds another stage to the specifed player. - - - Applies the specified modifiers for the specified player's preferred modifier set. - - - Applies the song options of ModsLevel_Preferred to the other ModsLevels. - - - Applies the specified modifiers for the specified player for the current stage. - - - Returns true if any player has performed a feat worthy of ranking. - - - The second argument is optional. Apply the GameCommand represented by sCommand - for pn, if given. See . - - - Checks various things to determine whether the game will crash when gameplay starts. Returns false and a string if gameplay cannot be entered safely.
- Might not work in all cases, but will catch things like a player not having - steps set or no current song or style. Mainly exists for people with a custom ScreenSelectMusic replacement.
- Example:
- local can, reason= GAMESTATE:CanSafelyEnterGameplay()
- if not can then
- lua.ReportScriptError("Cannot safely enter gameplay: " .. tostring(reason))
- end
-
- - Removes any stage modifiers that are illegal for course play. - - - Returns true if pn's options will disqualify them for ranking. - - - Returns true if enough credits have been inserted to join. - - - fishpolk.mid; See also: Rise of the Triad - - - Returns the environment table. See . - - - Returns the current for the specified . - - - Returns the current . - - - Return the number of inserted but unused coins. This number is - decremented when players join. - - - Return the number of coins needed to join based on the current coin and premium modes - as well as the number of people joined, if that matters for the premium mode. See - and . - - - The s in a are numbered sequentially - starting from 0. Return the number of the current . - - - Return the current number of seconds that have passed in the current song. This value can be negative. - - - Return the current . - - - Return the current . - - - Return the current . - - - Return the current . - - - Returns the current stage index (starts at 0). - - - Return the current for the specified Player. - - - Return a variable number of arguments based on the being - played by all players. For each distinct being played by - the players, in increasing order, - the difficulty and description of the is returned as strings. -
For example,
- local credits = {GAMESTATE:GetCurrentStepsCredits()};
- will make a table of the difficulties and descriptions. -
- - Return the current . - - - Return the current for the specified player. - - - Return a string representation of the default song options. - - - Returns the value. - - - Return the easiest of the - currently selected steps by all players. For example, if player 1 has - selected Hard steps and player 2 has selected Medium steps, Medium will - be returned. - - - - - - Return the Edit Local (during Profile editing) - or nil if it does not exist. - - - Returns the ID of the Edit Local (during Profile editing). - - - Return the source for the editor or nil - if it does not exist. - - - Returns a table of enabled players. - - - Returns the name of the currently expanded section. - - - Return the random seed for the game. - - - Return true if the gameplay lead in is enabled. If - false, gameplay begins immediately. - - - Return the hardest of the - currently selected steps by all players. For example, if player 1 has - selected Hard steps and player 2 has selected Medium steps, Hard will - be returned. - - - Returns an array of s corresponding to Human players. - - - Returns the index of the next song in the course. - - - Returns the master player number. - - - Returns true if the game is Multiplayer. - - - Returns the PlayerState for the specified MultiPlayer. - - - Returns the number of active multiplayer NoteFields. - - - Returns the number of players enabled. - - - Returns the number of sides joined. - - - Returns the number of stages for the current Song and its Steps or the current Course. - - - Returns the number of stages left for player pn. - - - Returns the display name for player pn. - - - Returns the PlayerState for player pn. - - - Returns the current PlayMode. - - - Returns the preferred difficulty. - - - Returns the preferred song. - - - Returns the preferred song group. - - - Returns the current Premium. - - - - Returns the smallest number of stages left for any human player. - - - [01 alias.lua] Returns the current beat of the song. - - - [01 alias.lua] Returns the current beat of the song without an offset. - - - Returns the current visible beat of the song. - - - [01 alias.lua] Returns the song's current beats per second. - - - [01 alias.lua] Returns true if a delay is active in the song. - - - [01 alias.lua] Returns true if the song is currently in a freeze. - - - Returns the song options for the specified ModsLevel as a string. - - - Returns the song options as a string. - - - Returns the song options for the specified ModsLevel as an object. - - - Returns how much of the song is through at beat fBeat. - - - Returns the current SongPosition. - - - Returns the current SortOrder. - - - Returns the StageResult for player pn. - - - Returns the current stage index. - - - Returns the current StepsSeconds, which is the time value used to set the samples in a player's life record. - - - Return the random seed for the current stage. - - - Returns true if the workout goal is complete. - - - Returns true if an extra stage was earned. - - - Returns true if either player does not have a profile loaded, and there is a loadable profile. - - - Returns true if either player has a profile loaded. - - - Returns true if we are specifically in the Step Editor's - editing portion. If in recording or playing mode, this will return - false. - - - Inserts iCoins number of coins. iCoins can be negative or positive. - - - Inserts one credit. To deduct a credit, pass a negative integer representing the number - of coins per credit to InsertCoin. - - - Returns true if this is an extra stage. - - - Returns true if any human player is using a memory card. - - - Returns true if playing in Battle mode. - - - Returns true if playing in a Course mode. - - - Returns true if in Demonstration mode. - - - Returns true if the match was a draw. - - - Returns true if Event Mode is on, temporary or otherwise. - - - Returns true if this is the first extra stage. - - - Returns true if this is the second extra stage. - - - Returns true if player pn has completed the current Goal. - - - Returns true if player pn is human. - - - Returns true if player pn is enabled. - - - Returns true if player pn has joined the game. - - - Returns true if player pn is the winner. - - - Joins player pn. Does not deduct coins. - - - Similar to JoinPlayer, but checks whether the player is allowed to join and returns false if the player is not allowed to join. Also deducts coins for joining. A player can't join if PlayersCanJoin() returns false, or that side is already joined (is true for both sides when in a style that is OnePlayerTwoSides), or there are not enough coins. - - - If profiles are not loaded, this will load the profiles for each player. It will load from memory cards if they are present, and local profiles otherwise. It will load edits if LoadEdits is true, or by default if the argument is omitted. - - - Returns true if player pn is using modifier sModifier. - - - Returns true if players can join the game. - - - Refreshes the NoteSkin data for the current game. - - - Resets the GameState. - - - Resets the specific Player's mods to the default settings. - - - Saves the bookkeeping and machine profile data. - - - Save profiles. - - - Sets the current for the specified . - - - Sets the current Course to course. - - - Sets the current PlayMode to pm. - - - Sets the current Song to song. - - - Sets Player pn's current Steps to steps. - - - Sets current Style to the provided style. Either a style object or a style string can be provided. If current steps for either player are not valid in the new style, they will be cleared. - - - Sets the current Trail to trail. - - - Tells the engine that the theme explicitly set the fail type for the players so that it won't override it with the easier settings for beginner or easy. - - - Sets if the Jukebox should use modifiers. - - - - - - Sets the number of multiplayer notefields to iFields - - - Sets the preferred difficulty of Player pn to Difficulty dc. - - - Sets the preferred Song to song. - - - Sets the preferred song group to sGroup. - - - Sets the Song Options from so using ModsLevel m. - - - Turns temporary Event Mode on or off, depending on bOn. - - - Stores the ranking name for the player. Use this at the end of a round, on a name entry screen or similar, to set the name for the high scores the player has earned. - - - Determines if Judgment W1 should be shown based on bOn. - - - Unjoins player pn. - -
- - - Loads the GradeDisplay commands from the Metrics in group sMetricsGroup. - - - Sets the GradeDisplay to show Grade g. - - - - - Loads the GraphDisplay commands from the Metrics in group sMetricsGroup. - - - Sets the values of the GraphDisplay using the specified StageStats and PlayerStageStats. - - - - - Sets the GrooveRadar values for Player pn to empty. - - - Sets the GrooveRadar values for Player pn from RadarValues rv - - - Sets the GrooveRadar values for Player pn to the specified (floating point) values in the table. - - - - - Returns two tables representing the tips and alternate tips in the HelpDisplay. - - - [02 HelpDisplay.lua] Sets the tips from a Song or Course. - - - Sets the seconds between switches of tips to fSeconds. - - - Sets the HelpDisplay's tips using tips (and optionally altTips). - - - Sets the HelpDisplay's text from sTips using colons to separate new sections. - - - - - Returns the date and time the high score was achieved. - - - Returns the Grade of this high score. - - - Returns the HighScore for this PlayerStageStats. - - - Return the number of HoldNoteScores that match hns. - - - Returns the Max Combo of this high score. - - - Returns the modifiers used for this HighScore. - - - Returns the name associated with the high score. - - - Returns the Peak Combo Award for this high score. - - - Returns the percentage of dance points associated with the high score. - - - Returns the RadarValues for this HighScore. - - - Returns the score associated with the high score. - - - Retrns the Stage Award for this high score. - - - Returns the number of seconds survived associated with the high score. - - - Return the number of TapNoteScores that match tns. - - - Returns true if this high score's name uses a fill-in marker. - - - - - You can get a HighScoreList using . - - - Returns a table of the high scores. - - - Returns the highest score for name in the list. Returns nil if there is no score for name in the list. - - - Returns the rank of the highest score for name in the list. Returns 0 if there is no score for name in the list. (returns 1 if name has the top score, 2 if name has the second place score, and so on) - - - - - Loads the HoldJudgment for the specified MultiPlayer. - - - - - Returns the mouse wheel value. - - - Returns the X position of the mouse. - - - Returns the Y position of the mouse. - - - - - Returns the amount of life left in the LifeMeter as a float in the range 0..1. - - - Returns true if failing. - - - Returns true if the LifeMeter is "hot". - - - Returns true if in danger. - - - - - Changes the player's life by iNumLives. (Negative values subtract lives.) - - - Returns the number of lives remaining. - - - Returns the number of total lives. - - - - - Returns true if player pn's card is locked. - - - Return the state for player pn. - - - Returns the name of the storage device. - - - Returns true if player pn's name is available. - - - - - Stops the MenuTimer by setting it to 99.99 and pausing. - - - Returns the current MenuTimer's value. - - - Pauses the MenuTimer, stopping it from counting down. - - - Compatibility alias for SetSeconds. - - - Sets the MenuTimer's value to fSeconds. - - - Sets the MenuTimer's silent setting to bSilent. - - - Starts up the timer. - - - Sets the MenuTimer's stealth setting to bStealth. If - true, the timer will be invisible and silent. - - - Stops the MenuTimer by setting it to 0 and pausing. - - - - - Broadcast the message to all listeners subscribed to sMessage. The - second argument is an optional table of parameters. It may be omitted or explicitly - set to nil. - - - Sets whether logging of messages is enabled. If log is true, all messages that pass through Broadcast (from the engine for from the theme or from anywhere else), will be logged with Trace. - - - - - Sets the width of the MeterDisplay to fWidth. - - - - - Returns the model's default animation. - - - Controls if the model should loop or not. - - - Plays animation sAniName at fPlayRate speed (default 1.0). - - - Sets how far into the animation the model is. - - - Sets the current animation's playback rate to fRate. - - - Sets the model's default animation to sAnimation at fPlayRate speed (default 1.0). - - - - Returns the number of states the Model has. - - - - - Loads the ModIconRow of Player pn from the Metrics in group sMetricsGroup. - - - - - Changes the sort order of the wheel. Returns true if the order was changed. - - - Returns the name of the currently selected section. - - - Returns true if the MusicWheel is currently handling Roulette selection. - - - Selects a song. Returns false on failure. - - - Selects a course. Returns false on failure. - - - - - Returns a string from the specified element and value. - - - Returns a string from the specified element and value using NoteSkin sNoteSkin. - - - Returns a command from the specified element and value. - - - Returns a command from the specified element and value using NoteSkin sNoteSkin. - - - Returns a bool from the specified element and value. - - - Returns a bool from the specified element and value using NoteSkin sNoteSkin. - - - Returns a float from the specified element and value. - - - Returns a float from the specified element and value using NoteSkin sNoteSkin. - - - Returns a integer from the specified element and value. - - - Returns a integer from the specified element and value using NoteSkin sNoteSkin. - - - Returns the path for the specified sButton sElement. - - - Returns the path for the specified sButton sElement using NoteSkin sNoteSkin. - - - Returns the actor for the specified sButton sElement. - - - Returns the actor for the specified sButton sElement using NoteSkin sNoteSkin. - - - - Returns true if the strName noteskin exists in the current gametype. - - - Returns a table of noteskin names for the current gametype. - - - - - All functions in this class have camel case equivalents, use whichever naming style you prefer.
- The spline handler holds info on how the spline is used by the engine.
- Each get/set pair of functions in this class is for a different aspect of the spline's behavior. -
- - Returns the spline for this handler. - - - Returns the beats per t value of the spline. If the beats_per_t is 4, then a note must be on screen for 4 beats to traverse from one point on the spline to the next. - - - Sets the beats per t value for the spline. - - - Returns the t value that receptors are evaluated at. - - - the t value that receptors are evaluated at. - - - Returns the mode the spline is set to.
- "NoteColumnSplineMode_Disabled" means the spline will not affect the notes or receptors at all.
- "NoteColumnSplineMode_Offset" means the spline will added to the effects from the mods.
- "NoteColumnSplineMode_Position" means only the spline affect the notes and mods will be ignored. (but only mods that affect the same aspect of the note as the spline will be disabled. So a rotation spline won't disable Mini or Tiny, but a zoom spline will, and a zoom spline won't disable Dizzy, Twirl, or Roll, but a rotation spline will.) -
- - Sets the current spline mode for this handler. - - - Returns whether the current song beat is subtracted from a note's beat when calculating the t value to use on the spline. - - - Sets whether the current song beat is subtracted from a note's beat when calculating the t value to use on the spline. - -
- - - All functions in this class have camel case equivalents, use whichever naming style you prefer.
- Position, rotation, and zoom each have separate spline handlers to allow them to have separate independent behavior.
- It is important to note that the spline handlers are inside the tween state, so whenever you start a new tween on the actor, you need to refetch the spline handlers.
-
- - Returns the handler for the position spline. - - - Returns the handler for the rotation spline.
- The rotation applied by the rotation spline is in radians.
- For convenience, the spatial extent of the rotation spline defaults to 2pi. -
- - Returns the handler for the zoom spline. - -
- - - All functions in this class have camel case equivalents, use whichever naming style you prefer.
-
- - Makes the NoteField act as if a hold note was hit in the column, with the given score and bright setting.
- The callback for did_hold_note will not be called. -
- - Makes the NoteField act as if a tap note was hit in the column, with the given score and bright setting.
- The callback for did_tap_note will not be called. -
- - Returns a table of the actors for the columns. This means that each column is an actor, so you can move it around or animate it like an actor. See the NoteColumnRenderer class for a list of special functions for the column's actor. - - - Same as SetDidTapNoteCallback, but for hold notes. Uses HoldNoteScore instead of TapNoteScore. - - - Sets the function that the NoteField will call whenever a tap note is hit.
- The callback function is passed the column, the TapNoteScore, and whether the explosion will be bright.
- The callback function can return changed values for the NoteField to use instead of the ones that were passed.
- Pass nil instead of a function to clear the callback. -
- - Makes the NoteField act as if a press occurred in the column.
- The callback for set_pressed will not be called. -
- - Sets the function that the NoteField will call whenever a press occurs.
- The callback function is passed the column for the press.
- The callback function can return changed values for the NoteField to use instead of the ones that were passed.
- Pass nil instead of a function to clear the callback. -
- - Sets the function that the NoteField will call whenever a step occurs.
- The callback function is passed the column and the TapNoteScore for the step.
- The callback function can return changed values for the NoteField to use instead of the ones that were passed.
- Pass nil instead of a function to clear the callback. -
- - Makes the NoteField act as if a step occurred in the column with the given score. - The callback for Step will not be called. - -
- - - Returns true if the first item in the row goes down. - - - Returns an index of the choice in the row that player pn is on. - - - Returns the OptionRow's layout type. - - - Returns the name of the OptionRow. - - - Returns the number of choices in this OptionRow. - - - Returns the row title string. - - - Returns the OptionRow's select type. - - - Returns true if this row is focused by player pn. - - - Returns true if this row forces one choice on all players. - - - - - Sets the PaneDisplay from the GameState. - - - - - Sets the PercentageDisplay from the specified PlayerState and PlayerStageStats. - - - - - Changes the life value by delta. This will broadcast a LifeChangedMessageCommand, to allow custom life bars to update to the new value. Do not call ChangeLife from within LifeChangedMessageCommand. - - - Sets the life to value. This will broadcast a LifeChangedMessageCommand, to allow custom life bars to update to the new value. Do not call SetLife from within LifeChangedMessageCommand. - - - Returns the current TimingData for this player. - - - Sets Actor with Combo position. - - - Sets Actor with Judgment position. - - - - (PlayerInfo is a part of ScreenGameplay.) - - Returns the of player pn. - - - Returns the Steps located at index in the current steps queue. - - - - - All these functions have an optional last argument: If the last argument is the boolean value true, then instead of returning the previous settings as normal, they will instead return the PlayerOptions object.
- This allows you to chain them like this:
- player_options:Twirl(5, 1, true):Roll(5, true):Dizzy(true):Twirl()
-
- Special note: Functions that take a bool as their arg must have true as the second arg to be used with chaining.
- "player_options:Backwards(true, true):Beat(5)" will chain, "player_options:Backwards(true):Beat(5)" will not chain.
-
- Most options fall into one of four types: float, int, bool, or enum.
- Float type options have this interface:
- Option(value, approach_speed)
- If value is a float, sets the TimeSpacing modifier to value.
- If approach_speed is a float, sets the speed of the transition to approach_speed. Returns the previous values of both.
- approach_speed is in units of n per second. value will be approached at the rate of approach_speed per second.
- Note that the value and the approach speed arguments are both independently optional.
- Example:
- a,b= options:Boost() -- Sets a to the current value and b to the current approach_speed.
- a,b= options:Boost(5, .5) -- Stores the previous values in a and b, NOT to 5 and .5. Sets the value to 5 and the approach speed to .5.
- a,b= options:Boost(5) -- Sets a and b to the previous values, NOT to 5 and .5. Sets the value to 5 and leaves the approach speed at whatever it was.
-
- Setting the approach speed only matters when modifying the PlayerOptions from ModsLevel_Song.
- Int type options are similar to float in that they return and take a number, but they do not have an approach speed.
- Bool type options have an almost identical interface, the difference is that they can not have an approach speed.
- Enum type options are almost identical to bool type. They take and return an enum value.
- For brevity, the functions are only given a description if the option requires careful handling or does not follow the float or bool interfaces.
-
- - - - - - - - - - - - - - - - If the player has a CMod set, returns the value of that CMod and its associated approach speed. Returns nil otherwise.
- If the optional first argument is passed, sets the CMod to the value and disables any XMod or MMod that is set.
- If the optional second argument is passed, sets the speed at which the transition occurs. -
- - - - - - - If the player is using Distant (zero skew and positive tilt), returns the value of tilt and its approach_speed.
- Returns nil otherwise.
- If the optional first argument is passed, sets tilt to value and skew to zero.
- If the optional second argument is passed, sets the approach_speed for skew and tilt to it. -
- - - - - - Sets the for the player, if the optional argument is provided. Returns the that was previously set. - - - - - Returns true if step attacks or random attacks are enabled. - - - Returns true if the current PlayerOptions makes the current Course/Trail easier. - - - Returns true if the current PlayerOptions makes the current Song/Steps easier. - - - If the player is using Hallway (zero skew and negative tilt), returns the value of tilt and its approach_speed.
- Returns nil otherwise.
- If the optional first argument is passed, sets tilt to negative value and skew to zero.
- Pass in a positive value for the familiar meaning of Hallway.
- If the optional second argument is passed, sets the approach_speed for skew and tilt to it. -
- - - - - If the player is using Incoming ((positive skew and negative tilt) or (negative skew and positive tilt)), returns the value of skew and its approach_speed.
- Returns nil otherwise.
- If the optional first argument is passed, sets tilt to negative value and skew to value.
- Pass in a positive value for the familiar meaning of Incoming.
- If the optional second argument is passed, sets the approach_speed for skew and tilt to it. -
- - - - - - MaxScrollBPM is one of the variables for controlling the speed mod.
- Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
- It is the setting for the MMod.
- MMods are not tweenable or settable on ScreenGameplay. Use XMods if you need such an effect. -
- - - Sets the min TapNoteScore required for the notes to disappear after being hit. - - - If the player has a MMod set, returns the value of that MMod and its associated approach speed. Returns nil otherwise.
- If the optional first argument is passed, sets the MMod to the value and disables any CMod or XMod that is set.
- If the optional second argument is passed, sets the speed at which the transition occurs.
- MMods are not tweenable or settable on ScreenGameplay. Use XMods if you need such an effect. -
- - - - - - - - - - - - - Sets the NoteSkin to the named noteskin, unless name is nil or the noteskin does not exist. Returns the name of the previous noteskin and whether the set attempt succeeded.
- Changing the noteskin during a song is not supported.
- Example:
- note_name= options:NoteSkin() -- Sets note_name to the player's current noteskin.
- prev_note_name, succeeded= options:NoteSkin("cel") -- Sets prev_note_name to the noteskin the player had set, changes the current noteskin to "cel", sets succeeded to true if the "cel" noteskin exists.
-
- - If the player is using Overhead (0 tilt, 0 skew), returns true.
- If true is passed, sets the tilt and skew to 0. -
- - - - - - - - - - - - ScrollBPM is one of the variables for controlling the speed mod.
- Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
- It is the setting for the CMod. -
- - ScrollSpeed is one of the variables for controlling the speed mod.
- Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
- It is the setting for the XMod. -
- - - Skew is one of the mods for controlling the perspective. Use Overhead, Distant, Incoming, Space, Distant, or Hallway for controlling the perspective in the old way.
- Skew moves the vanishing point for the note field away from the center of the screen.
- Skew has no effect in single mode if Center1Player is true.
- Skew has no effect in double mode.
-
- - - - If the player is using Space ((positive skew and positive tilt) or (negative skew and negative tilt)), returns the value of skew and its approach_speed.
- Returns nil otherwise.
- If the optional first argument is passed, sets tilt to value and skew to value.
- If the optional second argument is passed, sets the approach_speed for skew and tilt to it. -
- - - - - - - - TimeSpacing is one of the variables for controlling the speed mod.
- Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
- It controls whether the speed mod is in X mode or C mode. It should only be set to 0 or 1, and is only a float value to allow tweening between the two states. -
- - Tilt is one of the mods for controlling the perspective. Use Overhead, Distant, Incoming, Space, Distant, or Hallway for controlling the perspective in the old way.
- Tilt tilts the note field forward and back. -
- - - - - - - - Returns true if the player is using reverse. (equivalent to GetReverse() == 1.0) - - - - - If the player has a XMod set, returns the value of that XMod and its associated approach speed. Returns nil otherwise.
- If the optional first argument is passed, sets the XMod to the value and disables any CMod or MMod that is set.
- If the optional second argument is passed, sets the speed at which the transition occurs. -
- -
- - - Fails the player. - - - Returns true if a full combo (TNS_W3 and up) was obtained. - - - Returns true if a full combo (tns and up) was obtained. - - - Returns the number of Dance Points obtained by the player. - - - Returns how long the player has been alive. - - - Returns the best tap note score for a full combo. - - - Returns the number of calories burned. - - - Returns a table of all the combos. Each entry in the table is a table containing the StartSecond, SizeSeconds, Count, Rollover, StageCount, and IsZero information for that combo. - - - Returns the current possible maximum score. - - - Returns the player's current combo. - - - Returns the player's current life from 0..1. - - - Returns the player's current miss combo. - - - Returns the number of Dance Points possible to be obtained by the player. - - - Returns the player's current score multiplier. - - - Returns true if the player failed. - - - Returns the player's grade. - - - Returns the player's HighScore. - - - Returns the number of judgments for a specified HoldNoteScore. - - - Returns the player's actual score on the lesson. - - - Returns the score needed to pass the lesson. - - - Returns table of samples of the life record from 0 to last_second. - 'samples' determines the size of the table. 'samples' defaults to 100 - if not specified. - - - Returns the player's life remaining seconds. - - - Returns the machine high score index for this performance. - - - Returns the number of controller steps. - - - Returns the peak combo award for this performance. - - - Returns the personal high score index for this performance. - - - Returns a table of played steps. - - - Gets the percentage of taps that were scored as tns. - - - Returns the player's Dance Point percentage. - - - Returns the number of possible Dance Points. - - - Returns a table of possible steps. - - - Returns a RadarValues object representing the player's actual performance. - - - Returns a RadarValues object representing the total values for the song. - - - Returns the score. - - - Returns the number of songs passed. - - - Returns the number of songs played. - - - Returns the stage award for this performance. - - - Returns how long the player survived in seconds. - - - Returns the number of judgments for a specified TapNoteScore. - - - Returns the max combo for this performance. - - - Returns true if the player was disqualified from ranking. - - - - - Applies the player options of ModsLevel_Preferred to the other ModsLevels. - - - Returns the current PlayerOptions for this PlayerState. - - - Returns the HealthState for this PlayerState. - - - Returns the multiplayer number for this PlayerState. - - - Returns the PlayerController for this PlayerState. - - - Returns the player number for this PlayerState. - - - Returns a PlayerOptions object for the specified ModsLevel. - - - Returns a string of player options for the specified ModsLevel. (was GetPlayerOptions before sm-ssc v1.2.3) - - - Returns a table of strings, containing the player options for the specified ModsLevel. - - - Returns the SongPosition for this PlayerState. - - - Returns the current Super Meter level for this PlayerState. - - - Sets the player options to sPlayerOptions for the specified ModsLevel. - - - - - Return the value of the preference sPreference. - - - Return true if preference sPreference exists. - - - Set the value of the preference sPreference to value. - - - Reset preference sPreference to the default value. - - - Saves preferences to disk. - - - - - Adds cals to the daily total. - - - Adds a screenshot entry to the profile. filename must be the full path of the screenshot, as returned by SaveScreenshot. - - - Calculates the number of calories burned based on the heart rate (in beats per minute), the duration (in seconds), and data in the profile. - - - Returns the age. - - - Returns a table of all high score names that have been used on this profile. - - - Returns the birth year. - - - Returns the number of calories burned during the current day. - - - Returns the profile's high scores for the specified ranking category. - - - Returns the Character being used by this profile. - - - Returns a composite of your high scores over courses with the specified StepsType and Difficulty. - - - Returns the percentage of courses that you've completed with the specified StepsType and Difficulty. - - - Returns the possible score of courses with the specified StepsType and Difficulty. - - - Returns the profile's display name. - - - Return the number of calories burned as a string. - - - Returns the number of calories needed to reach the goal. - - - Returns the number of seconds needed to reach the goal. - - - Returns the current goal type. - - - Returns the GUID of this Profile. - - - Returns whether this profile ignores the step count based calorie calculation. - - - Returns whether this profile uses the male formula when CalculateCaloriesFromHeartRate is used. - - - Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: Course c, Trail t) - - - Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: Course c, Trail t)
- If the profile does not have a HighScoreList for the Song and Steps, returns nil. Use this to avoid increasing the memory footprint of the profile when checking the score lists for every song and steps. -
- - Returns the last played Course for this profile. - - - Returns the last played Song for this profile. - - - Returns the last used high score name. - - - Returns the number of Toasties gotten using the specified profile. - - - Returns the profile's most popular course. - - - Returns the profile's most popular song. - - - Returns the total number of songs played with the profile. - - - Returns the position the profile should have in its category in the list. - - - Returns the number of times song s has been played with the profile. - - - Returns a composite of your high scores over songs with the specified StepsType and Difficulty. - - - Returns the percent complete for all songs and courses for the specified StepsType st. - - - Returns the percentage of songs that you've completed with the specified StepsType and Difficulty. - - - Returns the possible score of songs with the specified StepsType and Difficulty. - - - Return the total number of calories burned. - - - Returns the number of dance points earned. - - - Returns the number of Hands stepped on. - - - Returns the number of successful Holds. - - - Returns the number of Jumps stepped on. - - - Returns the number of successful Lifts. - - - Returns the number of Mines stepped on. - - - Returns the total number of songs played with the profile. - - - Returns the number of successful Rolls. - - - Returns the number of steps with the specified StepsType and Difficulty that you've scored a certain Grade g on. - - - Returns the number of Taps and successful Holds. - - - Returns the number of trails with the specified StepsType and Difficulty that you've scored a certain Grade g on. - - - Returns the type of the profile. The type of the profile is only used to determine where the profile shows up in the list of profiles, and that problem is already handled by ProfileManager, so if you're reading this, this function only exists so you can make your theme color this profile's list entry based on the type or something like that. - - - Returns the user table for this Profile. - - - Returns the VO2 max for this profile. - - - Returns how much the player weighs. - - - Returns true if the player has passed any steps in the specified Song s. - - - Returns true if the specified code sUnlockEntryID is unlocked. - - - Sets the birth year of the profile. - - - Sets the current for the Profile. - - - Sets the display name of the profile to name. - - - Sets the goal to iCals calories. - - - Sets the goal to iSecs seconds. - - - Sets the current goal type to gt. - - - Sets whether this profile ignores the step count based calorie counting. - - - Sets whether this profile uses the male formula when CalculateCaloriesFromHeartRate is used. - - - Sets last used high score name. - - - Sets the VO2 max for the profile. 0 is treated as unset. - - - Sets how much the player weighs (in pounds) to weightPounds. - - - - Returns the amount of time this profile has spent in gameplay (in seconds). - - - Returns the number of sessions this profile has had. - - - Returns the total session length (in seconds) of this profile. - -
- - - Returns the Profile for the specified profile ID. - - - Returns a table of the local profile display names. - - - - - Returns a table of the local profile IDs. - - - - Retuns the machine profile. - - - Retuns the amount of local profiles. - - - Returns the player name for player pn. - - - Returns the profile for player pn. - - - Returns the profile directory of the specified ProfileSlot. - - - Returns the number of times Song s has been played with the specified ProfileSlot. - - - Returns the current stats prefix. - - - Returns true if player pn's profile is persistent. - - - Returns true if Song s has never been played before (according to the machine profile). - - - - - Returns true if the profile from the memory card is new. - - - Returns true if pn's Profile was loaded from a memory card. - - - - Returns true if the last load of player pn's profile was a LastGood copy of the profile. - - - Returns true if the last load of player pn's profile resulted in a tampered or corrupt profile. - - - Saves the local profile with the specified ID. - - - Saves the machine profile. - - - Saves the profile for player pn. - - - Sets the current stats prefix. The stats prefix is prepended to the Stats.xml file when loading or saving a profile. SetStatsPrefix will reload all profiles from the Stats.xml that has the given prefix. In general, score entries are the only thing not preserved when changing the stats prefix. Profile::HandleStatsPrefixChange in Profile.cpp lists the fields that are preserved. - - - - - Returns the value of rc from . - - - - - You must call create_bezier to create a RageBezier2D to use any of these functions. When you are done with the object, destroy it with its destroy function to avoid a memory leak.
- A RageBezier2D is two RageQuadratics, one for the x coordinate and one for the y.
- This class is provided as a tool for designers working with bezier tweens who need a tool that displays the tween curve visually.
- If you use Actor:tween(time, "TweenType_Bezier", {xa, ya, xb, yb, xc, yc, xd, yd}) to tween an actor, the actor creates a RageBezier2D internally and calls evaluate_y_from_x each frame to set where it is in the tween. -
- - Destroys the RageBezier2D. Do not attempt to use it after it has been destroyed. - - - Evaluates the bezier curve at the given t and returns the x and y values. This is equivalent to using get_x and get_y to fetch the quadratic parts and calling evaluate on them directly. - - - Takes the x given and converts it to a t value, then evaluates the y quadratic with the t value and returns the result. - - - Returns the RageQuadratic used for the x component. - - - Returns the RageQuadratic used for the y component. - - - Sets the values used by the two quadratics. This is equivalent to using get_x and get_y to get the quadratics and setting them directly. Note that the components for the x quadratic and the y quadratic are interleaved. - -
- - - Return the height of the display. - - - Return the width of the display. - - - Return the number of frames per second. - - - Return the VPF. - - - Return the cumulative FPS. - - - - - These commands require a RageFile handle. You can create one using - . - - - Returns true if the current position within the file is the end. (EOF = End of File) - - - Clears the last error message. - - - Closes the file and releases it from memory. - - - Safely deletes the file handle. - - - Flushes the buffer for the file handle, writing any pending output to disk. - - - Gets the last error message and returns it. - - - Gets a line and returns it. - - - Opens a file at sPath (relative to the StepMania root directory).
- iAccessType can be set to read (1), write (2), stream (4) or flush to disk on close (8).
- These can also be combined with addition. For example, to set up read and write, set iAccessType to 3 (1+2). -
- - Puts a new line in the file. - - - Returns a string containing the entire contents of the file. - - - Returns length bytes from the RageFile's current position. - - - Seeks to a position in the file and returns the new position. - - - Returns the current position in the file. - - - Writes a file with the contents of str. - -
- - - Returns true if a file exists at sPath. - - - Returns a listing of files from sPath. The last two arguments are optional (and default to false). - - - Returns a file's size in bytes. - - - Returns the hash of the file at sPath. - - - - - Return an array of connected input device descriptions. - - - - - If you use Actor:tween(time, "TweenType_Bezier", {a, b, c, d}) to tween an actor, the actor creates a RageQuadratic internally and calls evaluate each frame to set where it is in the tween. - - - Evaluates the quadratic at the given t value and returns the result. - - - Returns the four values that form the quadratic equation. This function returns multiple values, so you must do something like this to get them:
- a, b, c, d= quadratic:get_bezier() -
- - Equivalent to evaluate(1), but faster. - - - Equivalent to evaluate(0), but faster. - - - Returns the slope of the curve at the given t value. - - - Sets the four values that form the quadratic equation. - - - Sets the four values that form the quadratic equation, treating the arguments as from a cubic equation instead of as from a bezier curve. - -
- - - See for loading a sound. - - - Returns the length of the sound loaded into this RageSound. Returns -1 if no sound is loaded. - - - Actually sets the value of sProperty to fVal. The supported properties depend on how the associated was loaded. - - - Attempts (and typically fails) to set the value of sProperty to fVal. The supported properties depend on how the associated was loaded. - - - Sets the pitch to fPitch. The associated have SupportsRateChanging = true on load. - - - Sets the speed (that is, the rate at which the sound plays) to fSpeed. The associated must have SupportsRateChanging = true on load. - - - Sets the volume to fVolume, which is between 0..1. - - - - - Returns the source width. - - - Returns the source height. - - - Returns the texture width. - - - Returns the texture height. - - - Returns the image width. - - - Returns the image height. - - - Returns the number of frames in this texture. - - - Returns the path to the texture's file. - - - Return the texture coordinate rectangle as {left, top, right, bottom}. - - - Sets the animation or movie looping to bLoop. - - - Sets the animation or movie position to fPos. - - - Sets the animation or movie playback rate to fRate. - - - Reloads the texture. - - - - - Loads the metrics for this RollingNumbers from sGroupName. - - - Sets the target number to f. - - - - - This adds the lua function "callback" to the list of functions the screen will pass input to. Whenever an input event occurs, callback will be passed a table with the details of the event. callback must return a bool to indicate whether the event was handled. If callback returns true, the event will not be passed any further.
- This should not be used to provide text input because that would not handle localization or different keyboard layouts.
- The screen and the callbacks will both be passed input events, so be aware of what input the current screen responds to and consider the effects.
- Details of the table containing the event data:
- {
- DeviceInput= { -- The raw details of the event.
- device= string, -- The type of device. The first half of the string will be "Device_", the second half will be from InputDeviceNames in RageInputDevice.cpp.
- button= string, -- The button that was pressed. the first half of the string will be "DeviceButton_", the second half will be from InitNames in RageInputDevice.cpp.
- level= float, -- A floating point value for analog input.
- z= float, -- Mousewheel input.
- down= bool, -- Whether the button is down. This is level with a threshold and debouncing applied.
- ago= float, -- How long ago this input occurred, in seconds.
- is_joystick= bool, -- True if the device is a joystick.
- is_mouse= bool -- True if the device is a mouse.
- }, -- This ends the list of things inside the DeviceInput part of the table.
- controller= string, -- The game controller this event was mapped to. "GameController_1" or "GameController_2", or nil if the event wasn't mapped to either controller.
- button= string, -- The semi-raw button that was pressed. This is what the button was mapped to by the keymap settings, but without the conversions that occur when OnlyDedicatedMenuButtons is true. Will be empty if the button was not mapped.
- type= string, -- The type of event. "InputEventType_FirstPress", "InputEventType_Repeat", or "InputEventType_Release".
- GameButton= string, -- The cooked button that was pressed. This is button with mapping that occurs when OnlyDedicatedMenuButtons is true applied. This is nil for unmapped buttons.
- PlayerNumber= PlayerNumber, -- The player that the controller is mapped to, or nil.
- MultiPlayer= string, -- Unknown purpose.
- } -
- - Returns the name of the next Screen. - - - Returns the name of the previous Screen. - - - Returns the ScreenType for this Screen. - - - Locks input for f seconds. - - - [02 Other.lua] Gets a metric from the current Screen. - - - Posts a message with the text sScreenMsg to the Screen after fDelay seconds. - - - This removes the callback from the list. - - - Sets the NextScreen value to name. - - - Sets the PrevScreen value to name. - - - [02 Other.lua] Gets a string from the current Screen in the current language. - -
- - - Returns the current . - - - - - Returns the current StageStats. - - - - - This should behave identically to the normal back button behavior. This function is for the pause menu to use when the player forfeits or restarts, so that a score isn't saved. - - - Returns true if a single has its NoteField centered. - - - Returns a dummy PlayerInfo for the specified index. - - - Returns the current haste rate. HasteRate * MusicRate is the current total rate the music is multiplied by. - - - Returns the for the specified pn. - - - Returns the next in the current . - - - Returns the PlayerInfo for player pn. - - - Returns the current true beats per second for the specified player.
- This takes into account the current music rate and the current haste effect.
- If you are displaying the BPM on ScreenGameplay, this is what you should use to have correct behavior when Haste and/or a music rate mod are in effect. -
- - This is part of the system for controlling how haste behaves.
- Read Docs/Themerdocs/haste.txt. -
- - This is part of the system for controlling how haste behaves.
- Read Docs/Themerdocs/haste.txt. -
- - This is part of the system for controlling how haste behaves.
- Read Docs/Themerdocs/haste.txt. -
- - This is part of the system for controlling how haste behaves.
- Read Docs/Themerdocs/haste.txt. -
- - Sets the next Screen to be loaded. - - - Returns true if the game is paused. - - - Pauses or unpauses the game, depending on the value of bPause. - -
- - - Returns the LifeMeter. - - - - - Adds a screen at the top of the screen stack. (sMessage is an optional ScreenMessage posted once the new screen is finished.) - - - Gets the screen at the top of the screen stack. - - - Returns whether the input for the player has been redirected away from the normal screen input function. Input that has been redirected is only sent to lua input callbacks. - - - Plays the invalid sound. - - - Plays the start sound. - - - Plays the coin sound. - - - Plays the cancel sound. - - - Plays the screenshot sound. - - - Reloads any loaded overlay screens. - - - Returns true if screen class s exists. - - - Returns true if screen s is prepared. - - - Sets the next screen to s. - - - Sets whether the input for the player has been redirected away from the normal screen input function. Input that has been redirected is only sent to lua input callbacks.
- This can be useful when putting a custom menu on a screen, and you want to disable the built in actors while the menu is open. Then you handle input through an input callback until the player closes the menu. -
- - Broadcasts a system message. - -
- - - Returns true if Player pn backspaced successfully. - - - Returns true if Player pn was able to add sKey to their name. - - - Attempts to finish Player pn and returns true - if successful. - - - Returns true if anyone is entering their name. - - - Returns true if anyone is still entering their name.
- (As opposed to those who are Finalized; see ) -
- - Returns true if Player pn is entering their name. - - - Returns true if Player pn is finished entering their name. - - - Gets the currently selected letter of Player pn. - -
- - - Returns the number of active players. - - - - - Returns true if all active players are on the last options row. - - - Returns true if the specified player is on an items that ends the screen. - - - Returns the current row that player pn is on. (Was previously GetCurrentRow.) - - - Returns the number of rows on the screen. - - - Returns the specified OptionRow. - - - - - Returns true if we are going to PlayerOptions. - - - - - Continues to the next screen. - - - Returns true if there is a profile that can be loaded. - - - - - Continues to the next screen. - - - Returns true if there is a profile that can be saved. - - - - - Returns player pn's current selected item as an integer. - - - - - Returns false if the options list is already open or the UseOptionsList metric is false. - - - Returns true if the player is going to the options screen. - - - Returns the MusicWheel used on this screen. - - - Opens the OptionsList for Player pn - - - [02 StageMods.lua] Sets up modifiers for course modes. - - - [02 StageMods.lua] Sets up modifiers for non-course modes. - - - - - Tells the screen to go to the previous screen. - - - Attempts to finish the screen and returns true - if successful. - - - Returns the profile index of the specified Player. - - - Sets the profile index of Player pn to iProfileIndex. - - - - - TextEntrySettings is implemented similar to the Attributes in BitmapText. Formatting issues prevent the sample from being properly shown here.
Please see docs/Themerdocs/ScreenTextEntry.txt for the TextEntrySettings format. -
- - Sets up a ScreenTextEntry's values. - -
- - - Tells the screen to go to the previous screen. - - - Returns true if the screen is currently transitioning. - - - Tells the screen to go to play its Out transition, and then posts the ScreenMessage sScreenMsg. To go to the next screen, use "SM_GoToNextScreen" as the argument. - - - Sets whether the screen allows late joining. This only works for screens that are just ScreenWithMenuElements, as most derived screens have their own hard coded function for whether late joining is allowed. - - - - - Returns an array of all the available objects for a . - - - Returns the path to the song's background image. - - - Returns the path to the song's banner. - - - Returns a table with all the data for the song's BGCHANGES line.
- Each element of the table is one change like this:
- {start_beat= 1.0, rate= 1.0, transition= "example", effect= "example", file1= "example", file2= "example", color1= "#FFFFFFFF", color2= "#FFFFFFFF"} -
- - Returns the path to the song's CD image. - - - Gets the path to the CDTitle. - - - Returns the path to the song's disc image (different from CD, think Pump). - - - Returns the displayed artist of the song. - - - Returns a table of 2 floats containing the display BPMs. - - - Returns the displayed full title of the song, including subtitle. - - - Returns the displayed main title of the song. - - - Returns the displayed subtitle of the song. - - - Returns the first beat of the song. - - - Returns the first second of the song. - - - Returns the genre of the song. - - - Returns the group name that the song is in. - - - Returns the path to the song's jacket image. - - - Returns the last beat of the song. - - - Returns the last second of the song. - - - Gets the path to the lyrics. - - - GetDisplayMainTitle checks the ShowNativeLanguage pref and returns the transliterated title is that pref is false.
- GetMainTitle (this function) does not check that pref. Instead, it directly returns the title, exactly as it is in the #TITLE field in the simfile. -
- - Gets the path to the music file. - - - Returns a Step object if the StepType and Difficulty exist. - - - Gets the Song's origin. - - - Returns the path to the Song's preview music. This handles the #PREVIEW tag internally, so it works with songs that use it and songs that don't. - - - Returns the path to the Song's preview video, if it exists. (Returns nil otherwise.) - - - Gets the length of a song's sample time in seconds. - - - Gets the starting position of a song sample in seconds. - - - Returns the song's directory. - - - Returns the songfile path. - - - [02 Other.lua] Returns the number of stages this song costs. - - - Returns a table of Steps that have StepsType st. - - - Returns how long the longest stepchart is in seconds. - - - Returns the song's TimingData. - - - Returns the transliterated artist of the song. - - - Returns the transliterated full title of the song, including subtitle. - - - Returns the transliterated main title of the song. - - - Returns the transliterated subtitle of the song. - - - Returns true if the song has steps for the specified difficulty in st. - - - Returns true if the song has attacks. - - - Returns true if the song has a background. - - - Returns true if the song has a banner. - - - Returns true if the song has BGChanges. - - - Returns true if the song has a CD image. - - - Returns true if the song has a CDTitle. - - - Returns true if the song has a Disc graphic. - - - Returns true if the song has edits. - - - Returns true if the song has a jacket graphic. - - - Returns true if the song has lyrics. - - - Returns true if the song has music. - - - Returns true if the song has a preview video. - - - Returns true if the song has significant BPM changes or stops. - - - Returns true if the song has the specified StepsType. - - - Returns true if the song's DisplayBPM is constant. - - - Returns true if the song's DisplayBPM is random. - - - Returns true if the song's DisplayBPM is secret. - - - Returns true if the song is considered easy. - - - Returns true if the song is enabled. - - - Returns true if the song meets the criteria for a "Long Version". - - - Returns true if the song meets the criteria for "Marathon" length. - - - Returns true if the song and the specified steps have different timing. - - - Returns true if the song only has Beginner steps. - - - Returns the length of the song in seconds. - - - Returns true if the song is normally displayed. - - - Returns true if the song is shown in Demonstration and Ranking. - -
- - - Returns true if the specified course group exists. - - - Returns true if the specified song group exists. - - - Returns a Course if one matching sCourse is found. - - - Returns a Song if one matching sSong is found. - - - Returns an array of all the installed courses. - - - Returns an array of all the installed songs. - - - Returns the course color of Course c. - - - Returns the path to the specified course group's banner. - - - Returns a table containing all of the course group names. - - - Returns a table with all of the courses in the specified group. - - - Returns the extra stage info (Song, Steps) for the specified Style s. (If bExtra2 is true, it will use the second Extra Stage data instead of the first. Again, Lua.xsd sucks) - - - Returns the number of courses loaded via Additional folders. - - - Returns the number of songs loaded via Additional folders. - - - Returns the number of course groups. - - - Returns the number of courses. - - - Returns the number of selectable and unlocked songs. - - - Returns the number of song groups. - - - Returns the number of songs. - - - Returns the number of locked songs, regardless of reason for locking. - - - Returns the number of unlocked songs. - - - Returns a table of popular courses for the specified CourseType. - - - Returns a table of popular songs. - - - Returns a table of courses as they'd appear in preferred sort. - - - Returns a table of songs as they'd appear in preferred sort. - - - Returns a random course. - - - Returns a random song. - - - Returns the song color of Song s. - - - Returns a Song given a set of Steps st. - - - Returns the path to the specified song group's banner. - - - Returns the song group color of sGroupName. - - - Returns a table containing all of the song group names. - - - Returns the rank (popularity) of Song s. - - - Returns a table containing all of the songs in group sGroupName. - - - Returns the shortened group name (based on entries in Translations.xml). - - - Loads preferred courses from {theme}/Other/SongManager sListName.txt. - - - Loads preferred songs from {theme}/Other/SongManager sListName.txt. - - - Returns the preferred sort section name for the specified Song. - - - Returns true if the specified course was loaded from AdditionalCourses. - - - Returns true if the specified song was loaded from AdditionalSongs. - - - - - See the description for PlayerOptions. The functions follow the same design. - - - - - - - - - - - - - - - - - Limited to the range 0 < rate <= 3 because speeds greater than 3 are likely to crash. - - - A multiplier for the haste system. Limited to the range -1 to 1. - - - - - Returns the current beats per second. - - - Returns true if a Delay is active. - - - Returns true if a Freeze is active. - - - - - - - - - - - - - - - - - - Returns the row where a warp appears. - - - Returns the warp destination length. - - - - - Returns the length of the animation in seconds. - - - Gets whether the Sprite should call the decode function for its texture during updates. - - - Return the number of states this Sprite has. - - - Returns the Sprite's current state (frame number in a multi-frame sprite). - - - Returns the Sprite's texture. - - - [02 Sprite.lua] Returns a Frames table consisting of iNumFrames frames lasting for a total of fSeconds seconds. This function is not a member function and should be used as Frames = Sprite.LinearFrames( 5, 2.6 ). - - - If sPath is nil, then unload the texture. Otherwise, load the texture at path sPath. - - - Load the song background texture at sPath. - - - Load the song banner texture at sPath. - - - [02 Sprite.lua] Loads the background from the current Song or the first Trail entry. - - - [02 Sprite.lua] Load the texture for song's background. - - - [02 Sprite.lua] Load the texture for song's banner. - - - Sets the custom image rectangle. (Works in image pixel space.) - - - Sets custom offsets for the corners of the Sprite. Coordinates are paired, - corner order is upper left, lower left, lower right, upper right. - - - Turns off the custom pos coords for the sprite. - - - Sets whether the Sprite should call the decode function for its texture during updates. - - - Set the to mode. - - - Sets the number of seconds into the animation to fSeconds. - - - Sets the properties of the states of the sprite. The properties table is identical to the "Frames" table that can be put in the sprite when calling Def.Sprite.
- Example:
- {{Frame= 0, Delay= .016, {0, 0}, {.25, .25}},
- {Frame= 1, Delay= .016, {0, 0}, {.25, .25}},
- {Frame= 2, Delay= .016, {0, 0}, {.25, .25}},
- {Frame= 3, Delay= .016, {0, 0}, {.25, .25}},
- }
- Frame is optional, defaulting to 0.
- Delay is optional, defaulting to 0.
- The two tables are optional upper left and lower right corners of the fraction of the frame to use. The example makes the sprite only use the upper left corner of each frame.
- Simpler example:
- {{Frame= 0, Delay= .016}, {Frame= 1, Delay= .016}, {Frame= 2, Delay= .016}, {Frame= 3, Delay= .016}}
- This example makes the sprite use the whole of each frame. -
- - Set the texture to texture. - - - - - - Allows the themer to set a custom texture rectangle that effects the way the texture is drawn. - - - Returns true if the sprite is using the effect clock for texcoordvelocity. - - - [02 Sprite.lua] Call RageTexture:loop( bLoop ) on the texture. - - - [02 Sprite.lua] Call RageTexture:position( fPos ) on the texture. - - - [02 Sprite.lua] Call RageTexture:rate( fRate ) on the texture. - - - Scale the Sprite to width fWidth and height fHeight clipping if the dimensions do not match. - - - Set the Sprite's state to iNewState. - - - If use is true, then the sprite will use the effect clock for texcoordvelocity. - - - - - - Set the texture coordinate velocity which controls how the Sprite changes as it animates. A velocity of 1 makes the texture scroll all the way once per second. - - - - Crops the Sprite to fWidthxfHeight. - - - [01 alias.lua] Alias for CropTo. - - - Sets all the state delays to fRate. Useful for Sprites that need to change by BPM (e.g. Tran from DDR 5th Mix, the cube from DS EuroMix 2). - -
- - - Returns true if everyone failed. - - - Returns the EarnedExtraStage value. - - - Returns the number of seconds played. - - - Returns the PlayerStageStats of multiplayer mp. - - - - Returns the PlayerStageStats of player pn. - - - - Returns the Stage value. - - - Returns the stage index. - - - Returns true if at least one person passed. - - - Returns true if player pn has a high score. - - - - - Returns the accumulated played StageStats. - - - Returns the best final grade. - - - Returns the best grade. - - - Returns the current StageStats. - - - Returns player pn's final grade. - - - Get the StageStats from iAgo rounds ago. - - - Returns the number of stages played. - - - Returns the worst grade. - - - Resets the stats. - - - - - Returns the author that made that particular Steps pattern. - - - Returns the Steps chart name. - - - Returns the Chart Style for this Steps. - - - Returns the Steps description. - - - Returns the Steps difficulty. - - - Returns a table with the minimum and maximum values from the DisplayBPM. - - - Returns the DisplayBPM type. - - - Returns the Steps filename from the Cache. - - - Returns a hash of the Steps. - - - Returns the numerical difficulty of the Steps. - - - Returns true if the Steps has any attacks. - - - Returns true if the Steps pattern has significant timing changes. - - - Returns the complete list of RadarValues for player pn. Use to grab a specific value. - - - Returns the Steps type. - - - Returns the TimingData for the Steps. - - - Returns true if the Steps are an edit. - - - Returns true if the Steps are a player edit (loaded from a profile). - - - Returns true if the steps were automatically generated. - - - Returns true if the DisplayBPM is constant. - - - Returns true if the DisplayBPM is random. - - - Returns true if the DisplayBPM is secret. - - - Returns the predicted meter for this Step. - - - Returns true if the Steps use different TimingData from the Song. - - - - - Loads the StepsDisplay commands from the Metrics in group sMetricsGroup. - - - Sets the StepsDisplay from the GameState using Player pn. - - - Sets the StepsDisplay based on Steps pSteps. - - - Sets the StepsDisplay based on the passed in StepsType, iMeter, and Difficulty. - - - Sets the StepsDisplay based on Trail pTrail. - - - - - Returns the number of total tracks per player this Style contains (e.g. 4 for dance-versus, but 8 for dance-double). - - - Returns the name of the Style. - - - Returns the StepsType for this Style. - - - Returns the StyleType for this Style. - - - Returns a table containing the Track, XOffset, and Name of the column. - - - Returns the draw order of the column. - - - Returns the width of the notefield for the given player with this style. - - - Returns true if this style locks the difficulty for both players. - - - Deprecated. Always returns false. - - - - - Returns the of the Tap Note. - - - Returns the of the Tap Note. - - - Returns the of the Tap Note. - - - Returns the of the Tap Note. - - - Returns the of the Tap Note. Relevant for routine steps. - - - Returns the Attack Modifiers of the Tap Note. - - - Returns the Attack Duration of the Tap Note in seconds. - - - Returns the Keysound Index of the Tap Note. - - - Returns the Hold Duration of the Tap Note in beats. - - - Returns the of the Tap Note. - - - - - Returns the of the Tap Note. - - - Returns the TapNotOffset of the Tap Note. - - - Returns true if the Tap Note was judged with a result that would stop it from drawing. - - - - - Returns the of the Hold Note. - - - Returns the life of the Hold Note. - - - Returns the amount of time the hold has overlapped the target. - - - Returns the last beat the Hold Note was held. - - - Returns the number of checkpoints hit. - - - Returns the number of checkpoints missed. - - - Returns true if the note was initiated and is being held. - - - Returns true if the note was initiated. - - - - - Loads the TextBanner from the specified metrics group. - - - Loads the TextBanner's child elements from a . - - - Loads the TextBanner's child elements from strings. - - - - - Returns true if the specified language exists in the current theme. - - - Returns true if the specified theme exists. - - - [02 Utilities.lua] Returns the absolute path of a file in the theme. - - - Returns the current language. - - - Returns the theme's current directory. - - - Returns the name of the current theme. - - - Returns the value of Element in Class from metrics.ini. - - - Returns the names of all elements in Class from metrics.ini. - - - Returns the number of selectable themes. - - - Returns the path of ClassName Element in the BGAnimations folder. - - - Returns the path of an element in the Fonts folder. - - - Returns the path of an element in the Graphics folder. - - - returns three strings: BGAnimation ResolvedPath, MatchingMetricsGroup, MatchingElement. Used in LoadFallbackB in themes/_fallback/02 Other.lua. (Lua.xsd sucks) - - - Returns the path of an element in the Other folder. - - - Returns the path of an element in the Sounds folder. - - - Returns a table of selectable theme directories. - - - Returns the value of Element in Class for the currently loaded language. - - - Returns the names of all elements in Class for the currently loaded language. - - - Returns the author of the current theme or "[unknown author]". - - - Returns the display name of the current theme. - - - Returns true if the theme has the specified metric. - - - Returns true if the theme has the specified string. - - - Returns true if the specified theme is selectable. - - - Reloads the current theme's metrics. - - - - - - Changes the current theme.
- After the theme changes, the screen specified by the Common::AfterThemeChangeScreen metric will be loaded.
- The Common::InitialScreen metric will be used if Common::AfterThemeChangeScreen is blank or invalid. -
-
- - - GetBPMsAndTimes, GetStops, GetDelays, GetLabels, GetWarps, GetCombos, GetTimeSignatures, GetTickcounts, GetFakes, GetScrolls, and GetSpeeds all have two different modes.
- If false (or nothing) is the argument to these functions, they return tables of strings. The strings are numbers separated by '='.
- If the argument is true, they return tables of tables, and the inner tables contain numbers as described for each function.
- The first form is kept around and is the default for compatibility with older themes. The advantage of the second form is that you no longer need to have a bit of code in your theme to transform the string into a table of numbers before you can use it.
- Example:
- local bpmsand= timing_data:GetBPMsAndTimes()
- for i, s in ipairs(bpmsand) do
- local sand= split("=", s)
- bpmsand[i]= {tonumber(sand[1]), tonumber(sand[2])}
- end
- -- do something that looks at all the bpms and times.
- Becomes:
- local bpmsand= timing_data:GetBPMsAndTimes(true)
- -- do something that looks at all the bpms and times.
-
- - Returns the minimum and maximum BPM of the song in a table (in that order). - - - Returns the beat from fElapsedTime. - - - Returns the BPM at fBeat. - - - Returns a table of the BPMs as floats. - - - Returns a table of the BPMs and the times they happen as tables. The first value is the beat. The second value is the bpm. - - - Returns the elapsed time from fBeat. - - - Returns a table of the Stops and the times they happen as tables. The first value is the beat. The second value is the length. - - - Returns a table of the Delays and the times they happen as tables. The first value is the beat. The second value is the length. - - - Returns a table of the Labels and the times they happen as tables. The first value is the beat. The second value is the label. - - - Returns a table of the Warps and the times they happen as tables. The first value is the beat. The second value is the number of beats to warp over. - - - Returns a table of the Combos and the times they happen as tables. The first value is the beat. The second value is the combo. The third value is the miss combo. - - - Returns a table of the Time Signatures and the times they happen as tables. The first value is the beat. The second value is the numerator. The third value is the denominator. - - - Returns a table of the Tickcounts and the times they happen as tables. The first value is the beat. The second value is the number of ticks per beat. - - - Returns a table of the Fakes and the times they happen as tables. The first value is the beat. The second value is the number of beats to not judge. - - - Returns a table of the Scrolls and the times they happen as tables. The first value is the beat. The second value is the scroll rate ratio. - - - Returns a table of the Speeds and the times they happen as tables. The first value is the beat. The second value is the scroll rate ratio. The third value is the length of time to fully activate. The fourth value is the unit of activation (0 for beats, 1 for seconds). - - - Returns true if the TimingData contains BPM changes. - - - Returns true if the TimingData contains delays. - - - Returns true if the TimingData contains any BPM changes with a negative BPM. - - - Returns true if the TimingData contains stops. - - - Returns true if the TimingData contains warps. - - - returns true if the TimingData contains fake segments. - - - Returns true if the TimingData contains speed scrolling changes. - - - Returns true if the TimingData contains general scrolling changes. - -
- - - Returns true if song s is in the Trail. - - - Returns an array with all the artists in the Trail. - - - Returns the Trail's difficulty. - - - Returns the length of this Trail in seconds. - - - Returns a table of TrailEntry items. - - - Returns the Trail's difficulty rating. - - - Returns the Trail's RadarValues. - - - Returns the Trail's StepsType. - - - Returns the Trail's total meter - - - Returns the TrailEntry at index iEntry. - - - Returns true if any of the Trail entries are secret. - - - - - Returns a string of modifiers used in this TrailEntry. - - - Returns the Song used in this TrailEntry. - - - Returns the Steps used in this TrailEntry. - - - (why'd I think this was a good idea when we have ?) - - - - - Sets the UnlockEntry's ID to m_sEntryID. - - - Sets the UnlockEntry's course to sCourseName.
- Example: course,"Driven" -
- - Returns the code for this unlock. - - - Returns the Course for this unlock. - - - Returns the unlock description. - - - Returns the UnlockRequirement. - - - Returns true if the UnlockEntry requires you to pass Hard steps. - - - Returns true if the UnlockEntry requires you to pass Challenge steps. - - - Returns the Song related to the UnlockEntry. - - - Get all of the steps locked based on StepsType. - - - Get all of the steps locked based on difficulty. - - - Returns the UnlockRewardType for this entry. - - - Returns true if the UnlockEntry is locked. - - - Sets the UnlockEntry's modifier to sModifier. - - - Sets the requirement for this unlock to m_fRequirement. - - - Makes the UnlockEntry require passing Hard steps. - - - Makes the UnlockEntry require passing Challenge steps. - - - Makes the UnlockEntry hide in Roulette. - - - Sets the UnlockEntry's song to sSongName. sSongName also requires the group.
- Example: song,"In The Groove/Pandemonium" -
- - Sets the UnlockEntry to unlock a specified song's steps.
- Example: steps,"In The Groove/Pandemonium","expert" -
- - Sets the UnlockEntry to unlock a specified song's stepstype. - -
- - - Returns true if there are any unlocks to celebrate. - - - Returns the associated EntryID. - - - Returns the number of unlocked items. - - - Returns the number of all unlock items, regardless of status. - - - Returns the number of points for the machine profile based on the specified UnlockRequirement. - - - Returns the number of points for the specified profile based on the specified UnlockRequirement. - - - Returns the number of points until the next unlock. - - - Returns a table of songs unlocked by UnlockEntry sEntryID. - - - Returns a table of steps unlocked by UnlockEntry sEntryID. - - - Returns the UnlockEntry at iIndex. - - - Returns the UnlockEntry index to celebrate. - - - Sets the preferred Song/Course to the specified sUnlockEntryID - - - Unlocks an entry by ID. - - - Unlocks an entry by index. - - - Determines if a song is locked by any means. The number returned determines - how the song is locked. - - - - - Returns the wheel's current index. - - - Returns the total number of items in the wheel. - - - Returns the WheelItemDataType of the selected item. - - - Returns the WheelItem at index iIndex. - - - Returns true if the wheel is locked. - - - Returns true if the wheel is settled/stopped moving. - - - Moves the wheel by n. - - - Attempts to set the open section to sSection. - - - - - Returns the color of this wheel item. - - - Returns the text of this wheel item. - - - Returns the type of this wheel item. - - - Returns whether the wheel item has been loaded yet. If this function returns false, calling any other WheelItemBase function will result in an error.
- A specific case where this is known to happen is commands that trigger on CurrentSongChanged because the music wheel clears the current song before it finishes loading if the current song is longer than the number of stages remaining. -
-
- - - Sets the WorkoutGraph from the current Workout. - - - Sets the WorkoutGraph from GameState and song index iSongIndex. - - -
- - - - - Blending modes. See . - - - - - Horizontal alignment. See . - - - - - Vertical alignment. See . - - - -
+ + + + + + + + + + + [02 Colors.lua] Returns a color with the specified alpha. + + + Use this to make a current value approach a goal value at the given speed. Speed must not be negative. The value will not overshoot the goal.
+ Note: When you see the error "approach: speed 1 is negative." it means that the speed value passed was negative. The 1 is there because approach and multiapproach use the same internal function and can be ignored when using approach. +
+ + [03 CustomSpeedMods.lua] + + + [02 StageMods.lua] + + + [02 StageMods.lua] + + + Issues an error when v is false (or nil). Returns all arguments otherwise. sAssertMessage is an optional error message (the default is "assertion failed!"). + + + Returns the base name of file path. + + + [02 Colors.lua] Boosts the specified color by multiplying its values by fBoost. + + + [02 Colors.lua] Modifies the brightness of the specified color. + + + [02 Utilities.lua] Returns true if Center 1P is being used. + + + [03 Gameplay.lua] Returns true if checkpoint judgments and tap judgments + are considered separate, or false otherwise. + + + CLAMP is an all-female Japanese mangaka group that formed in the mid 1980s. + Erm, I mean... Clamps fValue between fLow and fHigh. + + + [04 KeymapGuard.lua] + + + Closes any connection to an online server. + + + A generic interface to Lua's garbage collector. Performs different functions based on the value of opt. + + + Returns a color from a string. color can be in hex ("#FFFFFFFF") or 0..1 values ("1.0,1.0,1.0,1.0"), in RGBA order. + + + [02 Colors.lua] Returns a darker tone of the color. (Specifically c[1]/2, c[2]/2, c[3]/2, c[4]) + + + [02 Colors.lua] Returns a lighter tone of the color. (Specifically c[1]+(c[1]/2), c[2]+(c[2]/2), c[3]+(c[3]/2), c[4]) + + + [02 Colors.lua] Returns a midtone of the color. (Specifically c[1]/1.5, c[2]/1.5, c[3]/1.5, c[4]) + + + [02 Colors.lua] Returns a hex representation for the specified color. + + + [02 Colors.lua] Takes in a color and returns a table with the HSV values. + + + [03 Gameplay.lua] Determines what TapNoteScore allows for continuing the combo. + + + [03 Gameplay.lua] Determines what TapNoteScore allows for maintaining the combo. + + + [03 Gameplay.lua] Determines if combo should be per row (Jump = 1) or per column (Jump = 2). + + + [02 Other.lua] The combo trasform command. + + + [03 Gameplay.lua] Returns the UserPrefComboUnderField user preference value. + + + This will take the number and insert a comma every three digits, as normal in English for writing large numbers.
+ number can be a string, an integer, or a float.
+ comma is an optional argument that is used instead of a comma.
+ "commify(1234, 'cat')" will result in "1cat234".
+ dot is an optional argument that is used instead of a dot to find the end of the part that should be commified.
+ "commify('1234cat5678', ',', 'cat')" will result in "1,234cat5678", but "commify('1234cat5678')" will result in "12,34c,at5,678".
+ The comma and dot arguments are provided to ease compliance with locales or languages that do not use comma and dot in numbers the way English does. +
+ + Tries to connect to the server at sAddress. + + + Recursively searches dir for xml files of actors and + converts them to equivalent lua files. See Docs/Themerdocs/XmlToLua.txt + for details. + + + Creates a RageBezier2D for you to use. Make sure you destroy the RageBezier2D when you're done with it, or you will have a memory leak. + + + Creates a CubicSplineN for you to use. Make sure you destroy the CubicSplineN when you're done with it, or you will have a memory leak. + + + [02 Colors.lua] + + + [02 Colors.lua] + + + [02 Colors.lua] + + + Returns the current day of the month. + + + Returns the current day of the year. + + + [02 Serialize] Recursively deep-copy a table. + + + [01 base.lua] "Override Lua's dofile to use our loadfile." + + + [03 Gameplay.lua] + + + [03 Gameplay.lua] + + + [02 Utilities.lua] Old name for approach. + + + This function creates files in the theme's Languages folder listing all the strings that have no translation and all the strings that are unused.
+ Strings that do not have an entry in the master language are considered unused.
+ master_lang_name is the name of the ini file that contains the language with all strings used by the theme.
+ Example: find_missing_strings_in_theme_translations("my_best_theme", "en.ini") +
+ + [02 Utilities.lua] Return the index of a true value in list. + + + [02 Utilities.lua] Find a key in tab with the given value. + + + func takes a key and a value. + + + Returns the number passed to the function followed by its suffix ("th", "nd", and so on). + + + + Returns fPercentDancePoints formatted as a percentage. + + + [03 Gameplay.lua] Returns a list of valid styles for the current gametype. + + + [03 Gameplay.lua] + + + Returns the corresponding CustomDifficulty string for a StepsType/Difficulty (/optional CourseType) combination. + + + [04 Scoring.lua] "Get the radar values directly. The individual steps aren't used much." + + + [02 Other.lua] Returns a string with the Edit Mode SubScreens. + + + [03 EnvUtils2.lua] Returns the value of name from the Env table. + + + [03 Gameplay.lua] Returns the number at which the Extra color should be used. + + + Returns a corresponding for the given percentage. + + + Returns the current Life Difficulty. + + + Returns the length of the music file found at path.
+ If you are loading the sound into an ActorSound, ActorSound:get to get its RageSound then use RageSound's get_length function instead to avoid loading the file twice. +
+ + Returns a table of the names of the sound drivers available. If the SoundDriver preference is set to something that is not in this list, StepMania WILL NOT START UP. Changes to the SoundDriver preference do not take effect until the next time StepMania starts up. + + + Returns a string representing the name of the operating system being used. (e.g. "Windows", "Linux", "Mac, "Unknown") + + + [02 Utilities.lua] "This returns a profile, preferably a player one. If there isn't one, [it falls] back on the machine profile." + + + [03 ThemePrefs.lua] Returns true if player pn is using ProTiming. + + + [02 Utilities.lua] Returns a path to a random song background. + + + [02 Actor.lua] + + + [02 Actor.lua] + + + Returns the display aspect ratio. + + + Returns the name of the currently connected server. + + + [02 Utilities.lua] Returns a path to the current songs background. + + + [03 Gameplay.lua] + + + Returns the theme's aspect ratio. + + + [03 ThemePrefs.lua] (Alias for .) + + + Returns the current Timing difficulty. + + + Returns the current time since the program was started. Includes time that was spent loading songs. + + + [01 alias.lua] + + + [01 alias.lua] + + + [04 Scoring.lua] "Retrieve the amount of taps/holds/rolls involved." Used in some scoring formulas. + + + [03 UserPreferences2.lua] Themer-facing function for getting a user preference. + + + [03 UserPreferences2.lua] Themer-facing function for getting a user preference as a boolean. + + + [03 UserPreferences2.lua] Themer-facing function for getting a user preference as a color. + + + [03 UserPreferences2.lua] Themer-facing function for getting a user preference as a number. + + + [02 Colors.lua] Returns the color's alpha if it has any, otherwise returns 1. + + + [03 Gameplay.lua] Returns the value to start showing the combo at. + + + [03 Gameplay.lua] Returns true if you need to step on hold heads to activate them. + + + [03 Gameplay.lua] Returns 0 in pump mode, TimingWindowSecondsHold preference value in any other game mode. + + + Returns the current hour. + + + [02 Colors.lua] Converts a color from HSV values to something StepMania can understand. + hue is from 0-360, saturation and value are 0..1 + + + [02 Colors.lua] Converts a color from HSV values with alpha to something StepMania can understand. + hue is from 0-360, saturation, value, and alpha are 0..1 + + + [02 Colors.lua] "Converts a set of HSV values to a color." + + + [02 Colors.lua] "Takes in a normal color and returns the hex representation. (Adapted from code in LuaBit)" + + + [02 Colors.lua] Changes the hue of the input color. + + + [03 ThemePrefs.lua] Initializes various user preferences. + + + [01 base.lua] "Like ipairs(), but returns only values." + + + [02 Utilities.lua] Returns true if the coin mode is not set to CoinMode_Home. + + + Returns true if Event Mode is turned on. + + + [02 Utilities.lua] Returns true if Arcade and the coin mode is CoinMode_Free. + + + [03 Gameplay.lua] Returns true if the current game is sGame. + + + [02 Utilities.lua] Returns true if the coin mode is set to CoinMode_Home. + + + Returns true if connected to the Internet. + + + Returns true if connected to StepMania Online. + + + Returns true if Player pn is logged on to a SMOnline server. + + + [04 Scoring.lua] Returns true if W1 is allowed (and tns == 'TapNoteScore_W2') + + + [02 Branches.lua] Returns true if Routine mode is being played. + + + [04 WidescreenHelpers.lua] Returns true if the aspect ratio is 16:10 (1.6) or higher. + + + [01 base.lua] "Like ipairs(), but returns only values." + + + [02 Utilities.lua] Joins a table, splitting each item with delimiter, returning a string of the results. + + + [02 Colors.lua] + + + [02 Colors.lua] + + + Returns a number linearly interpolated between start and end by percent. + + + Same as lerp, but for colors. All channels will reach the end of the interpolation at the same time. + + + Returns an Actor definition for the actor at sPath. If sPath points to a Lua file, any additional arguments will be passed to that script. + + + [02 ActorDef.lua] Loads an actor template. This is the actual core of LoadActor. + + + [02 ActorDef.lua] Loads an actor with params. + + + [01 base.lua] "Override Lua's loadfile to use lua.ReadFile." + + + [02 ActorDef.lua] Load the fallback BGA for the element that is currently being loaded. + + + [02 ActorDef.lua] Loads a font. + + + [02 Sprite.lua] Returns a Sprite with the current song's background. + + + Returns the length of the multi-byte character string sString. + + + Returns the current Minute. + + + [03 Gameplay.lua] Returns the value to start showing the miss combo at. + + + Creates a module. See the Lua manual for more details. + + + Returns the current month of the year (0-11). + + + Returns Month m as a localized string. + + + Returns Month m as a string. + + + Similar to approach, but operates on tables of values instead of single values. This will modify the contents of currents in place, as well as returning currents.
+ currents, goals, and speeds must all be the same size and contain only numbers.
+ multiplier is optional. The speeds in the speeds table will be multiplied by multiplier. This makes it more convenient to use multiapproach in a per-frame update: pass in the frame delta and the speeds will be scaled to the time that passed.
+ Note: When you see the error "approach: speed 1 is negative." it means that a speed value passed was negative. The 1 tells you which entry in the table was invalid. +
+ + "Allows a program to traverse all fields of a table. Its first argument is a + table and its second argument is an index in this table. + next returns the next index of the table and its associated value." + See the Lua manual for more details. + + + Converts a string such as 'oni' or 'expert' or 'trick' to the appropriate difficulty. + + + [03 ThemePrefs.lua] Returns a Lua option row for ProTiming. + + + "Returns three values: the function, the table t, and nil, + so that the construction for k,v in pairs(t) do body end + will iterate over all key–value pairs of table t." + + + [02 Colors.lua] + + + [02 Colors.lua] + + + [02 Utilities.lua] Converts a PlayerNumber into a short string (e.g. "P1", "P2"). + + + [02 Actor.lua] Returns either p1val or p2val depending on pn. + + + Returns a formatted percent with the specified numerator and denominator. + + + [00 init.lua] + + + [03 ThemePrefs.lua] Prints a table's contents to the log. + + + Returns the product family. (e.g. "StepMania") + + + Returns the product ID. (e.g. "StepMania 5") + + + Returns the product version. + + + "Checks whether v1 is equal to v2, without invoking any metamethod." + + + "Gets the real value of t[index], without invoking any metamethod." + + + "Sets the real value of t[index] to value, without invoking any metamethod." + The modified t is then returned. + + + [02 ActorDef.lua] Used internally by LoadActor to resolve a path. If optional is true, then a nil path is returned instead of emitting an error if no file is found. + + + [04 FileUtils.lua] Reads the file at path and returns its contents. + + + [03 UserPreferences2.lua] (internal) Reads the specified user preference from its config file. + + + Recursively prints all the children of the actor frame to the log file. This can be useful for finding out what actors are on a screen or just seeing what the structure of the actor tree looks like.
+ indent is an optional argument that will be prepended to every line. +
+ + Recursively prints all values in the table to the log file in the form "(key_type) key: (value_type) value" so that you know the type of the key and the value. Useful if you're not sure exactly what is in a table passed as a parameter.
+ indent is an optional argument that will be prepended to every line. +
+ + Sends the current style to the server. + + + Loads the specified module. See the Lua manual for more information. + + + [02 Utilities.lua] Round a number. + + + [03 Gameplay.lua] Returns the routine noteskin for player . + + + [03 Gameplay.lua] Returns the routine noteskin for player 2. + + + [02 Colors.lua] Modifies the saturation of the specified color + + + Saves a screenshot. If pn is nil, saves to the machine's Screenshots dir, otherwise saves to the profile's Screenshots dir. Saves as jpg if compress is true, or png if compress is false. The screenshot is signed if sign is true. prefix and suffix are optional strings to add to the beginning and end of the filename.
+ Returns success and full path of the resulting screenshot. +
+ + Scales x, originally within low1 and high1, to fall between low2 and high2. + + + [03 Gameplay.lua] Returns the primary ScoreKeeper class to use. + + + [00 alias.lua, 02 Other.lua] alias for . + + + [00 alias.lua, 02 Other.lua] alias for . + + + Returns the current second. + + + Converts fSecs to Minutes:Seconds:Milliseconds format using two digits for each section. + + + Converts fSecs to Minutes:Seconds.Milliseconds format using two digits for each section except Minutes (uses 1). + + + Converts fSecs to Minutes:Seconds format. + + + Converts fSecs to Minutes:Seconds.Milliseconds format. + + + Converts fSecs to Minutes:Seconds.Milliseconds format using two digits for each section. + + + Converts fSecs to Minutes:Seconds.Milliseconds format using two digits for each section except Milliseconds (uses 3). + + + "If index is a number, returns all arguments after argument + number index. Otherwise, index must be the string + "#", and [it] returns the total number of extra arguments it received." + + + [02 Branches.lua] Determines the correct music/course selection screen to use and returns it. + + + [03 Gameplay.lua] (soon to be deprecated) Returns a list of codes to use on ScreenSelectProfile. + + + [02 Serialize.lua] Serialize the table t. + + + [03 EnvUtils2.lua] Sets the value of name to value in the Env table. + + + [03 UserPreferences2.lua] Themer-facing function for setting a user preference. + + + [03 Gameplay.lua] + + + [02 ActorDef.lua] Returns true if a decoration should be shown on the current screen or not. + + + [03 CustomSpeedMods.lua] Returns a Lua option row with the custom speed mods defined in SpeedMods.txt. + + + [02 Utilities.lua] Splits a string at every occurence of delimiter, returning a table of the results. + + + [02 Colors.lua] + + + [02 Colors.lua] + + + [02 ActorDef.lua] + + + [02 ActorDef.lua] + + + [02 ActorDef.lua] + + + [02 Utilities.lua] Returns a shuffled version of t. + + + [02 Utilities.lua] Returns a slice of the specified table of size num. + + + [02 Utilities.lua] Look up each value in a table, returning a table with the resulting strings. + + + [02 TextBanner.lua] This function defines how the TextBanner is laid out. + + + [02 Utilities.lua] Converts a string or number to a bool. + + + Tries to convert e to a number. Returns nil if + it can't convert the input to a number. (base is optional.) + + + Converts e to a string. + + + [02 Enum.lua] Returns a string representing an enum starting from '_'. For example, passing PlayerNumber_P1 to this function will return P1. + + + [00 init.lua] Alias for . + + + Returns the type of the object as a string. See the Lua manual for valid return values. + + + "Returns the elements from the given table. + This function is equivalent to return list[i], list[i+1], ···, list[j]" + (i and j are optional; "by default, i is 1 and j is the length of the list.") + + + 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. + + + Returns the current version's build date. + + + Returns the current version's build time. + + + [00 init.lua] Alias for . + + + [04 WidescreenHelpers.lua] Depending on the screen width, scales between ar43 (4:3; 640px) and ar169 (16:9; 854px). + + + [02 Utilities.lua] + + + [02 ActorDef.lua] Wraps the children in an ActorFrame. + + + [04 FileUtils.lua] Writes buf to the file at path. + + + [03 GamePreferences.lua] + + + [03 UserPreferences2.lua] (internal) Writes user preference prefName to its config file with value being tostring'd. + + + Returns the current year. + + + + [03 ThemePrefs.lua] Returns a Lua option row for toggling AutoSetStyle. + + + [03 ThemePrefs.lua] Returns a Lua option row for displaying the score on ScreenGameplay. + + + [03 ThemePrefs.lua] Returns a Lua option row for displaying the StepsDisplay on ScreenGameplay. + + + [03 ThemePrefs.lua] Returns a Lua option row for determining the fail length. + + + [03 ThemePrefs.lua] Returns a Lua option row for determining the receptor arrow position. + + + [03 ThemePrefs.lua] Returns a Lua option row determining how deep the player options menu should go. + +
+ + + + + + Returns the for the file at sPath. + + + Returns true if sClassName is a registered Class. + + + Loads all commands and sets X and Y for the specified Actor. + + + Used internally by LoadActor to resolve a path. If optional is true, then a nil path is returned instead of emitting an error if no file is found. + + + + + Updates ArrowEffects, which sets current values for Tornado, Invert, and Beat. + + + Returns the Y Offset of a note in column iCol at beat fNoteBeat for the provided PlayerState. Y Offset is affected by Speed mods and Accel mods, and impacts most other arrow effects. + + + Returns the Y position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState.
+ fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player] +
+ + Returns the Y offset of a note in column iCol with a Y position of fYPos for the provided PlayerState.
+ fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player] +
+ + Returns the X position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. + + + Returns the Z position of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. + + + Returns the X rotation of a note with a Y offset of fYOffset for the provided PlayerState. + + + Returns the Y rotation of a note with a Y offset of fYOffset for the provided PlayerState. + + + Returns the Z rotation of a note at beat fNoteBeat for the provided PlayerState.
+ bIsHoldHead is an optional argument which defaults to false. If true, this function will return 0 if the [ArrowEffects] metric DizzyHoldHeads is false. +
+ + Returns the Z rotation of the receptors for the provided PlayerState. + + + Returns the Alpha of a note in column iCol with a Y offset of fYOffset for the provided PlayerState.
+ fPercentFadeToFail is optional and defaults to -1.
+ fYReverseOffsetPixels is the separation between targets with and without reverse. This argument is optional and will pull defaults from the metrics for [Player]
+ fDrawDistanceBeforeTargetsPixels is optional and will pull defaults from the [Player] metric DrawDistanceBeforeTargetsPixels
+ fFadeInPercentOfDrawFar is optional and will pull defaults from the [NoteField] metric FadeBeforeTargetsPercent
+
+ + Returns the Glow of a note in column iCol with a Y offset of fYOffset for the provided PlayerState. The arguments are the same as for GetAlpha. + + + Returns the brightness of a note at beat fNoteBeat for the provided PlayerState. + + + Returns true if any arrow effects for the provided PlayerState require the z buffer. + + + Returns the zoom of a note for the provided PlayerState. + + + Returns the FrameWidthScale of a hold part with a Y offset of fYOffset for the provided PlayerState.
fOverlappedTime is optional and will default to 0. +
+
+ + + Enumerated types are lookup tables associating a string to each numerical + value for each Enum. For example, + [1] would be the + string 'PlayerNumber_P1'.
+ The functions defined in the Enum namespace are valid member + functions of every Enum where the first argument is + omitted and the name of the Enum is used in place + of Enum. Instead of + Enum.GetName( + ) or + Enum.Reverse( + ), one can use + :GetName() or + :Reverse(), respectively. +
+ + Both x and y need to be elements of the enumerated + type e. Returns a value less than/greater than/equal to + 0 corresponding to the numerical value of x being + less than/greater than/equal to the numerical value of y as + determined by + Enum.Reverse( e ). + + + Returns the type of e. For example, + Enum.GetName( ) + will return the string 'PlayerNumber'. + + + Returns a reverse lookup table for the enumerated type e. For + example:
local r = + Enum.Reverse( );
+ local n = r['PlayerNumber_P2'];

+ The value of n in this case would be 1 corresponding + to the 0-based indexing using in C++ and not 2 as might be + expected for the 1-based indexing used in Lua. +
+
+ + + Returns true if the type of v is sType. + + + Flushes log files to disk. + + + + Tries to read the file at sPath. If successful, it returns the file's contents. + If unsuccessful, it returns two values: nil and "error". + + + Reports the error through the error reporting system. error_type is the type used for the dialog that is presented, a dialog will not appear for a type the user has chosen to ignore.
+ error is optional an defaults to "Script error occurred.". error_type is optional and defaults to "LUA_ERROR". +
+ + Calls func(...) with two LuaThreadVariables set, and returns the return values of func(). + + + Writes sString to log.txt. Aliased by + . + + + Writes sString to info.txt and log.txt as + a warning. Aliased by . + +
+ + + Returns a random number. Without arguments, the number is in the range 0..1. With a single argument (n), the number is in the range of 1..n. With two arguments (lower, upper), the number is in the range of l..u. + + + Sets the seed of the random number generator to seed. + + + + + Creates a RageFile handle with which one can use the commands in . + + + + + Gets the credits message for Player pn. + + + + + Returns a table with the playable Steps for the present Song based on the present Game. + + + Returns true if the song's steps (st) are playable. + + + Returns true if the song's StepsType (st) are playable. + + + + + Returns the number of songs in a Trail. + + + Returns the Trail's total length in seconds. + + +
+ + + + + + This adds a wrapper state around the Actor, which is like wrapping the Actor in an ActorFrame, except that you can use it on any actor, and add or remove wrapper states in response to things that happen while the screen is being used. (wrapping an Actor in an ActorFrame normally requires setting it up before the screen starts)
+ The ActorFrame that is returned is the wrapper state, for convenience.
+ An Actor can have any number of wrapper states. Use GetWrapperState to access wrapper states for the actor. +
+ + Returns the number of wrapper states the actor has. + + + Returns the wrapper state at index i. Think of wrapper states with a higher index as being "further out". Actor is inside Wrapper 1, Wrapper 1 is inside Wrapper 2, Wrapper 2 is inside Wrapper 3, and so on. + + + Removes the wrapper state at index i. + + + Returns the Actor's parent, or nil if it doesn't have one. + + + Returns the Actor's fake parent, or nil if it doesn't have one. + + + Sets the Actor's fake parent to p, or clears it if p is nil. + + + Returns the Actor's visibility. + + + Returns the Actor's x position. + + + Returns the Actor's y position. + + + Returns the Actor's z position. + + + Returns what the Actor's x position will be when it reaches its destination tween state. + + + Returns what the Actor's y position will be when it reaches its destination tween state. + + + Returns what the Actor's z position will be when it reaches its destination tween state. + + + Returns the Actor's zoom. + + + Returns the Actor's X zoom. + + + Returns the Actor's Y zoom. + + + Returns the Actor's Z zoom. + + + Sets Texture Filtering for an Actor to b. + + + Plays the commands that follow at an accelerated rate (fRate * fRate), where fRate is in seconds. + + + Adds a command to the Actor. + + + Adds rot to the Actor's current x rotation. + + + Adds rot to the Actor's current y rotation. + + + Adds rot to the Actor's current z rotation. + + + Adds xPos to the Actor's current x position. + + + Adds yPos to the Actor's current y position. + + + Adds zPos to the Actor's current z position. + + + [02 Actor.lua] Sets the alignment of an Actor, where h and v are in the range 0..1. + + + Sets whether or not the Actor should animate. + + + Sets the Actor's aux value. (This can be a solution for coupling data with an Actor.) + + + If true, cull the Actor's back faces. See also: . + + + Sets the Actor's base alpha to fAlpha, where fAlpha is in the range 0..1. + + + Sets the Actor's base X rotation to rot. + + + Sets the Actor's base Y rotation to rot. + + + Sets the Actor's base Z rotation to rot. + + + Sets the Actor's base zoom to zoom. + + + Sets the Actor's base X zoom to zoom. + + + Sets the Actor's base Y zoom to zoom. + + + Sets the Actor's base Z zoom to zoom. + + + Sets the Actor to use the specified blend mode. + + + Makes the Actor bob up and down. Can use to define different bobbing behavior. + + + Makes the Actor bounce, similar to bob but with one point acting as the ground. Can use to define different bouncing behavior (with effectmagnitude values relating to x, y, and z movement). + + + [02 Actor.lua] + + + [02 Actor.lua] + + + [02 Actor.lua] Centers an Actor on the screen. (equivalent to x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y) + + + [02 Actor.lua] Centers an Actor on the X axis. (equivalent to x,SCREEN_CENTER_X) + + + [02 Actor.lua] Centers an Actor on the y axis. (equivalent to y,SCREEN_CENTER_Y) + + + Determines if the z-buffer should be cleared or not. + + + [02 Actor.lua] Combines multiple interpolators for complex tweens. tweens + can either be a string like "linear,0.25,accelerate,0.75" or + a table with tween information { {Type="linear", Percent=0.25, Bezier=nil}, {Type="accelerate", Percent=0.75, Bezier=nil} } + + + Crops percent of the Actor from the bottom, where percent is in the range 0..1. + + + Crops percent of the Actor from the left, where percent is in the range 0..1. + + + Crops percent of the Actor from the right, where percent is in the range 0..1. + + + Crops percent of the Actor from the top, where percent is in the range 0..1. + + + Sets the Actor's cull mode to mode. + + + Plays the commands that follow at an decelerated rate (1 - (1-fRate) * (1-fRate)), where fRate is in seconds. + + + Set the Actor's diffuse color to c. + + + Sets the Actor's alpha level to fAlpha, where fAlpha is in the range 0..1. + + + Makes the Actor switch between two colors immediately. See Themerdocs/effect_colors.txt for an example. + + + Sets the Actor's bottom edge color to c. + + + Set the Actor's diffuse color to c, ignoring any alpha value in c. + + + Sets the Actor's left edge color to c. + + + Sets the Actor's lower left corner color to c. + + + Sets the Actor's lower right corner color to c. + + + Makes the Actor switch between two colors, jumping back to the first after reaching the second. See Themerdocs/effect_colors.txt for an example. + + + Sets the Actor's right edge color to c. + + + Makes the Actor shift between two colors smoothly. See Themerdocs/effect_colors.txt for an example. + + + Sets the Actor's top edge color to c. + + + Sets the Actor's upper left corner color to c. + + + Sets the Actor's upper right corner color to c. + + + Tells the Actor to draw itself. + + + Sets the Actor's draworder to iOrder, where larger values display first. + + + [02 Actor.lua] (Added in sm-ssc) + + + [02 Actor.lua] + + + Set the Actor's effect clock to s. + + + Sets the first effect color to c. + + + Sets the second effect color to c. + + + Set the Actor's effect magnitude in each direction to the given values. + + + Set the Actor's effect offset to fTime. The offset is added to the time into the effect before calculating percent_through_effect. + + + Set the Actor's effect period to fTime. + + + Set the Actor's effect timing.
+ hold_at_zero is before hold_at_full in the argument list for compatibility. A future version will probably swap them because it makes more sense to have hold_at_full come before hold_at_zero.
+ All effect timings must be greater than or equal to zero, at least one of them must be greater than zero.
+ The effect timing controls how long it takes an effect to cycle and how long it spends in each phase.
+ Depending on the effect clock, the actor's time into effect is updated every frame. That time is then translated into a percent_through_effect using the parameters to this function.
+
+ ramp_to_half is the amount of time for percent_through_effect to reach 0.5.
+ hold_at_half is the amount of time percent_through_effect will stay at 0.5.
+ ramp_to_full is the amount of time percent_through_effect will take to go from 0.5 to 1.0.
+ hold_at_full is the amount of time percent_through_effect will stay at 1.0.
+ After reaching the end of hold_at_full, percent_through_effect stays at 0 until hold_at_zero is over.
+
+ The different effects use percent_through_effect in different ways. Some use it to calculate percent_between_colors with this sine wave: sin((percent_through_effect + 0.25f) * 2 * PI ) / 2 + 0.5f
+ Some effects check the internal bool blink_on. blink_on is true if percent_through_effect is greater than 0.5 and false if percent_through_effect is less than or equal to 0.5.
+ Check the effect functions for individual explanations: diffuseblink, diffuseshift, glowblink, glowshift, glowramp, rainbow, wag, bounce, bob, pulse, spin, vibrate. +
+ + Set the hold_at_full part of the effect timing while leaving the others unchanged. + + + Fades percent of the Actor from the bottom where percent is in the range 0..1. + + + Fades percent of the Actor from the left where percent is in the range 0..1. + + + Fades percent of the Actor from the right where percent is in the range 0..1. + + + Fades percent of the Actor from the top where percent is in the range 0..1. + + + Finishes up an Actor's tween immediately. + + + [02 Actor.lua] Stretches an Actor to fill the entire screen. + + + Returns the Actor's aux value. + + + Returns the Actor's base X zoom value. + + + Returns the Actor's base Y zoom value. + + + Returns the Actor's base Z zoom value. + + + Returns true if the Actor has a command named sCmdName. + + + Returns the Actor's current diffuse color. + + + Returns the Actor's current diffusealpha. + + + Returns the Actor's current effect delta. + + + Returns the Actor's current effect magnitude as three floats (not one; I hate Lua.xsd). + + + Returns the Actor's current glow color. + + + Returns the Actor's horizontal alignment as a number in the range 0..1. + + + Returns the Actor's name. + + + Returns the number of states the Actor has. + + + Returns the Actor's current height. + + + + Returns the Actor's current X rotation. + + + Returns the Actor's current Y rotation. + + + Returns the Actor's current Z rotation. + + + Returns the number of seconds into the currently running effect (e.g. diffuseshift, bob). + + + Returns how much time is remaining for the current tween. + + + Returns the Actor's vertical alignment as a number in the range 0..1. + + + Returns the Actor's current width. + + + Returns the zoomed height of an Actor. + + + Returns the zoomed width of an Actor. + + + Returns true if this actor is currently set to use the effect delta for tweening. + + + Sets the Actor's glow color. + + + Makes the Actor glow between two colors immediately. See Themerdocs/effect_colors.txt for an example. + + + Makes the Actor glow between two colors smoothly, jumping back to the first at the end. See Themerdocs/effect_colors.txt for an example. + + + Makes the Actor glow between two colors smoothly. See Themerdocs/effect_colors.txt for an example. + + + Set the fractional horizontal alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is left aligned while an alignment of 1 is right aligned. See for the common case. + + + Sets the heading of this Actor to fHeading. + + + Hides the Actor for the specified amount of time. + + + [Deprecated] Compatibility alias for the hidden command, which was removed in sm-ssc. Use instead. + + + [02 Actor.lua] "Hide if b is true, but don't unhide if b is false." + + + Set the horizontal alignment of the Actor according to align. See for fractional alignment. + + + Hurries up an Actor's tweening by factor. + + + Plays the commands that follow at a normal rate, where fRate is in seconds. + + + [02 Lyrics.lua] Plays the lyric command for the specified side ("Back" or "Front"). + + + Sets the Actor's name to sName. + + + Stops the Actor's movement. (Usually used for Sprites or Models.) + + + Sets the pitch of this Actor to fPitch. + + + Starts the Actor's movement. (Usually used for Sprites or Models.) + + + Plays a command named sCommandName. params is passed to the command as an argument if it is a table. + + + [02 Actor.lua] Sets the visibility of the Actor based on p being a human player. + + + Makes the Actor grow and shrink. Can use to define different pulsing behavior. + + + Queues a command named sCommandName to be played. + + + Basically creates a command named !sMessageName (Note the ! at the beginning. The source code says this: "Hack: use "!" as a marker to broadcast a command, instead of playing a command, so we don't have to add yet another element to every tween state for this rarely-used command.") + + + Makes the Actor change colors continually using colors of the rainbow. Each channel follows a cosine wave, red starts at 0, green starts at 2pi/3, and blue starts at 4pi/3. + + + Sets the roll of this Actor to fRoll. + + + Set the Actor's rotation on the X axis to fAlign. + + + Set the Actor's rotation on the Y axis to fAlign. + + + Set the Actor's rotation on the Z axis to fAlign. + + + + [02 Actor.lua] An alternative version of . + + + [02 Actor.lua] + + + Scales the Actor to cover a rectangle defined by the four float arguments. + + + Scales the Actor to fit inside a rectangle defined by the four float arguments. + + + Sets the height of the Actor. + + + Sets the size of the Actor. + + + [01 alias.lua] Alias for setsize. + + + Sets a multi-framed Actor's state to iNewState. + + + Sets the width of the Actor. + + + Use this to make the actor use the effect clock to tween instead of using the global frame delta. + + + Sets the shadow's color to c. + + + Sets the Actor's shadow length to fLength. + + + Sets the Actor's horizontal shadow length to fLength. + + + Sets the Actor's vertical shadow length to fLength. + + + Skews the Actor on the x axis by fAmount. + + + Skews the Actor on the y axis by fAmount. + + + Waits fSeconds before executing the next command. + + + [02 Actor.lua] + + + Tells the Actor to spin. Can use to define different spinning behavior. + + + + Stops any effect the Actor has. + + + Stops any tweening. + + + Stretches the Actor to a rectangle of a specific size. + + + Translates the texture of the actor by x and y. + + + Determines if the Actor should use texture wrapping or not. + + + Uses type to determine the tween to use. The type must be one of the TweenType enum values. If the type is note TweenType_Bezier, the params table is ignored. If the type is TweenType_Bezier, then the params table must have 4 or 8 numbers. 4 numbers in the params creates a 1 dimensional bezier curve, 8 numbers creates a 2 dimensional bezier curve.
+ It's usually more convenient to use Actor:linear, Actor:accelerate, and so on, rather than using Actor:tween directly. +
+ + Set the fractional vertical alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is top aligned while an alignment of 1 is bottom aligned. See for the common case. + + + Set the vertical alignment of the Actor according to align. See for fractional alignment. + + + Makes the Actor vibrate violently. Can use to define different vibration behavior. + + + Sets an Actor's visibility to b. + + + Makes the Actor wag. Use to define different wag behavior. + + + Set the x position of the Actor to xPos. + + + Set the y position of the Actor to yPos. + + + Set the z position of the Actor to zPos. + + + Sets the z bias to fBias. + + + Enables/disables z-buffer depending on bUse. + + + Zooms the Actor to zoom scale. + + + Zooms the Actor on both the X and Y axis using zoomX and zoomY. + + + Zooms the Actor to zoom height. See also: . + + + Zooms the Actor to zoom width. See also: . + + + Zooms the Actor to zoom scale on the X axis. + + + Zooms the Actor to zoom scale on the Y axis. + + + Zooms the Actor to zoom scale on the Z axis. + + + Sets the z testing mode to write on pass if true, turns it off if false + + + Sets the z testing mode to testMode. + + + Sets z writing to true or false based on bWrite. + + + + [02 Actor.lua] Plays the commands that follow using a bezier curve to determine the rate. The curve must have 4 or 8 elements. This is a convenience wrapper around calling Actor:tween with TweenType_Bezier. + + + [02 Actor.lua] Stretches an Actor to cover the screen. (equivalent to stretchto,0,0,SCREEN_WIDTH,SCREEN_HEIGHT) + + + [02 Actor.lua] A customized version of pulse that is more appealing for on-beat effects. + + + [02 Actor.lua] Sets and Actor as a mask destination. + + + [02 Actor.lua] Sets an Actor as a mask source. (Also clears zbuffer; other mask sources need to not clear the zbuffer) + + + [02 Actor.lua] Make graphics their true size at any resolution. + + + [02 Actor.lua] Scale things back up after they have already been scaled down. + + + [02 Actor.lua] A customized version of pulse that is more appealing for on-beat effects. + + + Sets the x and y location of the Actor in one command. + +
+ + + Adds a child to the ActorFrame from the specified path. + + + Sets the field of view for the ActorFrame. + + + Returns the child with a name of sName.
+ If there are multiple children with that name, returns an array of those children.
+ The table also acts as a pass through layer, function calls pass through to the last child of that name. +
+ + Returns a table of all the children in the ActorFrame.
+ The table is indexed by the names of the children.
+ If there are multiple children with the same name, the entry for that name is an array of those children.
+ The table also acts as a pass through layer, function calls pass through to the last child of that name. +
+ + Gets the ActorFrame's Draw function. + + + Returns the number of children in the ActorFrame. + + + Gets the update function's rate. + + + Plays the sCommandName command on the ActorFrame's children. + + + Plays the sCommandName command on the ActorFrame's leaves. + + + Sets if the Actorframe should propagate commands to its children. + + + [02 Actor.lua] Propagates a command to the ActorFrame's children. + + + Removes all the children from the ActorFrame. + + + Removes the specified child from the ActorFrame. + + + Runs the commands in cmds on the ActorFrame's children. + + + Runs the commands in cmds on the ActorFrame's leaves. + + + Sets the ActorFrame's ambient light color to c. + + + Sets the ActorFrame's diffuse light color to c. + + + Sets if the ActorFrame should draw by Z position. + + + Sets the ActorFrame's Draw function to the specified Lua function. + + + Sets the field of view for the ActorFrame. + + + Currently unimplemented since it does not handle errors correctly. Arguments must be passed in as a table. + + + Sets the ActorFrame's specular light color to c. + + + Sets the ActorFrame's update function to the specified Lua function. + + + Sets the update function's rate to fRate. + + + Tells the ActorFrame to sort by draw order. + + + Sets the vanishing point for the ActorFrame. + +
+ + + Creates the ActorFrameTexture. + + + Enables/disables the Alpha Buffer. + + + Enables/disables the Depth Buffer. + + + Enables/disables + + + Enables/disables the Preserve Texture option. + + + Returns the texture. + + + Sets the Texture's name to sName. + + + + + Adds a texture to the ActorMultiTexture. Returns the number of texture units. + + + Clears all the textures from the ActorMultiTexture. + + + Sets the EffectMode on the ActorMultiTexture. + + + Sets the size of the ActorMultiTexture from the specified texture. + + + Sets the coordinates of the ActorMultiTexture. + + + Sets a TextureMode on the specified index. + + + + + The list of quad states is used to determine which animation state is used for each quad. The offset is added to the AMV's current state, and the resulting state is used. + + + Adds an animation state to the ActorMultiVertex. The state_data table must be like this:
+ {{left, top, right, bottom}, delay}
+ left, top, right, and bottom are pixel coordinates, starting at 0. If delay is 0 or negative, the state will last forever. +
+ + Forces the AMV to update the texture coordinates on all its quads, even if the current state has not changed. + + + Returns whether the AMV uses the animation state. + + + Sets whether the AMV uses the animation state.
+ This works best when using DrawMode_Quads.
+ AMV's can have animated textures like sprites. Each state tells the AMV what part of the texture to use, and how long the state lasts.
+ Use AddState to add a state onto the end, or SetStateProperties to set all the states at once, or SetState to set a single state.
+ Each quad has its own offset that is added to the current state. Use AddQuadState to add to the list of quad states, or SetQuadState to set an existing quad state. +
+ + Returns the number of states the AMV has. + + + Returns the number of quad states in the destination tween state for the AMV. + + + Returns the id of the current state. + + + Gets whether the AMV should call the decode function for its texture during updates. + + + Sets whether the AMV should call the decode function for its texture during updates. + + + Sets the current state. + + + Returns the offset of the requested quad state. + + + Sets the offset of the requested quad state. + + + Returns a table containing the data for the requested state. + + + Sets the requested state to the data in state_data. Similar to AddState, but SetStateData only works on states that have already been added. + + + Each element of the table must be a state_data table, and is used to construct one state. The table as a whole is the entire list of all states for the AMV. + + + Removes the requested state from the state list. + + + Removes the requested quad state from the quad state list. + + + Sets the delay for every state to delay. + + + Sets how far into its animation the AMV is. + + + Sets vertex number index with the properties provided. The tables of properties are each optional and can be provided in any order. + + + Sets multiple vertices at once. The elements of vertices should themselves be tables, of the form provided to SetVertex. If vertices is the first argument it will start from vertex 1. If an integer is provided before vertices it will start from that vertex. It will add vertices as necessary. + Example: self:SetVertices( { { { x1, y1, z1 } , { r1,g1,b1,a1 } , { tcx1,tcy1 } }; { { x2, y2, z2 } , { r2,g2,b2,a2 } , { tcx2,tcy2 } } } ) + + + Sets all the drawn verts of the ActorMultiVertex by evaluating the splines.
+ ("all the drawn verts" means all the verts between FirstToDraw and NumToDraw, the verts that are set to draw in the current tween state.)
+ The parts of the ActorMultiVertex are evenly spaced along the spline in terms of t value.
+ The exact behavior depends on the draw mode.
+ DrawMode_Quads uses all 4 splines, one for each corner.
+ DrawMode_QuadStrip and DrawMode_Strip use 2 splines, one for each edge of the strip.
+ DrawMode_Fan uses one spline, for the edge verts of the fan. The first vert is not touched because it is the center.
+ DrawMode_Triangles uses 3 splines, one for each corner.
+ DrawMode_SymmetricQuadStrip uses 3 splines, one on each edge and one in the center.
+ DrawMode_LineStrip uses 1 spline.
+
+ + Returns the requested spline. Spline indices range from 1 to 4.
+ ActorMultiVertex splines are not inside the tween state, and will not change the verts until you call SetVertsFromSplines. +
+ + Sets the number of vertices. + + + Returns the number of vertices + + + Sets the draw state variables to the values in the table.
+ Mode must be a DrawMode.
+ First is the index of the first vertex to draw.
+ Num is the number of vertices to draw. -1 for Num means draw all verts after First.
+ Any value not in the table defaults to the already set value.
+ Examples:
+ -- Sets all three parts of the draw state.
+ self:SetDrawState{Mode="DrawMode_Quads", First= 1, Num= -1}
+ -- Set only the draw mode. First and Num remain unchanged from previous.
+ self:SetDrawState{Mode="DrawMode_Quads"}
+ -- Set the first and number to draw. Draw mode remains unchanged.
+ self:SetDrawState{First= 3, Num= 4}
+
+ + Get the DrawMode of the destination tween state. + + + Get the FirstToDraw of the destination tween state. + + + Get the NumToDraw of the destination tween state. + + + Get the DrawMode of the current tween state. + + + Get the FirstToDraw of the current tween state. + + + Get the NumToDraw of the current tween state. + + + Returns the ActorMultiVertex's texture. + + + Sets the EffectMode of the ActorMultiVertex. + + + Sets the TextureMode of the ActorMultiVertex. + + + Sets the width of the line for DrawMode_LineStrip. + + + Sets the texture to texture + + + Sets the texture at from the file path path. + +
+ + + Returns the target of the ActorProxy. + + + Sets the ActorProxy target to a. + + + + + Returns the scroller's current item. + + + Returns the item the scroller's going to. + + + Returns how long it will take for the scroller to completely scroll through all its items. + + + Returns the number of items in the ActorScroller. + + + Returns the number of seconds the scroller pauses between items. + + + Returns the number of seconds until the scroller reaches its destination. + + + Compatibility alias for . + + + Positions the scroller items. + + + Scrolls through all the items in the scroller. + + + Compatibility alias for . + + + Scrolls through all the items in the scroller with padding at the beginning and end. + + + Compatibility alias for . + + + Sets the item the scroller should scroll to next and makes it the current item. + + + Sets the item the scroller should scroll to next. + + + Sets if the scroller should catch up fast. + + + Compatibility alias for . + + + Specifies if the scroller should loop or not. + + + Sets the scroller's mask to a Quad that is fWidth by fHeight pixels. + + + Sets the scroller to draw fNumItems items. + + + Sets the number of subdivisions in the scroller. + + + Compatibility alias for . + + + Sets the scroller's pause countdown to fSecs. + + + Sets the scroller's pause between items to fSeconds. + + + Sets how many seconds the scroller should spend on each item.
+ A value of 0 means the scroller will not scroll. +
+ + Compatibility alias for . + + + Sets the scroller's transform function to the specified Lua function. + + + Sets the scroller's transform function from fItemHeight. + + + Sets the scroller's transform function from fItemWidth. + +
+ + + This Actor represents a playable sound. There are two attributes that can be set on load.
+ * SupportPan - Let the sound pan from side to side.
+ * SupportRateChanging - Let the sound change rate and pitch.
+ * IsAction - If true, the sound is an action sound, and will be muted if the MuteActions preference is turned on. +
+ + Returns the that can be played by this Actor. + + + Returns whether the sound is an action. + + + Loads the sound at sPath. + + + Pauses or unpauses the sound based on bPause. + + + Plays the sound. + + + [02 Sound.lua] Plays the sound on the given player's side. You must set SupportPan = true on load. + + + Sets whether the sound is an action. + + + Stops the sound. + +
+ + + Returns true if Announcer sAnnouncer exists. + + + Returns a table of installed announcers. + + + Returns the current announcer's name. + + + Sets the announcer to sNewAnnouncer. + + + + + Returns true if the application presently has focus. + + + Returns the name of the architecture in use. + + + + + Returns true if the Banner is currently scrolling. + + + + + + Loads the background from an UnlockEntry. + + + Loads the banner from an UnlockEntry. + + + Loads the card image from the specified Character. + + + Loads the banner from the cache based on sPath (typically or ). + + + Loads a Banner from a specified Course. + + + Loads a Banner from a specified Song. + + + Loads a Banner from a specified Song Group. + + + Loads a Banner from a specified SortOrder. + + + Loads an icon from the specified Character. + + + See . + + + See . + + + + + + + + Add the attribute attr to the string at position + iPos.
+ The attribute is a table that must contain Length + which specifies how many (multi-byte) characters the attribute + is to apply. If Length=-1, then the attribute applies + until another attribute overrides it.
+ If the table contains Diffuse, then the color value + is applied to the range of text.
+ If the table contains Diffuses, then it should be + an array of 4 colors which specify the diffuse color for the + top left, top right, bottom left, and bottom right.
+ If the table contains Glow, then the color value + is applied as a glow to the range of text.
+ Example:
+ attr = { Length = 10; Diffuse = color("#AABBCC"); } +
+ + Clear all attributes associated with the BitmapText. + + + [02 Actor.lua] Sets the diffuse and stroke color of text in one command. + + + Returns the text that is currently set. + + + Causes each character of text to be randomly distorted by + distortion_percentage of its size when the text is set. The distortion + only changes when the text changes. + + + Turns off distortion. + + + Returns whether the diffuse colors in the attributes are multiplied by the general diffuse colors of the BitmapText. + + + If mult_attrs_with_diffuse is set to true, then the diffuse colors in the attributes are multiplied by the general diffuse colors of the BitmapText. + + + If bJitter is true, move each character of the string around by a small random amount. + + + If use_zoom is true, this BitmapText will use the zoom that has been applied to it when calculating to change its base zoom from maxheight or maxwidth. + + + Set the maximum height of the unzoomed text to fHeight. If fHeight is 0, then there is no maximum height. + + + Set the maximum width of the unzoomed text to fWidth. If fWidth is 0, then there is no maximum width. + + + [02 Actor.lua] Remove any stroke color. + + + [02 Actor.lua] Alias for setting to false. + + + If true, set each character of the text in turn to the rainbow colors in the metrics BitmapText::RainbowColor#. + + + Set the text to sText. This clears all attributes. + + + [02 Actor.lua] Sets text using string.format(sFormat, ...). + + + [02 Actor.lua] Alias for . + + + Sets the stroke color to c. + + + If the text is glowing, specify if just the stroke layer, just the inner layer, or both are affected by the glow. + + + If true, make all text uppercase. + + + Add iSpacing pixels of padding between lines of text. + + + Wrap the unzoomed text at iWidth pixels. If you or by x and you want the text wrapped at width, then you should use wrapwidthpixels(width/x). + +
+ + + Returns the text that is currently set at the exact moment you call it. This is likely only going to be useful in an Update command. + + + Sets the BPMDisplay from the specified Course. + + + Sets the BPMDisplay from the GameState. + + + Sets the BPMDisplay from the specified Song. + + + Sets the BPMDisplay from the specified Steps. + + + + + Returns the path to the character's card graphic. + + + Returns this character's directory. + + + Returns this character's ID. + + + Returns the path of the dancing animation of this character. + + + Returns the character's display name. + + + Returns the path to the character's icon. + + + Returns the path of the model of this character. + + + Returns the path of the rest animation of this character. + + + Returns the path to the character's ScreenSelectMode icon. + + + Returns the path to the character's ScreenStage icon. + + + Returns the path of the warm-up animation of this character. + + + + + Returns a table of all characters installed. + + + Return the corresponding to sID. + + + Returns a random character. + + + Returns the number of characters available. + + + + + Loads the ComboGraph commands from the Metrics in group sMetricsGroup. + + + Sets the values of the ComboGraph using the specified StageStats and PlayerStageStats. + + + + + Loads the ControllerStateDisplay from the specified GameController. + + + Loads the ControllerStateDisplay from the specified MultiPlayer. + + + + + Returns true if all of the songs in the course have been defined (as opposed to random songs). + + + Returns a table of all the Trails in the Course. + + + Returns the path to the Course's background. + + + Returns the path to the Course's banner. + + + Returns the Course's directory. + + + Returns a table of CourseEntry items. + + + Gets the CourseEntry at iIndex from the Course. + + + Returns the Course's . (Returns CourseType in SM5; integer in SM4) + + + Returns the description for this Course. + + + Returns the full display title of the Course. + + + Returns the estimated number of stages for the Course. + + + Returns the goal seconds for the Course. + + + Returns the Course's group name. + + + Returns the Course's . (Returns PlayMode in SM5; integer in SM4) + + + Returns the name of the person who scripted the Course. + + + Returns the total length of the Course in seconds. + + + Returns the full transliterated title of the Course. + + + Returns true if the Course has a background. + + + Returns true if the Course has a banner. + + + Returns true if the Course has modifiers. + + + Returns true if the Course has timed modifiers. + + + Returns true if the Course is an edit. + + + Returns true if the Course was automatically generated. + + + Returns true if the Course is Endless. + + + Returns true if the Course is Nonstop. + + + Returns true if the Course is Oni. + + + Returns true if the Course is playable in StepsType st. + + + Returns true if the Course is a ranking course. + + + + + Sets the CourseContentsList from the GameState. + + + + + Returns the Song that this CourseEntry corresponds to. + + + + Returns the number of lives gained after completing the song. + + + Returns the number of seconds gained after completing the song. + + + Returns any stage (non-timed) modifiers. + + + Returns the number of modifier changes in this CourseEntry. + + + Returns a comma-delimited string representing various facts about the CourseEntry. + + + Returns true if this CourseEntry is a fixed song. + + + Returns true if this CourseEntry is secret. + + + + + Generates a random UUID (version 4). + + + Returns the MD5 hash for the file at sPath. + + + Returns the MD5 hash for s. + + + Returns the SHA-1 hash for the file at sPath. + + + Returns the SHA-1 hash for s. + + + + + All functions in this class have camel case equivalents, use whichever naming style you prefer.
+ This spline implementation is a cubic spline.
+ A spline is a line calculated from a small set of points with mathematical smooting applied.
+ Splines can have any number of dimensions, but splines owned by actors (the ones inside NCSplineHandler and ActorMultiVertex) always have 3 dimensions.
+
+ + Solves the spline, setting the coefficients. + + + Evaluates the spline at the given t value, returning a table of the results for each dimension of the spline.
+ t can range from 0 to the value returned by get_max_t().
+ A normal spline will return its starting point for any t value less than 0 and its end point for any t value greater than the max.
+ A looped spline adjust the t value to be within the its range by adding or subtracting the max t as needed. (so if the max t is 4 and you evaluate at 5, it will return the same as if you evaluated at 1.) +
+ + Evaluates the derivative at t. + + + Evaluates the second derivative at t. + + + Evaluates the third derivative at t.
+ Second and third derivative functions exist because they're possible, not because they're expected to be useful. The fourth derivative would be 0 because the equation for evaluating the spline is "a + (b*t) + (c*t^2) + (d*t^3)". +
+ + Sets point i of the spline to the position specified by the table p. + + + Sets the coefficients of the spline at point i.
+ Each table must contain a value for each dimension of the spline.
+ Solving the spline normally should cover all normal usage, this is for people that want a spline with an abnormal behavior, so if you set the coefficients directly, expect to end up with an unsmooth shape. +
+ + Returns a table containing the tables of coefficients for the point i. + + + Sets the spatial extent of dimension d of the spline to e.
+ The spatial extent exists to handle numbers that exist in a finite looped space, instead of the flat infinite space.
+ To put it more concretely, spatial extent exists to allow a spline to control rotation with wrapping behavior at 0.0 and 2pi, instead of suddenly jerking from 2pi to 0.0. +
+ + Returns the spatial extent of dimension d of the spline. + + + Returns the max t value the spline extends to. For a normal spline, this will be size()-1. For a looped spline, this will be size(). + + + Sets the number of points in the spline. You must set the number of points before trying to set the position of any point. + + + Returns the number of points in the spline. + + + Sets the number of dimensions the spline has.
+ Splines that are owned by actors (the ones inside ActorMultiVertex and NCSplineHandler) cannot have their number of dimensions changed because the actors require them to have 3 dimensions. +
+ + Returns the number of dimensions the spline has. + + + Returns true of the spline has zero points, or false if it has more than zero points. + + + Sets whether the spline is looped. A looped spline is one where the end point is connected to the start point. + + + Returns whether the spline is looped. + + + Sets whether the spline is polygonal. If the spline is polygonal, then it will have straight lines between the points instead of curves. + + + Returns whether the spline is polygonal. + + + Sets whether the spline is dirty. A dirty spline is one that has been changed in some way that affects its shape. When solve() is called, the spline will only be solved if it is dirty. The dirty flag is automatically set by everything, so you should never have to call this function. + + + Returns whether the spline is currently dirty. + + + Destroys the spline, freeing the memory allocated for it. This can only be called on splines created with create_spline(). + +
+ + + Sets the DifficultyIcon's state from the difficulty passed in. + + + Sets the DifficultyIcon's Player to pn, + then sets the DifficultyIcon's state from the difficulty of Steps pSteps + + + Sets the DifficultyIcon's Player to pn, + then sets the DifficultyIcon's state from the difficulty of Trail pTrail + + + Sets the DifficultyIcon's Player to pn. + + + Blanks the DifficultyIcon. + + + + + Returns the index of the last banner loaded. + + + Loads the fallback course banner. + + + Loads the fallback banner. + + + Loads the card image from the specified Character. + + + Loads a Banner from a specified Course. + + + Loads a Banner from a specified Song. + + + Loads a Banner from a specified Song Group. + + + Loads a Banner from a specified SortOrder. + + + Loads an icon from the specified Character. + + + Loads the Random banner. + + + Loads the Roulette banner. + + + See . + + + See . + + + + + Sets the StepsDisplayList from the GameState. + + + + + Returns true if notes are counted separately in this game. + + + Returns the mapped judgment for tns. + + + Returns the name of the game such as "dance" or "pump". + + + Returns whether this game allows the players to have separate styles. + + + + + Returns any announcer that may have been set. + + + Returns any Character associated with this item (or nil if there isn't one). + + + Returns any Course that may have been set. + + + Returns a course difficulty, if one is set in the GameCommand. + + + Returns a difficulty, if one is set in the GameCommand. + + + Returns the index of this item. + + + Returns any MultiPlayer that may have been set. + + + Returns the choice name. + + + Returns the PlayMode associated with this GameCommand. + + + Returns any preferred modifiers that may have been set. + + + Returns any Profile ID that may have been set. + + + Returns any screen that may have been set as a string. + + + Returns any Song that may have been set. + + + Returns the name of any song group that may have been set. + + + Returns the sort order, if the GameCommand has set one. + + + Returns any stage modifiers that may have been set. + + + Returns any Steps that may have been set. + + + Returns any Style that may have been set. + + + Returns the display text. + + + Returns any Trail that may have been set. + + + Returns any Url that may have been set. + + + + + Return the first for the specified game. + + + Returns true if any noteskins exist for the specified Game s. + + + Return the localized string representation of st. + + + Returns a table of all selectable games. + + + Returns a table of all the styles for the that exist for game. + + + Sets the current game to Game. The second argument is optional, and if provided will determine which theme is loaded when the game changes. If the second argument is not provided, the default theme from the preferences for the new game type will be loaded.
+ If only the game changes, the screen specified by the Common::AfterGameChangeScreen metric will be loaded.
+ If the game and the theme both change, the screen specified by the Common::AfterGameAndThemeChangeScreen metric will be loaded.
+ The Common::InitialScreen metric will be used if the appropriate metric for the change is blank or invalid. +
+
+ + + Set the music volume to fVolume for fDuration seconds. + + + + Return the sound balance for pn. + + + Plays a sound from the current announcer. + + + Play the sound at musicPath starting from musicStart for + musicLength seconds one time. Both fadeIn and + fadeOut can be customized as required. loop + tells the sound manager to loop the music part. applyRate + tells the sound manager to apply the current music rate. If alignBeat + is true or nil, the length is automatically adjusted to cover an integer number of beats. + + + Play the sound at sPath one time. is_action is optional, if it is true, the sound is an action sound, and will be muted if the MuteActions preference is turned on. + + + Stops the music. + + + When music is requested to change, the new music does not start immediately due to latency and buffering. This will return true if the newest music has not yet actually begun. + + + + + Adds another stage to the specifed player. + + + Applies the specified modifiers for the specified player's preferred modifier set. + + + Applies the song options of ModsLevel_Preferred to the other ModsLevels. + + + Applies the specified modifiers for the specified player for the current stage. + + + Returns true if any player has performed a feat worthy of ranking. + + + The second argument is optional. Apply the GameCommand represented by sCommand + for pn, if given. See . + + + Checks various things to determine whether the game will crash when gameplay starts. Returns false and a string if gameplay cannot be entered safely.
+ Might not work in all cases, but will catch things like a player not having + steps set or no current song or style. Mainly exists for people with a custom ScreenSelectMusic replacement.
+ Example:
+ local can, reason= GAMESTATE:CanSafelyEnterGameplay()
+ if not can then
+ lua.ReportScriptError("Cannot safely enter gameplay: " .. tostring(reason))
+ end
+
+ + Removes any stage modifiers that are illegal for course play. + + + Returns true if pn's options will disqualify them for ranking. + + + Returns true if enough credits have been inserted to join. + + + fishpolk.mid; See also: Rise of the Triad + + + Returns the environment table. See . + + + Returns the current for the specified . + + + Returns the current . + + + Return the number of inserted but unused coins. This number is + decremented when players join. + + + Return the number of coins needed to join based on the current coin and premium modes + as well as the number of people joined, if that matters for the premium mode. See + and . + + + The s in a are numbered sequentially + starting from 0. Return the number of the current . + + + Return the current number of seconds that have passed in the current song. This value can be negative. + + + Return the current . + + + Return the current . + + + Return the current . + + + Return the current . + + + Returns the current stage index (starts at 0). + + + Return the current for the specified Player. + + + Return a variable number of arguments based on the being + played by all players. For each distinct being played by + the players, in increasing order, + the difficulty and description of the is returned as strings. +
For example,
+ local credits = {GAMESTATE:GetCurrentStepsCredits()};
+ will make a table of the difficulties and descriptions. +
+ + Return the current . + + + Return the current for the specified player. + + + Return a string representation of the default song options. + + + Returns the value. + + + Return the easiest of the + currently selected steps by all players. For example, if player 1 has + selected Hard steps and player 2 has selected Medium steps, Medium will + be returned. + + + + + + Return the Edit Local (during Profile editing) + or nil if it does not exist. + + + Returns the ID of the Edit Local (during Profile editing). + + + Return the source for the editor or nil + if it does not exist. + + + Returns a table of enabled players. + + + Returns the name of the currently expanded section. + + + Return the random seed for the game. + + + Return true if the gameplay lead in is enabled. If + false, gameplay begins immediately. + + + Return the hardest of the + currently selected steps by all players. For example, if player 1 has + selected Hard steps and player 2 has selected Medium steps, Hard will + be returned. + + + Returns an array of s corresponding to Human players. + + + Returns the index of the next song in the course. + + + Returns the master player number. + + + Returns true if the game is Multiplayer. + + + Returns the PlayerState for the specified MultiPlayer. + + + Returns the number of active multiplayer NoteFields. + + + Returns the number of players enabled. + + + Returns the number of sides joined. + + + Returns the number of stages for the current Song and its Steps or the current Course. + + + Returns the number of stages left for player pn. + + + Returns the display name for player pn. + + + Returns the PlayerState for player pn. + + + Returns the current PlayMode. + + + Returns the preferred difficulty. + + + Returns the preferred song. + + + Returns the preferred song group. + + + Returns the current Premium. + + + + Returns the smallest number of stages left for any human player. + + + [01 alias.lua] Returns the current beat of the song. + + + [01 alias.lua] Returns the current beat of the song without an offset. + + + Returns the current visible beat of the song. + + + [01 alias.lua] Returns the song's current beats per second. + + + [01 alias.lua] Returns true if a delay is active in the song. + + + [01 alias.lua] Returns true if the song is currently in a freeze. + + + Returns the song options for the specified ModsLevel as a string. + + + Returns the song options as a string. + + + Returns the song options for the specified ModsLevel as an object. + + + Returns how much of the song is through at beat fBeat. + + + Returns the current SongPosition. + + + Returns the current SortOrder. + + + Returns the StageResult for player pn. + + + Returns the current stage index. + + + Returns the current StepsSeconds, which is the time value used to set the samples in a player's life record. + + + Return the random seed for the current stage. + + + Returns true if the workout goal is complete. + + + Returns true if an extra stage was earned. + + + Returns true if either player does not have a profile loaded, and there is a loadable profile. + + + Returns true if either player has a profile loaded. + + + Returns true if we are specifically in the Step Editor's + editing portion. If in recording or playing mode, this will return + false. + + + Inserts iCoins number of coins. iCoins can be negative or positive. + + + Inserts one credit. To deduct a credit, pass a negative integer representing the number + of coins per credit to InsertCoin. + + + Returns true if this is an extra stage. + + + Returns true if any human player is using a memory card. + + + Returns true if playing in Battle mode. + + + Returns true if playing in a Course mode. + + + Returns true if in Demonstration mode. + + + Returns true if the match was a draw. + + + Returns true if Event Mode is on, temporary or otherwise. + + + Returns true if this is the first extra stage. + + + Returns true if this is the second extra stage. + + + Returns true if player pn has completed the current Goal. + + + Returns true if player pn is human. + + + Returns true if player pn is enabled. + + + Returns true if player pn has joined the game. + + + Returns true if player pn is the winner. + + + Joins player pn. Does not deduct coins. + + + Similar to JoinPlayer, but checks whether the player is allowed to join and returns false if the player is not allowed to join. Also deducts coins for joining. A player can't join if PlayersCanJoin() returns false, or that side is already joined (is true for both sides when in a style that is OnePlayerTwoSides), or there are not enough coins. + + + If profiles are not loaded, this will load the profiles for each player. It will load from memory cards if they are present, and local profiles otherwise. It will load edits if LoadEdits is true, or by default if the argument is omitted. + + + Returns true if player pn is using modifier sModifier. + + + Returns true if players can join the game. + + + Refreshes the NoteSkin data for the current game. + + + Resets the GameState. + + + Resets the specific Player's mods to the default settings. + + + Saves the bookkeeping and machine profile data. + + + Save profiles. + + + Sets the current for the specified . + + + Sets the current Course to course. + + + Sets the current PlayMode to pm. + + + Sets the current Song to song. + + + Sets Player pn's current Steps to steps. + + + Sets current Style to the provided style. Either a style object or a style string can be provided. If current steps for either player are not valid in the new style, they will be cleared. + + + Sets the current Trail to trail. + + + Tells the engine that the theme explicitly set the fail type for the players so that it won't override it with the easier settings for beginner or easy. + + + Sets if the Jukebox should use modifiers. + + + + + + Sets the number of multiplayer notefields to iFields + + + Sets the preferred difficulty of Player pn to Difficulty dc. + + + Sets the preferred Song to song. + + + Sets the preferred song group to sGroup. + + + Sets the Song Options from so using ModsLevel m. + + + Turns temporary Event Mode on or off, depending on bOn. + + + Stores the ranking name for the player. Use this at the end of a round, on a name entry screen or similar, to set the name for the high scores the player has earned. + + + Determines if Judgment W1 should be shown based on bOn. + + + Unjoins player pn. + +
+ + + Loads the GradeDisplay commands from the Metrics in group sMetricsGroup. + + + Sets the GradeDisplay to show Grade g. + + + + + Loads the GraphDisplay commands from the Metrics in group sMetricsGroup. + + + Sets the values of the GraphDisplay using the specified StageStats and PlayerStageStats. + + + + + Sets the GrooveRadar values for Player pn to empty. + + + Sets the GrooveRadar values for Player pn from RadarValues rv + + + Sets the GrooveRadar values for Player pn to the specified (floating point) values in the table. + + + + + Returns two tables representing the tips and alternate tips in the HelpDisplay. + + + [02 HelpDisplay.lua] Sets the tips from a Song or Course. + + + Sets the seconds between switches of tips to fSeconds. + + + Sets the HelpDisplay's tips using tips (and optionally altTips). + + + Sets the HelpDisplay's text from sTips using colons to separate new sections. + + + + + Returns the date and time the high score was achieved. + + + Returns the Grade of this high score. + + + Returns the HighScore for this PlayerStageStats. + + + Return the number of HoldNoteScores that match hns. + + + Returns the Max Combo of this high score. + + + Returns the modifiers used for this HighScore. + + + Returns the name associated with the high score. + + + Returns the Peak Combo Award for this high score. + + + Returns the percentage of dance points associated with the high score. + + + Returns the RadarValues for this HighScore. + + + Returns the score associated with the high score. + + + Retrns the Stage Award for this high score. + + + Returns the number of seconds survived associated with the high score. + + + Return the number of TapNoteScores that match tns. + + + Returns true if this high score's name uses a fill-in marker. + + + + + You can get a HighScoreList using . + + + Returns a table of the high scores. + + + Returns the highest score for name in the list. Returns nil if there is no score for name in the list. + + + Returns the rank of the highest score for name in the list. Returns 0 if there is no score for name in the list. (returns 1 if name has the top score, 2 if name has the second place score, and so on) + + + + + Loads the HoldJudgment for the specified MultiPlayer. + + + + + Returns the mouse wheel value. + + + Returns the X position of the mouse. + + + Returns the Y position of the mouse. + + + + + Returns the amount of life left in the LifeMeter as a float in the range 0..1. + + + Returns true if failing. + + + Returns true if the LifeMeter is "hot". + + + Returns true if in danger. + + + + + Changes the player's life by iNumLives. (Negative values subtract lives.) + + + Returns the number of lives remaining. + + + Returns the number of total lives. + + + + + Returns true if player pn's card is locked. + + + Return the state for player pn. + + + Returns the name of the storage device. + + + Returns true if player pn's name is available. + + + + + Stops the MenuTimer by setting it to 99.99 and pausing. + + + Returns the current MenuTimer's value. + + + Pauses the MenuTimer, stopping it from counting down. + + + Compatibility alias for SetSeconds. + + + Sets the MenuTimer's value to fSeconds. + + + Sets the MenuTimer's silent setting to bSilent. + + + Starts up the timer. + + + Sets the MenuTimer's stealth setting to bStealth. If + true, the timer will be invisible and silent. + + + Stops the MenuTimer by setting it to 0 and pausing. + + + + + Broadcast the message to all listeners subscribed to sMessage. The + second argument is an optional table of parameters. It may be omitted or explicitly + set to nil. + + + Sets whether logging of messages is enabled. If log is true, all messages that pass through Broadcast (from the engine for from the theme or from anywhere else), will be logged with Trace. + + + + + Sets the width of the MeterDisplay to fWidth. + + + + + Returns the model's default animation. + + + Controls if the model should loop or not. + + + Plays animation sAniName at fPlayRate speed (default 1.0). + + + Sets how far into the animation the model is. + + + Sets the current animation's playback rate to fRate. + + + Sets the model's default animation to sAnimation at fPlayRate speed (default 1.0). + + + + Returns the number of states the Model has. + + + + + Loads the ModIconRow of Player pn from the Metrics in group sMetricsGroup. + + + + + Changes the sort order of the wheel. Returns true if the order was changed. + + + Returns the name of the currently selected section. + + + Returns true if the MusicWheel is currently handling Roulette selection. + + + Selects a song. Returns false on failure. + + + Selects a course. Returns false on failure. + + + + + Returns a string from the specified element and value. + + + Returns a string from the specified element and value using NoteSkin sNoteSkin. + + + Returns a command from the specified element and value. + + + Returns a command from the specified element and value using NoteSkin sNoteSkin. + + + Returns a bool from the specified element and value. + + + Returns a bool from the specified element and value using NoteSkin sNoteSkin. + + + Returns a float from the specified element and value. + + + Returns a float from the specified element and value using NoteSkin sNoteSkin. + + + Returns a integer from the specified element and value. + + + Returns a integer from the specified element and value using NoteSkin sNoteSkin. + + + Returns the path for the specified sButton sElement. + + + Returns the path for the specified sButton sElement using NoteSkin sNoteSkin. + + + Returns the actor for the specified sButton sElement. + + + Returns the actor for the specified sButton sElement using NoteSkin sNoteSkin. + + + + Returns true if the strName noteskin exists in the current gametype. + + + Returns a table of noteskin names for the current gametype. + + + + + All functions in this class have camel case equivalents, use whichever naming style you prefer.
+ The spline handler holds info on how the spline is used by the engine.
+ Each get/set pair of functions in this class is for a different aspect of the spline's behavior. +
+ + Returns the spline for this handler. + + + Returns the beats per t value of the spline. If the beats_per_t is 4, then a note must be on screen for 4 beats to traverse from one point on the spline to the next. + + + Sets the beats per t value for the spline. + + + Returns the t value that receptors are evaluated at. + + + the t value that receptors are evaluated at. + + + Returns the mode the spline is set to.
+ "NoteColumnSplineMode_Disabled" means the spline will not affect the notes or receptors at all.
+ "NoteColumnSplineMode_Offset" means the spline will added to the effects from the mods.
+ "NoteColumnSplineMode_Position" means only the spline affect the notes and mods will be ignored. (but only mods that affect the same aspect of the note as the spline will be disabled. So a rotation spline won't disable Mini or Tiny, but a zoom spline will, and a zoom spline won't disable Dizzy, Twirl, or Roll, but a rotation spline will.) +
+ + Sets the current spline mode for this handler. + + + Returns whether the current song beat is subtracted from a note's beat when calculating the t value to use on the spline. + + + Sets whether the current song beat is subtracted from a note's beat when calculating the t value to use on the spline. + +
+ + + All functions in this class have camel case equivalents, use whichever naming style you prefer.
+ Position, rotation, and zoom each have separate spline handlers to allow them to have separate independent behavior.
+ It is important to note that the spline handlers are inside the tween state, so whenever you start a new tween on the actor, you need to refetch the spline handlers.
+
+ + Returns the handler for the position spline. + + + Returns the handler for the rotation spline.
+ The rotation applied by the rotation spline is in radians.
+ For convenience, the spatial extent of the rotation spline defaults to 2pi. +
+ + Returns the handler for the zoom spline. + +
+ + + All functions in this class have camel case equivalents, use whichever naming style you prefer.
+
+ + Makes the NoteField act as if a hold note was hit in the column, with the given score and bright setting.
+ The callback for did_hold_note will not be called. +
+ + Makes the NoteField act as if a tap note was hit in the column, with the given score and bright setting.
+ The callback for did_tap_note will not be called. +
+ + Returns a table of the actors for the columns. This means that each column is an actor, so you can move it around or animate it like an actor. See the NoteColumnRenderer class for a list of special functions for the column's actor. + + + Same as SetDidTapNoteCallback, but for hold notes. Uses HoldNoteScore instead of TapNoteScore. + + + Sets the function that the NoteField will call whenever a tap note is hit.
+ The callback function is passed the column, the TapNoteScore, and whether the explosion will be bright.
+ The callback function can return changed values for the NoteField to use instead of the ones that were passed.
+ Pass nil instead of a function to clear the callback. +
+ + Makes the NoteField act as if a press occurred in the column.
+ The callback for set_pressed will not be called. +
+ + Sets the function that the NoteField will call whenever a press occurs.
+ The callback function is passed the column for the press.
+ The callback function can return changed values for the NoteField to use instead of the ones that were passed.
+ Pass nil instead of a function to clear the callback. +
+ + Sets the function that the NoteField will call whenever a step occurs.
+ The callback function is passed the column and the TapNoteScore for the step.
+ The callback function can return changed values for the NoteField to use instead of the ones that were passed.
+ Pass nil instead of a function to clear the callback. +
+ + Makes the NoteField act as if a step occurred in the column with the given score. + The callback for Step will not be called. + +
+ + + Returns true if the first item in the row goes down. + + + Returns an index of the choice in the row that player pn is on. + + + Returns the OptionRow's layout type. + + + Returns the name of the OptionRow. + + + Returns the number of choices in this OptionRow. + + + Returns the row title string. + + + Returns the OptionRow's select type. + + + Returns true if this row is focused by player pn. + + + Returns true if this row forces one choice on all players. + + + + + Sets the PaneDisplay from the GameState. + + + + + Sets the PercentageDisplay from the specified PlayerState and PlayerStageStats. + + + + + Changes the life value by delta. This will broadcast a LifeChangedMessageCommand, to allow custom life bars to update to the new value. Do not call ChangeLife from within LifeChangedMessageCommand. + + + Sets the life to value. This will broadcast a LifeChangedMessageCommand, to allow custom life bars to update to the new value. Do not call SetLife from within LifeChangedMessageCommand. + + + Returns the current TimingData for this player. + + + Sets Actor with Combo position. + + + Sets Actor with Judgment position. + + + + (PlayerInfo is a part of ScreenGameplay.) + + Returns the of player pn. + + + Returns the Steps located at index in the current steps queue. + + + + + All these functions have an optional last argument: If the last argument is the boolean value true, then instead of returning the previous settings as normal, they will instead return the PlayerOptions object.
+ This allows you to chain them like this:
+ player_options:Twirl(5, 1, true):Roll(5, true):Dizzy(true):Twirl()
+
+ Special note: Functions that take a bool as their arg must have true as the second arg to be used with chaining.
+ "player_options:Backwards(true, true):Beat(5)" will chain, "player_options:Backwards(true):Beat(5)" will not chain.
+
+ Most options fall into one of four types: float, int, bool, or enum.
+ Float type options have this interface:
+ Option(value, approach_speed)
+ If value is a float, sets the TimeSpacing modifier to value.
+ If approach_speed is a float, sets the speed of the transition to approach_speed. Returns the previous values of both.
+ approach_speed is in units of n per second. value will be approached at the rate of approach_speed per second.
+ Note that the value and the approach speed arguments are both independently optional.
+ Example:
+ a,b= options:Boost() -- Sets a to the current value and b to the current approach_speed.
+ a,b= options:Boost(5, .5) -- Stores the previous values in a and b, NOT to 5 and .5. Sets the value to 5 and the approach speed to .5.
+ a,b= options:Boost(5) -- Sets a and b to the previous values, NOT to 5 and .5. Sets the value to 5 and leaves the approach speed at whatever it was.
+
+ Setting the approach speed only matters when modifying the PlayerOptions from ModsLevel_Song.
+ Int type options are similar to float in that they return and take a number, but they do not have an approach speed.
+ Bool type options have an almost identical interface, the difference is that they can not have an approach speed.
+ Enum type options are almost identical to bool type. They take and return an enum value.
+ For brevity, the functions are only given a description if the option requires careful handling or does not follow the float or bool interfaces.
+
+ + + + + + + + + + + + + + + + If the player has a CMod set, returns the value of that CMod and its associated approach speed. Returns nil otherwise.
+ If the optional first argument is passed, sets the CMod to the value and disables any XMod or MMod that is set.
+ If the optional second argument is passed, sets the speed at which the transition occurs. +
+ + + + + + + If the player is using Distant (zero skew and positive tilt), returns the value of tilt and its approach_speed.
+ Returns nil otherwise.
+ If the optional first argument is passed, sets tilt to value and skew to zero.
+ If the optional second argument is passed, sets the approach_speed for skew and tilt to it. +
+ + + + + + Sets the for the player, if the optional argument is provided. Returns the that was previously set. + + + + + Returns true if step attacks or random attacks are enabled. + + + Returns true if the current PlayerOptions makes the current Course/Trail easier. + + + Returns true if the current PlayerOptions makes the current Song/Steps easier. + + + If the player is using Hallway (zero skew and negative tilt), returns the value of tilt and its approach_speed.
+ Returns nil otherwise.
+ If the optional first argument is passed, sets tilt to negative value and skew to zero.
+ Pass in a positive value for the familiar meaning of Hallway.
+ If the optional second argument is passed, sets the approach_speed for skew and tilt to it. +
+ + + + + If the player is using Incoming ((positive skew and negative tilt) or (negative skew and positive tilt)), returns the value of skew and its approach_speed.
+ Returns nil otherwise.
+ If the optional first argument is passed, sets tilt to negative value and skew to value.
+ Pass in a positive value for the familiar meaning of Incoming.
+ If the optional second argument is passed, sets the approach_speed for skew and tilt to it. +
+ + + + + + MaxScrollBPM is one of the variables for controlling the speed mod.
+ Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
+ It is the setting for the MMod.
+ MMods are not tweenable or settable on ScreenGameplay. Use XMods if you need such an effect. +
+ + + Sets the min TapNoteScore required for the notes to disappear after being hit. + + + If the player has a MMod set, returns the value of that MMod and its associated approach speed. Returns nil otherwise.
+ If the optional first argument is passed, sets the MMod to the value and disables any CMod or XMod that is set.
+ If the optional second argument is passed, sets the speed at which the transition occurs.
+ MMods are not tweenable or settable on ScreenGameplay. Use XMods if you need such an effect. +
+ + + + + + + + + + + + + Sets the NoteSkin to the named noteskin, unless name is nil or the noteskin does not exist. Returns the name of the previous noteskin and whether the set attempt succeeded.
+ Changing the noteskin during a song is not supported.
+ Example:
+ note_name= options:NoteSkin() -- Sets note_name to the player's current noteskin.
+ prev_note_name, succeeded= options:NoteSkin("cel") -- Sets prev_note_name to the noteskin the player had set, changes the current noteskin to "cel", sets succeeded to true if the "cel" noteskin exists.
+
+ + If the player is using Overhead (0 tilt, 0 skew), returns true.
+ If true is passed, sets the tilt and skew to 0. +
+ + + + + + + + + + + + ScrollBPM is one of the variables for controlling the speed mod.
+ Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
+ It is the setting for the CMod. +
+ + ScrollSpeed is one of the variables for controlling the speed mod.
+ Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
+ It is the setting for the XMod. +
+ + + Skew is one of the mods for controlling the perspective. Use Overhead, Distant, Incoming, Space, Distant, or Hallway for controlling the perspective in the old way.
+ Skew moves the vanishing point for the note field away from the center of the screen.
+ Skew has no effect in single mode if Center1Player is true.
+ Skew has no effect in double mode.
+
+ + + + If the player is using Space ((positive skew and positive tilt) or (negative skew and negative tilt)), returns the value of skew and its approach_speed.
+ Returns nil otherwise.
+ If the optional first argument is passed, sets tilt to value and skew to value.
+ If the optional second argument is passed, sets the approach_speed for skew and tilt to it. +
+ + + + + + + + TimeSpacing is one of the variables for controlling the speed mod.
+ Use CMod, XMod, or MMod to set the speed mod unless you have a good reason not to.
+ It controls whether the speed mod is in X mode or C mode. It should only be set to 0 or 1, and is only a float value to allow tweening between the two states. +
+ + Tilt is one of the mods for controlling the perspective. Use Overhead, Distant, Incoming, Space, Distant, or Hallway for controlling the perspective in the old way.
+ Tilt tilts the note field forward and back. +
+ + + + + + + + Returns true if the player is using reverse. (equivalent to GetReverse() == 1.0) + + + + + If the player has a XMod set, returns the value of that XMod and its associated approach speed. Returns nil otherwise.
+ If the optional first argument is passed, sets the XMod to the value and disables any CMod or MMod that is set.
+ If the optional second argument is passed, sets the speed at which the transition occurs. +
+ +
+ + + Fails the player. + + + Returns true if a full combo (TNS_W3 and up) was obtained. + + + Returns true if a full combo (tns and up) was obtained. + + + Returns the number of Dance Points obtained by the player. + + + Returns how long the player has been alive. + + + Returns the best tap note score for a full combo. + + + Returns the number of calories burned. + + + Returns a table of all the combos. Each entry in the table is a table containing the StartSecond, SizeSeconds, Count, Rollover, StageCount, and IsZero information for that combo. + + + Returns the current possible maximum score. + + + Returns the player's current combo. + + + Returns the player's current life from 0..1. + + + Returns the player's current miss combo. + + + Returns the number of Dance Points possible to be obtained by the player. + + + Returns the player's current score multiplier. + + + Returns true if the player failed. + + + Returns the player's grade. + + + Returns the player's HighScore. + + + Returns the number of judgments for a specified HoldNoteScore. + + + Returns the player's actual score on the lesson. + + + Returns the score needed to pass the lesson. + + + Returns table of samples of the life record from 0 to last_second. + 'samples' determines the size of the table. 'samples' defaults to 100 + if not specified. + + + Returns the player's life remaining seconds. + + + Returns the machine high score index for this performance. + + + Returns the number of controller steps. + + + Returns the peak combo award for this performance. + + + Returns the personal high score index for this performance. + + + Returns a table of played steps. + + + Gets the percentage of taps that were scored as tns. + + + Returns the player's Dance Point percentage. + + + Returns the number of possible Dance Points. + + + Returns a table of possible steps. + + + Returns a RadarValues object representing the player's actual performance. + + + Returns a RadarValues object representing the total values for the song. + + + Returns the score. + + + Returns the number of songs passed. + + + Returns the number of songs played. + + + Returns the stage award for this performance. + + + Returns how long the player survived in seconds. + + + Returns the number of judgments for a specified TapNoteScore. + + + Returns the max combo for this performance. + + + Returns true if the player was disqualified from ranking. + + + + + Applies the player options of ModsLevel_Preferred to the other ModsLevels. + + + Returns the current PlayerOptions for this PlayerState. + + + Returns the HealthState for this PlayerState. + + + Returns the multiplayer number for this PlayerState. + + + Returns the PlayerController for this PlayerState. + + + Returns the player number for this PlayerState. + + + Returns a PlayerOptions object for the specified ModsLevel. + + + Returns a string of player options for the specified ModsLevel. (was GetPlayerOptions before sm-ssc v1.2.3) + + + Returns a table of strings, containing the player options for the specified ModsLevel. + + + Returns the SongPosition for this PlayerState. + + + Returns the current Super Meter level for this PlayerState. + + + Sets the player options to sPlayerOptions for the specified ModsLevel. + + + + + Return the value of the preference sPreference. + + + Return true if preference sPreference exists. + + + Set the value of the preference sPreference to value. + + + Reset preference sPreference to the default value. + + + Saves preferences to disk. + + + + + Adds cals to the daily total. + + + Adds a screenshot entry to the profile. filename must be the full path of the screenshot, as returned by SaveScreenshot. + + + Calculates the number of calories burned based on the heart rate (in beats per minute), the duration (in seconds), and data in the profile. + + + Returns the age. + + + Returns a table of all high score names that have been used on this profile. + + + Returns the birth year. + + + Returns the number of calories burned during the current day. + + + Returns the profile's high scores for the specified ranking category. + + + Returns the Character being used by this profile. + + + Returns a composite of your high scores over courses with the specified StepsType and Difficulty. + + + Returns the percentage of courses that you've completed with the specified StepsType and Difficulty. + + + Returns the possible score of courses with the specified StepsType and Difficulty. + + + Returns the profile's display name. + + + Return the number of calories burned as a string. + + + Returns the number of calories needed to reach the goal. + + + Returns the number of seconds needed to reach the goal. + + + Returns the current goal type. + + + Returns the GUID of this Profile. + + + Returns whether this profile ignores the step count based calorie calculation. + + + Returns whether this profile uses the male formula when CalculateCaloriesFromHeartRate is used. + + + Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: Course c, Trail t) + + + Gets the profile's HighScoreList for a specified Song and Steps. (Alternate arguments for Courses: Course c, Trail t)
+ If the profile does not have a HighScoreList for the Song and Steps, returns nil. Use this to avoid increasing the memory footprint of the profile when checking the score lists for every song and steps. +
+ + Returns the last played Course for this profile. + + + Returns the last played Song for this profile. + + + Returns the last used high score name. + + + Returns the number of Toasties gotten using the specified profile. + + + Returns the profile's most popular course. + + + Returns the profile's most popular song. + + + Returns the total number of songs played with the profile. + + + Returns the position the profile should have in its category in the list. + + + Returns the number of times song s has been played with the profile. + + + Returns a composite of your high scores over songs with the specified StepsType and Difficulty. + + + Returns the percent complete for all songs and courses for the specified StepsType st. + + + Returns the percentage of songs that you've completed with the specified StepsType and Difficulty. + + + Returns the possible score of songs with the specified StepsType and Difficulty. + + + Return the total number of calories burned. + + + Returns the number of dance points earned. + + + Returns the number of Hands stepped on. + + + Returns the number of successful Holds. + + + Returns the number of Jumps stepped on. + + + Returns the number of successful Lifts. + + + Returns the number of Mines stepped on. + + + Returns the total number of songs played with the profile. + + + Returns the number of successful Rolls. + + + Returns the number of steps with the specified StepsType and Difficulty that you've scored a certain Grade g on. + + + Returns the number of Taps and successful Holds. + + + Returns the number of trails with the specified StepsType and Difficulty that you've scored a certain Grade g on. + + + Returns the type of the profile. The type of the profile is only used to determine where the profile shows up in the list of profiles, and that problem is already handled by ProfileManager, so if you're reading this, this function only exists so you can make your theme color this profile's list entry based on the type or something like that. + + + Returns the user table for this Profile. + + + Returns the VO2 max for this profile. + + + Returns how much the player weighs. + + + Returns true if the player has passed any steps in the specified Song s. + + + Returns true if the specified code sUnlockEntryID is unlocked. + + + Sets the birth year of the profile. + + + Sets the current for the Profile. + + + Sets the display name of the profile to name. + + + Sets the goal to iCals calories. + + + Sets the goal to iSecs seconds. + + + Sets the current goal type to gt. + + + Sets whether this profile ignores the step count based calorie counting. + + + Sets whether this profile uses the male formula when CalculateCaloriesFromHeartRate is used. + + + Sets last used high score name. + + + Sets the VO2 max for the profile. 0 is treated as unset. + + + Sets how much the player weighs (in pounds) to weightPounds. + + + + Returns the amount of time this profile has spent in gameplay (in seconds). + + + Returns the number of sessions this profile has had. + + + Returns the total session length (in seconds) of this profile. + +
+ + + Returns the Profile for the specified profile ID. + + + Returns a table of the local profile display names. + + + + + Returns a table of the local profile IDs. + + + + Retuns the machine profile. + + + Retuns the amount of local profiles. + + + Returns the player name for player pn. + + + Returns the profile for player pn. + + + Returns the profile directory of the specified ProfileSlot. + + + Returns the number of times Song s has been played with the specified ProfileSlot. + + + Returns the current stats prefix. + + + Returns true if player pn's profile is persistent. + + + Returns true if Song s has never been played before (according to the machine profile). + + + + + Returns true if the profile from the memory card is new. + + + Returns true if pn's Profile was loaded from a memory card. + + + + Returns true if the last load of player pn's profile was a LastGood copy of the profile. + + + Returns true if the last load of player pn's profile resulted in a tampered or corrupt profile. + + + Saves the local profile with the specified ID. + + + Saves the machine profile. + + + Saves the profile for player pn. + + + Sets the current stats prefix. The stats prefix is prepended to the Stats.xml file when loading or saving a profile. SetStatsPrefix will reload all profiles from the Stats.xml that has the given prefix. In general, score entries are the only thing not preserved when changing the stats prefix. Profile::HandleStatsPrefixChange in Profile.cpp lists the fields that are preserved. + + + + + Returns the value of rc from . + + + + + You must call create_bezier to create a RageBezier2D to use any of these functions. When you are done with the object, destroy it with its destroy function to avoid a memory leak.
+ A RageBezier2D is two RageQuadratics, one for the x coordinate and one for the y.
+ This class is provided as a tool for designers working with bezier tweens who need a tool that displays the tween curve visually.
+ If you use Actor:tween(time, "TweenType_Bezier", {xa, ya, xb, yb, xc, yc, xd, yd}) to tween an actor, the actor creates a RageBezier2D internally and calls evaluate_y_from_x each frame to set where it is in the tween. +
+ + Destroys the RageBezier2D. Do not attempt to use it after it has been destroyed. + + + Evaluates the bezier curve at the given t and returns the x and y values. This is equivalent to using get_x and get_y to fetch the quadratic parts and calling evaluate on them directly. + + + Takes the x given and converts it to a t value, then evaluates the y quadratic with the t value and returns the result. + + + Returns the RageQuadratic used for the x component. + + + Returns the RageQuadratic used for the y component. + + + Sets the values used by the two quadratics. This is equivalent to using get_x and get_y to get the quadratics and setting them directly. Note that the components for the x quadratic and the y quadratic are interleaved. + +
+ + + Return the height of the display. + + + Return the width of the display. + + + Return the number of frames per second. + + + Return the VPF. + + + Return the cumulative FPS. + + + + + These commands require a RageFile handle. You can create one using + . + + + Returns true if the current position within the file is the end. (EOF = End of File) + + + Clears the last error message. + + + Closes the file and releases it from memory. + + + Safely deletes the file handle. + + + Flushes the buffer for the file handle, writing any pending output to disk. + + + Gets the last error message and returns it. + + + Gets a line and returns it. + + + Opens a file at sPath (relative to the StepMania root directory).
+ iAccessType can be set to read (1), write (2), stream (4) or flush to disk on close (8).
+ These can also be combined with addition. For example, to set up read and write, set iAccessType to 3 (1+2). +
+ + Puts a new line in the file. + + + Returns a string containing the entire contents of the file. + + + Returns length bytes from the RageFile's current position. + + + Seeks to a position in the file and returns the new position. + + + Returns the current position in the file. + + + Writes a file with the contents of str. + +
+ + + Returns true if a file exists at sPath. + + + Returns a listing of files from sPath. The last two arguments are optional (and default to false). + + + Returns a file's size in bytes. + + + Returns the hash of the file at sPath. + + + + + Return an array of connected input device descriptions. + + + + + If you use Actor:tween(time, "TweenType_Bezier", {a, b, c, d}) to tween an actor, the actor creates a RageQuadratic internally and calls evaluate each frame to set where it is in the tween. + + + Evaluates the quadratic at the given t value and returns the result. + + + Returns the four values that form the quadratic equation. This function returns multiple values, so you must do something like this to get them:
+ a, b, c, d= quadratic:get_bezier() +
+ + Equivalent to evaluate(1), but faster. + + + Equivalent to evaluate(0), but faster. + + + Returns the slope of the curve at the given t value. + + + Sets the four values that form the quadratic equation. + + + Sets the four values that form the quadratic equation, treating the arguments as from a cubic equation instead of as from a bezier curve. + +
+ + + See for loading a sound. + + + Returns the length of the sound loaded into this RageSound. Returns -1 if no sound is loaded. + + + Actually sets the value of sProperty to fVal. The supported properties depend on how the associated was loaded. + + + Attempts (and typically fails) to set the value of sProperty to fVal. The supported properties depend on how the associated was loaded. + + + Sets the pitch to fPitch. The associated have SupportsRateChanging = true on load. + + + Sets the speed (that is, the rate at which the sound plays) to fSpeed. The associated must have SupportsRateChanging = true on load. + + + Sets the volume to fVolume, which is between 0..1. + + + + + Returns the source width. + + + Returns the source height. + + + Returns the texture width. + + + Returns the texture height. + + + Returns the image width. + + + Returns the image height. + + + Returns the number of frames in this texture. + + + Returns the path to the texture's file. + + + Return the texture coordinate rectangle as {left, top, right, bottom}. + + + Sets the animation or movie looping to bLoop. + + + Sets the animation or movie position to fPos. + + + Sets the animation or movie playback rate to fRate. + + + Reloads the texture. + + + + + Loads the metrics for this RollingNumbers from sGroupName. + + + Sets the target number to f. + + + + + This adds the lua function "callback" to the list of functions the screen will pass input to. Whenever an input event occurs, callback will be passed a table with the details of the event. callback must return a bool to indicate whether the event was handled. If callback returns true, the event will not be passed any further.
+ This should not be used to provide text input because that would not handle localization or different keyboard layouts.
+ The screen and the callbacks will both be passed input events, so be aware of what input the current screen responds to and consider the effects.
+ Details of the table containing the event data:
+ {
+ DeviceInput= { -- The raw details of the event.
+ device= string, -- The type of device. The first half of the string will be "Device_", the second half will be from InputDeviceNames in RageInputDevice.cpp.
+ button= string, -- The button that was pressed. the first half of the string will be "DeviceButton_", the second half will be from InitNames in RageInputDevice.cpp.
+ level= float, -- A floating point value for analog input.
+ z= float, -- Mousewheel input.
+ down= bool, -- Whether the button is down. This is level with a threshold and debouncing applied.
+ ago= float, -- How long ago this input occurred, in seconds.
+ is_joystick= bool, -- True if the device is a joystick.
+ is_mouse= bool -- True if the device is a mouse.
+ }, -- This ends the list of things inside the DeviceInput part of the table.
+ controller= string, -- The game controller this event was mapped to. "GameController_1" or "GameController_2", or nil if the event wasn't mapped to either controller.
+ button= string, -- The semi-raw button that was pressed. This is what the button was mapped to by the keymap settings, but without the conversions that occur when OnlyDedicatedMenuButtons is true. Will be empty if the button was not mapped.
+ type= string, -- The type of event. "InputEventType_FirstPress", "InputEventType_Repeat", or "InputEventType_Release".
+ GameButton= string, -- The cooked button that was pressed. This is button with mapping that occurs when OnlyDedicatedMenuButtons is true applied. This is nil for unmapped buttons.
+ PlayerNumber= PlayerNumber, -- The player that the controller is mapped to, or nil.
+ MultiPlayer= string, -- Unknown purpose.
+ } +
+ + Returns the name of the next Screen. + + + Returns the name of the previous Screen. + + + Returns the ScreenType for this Screen. + + + Locks input for f seconds. + + + [02 Other.lua] Gets a metric from the current Screen. + + + Posts a message with the text sScreenMsg to the Screen after fDelay seconds. + + + This removes the callback from the list. + + + Sets the NextScreen value to name. + + + Sets the PrevScreen value to name. + + + [02 Other.lua] Gets a string from the current Screen in the current language. + +
+ + + Returns the current . + + + + + Returns the current StageStats. + + + + + This should behave identically to the normal back button behavior. This function is for the pause menu to use when the player forfeits or restarts, so that a score isn't saved. + + + Returns true if a single has its NoteField centered. + + + Returns a dummy PlayerInfo for the specified index. + + + Returns the current haste rate. HasteRate * MusicRate is the current total rate the music is multiplied by. + + + Returns the for the specified pn. + + + Returns the next in the current . + + + Returns the PlayerInfo for player pn. + + + Returns the current true beats per second for the specified player.
+ This takes into account the current music rate and the current haste effect.
+ If you are displaying the BPM on ScreenGameplay, this is what you should use to have correct behavior when Haste and/or a music rate mod are in effect. +
+ + This is part of the system for controlling how haste behaves.
+ Read Docs/Themerdocs/haste.txt. +
+ + This is part of the system for controlling how haste behaves.
+ Read Docs/Themerdocs/haste.txt. +
+ + This is part of the system for controlling how haste behaves.
+ Read Docs/Themerdocs/haste.txt. +
+ + This is part of the system for controlling how haste behaves.
+ Read Docs/Themerdocs/haste.txt. +
+ + Sets the next Screen to be loaded. + + + Returns true if the game is paused. + + + Pauses or unpauses the game, depending on the value of bPause. + +
+ + + Returns the LifeMeter. + + + + + Adds a screen at the top of the screen stack. (sMessage is an optional ScreenMessage posted once the new screen is finished.) + + + Gets the screen at the top of the screen stack. + + + Returns whether the input for the player has been redirected away from the normal screen input function. Input that has been redirected is only sent to lua input callbacks. + + + Plays the invalid sound. + + + Plays the start sound. + + + Plays the coin sound. + + + Plays the cancel sound. + + + Plays the screenshot sound. + + + Reloads any loaded overlay screens. + + + Returns true if screen class s exists. + + + Returns true if screen s is prepared. + + + Sets the next screen to s. + + + Sets whether the input for the player has been redirected away from the normal screen input function. Input that has been redirected is only sent to lua input callbacks.
+ This can be useful when putting a custom menu on a screen, and you want to disable the built in actors while the menu is open. Then you handle input through an input callback until the player closes the menu. +
+ + Broadcasts a system message. + +
+ + + Returns true if Player pn backspaced successfully. + + + Returns true if Player pn was able to add sKey to their name. + + + Attempts to finish Player pn and returns true + if successful. + + + Returns true if anyone is entering their name. + + + Returns true if anyone is still entering their name.
+ (As opposed to those who are Finalized; see ) +
+ + Returns true if Player pn is entering their name. + + + Returns true if Player pn is finished entering their name. + + + Gets the currently selected letter of Player pn. + +
+ + + Returns the number of active players. + + + + + Returns true if all active players are on the last options row. + + + Returns true if the specified player is on an items that ends the screen. + + + Returns the current row that player pn is on. (Was previously GetCurrentRow.) + + + Returns the number of rows on the screen. + + + Returns the specified OptionRow. + + + + + Returns true if we are going to PlayerOptions. + + + + + Continues to the next screen. + + + Returns true if there is a profile that can be loaded. + + + + + Continues to the next screen. + + + Returns true if there is a profile that can be saved. + + + + + Returns player pn's current selected item as an integer. + + + + + Returns false if the options list is already open or the UseOptionsList metric is false. + + + Returns true if the player is going to the options screen. + + + Returns the MusicWheel used on this screen. + + + Opens the OptionsList for Player pn + + + [02 StageMods.lua] Sets up modifiers for course modes. + + + [02 StageMods.lua] Sets up modifiers for non-course modes. + + + + + Tells the screen to go to the previous screen. + + + Attempts to finish the screen and returns true + if successful. + + + Returns the profile index of the specified Player. + + + Sets the profile index of Player pn to iProfileIndex. + + + + + TextEntrySettings is implemented similar to the Attributes in BitmapText. Formatting issues prevent the sample from being properly shown here.
Please see docs/Themerdocs/ScreenTextEntry.txt for the TextEntrySettings format. +
+ + Sets up a ScreenTextEntry's values. + +
+ + + Tells the screen to go to the previous screen. + + + Returns true if the screen is currently transitioning. + + + Tells the screen to go to play its Out transition, and then posts the ScreenMessage sScreenMsg. To go to the next screen, use "SM_GoToNextScreen" as the argument. + + + Sets whether the screen allows late joining. This only works for screens that are just ScreenWithMenuElements, as most derived screens have their own hard coded function for whether late joining is allowed. + + + + + Returns an array of all the available objects for a . + + + Returns the path to the song's background image. + + + Returns the path to the song's banner. + + + Returns a table with all the data for the song's BGCHANGES line.
+ Each element of the table is one change like this:
+ {start_beat= 1.0, rate= 1.0, transition= "example", effect= "example", file1= "example", file2= "example", color1= "#FFFFFFFF", color2= "#FFFFFFFF"} +
+ + Returns the path to the song's CD image. + + + Gets the path to the CDTitle. + + + Returns the path to the song's disc image (different from CD, think Pump). + + + Returns the displayed artist of the song. + + + Returns a table of 2 floats containing the display BPMs. + + + Returns the displayed full title of the song, including subtitle. + + + Returns the displayed main title of the song. + + + Returns the displayed subtitle of the song. + + + Returns the first beat of the song. + + + Returns the first second of the song. + + + Returns the genre of the song. + + + Returns the group name that the song is in. + + + Returns the path to the song's jacket image. + + + Returns the last beat of the song. + + + Returns the last second of the song. + + + Gets the path to the lyrics. + + + GetDisplayMainTitle checks the ShowNativeLanguage pref and returns the transliterated title is that pref is false.
+ GetMainTitle (this function) does not check that pref. Instead, it directly returns the title, exactly as it is in the #TITLE field in the simfile. +
+ + Gets the path to the music file. + + + Returns a Step object if the StepType and Difficulty exist. + + + Gets the Song's origin. + + + Returns the path to the Song's preview music. This handles the #PREVIEW tag internally, so it works with songs that use it and songs that don't. + + + Returns the path to the Song's preview video, if it exists. (Returns nil otherwise.) + + + Gets the length of a song's sample time in seconds. + + + Gets the starting position of a song sample in seconds. + + + Returns the song's directory. + + + Returns the songfile path. + + + [02 Other.lua] Returns the number of stages this song costs. + + + Returns a table of Steps that have StepsType st. + + + Returns how long the longest stepchart is in seconds. + + + Returns the song's TimingData. + + + Returns the transliterated artist of the song. + + + Returns the transliterated full title of the song, including subtitle. + + + Returns the transliterated main title of the song. + + + Returns the transliterated subtitle of the song. + + + Returns true if the song has steps for the specified difficulty in st. + + + Returns true if the song has attacks. + + + Returns true if the song has a background. + + + Returns true if the song has a banner. + + + Returns true if the song has BGChanges. + + + Returns true if the song has a CD image. + + + Returns true if the song has a CDTitle. + + + Returns true if the song has a Disc graphic. + + + Returns true if the song has edits. + + + Returns true if the song has a jacket graphic. + + + Returns true if the song has lyrics. + + + Returns true if the song has music. + + + Returns true if the song has a preview video. + + + Returns true if the song has significant BPM changes or stops. + + + Returns true if the song has the specified StepsType. + + + Returns true if the song's DisplayBPM is constant. + + + Returns true if the song's DisplayBPM is random. + + + Returns true if the song's DisplayBPM is secret. + + + Returns true if the song is considered easy. + + + Returns true if the song is enabled. + + + Returns true if the song meets the criteria for a "Long Version". + + + Returns true if the song meets the criteria for "Marathon" length. + + + Returns true if the song and the specified steps have different timing. + + + Returns true if the song only has Beginner steps. + + + Returns the length of the song in seconds. + + + Returns true if the song is normally displayed. + + + Returns true if the song is shown in Demonstration and Ranking. + +
+ + + Returns true if the specified course group exists. + + + Returns true if the specified song group exists. + + + Returns a Course if one matching sCourse is found. + + + Returns a Song if one matching sSong is found. + + + Returns an array of all the installed courses. + + + Returns an array of all the installed songs. + + + Returns the course color of Course c. + + + Returns the path to the specified course group's banner. + + + Returns a table containing all of the course group names. + + + Returns a table with all of the courses in the specified group. + + + Returns the extra stage info (Song, Steps) for the specified Style s. (If bExtra2 is true, it will use the second Extra Stage data instead of the first. Again, Lua.xsd sucks) + + + Returns the number of courses loaded via Additional folders. + + + Returns the number of songs loaded via Additional folders. + + + Returns the number of course groups. + + + Returns the number of courses. + + + Returns the number of selectable and unlocked songs. + + + Returns the number of song groups. + + + Returns the number of songs. + + + Returns the number of locked songs, regardless of reason for locking. + + + Returns the number of unlocked songs. + + + Returns a table of popular courses for the specified CourseType. + + + Returns a table of popular songs. + + + Returns a table of courses as they'd appear in preferred sort. + + + Returns a table of songs as they'd appear in preferred sort. + + + Returns a random course. + + + Returns a random song. + + + Returns the song color of Song s. + + + Returns a Song given a set of Steps st. + + + Returns the path to the specified song group's banner. + + + Returns the song group color of sGroupName. + + + Returns a table containing all of the song group names. + + + Returns the rank (popularity) of Song s. + + + Returns a table containing all of the songs in group sGroupName. + + + Returns the shortened group name (based on entries in Translations.xml). + + + Loads preferred courses from {theme}/Other/SongManager sListName.txt. + + + Loads preferred songs from {theme}/Other/SongManager sListName.txt. + + + Returns the preferred sort section name for the specified Song. + + + Returns true if the specified course was loaded from AdditionalCourses. + + + Returns true if the specified song was loaded from AdditionalSongs. + + + + + See the description for PlayerOptions. The functions follow the same design. + + + + + + + + + + + + + + + + + Limited to the range 0 < rate <= 3 because speeds greater than 3 are likely to crash. + + + A multiplier for the haste system. Limited to the range -1 to 1. + + + + + Returns the current beats per second. + + + Returns true if a Delay is active. + + + Returns true if a Freeze is active. + + + + + + + + + + + + + + + + + + Returns the row where a warp appears. + + + Returns the warp destination length. + + + + + Returns the length of the animation in seconds. + + + Gets whether the Sprite should call the decode function for its texture during updates. + + + Return the number of states this Sprite has. + + + Returns the Sprite's current state (frame number in a multi-frame sprite). + + + Returns the Sprite's texture. + + + [02 Sprite.lua] Returns a Frames table consisting of iNumFrames frames lasting for a total of fSeconds seconds. This function is not a member function and should be used as Frames = Sprite.LinearFrames( 5, 2.6 ). + + + If sPath is nil, then unload the texture. Otherwise, load the texture at path sPath. + + + Load the song background texture at sPath. + + + Load the song banner texture at sPath. + + + [02 Sprite.lua] Loads the background from the current Song or the first Trail entry. + + + [02 Sprite.lua] Load the texture for song's background. + + + [02 Sprite.lua] Load the texture for song's banner. + + + Sets the custom image rectangle. (Works in image pixel space.) + + + Sets custom offsets for the corners of the Sprite. Coordinates are paired, + corner order is upper left, lower left, lower right, upper right. + + + Turns off the custom pos coords for the sprite. + + + Sets whether the Sprite should call the decode function for its texture during updates. + + + Set the to mode. + + + Sets the number of seconds into the animation to fSeconds. + + + Sets the properties of the states of the sprite. The properties table is identical to the "Frames" table that can be put in the sprite when calling Def.Sprite.
+ Example:
+ {{Frame= 0, Delay= .016, {0, 0}, {.25, .25}},
+ {Frame= 1, Delay= .016, {0, 0}, {.25, .25}},
+ {Frame= 2, Delay= .016, {0, 0}, {.25, .25}},
+ {Frame= 3, Delay= .016, {0, 0}, {.25, .25}},
+ }
+ Frame is optional, defaulting to 0.
+ Delay is optional, defaulting to 0.
+ The two tables are optional upper left and lower right corners of the fraction of the frame to use. The example makes the sprite only use the upper left corner of each frame.
+ Simpler example:
+ {{Frame= 0, Delay= .016}, {Frame= 1, Delay= .016}, {Frame= 2, Delay= .016}, {Frame= 3, Delay= .016}}
+ This example makes the sprite use the whole of each frame. +
+ + Set the texture to texture. + + + + + + Allows the themer to set a custom texture rectangle that effects the way the texture is drawn. + + + Returns true if the sprite is using the effect clock for texcoordvelocity. + + + [02 Sprite.lua] Call RageTexture:loop( bLoop ) on the texture. + + + [02 Sprite.lua] Call RageTexture:position( fPos ) on the texture. + + + [02 Sprite.lua] Call RageTexture:rate( fRate ) on the texture. + + + Scale the Sprite to width fWidth and height fHeight clipping if the dimensions do not match. + + + Set the Sprite's state to iNewState. + + + If use is true, then the sprite will use the effect clock for texcoordvelocity. + + + + + + Set the texture coordinate velocity which controls how the Sprite changes as it animates. A velocity of 1 makes the texture scroll all the way once per second. + + + + Crops the Sprite to fWidthxfHeight. + + + [01 alias.lua] Alias for CropTo. + + + Sets all the state delays to fRate. Useful for Sprites that need to change by BPM (e.g. Tran from DDR 5th Mix, the cube from DS EuroMix 2). + +
+ + + Returns true if everyone failed. + + + Returns the EarnedExtraStage value. + + + Returns the number of seconds played. + + + Returns the PlayerStageStats of multiplayer mp. + + + + Returns the PlayerStageStats of player pn. + + + + Returns the Stage value. + + + Returns the stage index. + + + Returns true if at least one person passed. + + + Returns true if player pn has a high score. + + + + + Returns the accumulated played StageStats. + + + Returns the best final grade. + + + Returns the best grade. + + + Returns the current StageStats. + + + Returns player pn's final grade. + + + Get the StageStats from iAgo rounds ago. + + + Returns the number of stages played. + + + Returns the worst grade. + + + Resets the stats. + + + + + Returns the author that made that particular Steps pattern. + + + Returns the Steps chart name. + + + Returns the Chart Style for this Steps. + + + Returns the Steps description. + + + Returns the Steps difficulty. + + + Returns a table with the minimum and maximum values from the DisplayBPM. + + + Returns the DisplayBPM type. + + + Returns the Steps filename from the Cache. + + + Returns a hash of the Steps. + + + Returns the numerical difficulty of the Steps. + + + Returns true if the Steps has any attacks. + + + Returns true if the Steps pattern has significant timing changes. + + + Returns the complete list of RadarValues for player pn. Use to grab a specific value. + + + Returns the Steps type. + + + Returns the TimingData for the Steps. + + + Returns true if the Steps are an edit. + + + Returns true if the Steps are a player edit (loaded from a profile). + + + Returns true if the steps were automatically generated. + + + Returns true if the DisplayBPM is constant. + + + Returns true if the DisplayBPM is random. + + + Returns true if the DisplayBPM is secret. + + + Returns the predicted meter for this Step. + + + Returns true if the Steps use different TimingData from the Song. + + + + + Loads the StepsDisplay commands from the Metrics in group sMetricsGroup. + + + Sets the StepsDisplay from the GameState using Player pn. + + + Sets the StepsDisplay based on Steps pSteps. + + + Sets the StepsDisplay based on the passed in StepsType, iMeter, and Difficulty. + + + Sets the StepsDisplay based on Trail pTrail. + + + + + Returns the number of total tracks per player this Style contains (e.g. 4 for dance-versus, but 8 for dance-double). + + + Returns the name of the Style. + + + Returns the StepsType for this Style. + + + Returns the StyleType for this Style. + + + Returns a table containing the Track, XOffset, and Name of the column. + + + Returns the draw order of the column. + + + Returns the width of the notefield for the given player with this style. + + + Returns true if this style locks the difficulty for both players. + + + Deprecated. Always returns false. + + + + + Returns the of the Tap Note. + + + Returns the of the Tap Note. + + + Returns the of the Tap Note. + + + Returns the of the Tap Note. + + + Returns the of the Tap Note. Relevant for routine steps. + + + Returns the Attack Modifiers of the Tap Note. + + + Returns the Attack Duration of the Tap Note in seconds. + + + Returns the Keysound Index of the Tap Note. + + + Returns the Hold Duration of the Tap Note in beats. + + + Returns the of the Tap Note. + + + + + Returns the of the Tap Note. + + + Returns the TapNotOffset of the Tap Note. + + + Returns true if the Tap Note was judged with a result that would stop it from drawing. + + + + + Returns the of the Hold Note. + + + Returns the life of the Hold Note. + + + Returns the amount of time the hold has overlapped the target. + + + Returns the last beat the Hold Note was held. + + + Returns the number of checkpoints hit. + + + Returns the number of checkpoints missed. + + + Returns true if the note was initiated and is being held. + + + Returns true if the note was initiated. + + + + + Loads the TextBanner from the specified metrics group. + + + Loads the TextBanner's child elements from a . + + + Loads the TextBanner's child elements from strings. + + + + + Returns true if the specified language exists in the current theme. + + + Returns true if the specified theme exists. + + + [02 Utilities.lua] Returns the absolute path of a file in the theme. + + + Returns the current language. + + + Returns the theme's current directory. + + + Returns the name of the current theme. + + + Returns the value of Element in Class from metrics.ini. + + + Returns the names of all elements in Class from metrics.ini. + + + Returns the number of selectable themes. + + + Returns the path of ClassName Element in the BGAnimations folder. + + + Returns the path of an element in the Fonts folder. + + + Returns the path of an element in the Graphics folder. + + + returns three strings: BGAnimation ResolvedPath, MatchingMetricsGroup, MatchingElement. Used in LoadFallbackB in themes/_fallback/02 Other.lua. (Lua.xsd sucks) + + + Returns the path of an element in the Other folder. + + + Returns the path of an element in the Sounds folder. + + + Returns a table of selectable theme directories. + + + Returns the value of Element in Class for the currently loaded language. + + + Returns the names of all elements in Class for the currently loaded language. + + + Returns the author of the current theme or "[unknown author]". + + + Returns the display name of the current theme. + + + Returns true if the theme has the specified metric. + + + Returns true if the theme has the specified string. + + + Returns true if the specified theme is selectable. + + + Reloads the current theme's metrics. + + + + + + Changes the current theme.
+ After the theme changes, the screen specified by the Common::AfterThemeChangeScreen metric will be loaded.
+ The Common::InitialScreen metric will be used if Common::AfterThemeChangeScreen is blank or invalid. +
+
+ + + GetBPMsAndTimes, GetStops, GetDelays, GetLabels, GetWarps, GetCombos, GetTimeSignatures, GetTickcounts, GetFakes, GetScrolls, and GetSpeeds all have two different modes.
+ If false (or nothing) is the argument to these functions, they return tables of strings. The strings are numbers separated by '='.
+ If the argument is true, they return tables of tables, and the inner tables contain numbers as described for each function.
+ The first form is kept around and is the default for compatibility with older themes. The advantage of the second form is that you no longer need to have a bit of code in your theme to transform the string into a table of numbers before you can use it.
+ Example:
+ local bpmsand= timing_data:GetBPMsAndTimes()
+ for i, s in ipairs(bpmsand) do
+ local sand= split("=", s)
+ bpmsand[i]= {tonumber(sand[1]), tonumber(sand[2])}
+ end
+ -- do something that looks at all the bpms and times.
+ Becomes:
+ local bpmsand= timing_data:GetBPMsAndTimes(true)
+ -- do something that looks at all the bpms and times.
+
+ + Returns the minimum and maximum BPM of the song in a table (in that order). + + + Returns the beat from fElapsedTime. + + + Returns the BPM at fBeat. + + + Returns a table of the BPMs as floats. + + + Returns a table of the BPMs and the times they happen as tables. The first value is the beat. The second value is the bpm. + + + Returns the elapsed time from fBeat. + + + Returns a table of the Stops and the times they happen as tables. The first value is the beat. The second value is the length. + + + Returns a table of the Delays and the times they happen as tables. The first value is the beat. The second value is the length. + + + Returns a table of the Labels and the times they happen as tables. The first value is the beat. The second value is the label. + + + Returns a table of the Warps and the times they happen as tables. The first value is the beat. The second value is the number of beats to warp over. + + + Returns a table of the Combos and the times they happen as tables. The first value is the beat. The second value is the combo. The third value is the miss combo. + + + Returns a table of the Time Signatures and the times they happen as tables. The first value is the beat. The second value is the numerator. The third value is the denominator. + + + Returns a table of the Tickcounts and the times they happen as tables. The first value is the beat. The second value is the number of ticks per beat. + + + Returns a table of the Fakes and the times they happen as tables. The first value is the beat. The second value is the number of beats to not judge. + + + Returns a table of the Scrolls and the times they happen as tables. The first value is the beat. The second value is the scroll rate ratio. + + + Returns a table of the Speeds and the times they happen as tables. The first value is the beat. The second value is the scroll rate ratio. The third value is the length of time to fully activate. The fourth value is the unit of activation (0 for beats, 1 for seconds). + + + Returns true if the TimingData contains BPM changes. + + + Returns true if the TimingData contains delays. + + + Returns true if the TimingData contains any BPM changes with a negative BPM. + + + Returns true if the TimingData contains stops. + + + Returns true if the TimingData contains warps. + + + returns true if the TimingData contains fake segments. + + + Returns true if the TimingData contains speed scrolling changes. + + + Returns true if the TimingData contains general scrolling changes. + +
+ + + Returns true if song s is in the Trail. + + + Returns an array with all the artists in the Trail. + + + Returns the Trail's difficulty. + + + Returns the length of this Trail in seconds. + + + Returns a table of TrailEntry items. + + + Returns the Trail's difficulty rating. + + + Returns the Trail's RadarValues. + + + Returns the Trail's StepsType. + + + Returns the Trail's total meter + + + Returns the TrailEntry at index iEntry. + + + Returns true if any of the Trail entries are secret. + + + + + Returns a string of modifiers used in this TrailEntry. + + + Returns the Song used in this TrailEntry. + + + Returns the Steps used in this TrailEntry. + + + (why'd I think this was a good idea when we have ?) + + + + + Sets the UnlockEntry's ID to m_sEntryID. + + + Sets the UnlockEntry's course to sCourseName.
+ Example: course,"Driven" +
+ + Returns the code for this unlock. + + + Returns the Course for this unlock. + + + Returns the unlock description. + + + Returns the UnlockRequirement. + + + Returns true if the UnlockEntry requires you to pass Hard steps. + + + Returns true if the UnlockEntry requires you to pass Challenge steps. + + + Returns the Song related to the UnlockEntry. + + + Get all of the steps locked based on StepsType. + + + Get all of the steps locked based on difficulty. + + + Returns the UnlockRewardType for this entry. + + + Returns true if the UnlockEntry is locked. + + + Sets the UnlockEntry's modifier to sModifier. + + + Sets the requirement for this unlock to m_fRequirement. + + + Makes the UnlockEntry require passing Hard steps. + + + Makes the UnlockEntry require passing Challenge steps. + + + Makes the UnlockEntry hide in Roulette. + + + Sets the UnlockEntry's song to sSongName. sSongName also requires the group.
+ Example: song,"In The Groove/Pandemonium" +
+ + Sets the UnlockEntry to unlock a specified song's steps.
+ Example: steps,"In The Groove/Pandemonium","expert" +
+ + Sets the UnlockEntry to unlock a specified song's stepstype. + +
+ + + Returns true if there are any unlocks to celebrate. + + + Returns the associated EntryID. + + + Returns the number of unlocked items. + + + Returns the number of all unlock items, regardless of status. + + + Returns the number of points for the machine profile based on the specified UnlockRequirement. + + + Returns the number of points for the specified profile based on the specified UnlockRequirement. + + + Returns the number of points until the next unlock. + + + Returns a table of songs unlocked by UnlockEntry sEntryID. + + + Returns a table of steps unlocked by UnlockEntry sEntryID. + + + Returns the UnlockEntry at iIndex. + + + Returns the UnlockEntry index to celebrate. + + + Sets the preferred Song/Course to the specified sUnlockEntryID + + + Unlocks an entry by ID. + + + Unlocks an entry by index. + + + Determines if a song is locked by any means. The number returned determines + how the song is locked. + + + + + Returns the wheel's current index. + + + Returns the total number of items in the wheel. + + + Returns the WheelItemDataType of the selected item. + + + Returns the WheelItem at index iIndex. + + + Returns true if the wheel is locked. + + + Returns true if the wheel is settled/stopped moving. + + + Moves the wheel by n. + + + Attempts to set the open section to sSection. + + + + + Returns the color of this wheel item. + + + Returns the text of this wheel item. + + + Returns the type of this wheel item. + + + Returns whether the wheel item has been loaded yet. If this function returns false, calling any other WheelItemBase function will result in an error.
+ A specific case where this is known to happen is commands that trigger on CurrentSongChanged because the music wheel clears the current song before it finishes loading if the current song is longer than the number of stages remaining. +
+
+ + + Sets the WorkoutGraph from the current Workout. + + + Sets the WorkoutGraph from GameState and song index iSongIndex. + + +
+ + + + + Blending modes. See . + + + + + Horizontal alignment. See . + + + + + Vertical alignment. See . + + + +
diff --git a/Docs/legacy/Luadoc/a.lua b/Docs/legacy/Luadoc/a.lua new file mode 100644 index 0000000000..19707af4dc --- /dev/null +++ b/Docs/legacy/Luadoc/a.lua @@ -0,0 +1,22 @@ +require "lxp" + +local count = 0 +callbacks = { + StartElement = function (parser, name) + io.write("+ ", string.rep(" ", count), name, "\n") + count = count + 1 + end, + EndElement = function (parser, name) + count = count - 1 + io.write("- ", string.rep(" ", count), name, "\n") + end +} + +p = lxp.new(callbacks) + +for l in io.lines() do -- iterate lines + p:parse(l) -- parses the line + p:parse("\n") -- parses the end of line +end +p:parse() -- finishes the document +p:close() -- closes the parser \ No newline at end of file diff --git a/Docs/Luadoc/bgline.png b/Docs/legacy/Luadoc/bgline.png similarity index 100% rename from Docs/Luadoc/bgline.png rename to Docs/legacy/Luadoc/bgline.png diff --git a/Docs/Luadoc/closed.gif b/Docs/legacy/Luadoc/closed.gif similarity index 100% rename from Docs/Luadoc/closed.gif rename to Docs/legacy/Luadoc/closed.gif diff --git a/Docs/Luadoc/favicon.ico b/Docs/legacy/Luadoc/favicon.ico similarity index 100% rename from Docs/Luadoc/favicon.ico rename to Docs/legacy/Luadoc/favicon.ico diff --git a/Docs/Luadoc/open.gif b/Docs/legacy/Luadoc/open.gif similarity index 100% rename from Docs/Luadoc/open.gif rename to Docs/legacy/Luadoc/open.gif diff --git a/Docs/Mapping_keys_for_edit_mode.txt b/Docs/legacy/Mapping_keys_for_edit_mode.txt similarity index 100% rename from Docs/Mapping_keys_for_edit_mode.txt rename to Docs/legacy/Mapping_keys_for_edit_mode.txt diff --git a/Docs/README-GUIDELINES b/Docs/legacy/README-GUIDELINES similarity index 97% rename from Docs/README-GUIDELINES rename to Docs/legacy/README-GUIDELINES index 2dc30fba93..7707681340 100644 --- a/Docs/README-GUIDELINES +++ b/Docs/legacy/README-GUIDELINES @@ -1,30 +1,30 @@ -Bits of possibly less-than-obvious advice: - -archutils/ contains arch-specific code. This should contain code -shared by more than one arch/ driver. - -arch/ contains drivers for specific features that can be better -implemented nonportably. Most drivers (all except sound) contain -default, portable implementations, so StepMania should work mostly -out-of-the-box on platforms that are supported by the supporting -libraries (particularly SDL); only a sound driver needs to be -written. - - -Avoid accessing other singleton classes from singleton destructors. That -introduces dependencies on the order of destruction, and can cause problems -if one of the singletons throws an exception. - - -This kills VC: - -template static void YY( T opt ) { } -enum { A } a; -enum { A1 } b; -void XX() { YY(a); YY(b); } - -foo.obj : fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '?YY@@YAXW4__unnamed@@@Z' - -It mangles the template incorrectly. Solution: don't use anonymous -enums as template parameters; give them a name. - +Bits of possibly less-than-obvious advice: + +archutils/ contains arch-specific code. This should contain code +shared by more than one arch/ driver. + +arch/ contains drivers for specific features that can be better +implemented nonportably. Most drivers (all except sound) contain +default, portable implementations, so StepMania should work mostly +out-of-the-box on platforms that are supported by the supporting +libraries (particularly SDL); only a sound driver needs to be +written. + + +Avoid accessing other singleton classes from singleton destructors. That +introduces dependencies on the order of destruction, and can cause problems +if one of the singletons throws an exception. + + +This kills VC: + +template static void YY( T opt ) { } +enum { A } a; +enum { A1 } b; +void XX() { YY(a); YY(b); } + +foo.obj : fatal error LNK1179: invalid or corrupt file: duplicate COMDAT '?YY@@YAXW4__unnamed@@@Z' + +It mangles the template incorrectly. Solution: don't use anonymous +enums as template parameters; give them a name. + diff --git a/Docs/SimfileFormats/BMS/BM98Data_format_specification.html b/Docs/legacy/SimfileFormats/BMS/BM98Data_format_specification.html similarity index 100% rename from Docs/SimfileFormats/BMS/BM98Data_format_specification.html rename to Docs/legacy/SimfileFormats/BMS/BM98Data_format_specification.html diff --git a/Docs/SimfileFormats/BMS/BM98FinalSecret.html b/Docs/legacy/SimfileFormats/BMS/BM98FinalSecret.html similarity index 100% rename from Docs/SimfileFormats/BMS/BM98FinalSecret.html rename to Docs/legacy/SimfileFormats/BMS/BM98FinalSecret.html diff --git a/Docs/SimfileFormats/BMS/BMS_Reading_Tutorial.rtf b/Docs/legacy/SimfileFormats/BMS/BMS_Reading_Tutorial.rtf similarity index 100% rename from Docs/SimfileFormats/BMS/BMS_Reading_Tutorial.rtf rename to Docs/legacy/SimfileFormats/BMS/BMS_Reading_Tutorial.rtf diff --git a/Docs/SimfileFormats/BMS/BMS_Reading_Tutorial.txt b/Docs/legacy/SimfileFormats/BMS/BMS_Reading_Tutorial.txt similarity index 100% rename from Docs/SimfileFormats/BMS/BMS_Reading_Tutorial.txt rename to Docs/legacy/SimfileFormats/BMS/BMS_Reading_Tutorial.txt diff --git a/Docs/SimfileFormats/BMS/_src.txt b/Docs/legacy/SimfileFormats/BMS/_src.txt similarity index 100% rename from Docs/SimfileFormats/BMS/_src.txt rename to Docs/legacy/SimfileFormats/BMS/_src.txt diff --git a/Docs/SimfileFormats/BMS/tmp.txt b/Docs/legacy/SimfileFormats/BMS/tmp.txt similarity index 100% rename from Docs/SimfileFormats/BMS/tmp.txt rename to Docs/legacy/SimfileFormats/BMS/tmp.txt diff --git a/Docs/SimfileFormats/DWI/DWI.txt b/Docs/legacy/SimfileFormats/DWI/DWI.txt similarity index 100% rename from Docs/SimfileFormats/DWI/DWI.txt rename to Docs/legacy/SimfileFormats/DWI/DWI.txt diff --git a/Docs/SimfileFormats/DWI/readme.html b/Docs/legacy/SimfileFormats/DWI/readme.html similarity index 98% rename from Docs/SimfileFormats/DWI/readme.html rename to Docs/legacy/SimfileFormats/DWI/readme.html index cd66e320a0..4e8ba82485 100644 --- a/Docs/SimfileFormats/DWI/readme.html +++ b/Docs/legacy/SimfileFormats/DWI/readme.html @@ -1,1224 +1,1224 @@ -

DANCE WITH INTENSITY v2.50.00
-© SimWolf, 2003

- -
    -
  1. DISCLAIMER AND TERMS OF USE -
  2. WHAT'S NEW? -
  3. USING AND CONFIGURING DWI
     
      -
    • Basic Operation -
    • Song Sorting -
    • Selecting Song Modifiers -
    • Special keys -
    • Controller Configuration -
    • Gameplay Settings -
    • Sound Configuration -
    • Changing the Display from Windowed to Full-screen -
    • Sound effects -
    • Command-line options -
    • Testing a song -
    • Setting Skins -
    • Setting Announcer and Sound Effects -
    • Folder- and Genre- Specific Banners -
    • AVI Movie Support -
    • Sonique Visualizations (SVP) Support -
    • User Profiles -
      -
  4. DWI FILE FORMAT
       -
  5. NONSTOP MODE AND CRS FILE FORMAT -
  6. LRC (LYRICS) FILE FORMAT -
  7. LIMITATIONS -
  8. VERSION HISTORY -
  9. FUTURE DEVELOPMENT AND THANKS -
- -

1. DISCLAIMER AND TERMS OF USE

- -

This program is provided for free, as-is. Although it has been tested on multiple systems for compatability and reliability, you run this program at your own risk. I cannot be held responsible if the program causes file loss or other problems.

- -

THIS PROGRAM IS *NOT* FOR SALE!!! IT SHOULD NEVER BE BUNDLED WITH ANY OTHER FILES (MUSIC OR STEP FILES) ON ANY MEDIA, INCLUDING (BUT NOT LIMITED TO) CD's, DVD's, DISKS OR OTHER MEDIA.

- -

DWI is Donation-Ware. Although you are not required to donate, it would be greatly appreciated if you enjoy the program that you contribute something towards the developers.

- -

This program simulates a popular arcade and home video game. It was written to allow myself the ability to play songs from the games without having to switch CDs in my Playstation or Dreamcast, and also affords the ability to add new songs not currently available. It also allows for playing older songs with new play modes, such as downward-scrolling arrows. This program is being released to the public in the hopes that others would find it useful in the same manner.

- -

As such, this program REQUIRES responsibility on the part of the end-user (ie. YOU) to use the program LEGALLY. You should *ONLY* play songs where you:

- - - - - -
a)  Own the game from which that music comes from.
or b)  Own the soundtrack CD from which the music comes from.
or c)  Legally own rights to the music being used (ie. other CDs, etc.)
-

- -

I own all the available soundtracks and videogames for the music I own, and respectfully ask that you support the games and purchase them. Thank you.

- -

2. WHAT'S NEW?

- -
-v2.50.00 - August 14, 2003.
-            - NEW: Addition of WAVE, BRAKE, and 0.25x modifiers.
-            - BUGFIX: Stage numbers and various other numbers are coloured again.
-				- BUGFIX: Bonus stages now default to Heavy/Maniac again.
-            - OTHER: Various other bugs I can't remember that have been fixed.
-				
-
-

- -

3. USING AND CONFIGURING DWI

- -

BASIC OPERATION

- -

When you first run DWI, you will receive a warning screen about responsible use of the program. This warning screen will appear *EVERY* time the program detects new songs.

- -

DWI uses step-files with the extension ".DWI". These files go in their own folder along with their associated background and banner images. Optionally the music file can go in the same folder also.

- -

DWI supports multiple collections of songs, so you can organise your songs as you see fit. To do this, just create different sub-directories in the "Songs" folder.

- -

eg. For a song with a step-file of "abc.dwi", put into a collection called "My Songs", your directory structure should look like this:

-     <INSTALL directory>
-        + Songs
-           + My Songs
-              + abc
-                 + abc-banner.png   (any name, the program will detect that it's a banner)
-                 + abc-bg.png       (any name, the program will detect that it's a background)
-                 + abc.dwi          (any name)
-                 + (abc.mp3/wav)    (optional - otherwise FILE: tag is used).
-                 + (abc.lrc)        (optional - should have same base as DWI file).
-
-

- -

So, in each "song folder", there should be two image files (background and banner), the DWI file, and optionally the music file in MP3 or WAV format.

- -

Song Sorting

- -

When you are at the song select screen, simply press up or down to change the current collection you are in. Songs are organized alphabetically within each collection, and collections are organized alphabetically also.

- -

Another option is to sort your music by genre. To activate this, go to "Options Menu", then "System Menu", and change the sort method to "GENRE" *. This requires your DWI files to have a tag defining the genre to put the music into (see DWI format, below). Multiple genres can be given (separated by a comma), to make the same song appear in different collections. At the song select screen, press up or down to change the genre.

- -

You can also press Up-Left to change the sort method. This cycles through:

    -
  • Folder/Genre (default) -
  • Folder/Genre, Separated -
  • All Music (by title) -
  • All Music (by artist) -
  • BPM. -
  • Player's Best (top 64) -

- -

Selecting Song Modifiers

- -

At the song-select screen, press the "Select" button/key, and use the arrows to change options. When done, press "Select" again. Alternatively, you can hold down "Start" when selecting a song and you will be taken to a -screen where you can set your options.

- -

- - - - - - - - - -
Speed: 1.5x, 2.0x, 3.0x, 4.0x, 5.0x, 8.0x, 0.5x, 0.75x, 0.25x
Boost: BOOST, BRAKE, WAVE
Appear: HIDDEN, SUDDEN, STEALTH
Turn: LEFT, MIRROR, RIGHT, SHUFFLE
Other: LITTLE, FLAT, SOLO
Dark: DARK (can't see arrow indicators)
Scroll: REVERSE
Freeze: NOFREEZE
Power: POWER-DROP (gauge starts full and depletes), DEATH (must full-combo song)

- -

For courses and bonus stages, use the same text as above in the course definition file when setting modifiers.
-eg. #SONG:Default\MySong:BASIC:1.5x,HIDDEN,LEFT,FLAT;

- - -

Special keys

- -

The function keys will be used to adjust or enable various gameplay functions. Primarily these are designed for people creating DWI files and want to adjust timing.

- -

- - - - - - -
F1/F2 - Restarts the song (developer mode only)
F3/F4 - Adjust playback speed of song down/up (during song select/gameplay)
F5/F6 - Adjust BPM value down/up by 0.50 BPM. (during gameplay)
F7/F8 - Adjust BPM value down/up by 0.02 BPM. (during gameplay)
F9/F10 - Adjust GAP value down/up by 5ms. (during gameplay)
F12 - Toggle "Assist Click" on/off. (during song select/gameplay)

- -NB: Enable autoplay in the main options menu to prevent song from failing while fine-tuning. (Or set "GAME OVER" to "End of Song"... or just use developer mode). - -

Controller Configuration

- -

To change the inputs, simply go to the Options Menu from the main screen and goto "Keyboard Configuration" or "Gamepad Configuration". Choose to configure either Player 1 or Player 2's inputs and you will be prompted to press each key, joystick button or dancepad square in turn. You cannot choose an input that is currently in use. To skip joystick buttons, press the "TAB" key.

- -

When done, select "Return" to make the change take effect.

- -

Gameplay Settings

- -

Gameplay settings such as difficulty level, danger display, and end-of-game settings are selected from the Gameplay Configuration menu from the Options screen. These changes take effect immediately.

- -

Extra Stages

- -

If you AA a Heavy or Challenge mode song on the last stage and have Extra Stages enabled in the Game Options, you can play another song. The song(s) you can choose from are either generated randomly (3 for Extra Stage #1, one for Extra Stage #2), or can be defined in a CRS file.

- -

- - -
bonus-1.crs   Songs for Extra Stage #1
bonus-2.crs   Songs for Extra Stage #2

- -

NB: These CRS files go in the same directory as DWI2.exe, not the Courses folder.

- -

Sound Configuration

- -

The default sound settings for DWI are 44Khz, Stereo, 16-bit samples. However, you may want to lower these -settings on slower computers.

- -* NB: You must exit DWI and start it again for this change to take effect. - -

Changing the Display from Windowed to Full-screen

-

Go to the "System Menu" from the Options screen and change the display type.

- -* NB: You must exit DWI and start it again for this change to take effect. - -

Sound effects

- -

Sound effects are all in the "Sounds" directory. You can add or remove files to most directories, and the program will use the existing files during gameplay. However, files in the root of the sound-set directory and those in the "attract" and "combo" directories must be the same name in order for the program to find them and play them appropriately.

- -

Command-line options

- -

You can run DWI with various command line options to configure some values. (Please read the FAQ for details -on how to start the program with command line options). These options are available:

- -

- - - - - - - - - - - - - - - -
/sdl   Starts DWI in the software-only graphics mode.
/16bpp   Runs DWI in 16-bit colour mode (SDL), or uses a 16-bit primary surface (DirectX)
/32bpp   Runs DWI in 32-bit colour modes/32-bit primary surface.
/fullscreen   Runs DWI in fullscreen mode (may need to use to start on some cards)
/window   Runs DWI in a window. Some cards won't support this so DWI will try fullscreen.
/log   Creates a 'dance.log' file that can be useful for debugging.
/anysize   In DirectX mode, this tries to make textures in any size, rather than creating textures to the nearest power-of-two value (ie. a 75x60 image is loaded into a texture that big instead of a 128x64 one). This can speed up performance on some cards and save memory, if your card can handle it.
/sw   In SDL mode, surfaces are created in regular memory (default)
/hw   In SDL mode, surfaces are created in hardware memory (can improve performance if your card can handle it).
/priority:x   can force DWI to run as a more "important" program under Windows. "1" starts it as "ABOVE NORMAL", "2" is "TIME CRITICAL". May improve performance in certain cases. (Use with caution if you're running many other processes at the same time).
/sdevice:x   tells DWI to use a given sound-device. Use "/log" and look in dance.log first for a list of available sound-devices.
/fps:xx   makes DWI try to stay at a given framerate (20..100). If you've got a fast machine, this can really save on computer cycles.
/showsm   will add songs with only SMANIAC steps to the song-select screen.
/skipsearch   will prevent DWI from searching the Songs folder at startup.
/dither:0   will turn off the dithering effect DWI uses for semi-transparent images on old videocards that can't handle them. Some users may prefer this to remove the 'speckles' in the gameplay graphics.

- -

You can limit paging to virtual memory during gameplay (which can cause skips as Windows decides to write or retrieve data from disk) using these flags:

- -

- - -
/minRAM:xx   Instructs DWI to try to reserve at least this much physical memory from the Operating System. *
/maxRAM:xx   Instructs DWI to try to reserve at most this much physical memory from the Operating System. *
 
* Only works in Windows NT, 2000, and XP. Default is 16-32MB.

- -

Use these flags to fix strange behavior in DWI...

- -

- - - - - - - - - - - - - -
/key:nonexclusive   affect how DirectInput is initialized. Should be paired with one of /key:fg or /key:bg
/key:exclusive  
/key:fg   affect how DirectInput is intialized.
/key:bg  
/altcombo   for reasons known to the heavens and my machine in the basement, DWI would not display the 'lives' image in Nonstop Mode, instead locking up the computer. I'm convinced this is a videocard/driver issue, as the code to draw the image is exactly the same as the code to display any other image... but oh well. Using this command line argument will tell DWI to not try to display the image and instead write "X Lives" in its place, which seemed to make it work. Strange... but the option's there in case you run into the problem too.
/v5hack   some Voodoo card drivers seem to allocate space for textures incorrectly (off by one) - this should hopefully fix the problem.
/altmovie   Uses an alternate way of drawing the background movies and visualizations for older videocards that display solid-colour textures instead.
/noshade   Prevents the extra shading effect on the song-select wheel from being added.

- -

Testing a song

- -

- - - - - - - - - -
/test:...   You can start DWI in test/developer mode by using the "/test:..." command line argument. Provide the *folder* the .dwi file is in.
/style:...   use this set of steps (SINGLE, DOUBLE, SOLO). Default is SINGLE.
/level:...   use this level of steps (BASIC, ANOTHER, MANIAC, SMANIAC). Default is BASIC.
/p2   test using player 2's controls instead.
/speed:X   starts song at a given speed (1..5)
/scroll:X   starts song with given speed modifier (0.5, 0.75, 1.5, 2, 3, etc.)
/startat:<TIME>   jumps to a given time into the song (game-time). <TIME> can be given in minutes, seconds, or milliseconds. -
   ie.  /startat:1:05.5  (minutes)
-        /startat:65.5    (seconds)
-        /startat:65500   (ms)      - all the same position.
/tick:1   turns the assist click on at startup (default is off).
/dark   hides the fixed-place arrows during testing.

- -

Example:

- -

"DWI.exe /test:.\Songs\Development\MyNewSong /style:SINGLE /level:MANIAC /p2 /speed:4 /scroll:2 /startat:1:00"

- -

Starts testing the .dwi file found in \songs\development\mynewsong, in SINGLE mode, with MANIAC-level steps. Player 2's controls are used, and the song's speed is set to '4'. Arrows are displayed as though the "x2" modifier was active. The song starts at the 1-minute mark.

- -

Setting Skins

- -

Create different sub-directories within the "Skins" folder for each skin you wish to use. So, for example: -

-     <INSTALL directory>
-        + Skins
-            + Default  (leave as-is)
-            + Skin A
-            + Skin B
-            + ...         

- -

The filenames for each skin should be the same as in the default directory. If an image isn't found, the default is used. This way you can create skins that are relatively simple, or very elaborate ones. And you don't need to delete any of the original files. ;) There is a limit of 64 skins.

- -

Changes will take effect when you leave the Skin Selection screen.

- -

I do ask, however, that you keep the title of the program as "Dance With Intensity". Thank you. :)

- -

Setting Announcer and Sound Effects

- -

Similar to skins, just create new directories in the 'Sounds' folder for each sound set you wish to use. So, for example: -

-     <INSTALL directory>
-        + Sounds
-            + Default   (leave as-is)
-            + Jack
-            + Jill
-            + ...         

- -

The tree structure for each set should be the same as is used for the "Default" directory. For example: -

    + Jill
-        + attract    - files should be named attract-00.wav, attract-01.wav, attract-02.wav
-        |              (these are the sounds used on the title screen)
-        + combo      - files should be named combo-00.wav and combo-01.wav
-        |              ("100 Combo" and "Combo stopped")
-        + danger     - a set of files played when power level at danger or zero.
-        + eval
-        |   + A
-        |   + B      - sets of files to play at the evaluation screen based on grade
-        |   + ...   
-        + good       - a set of files played when power level in the 'good' range
-        + great      - "                                           " 'great' range
-        + over
-        |   + fail   - files played at game over screen (failure)
-        |   + pass   - "                              " (cleared all stages)
-        + select
-        |   + new    - files played when #STATUS:NEW; is set in DWI file and song is selected
-        |   + song   - files played when a song is selected
-        + start
-        +   + go     - files played at "Here we go!" screen.
-        +   + ready  - files played at "Ready?" screen.
-        + warning    - a set of files played when the power gauge is in the 'warning' range.

- -

There should not be more than 64 sound effects in a single subdirectory. There is a limit of 64 sets. Changes will take effect once you leave the Announcer/Sound Select screen. Please keep the title sound effect (attract-00.wav) as "Dance With Intensity".

- -

Folder- and Genre- Specific Banners

-

You can make DWI display a special banner for each folder when it is highlighted on the Song-Select Screen. To do this, simply put a standard (horizontal) banner with the same name as the folder in the 'Songs' folder. (eg. a banner for 'Default Songs' would be ".\Songs\Default Songs.png").

- -

If you have sorting by Genre on, you can have special banners for each Genre by putting banners in PNG format with the same name as the Genre referenced into ".\Genres". (eg. "Pop Music.png").

- -

Folder-Specific Banners can also be made for Courses too. Just put a PNG file with the same name as the subfolder the CRS files are in, in the "Courses" directory.

- -

AVI Movie Support

-

AVI movies can be played in the background while you play. See the "Background Animation" section below for more details on how this is set up. From the System Menu, you can tell DWI whether to not play AVI files at all, or set the quality level from 1 (worst) to 10 (full). The default is 5. Changing this value could affect your framerate, so play with the values to determine what works best for your system.

- -

Random animations are picked from the ./Movies/Random folder and played in the background of songs without a defined background script if enabled in the System Options menu. This folder can be changed by a flag in the DWI file also, enabling themes.

- -

Sonique Visualizations (SVP) Support

-

Sonique visualizations can be played in the background while you play. See the "Background Animation" section below for more details on how this is set up. From the System Menu, you can tell DWI whether to use them at all, or set the quality level from 1 (worst) to 10 (full). The default is 5. Changing this value could affect your framerate, so play with the values to determine what works best for your system.

- -

Random visualizations are picked from the ./Vis folder and played in the background of songs without a defined background script if enabled in the System Options menu. Their behavior can often be changed by editing the 'vis.ini' file that is created after they are used in DWI, similar to in Sonique.

- -

User Profiles

-

DWI2.40 introduced 'user profiles' - a way that multiple users can play DWI on the same machine and keep their own individual records. Setting up a new profile is easy - simply create a new subdirectory in the "Profiles" directory with the name of the user (15 characters or less), and inside that folder, put a 64x64 PNG file called 'user.png' to represent you in the game. Look at the 'Profiles/Sample User' folder for an example.

- -

When you use a profile, DWI will create an individual records file and profile information file in the same directory that keeps track of your individual achievements.

- -

When you get a high score, it will be saved to your own profile's records ("New Personal Best"), and, if you beat the overall high score, it will also be saved to the system records ("It's a New Record!"), with your username registered with it.

- -

Using a user-profile also lets you track some other statistics, such as overall high scores and combos for each mode. It will also store the last-used modifiers you used (eg. 2x speed modifier, Reverse) between sessions, so you don't have to set it again each time you start a new game.

- -

This option can be disabled in the Game Options Menu if you prefer.

- -4. DWI FILE FORMAT - -

Steps

- -

DWI uses step-files that are similar to the ".MSD" file format. However, there are new additions and some tags are treated slightly differently, so the extension was changed to avoid confusion. DWI files with these new additions will not work properly in other simulators.

- -

Step-patterns are defined in the same way as .MSD files - use the numeric keypad as a reference for most patterns: -

-  7=U+L     8=U      9=U+R
-
-  4=L                6=R
-
-  1=D+L     2=D      3=D+R
-
-    (U+D = A and L+R = B)
-

- -

A '0' indicates no step. Each character defaults to one 1/8 of a beat. Surround a series of characters with the following brackets to change the rate at which the steps come: -

-   (...)  = 1/16 steps
-   [...]  = 1/24 steps
-   {...}  = 1/64 steps
-   `...'  = 1/192 steps

- -

6-panel (Solo) mode uses additional characters: -

-   -\---- = C
-   ----/- = D
-
-   L\---- = E
-   -\D--- = F
-   -\-U-- = G
-   -\---R = H
-
-   L---/- = I
-   --D-/- = J
-   ---U/- = K
-   ----/R = L
-
-   -\--/- = M

- -

To do more than 2 panels at a time, you can join codes together with the "<..>" object, and they will all count as the same beat. So, to do a jump that involves Left, Right, Up-Left, and Up-Right, you could do: -

-   -\--/- = M
-   L----R = B
-   ======
-   L\--/R = <MB>  (or <LE>, <IH>, <46M>, etc.)

- -

MSD files from other simulators will work with DWI, with a change in the 'GAP' value being the only change usually necessary. DWI calculates the 'GAP' value differently than other simulators that use the MSD format.

- -

DWI does not support the BMS file format. There is a utility available that can convert any BMS file into DWI format. Each song only requires one DWI file for all of its steps, so if you are converting BMS files please remember that all the different difficulties of step patterns will be contained in the same DWI file.

- -

Hold Arrows

- -

In the DWI file format a hold arrow is signified with the ! symbol. The string 8!8 will begin an 'up' hold arrow, and the arrow will be released the next time the program encounters an 'up' arrow: by itself or combined with another arrow (7, 8, 9, A, etc.) The characters 7!4 would show both 'up' and 'left' arrows but only the left arrow would be held. The format could best be described as "show!hold".

- -

Tags

- -

These tags should be in every DWI file:

- -

- - - - -
#TITLE:...;   title of the song.
#ARTIST:...;   artist of the song.
#GAP:...;   number of milliseconds that pass before the program starts counting beats. Used to sync the steps to the music.
#BPM:...;   BPM of the music

- -

Additionally, the following tags can be given:

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
#DISPLAYTITLE:...;   provides an alternate version of the song name that can also include special characters.
#DISPLAYARTIST:...;  provides an alternate version of the artist name that can also include special characters.
-  
- Special Characters are denoted by giving filenames in curly-brackets.
- eg. #DISPLAYTITLE:The {kanji.png} Song;
-  
- The extra character files should be 50 pixels high and be black-and-white. The baseline for the font should be 34 pixels from the top.
-  
#DISPLAYBPM:...;tells DWI to display the BPM on the song select screen in a user-defined way.  Options can be:
-
-*    - BPM cycles randomly
-a    - BPM stays set at 'a' value (no cycling)
-a..b - BPM cycles between 'a' and 'b' values -
#FILE:...;   path to the music file to play (eg. /music/mysongs/abc.mp3 )
- (NB: if the file is not found, a .wav or .mp3 file in the same folder as the DWI file is used)
#MD5:...;   an MD5 string for the music file. Helps ensure that same music file is used on all systems.
#FREEZE:...;   a value of the format "BBB=sss". Indicates that at 'beat' "BBB", the motion of the arrows should stop for "sss" milliseconds. Turn on beat-display in the System menu to help determine what values to use. Multiple freezes can be given by separating them with commas.
#CHANGEBPM:...;   a value of the format "BBB=nnn". Indicates that at 'beat' "BBB", the speed of the arrows will change to reflect a new BPM of "nnn". Multiple BPM changes can be given by separating them with commas.
#STATUS:...;   can be "NEW" or "NORMAL". Changes the display of songs on the song-select screen.
#GENRE:...;   a genre to assign to the song if "sort by Genre" is selected in the System Options. Multiple Genres can be given by separating them with commas.
#CDTITLE:...;   points to a small graphic file (64x40) that will display in the song selection screen in the bottom right of the background, showing which CD the song is from. The colour of the pixel in the upper-left will be made transparent.
#SAMPLESTART:...;   the time in the music file that the preview music should start at the song-select screen. Can be given in Milliseconds (eg. 5230), Seconds (eg. 5.23), or minutes (eg. 0:05.23). Prefix the number with a "+" to factor in the GAP value.
#SAMPLELENGTH:...;   how long to play the preview music for at the song-select screen. Can be in milliseconds, seconds, or minutes.
#RANDSEED:x;   provide a number that will influence what AVIs DWI picks and their order. Will be the same animation each time if AVI filenames and count doesn't change (default is random each time).
#RANDSTART:x;   tells DWI what beat to start the animations on. Default is 32.
#RANDFOLDER:...;   tells DWI to look in another folder when choosing AVIs, allowing 'themed' folders.
#RANDLIST:...;   a list of comma-separated filenames to use in the folder.
-

- -

Each pattern of steps for different modes have the same basic format: -

#SINGLE:BASIC:X:...;
- ^      ^     ^ ^
- |      |     | + step patterns.  In doubles, the left pad's steps are given first, 
- |      |     |   then the right pad's, separated by a colon (:).
- |      |     |
- |      |     + difficulty rating.  Should be 1 or higher.
- |      |
- |      + Difficulty.  Can be one of "BASIC", "ANOTHER", "MANIAC", or "SMANIAC"
- |
- + Style.  Can be one of "SINGLE", "DOUBLE", "COUPLE", or "SOLO".  "COUPLE" is 
-   Battle-mode steps.

- -

Comments can be used by using "//". Everything after this on the same line in the file will be ignored.

- -

Background Animations, Movies, and Visualizations

- -

DWI allows for background animations using a special script within the step-file. A script consists of static images, animated images, and/or an AVI movie. Using the script, you can create a variety of layered effects. A sample animation is described below: -

-   #BACKGROUND:
-
-     M:MOVIE:.\movies\sfx.avi STARTAT:-1.0 LAYER:0;
-     V:VIS:.\Vis\somevis.svp LAYER:0;
-     E:FILE:.\anim\equalizer.png ANIMATE:10,33 POSITION:-33,0 SPACING:40,40 LAYER:1;
-     D:FILE:.\anim\dancer-m1.png ANIMATE:24,66 SIZE:2 MULT:0,0.5,1 SPACING:30,30 LAYER:1;
-     X:LAYER:1 OFF;
-
-     SCRIPT:M.......................
-            ................E...............
-            D...............X,V...............E...............D...............
-            X,M...............E...............D...............X,V...............
-            E...............D...............X,M...............E...............
-            D...............X,V...............E...............D...............
-            X,M...............E...............D...............X;
-
-   #END;

- -

The first part of the "BACKGROUND" definition defines the effects. Each effect is attributed to a letter or number ("a-z", "A-Z", "1-9"). The format for defining an effect is:

- -

- - - - - - - - - - - - - - - - - - -
The first four tags cannot be used together...
FILE:   path to a file. Either a still image, or an animation (multiple frames of animation are stacked *vertically* in the image).
MOVIE:   path to a standard Windows AVI file. Note that the movie won't play unless you have the right codecs installed in Windows. Movies are currently stretched to fill the whole screen.
VIS:   path to a Sonique Visualization plug-in (SVP). Visualizations are currently stretched to fill the whole screen and are always put on Layer 0, and no other commands will affect it.
OFF   turns off a layer, effectively making it invisible. Will not turn off layer 0.
 
LAYER:l   the layer to use (required): -
    0 - base layer.  
-        (Image/Movie is always tiled and SPACING is ignored).
-    1 - overlay layer
-    2 - overlay layer
-    3 - overlay layer
 
STARTAT:t   number of seconds into the AVI file to start at. If negative, the movie will wait that many seconds before playing. Can be decimal (eg. 1.3 = 1300ms).
MULT:r,g,b   Red, Green, and Blue pixels in the image/movie are tinted by the given amounts. This way the same image/movie can be used multiple times across DWI files and have different colours.
ANIMATE:f,n1,n2,...nF   indicates that the FILE contains multiple frames of animation. "f" is the number of frames of animation. Each following value is the number of milliseconds each frame of animation is displayed. If not enough time-values are given, the last given value is used. Ignored for MOVIE type.
MOVE:x,y   the image/movie is moved by the given number of pixels every millisecond.
SPACING:x,y   images are always tiled if they don't fill up the screen. This tag allows you to add some spacing between the images by the given number of pixels horizontally and vertically (Layer > 0)
SIZE:s   multiplies the image size by 's' in both directions. Must be a whole number.
KEEPPOS   normally when a new effect is turned on, its position is reset. This tag keeps the layer where it is, useful for keeping images moving smoothly.
KEEPTIME   (MOVIEs only) normally when a movie starts, it starts from the beginning or the time given in the "STARTAT" tag. Adding this tag will keep it playing so when that layer is enabled again, it will have kept going.

- -

Following the effect definition, comes the actual animation script. This is a sequence of characters in a similar way as the step-patterns are given - each character normally is 1/8 of a beat, though brackets can be used to change the time-values. In this way, background animations can be syched to the steps. It is suggested that the steps for "SINGLE:BASIC" are copied to after the "SCRIPT:" tag, and then the effects be set. In this way one knows that the script will match the same length of the music.

- -

The animations take effect as that point in the song is reached. Multiple effects can occur at the same time if they are separated with a comma. A period (.) means no new effect should take place at that point. A zero (0) turns off all effects and returns the background to the original graphic.

- -

More Information

- -

Please check our website for more information and links to useful resources.

- -

5. NONSTOP MODE AND CRS FILE FORMAT

- -

DWI uses special CRS files that should be put in subfolders of the "Courses" directory. Now courses -can be shared with others if they have the same files and directory structure as you.

- -

CRS files are similar to DWI files in structure. The file defines the basic details about the course, such as its name and which songs should be played. Currently these tags are supported:

- -

Required tags:

- -

- - - - -
#COURSE:...;   the name of the course.
#DISPLAYCOURSE:...;  alternate name of course that can include special characters. Similar to #DISPLAYTITLE and #DISPLAYARTIST in DWI files.
#SONG:...;  

defines a song in the course. This can either be a selection from the Player's Best (or Worst), a Random stage or a predefined stage. The syntax for each is given below: -

    PLAYER'S BEST/WORST STAGE:
-    #SONG:BESTx:[BASIC|ANOTHER|MANAIC|SMANIAC];
-    #SONG:WORSTx:[BASIC|ANOTHER|MANAIC|SMANIAC];
-    - choose a song with the given index 'x'.  So BEST1 is the most popular
-      song, and WORST5 is the 5th least popular song.  If the given 
-      difficulty is not available, DWI will choose the next closest difficulty.
-      Songs that are equally popular will be put in random order.
-
-    RANDOM STAGE:
-    #SONG:*:[a]|[a..b];
-    - choose a random song, with a difficulty rating equal to or between 'a' and 'b'.
-    - if only 'a' is given, 'b' is assumed to be the same as 'a'.
-
-    #SONG:*:[BASIC|ANOTHER|MANIAC|SMANAIC];
-    - choose a random song with a given difficulty level.
-
-    #SONG:folder\*:[a]|[a..b]|[BASIC|ANOTHER|MANIAC|SMANIAC];
-    - choose a random song from a given folder.
-                   
-    DEFINED STAGE:
-    #SONG:<FOLDER>\<SONG TITLE>:<DIFFICULTY>;
-    - will use a song from <FOLDER> with the given title.
-      So to play a song called "My Song", which is in 
-      './Songs/Default/mysong/mysong.dwi', on MANIAC, 
-      you would say:
-
-      #SONG:Default\My Song:MANIAC;

- -

NB: Either the TITLE or folder the DWI file is in can be used.

- -

In addition, modifiers can be defined for each song by adding a list of comma-separated values to the end of the #SONG line. These modifiers are the same as listed above, plus -

-     xRANDOM   - where 'x' is the number of random effects to apply.
-                 'x' can be 1 to 7.
-     AWARDx    - where 'x' is the number of lives to award after 
-                 finishing the stage.
-

-

So to play "My Song", Maniac, with 2.0x, Left, Hidden, and with one random effect, use:
-#SONG:Default\My Song:MANIAC:2.0x,LEFT,HIDDEN,1RANDOM;

- -

Optional tags:

- -

- - - - -
#REPEAT:...;   can be "YES" or "NO". If set, starts course over from the beginning after last song.
#COMBO:PERFECT;   during play, the combo counter will only go up if a "PERFECT" is made.
#COMBOMODE:1;   sets how much is added to the combo counter for jumps. Can be 1 or 2.
#LIVES:4;   sets the number of 'lives' given to each player at the start of game play. After each stage is cleared, a given number of lives is added, either by a value specified by the "AWARDx" tag in the CRS file, or using the scale below: -
    Song was 6 feet or less - 1 life.
-    Song was 7 or 8 feet    - 2 lives.
-    Song was 9 feet or more - 3 lives.
-

- -

At the course selection screen, courses that have songs without steps for the current style (SINGLE, DOUBLE, etc) will be filtered out. Courses are loaded when DWI starts.

- -

6. LRC (LYRICS) FILE FORMAT

-

DWI can display lyrics during a song if it finds a .LRC file in the same folder as the step-file. The file should have the same file-base as the .DWI file - so, for example, if your DWI file is called "mysong.dwi", the lyrics file should be called "mysong.lrc".

- -

This file is a simple text-file that tells the program what text to display and when. It can also define the colour the text is displayed in.

- -

Each line starts with a tag in the format [xxxxxx]. Currently, these tags are supported:

- -

- - - - -
[COLOUR]   Sets the colour for the following text. After the tag, a colour value is given in hex (ie. yellow would be 0xFFFF00). Up to 10 colour values can be given, separated by commas.
[offset:xxxx]   Makes timestamps following this tag have their times adjusted by 'xxxx' milliseconds. Use to fine-tune timings for lyrics.
[MM:SS.ss]  

Sets a time. The text following the tag will be shown on the screen after this time has passed, replacing any text that was there before. To clear text, provide just a tag with no text after it.

A line-break can be defined using the pipe "|" symbol.

-

A new colour can be selected from the defined colours by using "{cX}", where "X" is a number from 0 to 9.

-

- -

Sample LRC file:

-

[0:00.00]aye-aye-aye|aye-aye-aye|aye-aye-aye
-[0:05.30]Where's my samurai?
-[0:07.00]
-[COLOUR]0xffff00
-[0:13.50]I've been searching for a man
-[0:16.00]All across Japan.
-...etc...

- -

7. LIMITATIONS

- -

Partly due to the compiler and my own lack of knowledge in some areas, there are a number of limitations -imposed on the program that users should know about:

    -
  • No more than 2048 songs. -
  • No more than 64 sound effects in a single subdirectory of 'soundfx' -

- -

If the program runs slowly on your machine, try the following:

    -
  • Install the latest DirectX 8.1 drivers. -
  • Update the video drivers for your video card. -
  • Try running the game in fullscreen mode, and/or setting your screen resolution to 16-bit mode. -
  • Lower the sound quality to Mono, 8-bit, and/or 11 or 22Khz. -
  • Lower the quality of background movies if you use them a lot. -
  • Try limiting the framerate (/fps:xx). -

- -

8. VERSION HISTORY

- -

v2.49.00 - May 22, 2003.
-            - NEW: Addition of "Player's Best" and "Player's Worst" to CRS file format.
-            - NEW: Expanded functionality of random song selection in CRS files.  You can now
-              choose a random song by difficulty (instead of just foot ratings), and also select a 
-              random song in a particular folder
-            - NEW: Courses are now arranged in subfolders, allowing for different groupings of 
-              courses.  One set could be for nonstop, others for challenge; or you can divide the 
-              courses up by mix or genre, etc.  You can also give each folder its own banner, like
-              in the song select interface.
-                 NOTE: You will have to move your existing courses into subfolders for them to 
-                 be recognized!
-            - NEW: #DISPLAYBPM:[xxx..xxx]|[xxx]|[*]; added, to force a certain display type on 
-              song select screen.
-            - NEW: For users with old videocards that can't display semi-transparent images, you 
-              can now turn off the dithering effect that DWI uses if you like.  Use the 
-              '/dither:0' command line argument.
-            - Tweaks to how #RANDFOLDER:...; behaves, plus program now searches folder DWI file 
-              is in for a "Movies" sub-folder, or AVIs in the same folder first before using the 
-              default /Movies/Random folder.
-            - Tweaks to banner display on Evaluation screen (for when song/course had no banner)
-            - Tweaks to record-display for courses.
-            - Tweak to beat-display in-game and in developers mode, so numbers won't 'jiggle'.
-            - BUGFIX: 'tiled images' on song-select screen (BPM, stage #, difficulty) and during 
-              gameplay on some old videocards has been fixed.  You should probably consider 
-              upgrading to a better card though anyway. ;^)
-            - BUGFIX: Can now have up to 512 courses, instead of 64.  Oops. ;)
-            - BUGFIX: "combo continuing" playing on every step past 9999 combo.  BTW, I hate you. ;)
-            - BUGFIX: Game doesn't crash on entering course-select screen after you've added new 
-              CRS files.
-            - OTHER: Other bugfixes and tweaks that I can't begin to remember. :P
-
-v2.41.00 - February 15, 2003.
-            - CHANGE: Drawing of text made more efficient and slightly more readable, through better 
-              drawing of drop-shadows.
-            - CHANGE: textures for SVP plug-ins to draw to now adjusted to nearest multiple of 2, as I 
-              suspect some assume it's supposed to be like that for efficiency reasons, and otherwise 
-              might cause problems overrunning memory.
-            - BUGFIX: DWI2.log file now created properly again.  (d'oh!!!)
-            - BUGFIX: problem drawing certain images in 32bpp SDL mode fixed (eg. BPM display, star-wipe)
-            - BUGFIX: extra 'N/A" box no longer appears in Solo mode "Select Profile" if started with P1.
-            - BUGFIX: Better freeing of music samples after gameplay, credits, and on song-select screen.
-
-v2.40.00 - February 2, 2003.
-            - NEW: Addition of "User Profiles", a system to keep user-specific records and high 
-              scores similar to the 'name entry' system from DWI1, but with more features.  Individual
-              users can tailor their own icon and (if directories are the same across systems) take 
-              their records with them between machines.  Now tracks personal high scores and overall
-              high scores, all viewable in the Records screen. (Can be disabled in Options menu if you
-              prefer not to use it).
-            - NEW: Arrow set for DWI completely redone to feature true colour-cycling arrows like the
-              arcade.  Also, arrows are drawn in last-to-first order now instead of first-to-last.
-              (NB: Thanks to uKER for the help creating the new arrow set).
-            - NEW: You can pause the game with the "Pause/Break" key.  However, like autoplay, high
-              score will not be saved.
-            - CHANGE: Folder-specific banners treated differently - now DWI looks for a PNG file with 
-              the same name as the sub-folder, in the base "Songs" folder.  Should be easier to 
-              manage the banners all in one folder now.
-            - some freeze arrow behavior tweaked.
-            - shading on song-select wheel made less dark.
-            - more details on LRC file support added to this file.
-            - style icon colours in default skin fixed (they were reversed).
-            - if you pass a song reasonably well, you'll get that cheer as the 'Cleared' text appears.
-            - BUGFIX: strange wrapping in View Records/Nonstop mode for some songs with two lines fixed.
-            - BUGFIX: Song titles and artist names with special characters on Nonstop mode now display
-              correctly
-            - BUGFIX: Timing in Developer mode after adjusting GAP fixed.  Actually tested it this time. ;)
-            - BUGFIX: Realigning the word 'Test' in developer mode.
-            - BUGFIX: /startat in developer mode is more accurrate.
-            - BUGFIX: Bonus CRS files don't 'skip' songs that are next to each other in the songlist.
-            - VARIOUS: other small tweaks I can't remember. ;)
-
-v2.30.01 - January 3, 2003.
-            - AVI and SVP decoding optimized slightly to reduce load on main game function.
-            - flag added to turn off shading on song select wheel, if desired.
-            - BUGFIX: "Game Over" back in on failing in regular mode.  Oops.
-            - BUGFIX: "NEW!" status works.  Expires after 2 weeks now.  May require songlist reset.
-            - BUGFIX: animation thread closes properly between stages.
-            - BUGFIX: steps are judged better again.  Oops x 2.
-
-v2.30.00 - January 1, 2003.
-            - NEW: Implemented Sonique Visualization Plugins (SVP) for background animations.
-            - NEW: Folder- and Genre- specific banners, plus banners for Roulette 
-                   and Title/Artist sort options.
-            - NEW: Sort by difficulty added to Song Select screen.
-            - NEW: Multiple colours on same line of lyrics possible.
-            - NEW: Can adjust the number of stages between breaks in Nonstop Mode.
-            - NEW: Ability to disable Background Scripts.
-            - NEW: Ability to set default sort method.
-            - New 'default' banners and backgrounds.
-            - Banner and Sample Start load time reduced.
-            - Sort by BPM now much faster.
-            - Paths in Background Scripts can now have spaces (use quotes around path).
-            - Addition to Background Script commands to use Visualizations (on Layer 0).
-            - Long song names with special characters now wrap.
-            - Options Screens reorganized to group some things better.
-            - Adjustments to GAP in Development mode handled properly if changed in DWI file.
-            - Ability to change method for drawing movies/etc. to older method (slower, but good
-              for old videocards that just give solid-colour images instead now).
-            - CRS files can take either title or directory now.
-            - Stage number/display now graphical, and colours can be assigned in skin CFG file.
-            - "TAB" can be used in song-titles to force line-wrap.
-            - Font updated to include missing '~' character.
-            - Song select wheel now has some extra shading.
-            - Support for semi-transparant images on older videocards improved by addition of 
-              pattern dithering instead of simply "off" or "on".
-            - BUGFIX: Missing '0's in scores during gameplay.
-            - BUGFIX: Rounding of scores to proper multiples of 10000000 on some processors.
-            - BUGFIX: Early "GOOD" judgement on a freeze arrow + jump combination fixed.
-            - BUGFIX: "New" tag treated properly again.
-            - BUGFIX: Random AVI search assumed any file was an AVI, without checking extension.
-            - BUGFIX: Skin CFG file with Hex values in uppercase read properly now.
-
-v2.20.30 - November 30, 2002.
-            - General performance improvements.
-            - Options left-over from main game removed in demo.
-            - Command-line options added for fine-tuning memory usage (WinNT/2k/XP).
-            - Time displayed in developer mode should be correct now at different speeds.
-            - Can disable lyrics from the Options menu.
-            - BUGFIX: Genre tag correctly parsed again.
-            - BUGFIX: GeForce/Detonator drivers bug fixed.
-            - BUGFIX: Corrections to Lyric file handling (timestamps, no return after last line)
-
-v2.20.10 - November 21, 2002.
-            - Lyrics now displayed in Test mode
-            - Lyrics now enabled for songs with positive GAP values
-            - SMANIAC songs selectable in extra stages even if /showsm not used.
-            - STREAM bar glows on final tally screen if you've AAA'd all songs(!)
-            - backgrounds and banners with upper-case extensions now recognised correctly
-            - in addition to PNG files, JPGs and BMPs can be used as backgrounds.
-            - "OK" flash for Reverse-scrolling arrows added
-            - Songlist.html only written if files added/updated/deleted
-
-v2.20.00 - November 20, 2002.
-            - NEW: "Final Tally" screen added if number of stages not set to "Unlimited".
-            - NEW: Timer added to developer mode.
-            - NEW: Support for lyrics during songs added through use of "LRC" files.
-            - NEW: "/skipsearch" command line argument added.
-            - Ability to reset songlist completely from Options Menu.
-            - BUGFIX: Groove Radar values calculated correctly again.
-            - BUGFIX: "Lost life" sound playing during Arcade mode removed.
-            - BUGFIX: Sample now played when combo jumps from 99..101.
-            - BUGFIX: "Skipped" notes in autoplay fixed.
-            - BUGFIX: Stream bar glows in Evaluation Screen if full combo and combo mode set 
-                      to "ORIGINAL"
-            - BUGFIX: Folders with no files in them handled better when searching for files.
-
-v2.10.00 - November 12, 2002.
-            - NEW: Songlist rebuild is now automatic and time for incremental updates has been
-                   dramatically reduced, as the whole song database does not get rebuilt from 
-                   scratch each time now.  (NB: Special thanks to uKER for his code that 
-                   implements this).
-            - NEW: Extra stages implemented - extra stages can be defined in CRS files, or 
-                   random songs are chosen automatically.
-            - NEW: Extra character support in song titles, course titles, and artist names
-                   now possible with new tags to DWI format.
-            - NEW: Various drop-shadow colours can be defined in the skin-configuration file.
-            - NEW: "Flash" added for "OK" on freeze-arrows.
-            - NEW: DWI now uses version 1.7 of the BASS sound library.
-            - NEW: "/dark" added for Developer mode.
-            - NEW: "+" modifier added to "#SAMPLESTART:" tag - the GAP value is used as a 
-                   reference.
-            - Autoplay now possible in Nonstop mode.
-            - Centre positions for combo and judgement displays adjusted.
-            - movie decoding performance improved slightly.
-            - game starts at a default of 60FPS now.  Adjust with '/fps:xx' command-line.
-            - selecting difficulty on song-select screen requires discrete button presses, so
-              it won't cycle accidentally.
-            - BUGFIX: 'empty' space below song-names on Course selection screen corrected.
-            - BUGFIX: Various graphical glitches corrected.
-            - BUGFIX: 'negative percentages' in Nonstop mode fixed.
-            - BUGFIX: 'broken freeze arrows' glitch fixed.
-            - VARIOUS: various other tweaks and fixes that I can't remember. ;)
-
-v2.03.00 - September 12, 2002.
-            - NEW: 'Global GAP' adjustment added to System Options (affects all files)
-            - NEW: Ability to reset 'Player's Best" list added to Options.
-            - NEW: Rebuilding songlist also creates 'dwi2-songlist.html', for easier reference.
-            - colour for random songs in Nonstop mode brightened.
-            - switching from a song with CHALLENGE steps to one without that set reverts to HEAVY, not LIGHT.
-            - small graphical bug with freeze arrows ending cleaned up.
-            - freeze arrow graphics updated for up-left/up-right.
-            - new Nonstop course banner to replace the old ugly one. ;) (thanks, Cave)
-            - more Q/A added to FAQ.html
-            - BUGFIX: Scoring precision improved to make 'AAA'd songs add up correctly.
-            - BUGFIX: extra 'ticks' being played with "Little" mode on.
-            - BUGFIX: 'invisible' steps being played when Autoplay was on in "Little" mode.
-            - BUGFIX: jumping to a specific spot with different speeds in Developer mode corrected.
-            - BUGFIX: starting a song with "Start" in SDL mode won't automatically take you to Options screen.
-            - BUGFIX: arrows loaded correctly when switching skins again.
-
-v2.02.00 - August 16, 2002.
-            - NEW: Freeze arrows with normal steps at same time have both arrows in 
-                   freeze-colour.
-            - NEW: Up-left and up-right arrows in Solo mode redone to match other arrows.
-            - NEW: SOLO arrow set available in Options.
-            - NEW: Rebuilding Songlist now provides information on status 
-                   instead of appearing to 'freeze'.
-            - Numeric Keypad's 'ENTER' key now re-enabled.
-            - BUGFIX: Grading system fixed ('points' value correctly calculated now).
-            - BUGFIX: Problem with 'skipped' steps not registering in Nonstop mode fixed.
-            - BUGFIX: ESCAPE handled better under new keyboard method.
-            - BUGFIX: Can now exit developer mode properly.
-            - BUGFIX: problem with REVERSE and HIDDEN in CRS files fixed.
-            - BUGFIX: locking up in some DWIs with animated backgrounds fixed.
-            - BUGFIX: jumps treated correctly again.
-
-v2.01.10 - August 12, 2002.
-            - '/showsm' will show SMANIAC-only songs on the select screen, otherwise they're hidden
-            - All keys now read using DirectInput (or SDL) instead of using old Windows interfaces.  So 
-              problems with Escape and F1..F12 should be fixed now.
-            - BUGFIX: doubling of time in Nonstop Versus mode fixed
-            - BUGFIX: lives added properly now in Nonstop Doubles and Solo modes.
-            - BUGFIX: after rebuilding songlist, starting in Single mode should behave now.
-
-v2.01.00 - August 11, 2002.
-            - NEW: Press up-left ("sort") button on Results screen to switch to percentage-display
-            - NEW: Credits screen finally added.  Thanks to all who have helped. :)
-            - NEW: Support for more than two panels at a time in a jump.  (DWI specification tweaked slightly)
-            - NEW: '/v5hack' command-line argument for some strange Voodoo card drivers.  Might
-                   fix problems on Voodoo cards if you can't get it working right.
-            - NEW: Ability to specify number of lives added after each stage in Nonstop mode.  Also changed
-                   default behavior to give back lives in relation to difficulty of song just played.
-            - Groove radar values calculated better; now Chaos gives a better value, and all values are in 
-              relation to the length of the song now (so extended-length songs don't give too-large values).
-            - Songs with only SMANIAC steps are now selectable in regular song-select screen.
-            - If current difficulty selected is 'bumped' when moving to a song that doesn't have that set of 
-              steps, it'll go back to that setting when the next song that does is selected.
-            - Wrapping of song-titles tweaked to wrap on " -", not just "-".
-            - Power bar 'sliding' behavior tweaked.
-            - In Options Menu, currently-selected item is remembered when returning from sub-menus.
-            - Maximum number of songs allowed upped to 2048.
-            - BUGFIX: going to course-select screen after rebuilding songlist should work correctly now.
-            - BUGFIX: starting a song with 'start' on a gamepad won't take you to the options screen unless
-                      you hold it now.
-            - BUGFIX: 'beat' counter behavior fixed for when a BPM-pause/freeze occurs.
-            - BUGFIX: animations should behave now when speed is altered.
-
-v2.00.52 - I released the DirectInput implementation too soon, sorry.  This should solve the
-           issues with DX mode in some operating systems, and SDL mode.
-
-v2.00.5 - August 2, 2002.
-          - I now have WindowsXP... yay... so now I can test DWI in it...
-          - 'white flashes' during video playback fixed.
-          - grading system (rounding) bug fixed... (I think...).
-          - keyboard input now uses DirectInput for most things, instead of Windows functions - 
-            should hopefully be faster and avoid some lag problems some have been experiencing.
-          - second set of keyboard inputs can be configured now.
-          - can't change sort method after choosing "ROULETTE" anymore.
-
-v2.00.3 - July 25, 2002.
-          - fixes a number of graphical problems related to songs with positive GAP values.
-          - groove radar calculations now a bit more tolerant of mistakes in files.
-          - .75x and .5x modifiers corrected in Options screen.
-          - Stealth now selectable through both methods.
-          - New freeze arrow 'flash' animation as earlier version was getting mixed reviews. ;)
-          - fixed Roulette when "Sort by Genre" is used.
-          - Difficulty tweaked slightly.
-          - Failure of stage behaves properly again.
-
-          - IMPORTANT - I meant to do this with the first release of 2.00, but forgot -
-            DWI2's configuration is stored in 'dwi2.cfg', 'dwi2.sng', 'dwi2.rec', etc.
-            IF YOU HAVE BEEN RUNNING v2.00, PLEASE RENAME 'dance.*' 'dwi2.*'.
-            Sorry for the inconvenience.
-
-v2.00.0 - July 22, 2002.
-          - Completely overhauled DWI's interface.  The 'brushed metal' look is out in favor
-            of a new, more colourful design
-          - New, more readable and stylish font
-          - optional timer on gameplay screens to hurry things up
-          - hold 'START' when selecting a song to open up a new 'select options' screen
-            ('SELECT' will still let you change options as before also).
-          - DWI2 has removed old interfaces that I feel are outdated and in the process makes 
-            it much easier to update.  At the same time, the base skin has been updated 
-            considerably. (NB: old skins will not be recognized, sorry...)
-          - Nonstop Mode now keeps track of time, percent, etc.
-          - MAX2 scoring and grading system
-          - Smooth animations for judgements, combo display
-          - New animation for song start/end
-          - Groove Radar implemented (values calculated when Songlist is rebuilt)
-          - Roulette added to song-select screen
-          - 5th/MAX-style power bars and gameplay interfaces, freeze arrows, etc.
-          - completely redone evaluation screen
-          - usernames taken out - they were a pain to put in anyway
-          - Song banners now used on song-select screen if available.  Can be horizontal or
-            old diagonal-style (backgrounds used as before if no banner found)
-          - Records screen now keeps track of Nonstop records too
-          - new option '/fps:xx' lets you set a maximum framerate (20..100); saves processor 
-            time for other applications if you've got a fast machine
-          - multiple bugs fixed.
-
-SPECIAL NOTE: DWI 2.0's skins require a file called 'dwi2-skin.cfg' to work.  This is done
-              to avoid accidentally choosing an old skin.
-              The Sounds folder is very similar, but with new samples for some things.  Users
-              upgrading from 1.7 and lower should run 'convert.bat', which does the following:
-                 1) copy all files from \eval\S to \eval\SS
-                 2) rename \eval\SS \eval\AA
-                 3) rename \eval\SSS \eval\AAA
-                 4) remove \eval\S
-                 5) move all files from \select\song to \start\ready
-                 6) remove \select\song.  (You can also delete \select\new)
-
-v1.70.0 - June 17, 2002.
-          - New method for creating Nonstop Mode courses - introduction of "CRS" file format.
-            This should allow for easier creation of Nonstop Mode courses.  See below for details.
-          - Removed all old Nonstop-mode sections.
-          - New Nonstop Course selection screen.  Banners can be given to a course.  Also allows for 
-            playing defined courses in different modes.
-          - Two people can play Nonstop mode courses at the same time.
-          - Better record keeping for Nonstop mode courses.
-          - Style Select Screen modified.  SOLO mode is now selected by pressing up/down there.
-          - New "Failed" sequence - arrows stop and fade out now instead of still scrolling.
-          - Freeze arrow behavior tweaked.
-          - Combo system can be chosen in Options Screen.
-          - New command line argument "/sdevice:x" can tell DWI what sound device to use.
-            (view dance.log to see a listing of available devices first).
-
-v1.65.5 - June 7, 2002.
-          - Added sound effect for when you lose a life in Nonstop "Combo" mode.
-          - Updated freeze arrows to behave more like MAX.
-          - Freeze-arrows don't do as much damage as they used to. ;)
-          - MAX-like combo system.
-
-v1.65.0 - May 26, 2002.
-          - Added random background animations.  Put looping AVIs into ./Movies/Random
-            and DWI will use them automatically in the backgrounds for songs with 
-            no background script.
-          - Random animations can be enabled/disabled in the System Options.
-          - Addition of four new tags to DWI files:
-             #RANDSEED:x;     - provide a number that will influence what AVIs DWI picks.
-                                Will be the same animation each time if AVI filenames and count
-                                doesn't change (default is random each time).
-             #RANDSTART:x;    - tells DWI what beat to start the animations on.  Default is 32.
-             #RANDFOLDER:...; - tells DWI to look in another folder when choosing AVIs, 
-                                allowing 'themed' folders.
-             #RANDLIST:...;   - a list of comma-separated filenames to use in the folder.
-
-          - Ability to tweak timings for judging Perfect, Great, etc. steps in System Options.
-          - New "Select Style" interface added (default now for "DWI (Second Interface)" skin).
-            Use "SelectStyle=2" under "[GENERAL]" in the 'dwi-skin.cfg' file to enable.
-          - Crowd cheers or moans during gameplay based on performance.
-          - Music loop added to "Select Style" screens.
-          - Routine for displaying background animations put into separate thread now.
-          - New command-line argument: '/priority:x' can force DWI to run as a more "important"
-            program under Windows.  "1" starts it as "ABOVE NORMAL", "2" is "TIME CRITICAL".  May
-            improve performance in certain cases.
-          - BUGFIX: Selecting an SMANIAC song after a previous one in 1st Interface fixed.
-          - Other various bugfixes that I can't remember. ;)
-
-v1.62.3 - May 6, 2002.
-          - Minor bug fixes.  Main change is a tweak to the /test: command line arguments to 
-            accommodate folders on other drives to faciliate step-file creator authors.
-
-v1.62.2 - April 18, 2002.
-          - Speed of song can now be set to faster than normal play using F3/F4 during gameplay or 
-            at song select screen (1..5..9).
-          - bug fix: BPM shift won't reset background animation.
-          - bug fix: GAP adjustment should behave better now.
-          - More developer functions added:
-              /startat:

- -

9. FUTURE DEVELOPMENT AND THANKS

- -

A long time was spent making this program, and I believe that this first release is fairly complete in terms of features. New features will be considered as resources and interest permit.

- -

Special thanks go to DjDraftHorse for the announcer files - I think he did a fantastic job, very professional. Also he has been a great beta-tester and a sounding board for new ideas. Much appreciated!

- -

Also, a huge 'thank you' to BemaniRuler for beta-testing the program and your enthusiasm for the project. He's been a great help in creating the new interfaces and I appreciate him letting me incorporate some of his graphics from his earlier skins in the release of DWI 2.0.

- -

Thanks also to Durikkan for his help in implementing the Groove Radar - the values used are based off of his algorithm.

- -

BBW, for putting up with my incessant programming of the simulator and my exhorting of the joys of Bemani. ;)

- -

LagGed and the others at "The Melting Pot" for the resources available there concerning the file formats and other simulators, and his offer to host the distribution files. uKER for taking it upon himself to write some better code for song-management which I was able to implement into the main DWI code. YrevaTeneb for his writeup on how to create DWI files at the Melting Pot, and for permission to list it here. Also a special thanks to Apocalypse for his insight in getting DirectX working.

- -

Pawwaves to those in the furry community. :^)

- -

Enjoy...
-SimWolf.

+

DANCE WITH INTENSITY v2.50.00
+© SimWolf, 2003

+ +
    +
  1. DISCLAIMER AND TERMS OF USE +
  2. WHAT'S NEW? +
  3. USING AND CONFIGURING DWI
     
      +
    • Basic Operation +
    • Song Sorting +
    • Selecting Song Modifiers +
    • Special keys +
    • Controller Configuration +
    • Gameplay Settings +
    • Sound Configuration +
    • Changing the Display from Windowed to Full-screen +
    • Sound effects +
    • Command-line options +
    • Testing a song +
    • Setting Skins +
    • Setting Announcer and Sound Effects +
    • Folder- and Genre- Specific Banners +
    • AVI Movie Support +
    • Sonique Visualizations (SVP) Support +
    • User Profiles +
      +
  4. DWI FILE FORMAT
       +
  5. NONSTOP MODE AND CRS FILE FORMAT +
  6. LRC (LYRICS) FILE FORMAT +
  7. LIMITATIONS +
  8. VERSION HISTORY +
  9. FUTURE DEVELOPMENT AND THANKS +
+ +

1. DISCLAIMER AND TERMS OF USE

+ +

This program is provided for free, as-is. Although it has been tested on multiple systems for compatability and reliability, you run this program at your own risk. I cannot be held responsible if the program causes file loss or other problems.

+ +

THIS PROGRAM IS *NOT* FOR SALE!!! IT SHOULD NEVER BE BUNDLED WITH ANY OTHER FILES (MUSIC OR STEP FILES) ON ANY MEDIA, INCLUDING (BUT NOT LIMITED TO) CD's, DVD's, DISKS OR OTHER MEDIA.

+ +

DWI is Donation-Ware. Although you are not required to donate, it would be greatly appreciated if you enjoy the program that you contribute something towards the developers.

+ +

This program simulates a popular arcade and home video game. It was written to allow myself the ability to play songs from the games without having to switch CDs in my Playstation or Dreamcast, and also affords the ability to add new songs not currently available. It also allows for playing older songs with new play modes, such as downward-scrolling arrows. This program is being released to the public in the hopes that others would find it useful in the same manner.

+ +

As such, this program REQUIRES responsibility on the part of the end-user (ie. YOU) to use the program LEGALLY. You should *ONLY* play songs where you:

+ + + + + +
a)  Own the game from which that music comes from.
or b)  Own the soundtrack CD from which the music comes from.
or c)  Legally own rights to the music being used (ie. other CDs, etc.)
+

+ +

I own all the available soundtracks and videogames for the music I own, and respectfully ask that you support the games and purchase them. Thank you.

+ +

2. WHAT'S NEW?

+ +
+v2.50.00 - August 14, 2003.
+            - NEW: Addition of WAVE, BRAKE, and 0.25x modifiers.
+            - BUGFIX: Stage numbers and various other numbers are coloured again.
+				- BUGFIX: Bonus stages now default to Heavy/Maniac again.
+            - OTHER: Various other bugs I can't remember that have been fixed.
+				
+
+

+ +

3. USING AND CONFIGURING DWI

+ +

BASIC OPERATION

+ +

When you first run DWI, you will receive a warning screen about responsible use of the program. This warning screen will appear *EVERY* time the program detects new songs.

+ +

DWI uses step-files with the extension ".DWI". These files go in their own folder along with their associated background and banner images. Optionally the music file can go in the same folder also.

+ +

DWI supports multiple collections of songs, so you can organise your songs as you see fit. To do this, just create different sub-directories in the "Songs" folder.

+ +

eg. For a song with a step-file of "abc.dwi", put into a collection called "My Songs", your directory structure should look like this:

+     <INSTALL directory>
+        + Songs
+           + My Songs
+              + abc
+                 + abc-banner.png   (any name, the program will detect that it's a banner)
+                 + abc-bg.png       (any name, the program will detect that it's a background)
+                 + abc.dwi          (any name)
+                 + (abc.mp3/wav)    (optional - otherwise FILE: tag is used).
+                 + (abc.lrc)        (optional - should have same base as DWI file).
+
+

+ +

So, in each "song folder", there should be two image files (background and banner), the DWI file, and optionally the music file in MP3 or WAV format.

+ +

Song Sorting

+ +

When you are at the song select screen, simply press up or down to change the current collection you are in. Songs are organized alphabetically within each collection, and collections are organized alphabetically also.

+ +

Another option is to sort your music by genre. To activate this, go to "Options Menu", then "System Menu", and change the sort method to "GENRE" *. This requires your DWI files to have a tag defining the genre to put the music into (see DWI format, below). Multiple genres can be given (separated by a comma), to make the same song appear in different collections. At the song select screen, press up or down to change the genre.

+ +

You can also press Up-Left to change the sort method. This cycles through:

    +
  • Folder/Genre (default) +
  • Folder/Genre, Separated +
  • All Music (by title) +
  • All Music (by artist) +
  • BPM. +
  • Player's Best (top 64) +

+ +

Selecting Song Modifiers

+ +

At the song-select screen, press the "Select" button/key, and use the arrows to change options. When done, press "Select" again. Alternatively, you can hold down "Start" when selecting a song and you will be taken to a +screen where you can set your options.

+ +

+ + + + + + + + + +
Speed: 1.5x, 2.0x, 3.0x, 4.0x, 5.0x, 8.0x, 0.5x, 0.75x, 0.25x
Boost: BOOST, BRAKE, WAVE
Appear: HIDDEN, SUDDEN, STEALTH
Turn: LEFT, MIRROR, RIGHT, SHUFFLE
Other: LITTLE, FLAT, SOLO
Dark: DARK (can't see arrow indicators)
Scroll: REVERSE
Freeze: NOFREEZE
Power: POWER-DROP (gauge starts full and depletes), DEATH (must full-combo song)

+ +

For courses and bonus stages, use the same text as above in the course definition file when setting modifiers.
+eg. #SONG:Default\MySong:BASIC:1.5x,HIDDEN,LEFT,FLAT;

+ + +

Special keys

+ +

The function keys will be used to adjust or enable various gameplay functions. Primarily these are designed for people creating DWI files and want to adjust timing.

+ +

+ + + + + + +
F1/F2 - Restarts the song (developer mode only)
F3/F4 - Adjust playback speed of song down/up (during song select/gameplay)
F5/F6 - Adjust BPM value down/up by 0.50 BPM. (during gameplay)
F7/F8 - Adjust BPM value down/up by 0.02 BPM. (during gameplay)
F9/F10 - Adjust GAP value down/up by 5ms. (during gameplay)
F12 - Toggle "Assist Click" on/off. (during song select/gameplay)

+ +NB: Enable autoplay in the main options menu to prevent song from failing while fine-tuning. (Or set "GAME OVER" to "End of Song"... or just use developer mode). + +

Controller Configuration

+ +

To change the inputs, simply go to the Options Menu from the main screen and goto "Keyboard Configuration" or "Gamepad Configuration". Choose to configure either Player 1 or Player 2's inputs and you will be prompted to press each key, joystick button or dancepad square in turn. You cannot choose an input that is currently in use. To skip joystick buttons, press the "TAB" key.

+ +

When done, select "Return" to make the change take effect.

+ +

Gameplay Settings

+ +

Gameplay settings such as difficulty level, danger display, and end-of-game settings are selected from the Gameplay Configuration menu from the Options screen. These changes take effect immediately.

+ +

Extra Stages

+ +

If you AA a Heavy or Challenge mode song on the last stage and have Extra Stages enabled in the Game Options, you can play another song. The song(s) you can choose from are either generated randomly (3 for Extra Stage #1, one for Extra Stage #2), or can be defined in a CRS file.

+ +

+ + +
bonus-1.crs   Songs for Extra Stage #1
bonus-2.crs   Songs for Extra Stage #2

+ +

NB: These CRS files go in the same directory as DWI2.exe, not the Courses folder.

+ +

Sound Configuration

+ +

The default sound settings for DWI are 44Khz, Stereo, 16-bit samples. However, you may want to lower these +settings on slower computers.

+ +* NB: You must exit DWI and start it again for this change to take effect. + +

Changing the Display from Windowed to Full-screen

+

Go to the "System Menu" from the Options screen and change the display type.

+ +* NB: You must exit DWI and start it again for this change to take effect. + +

Sound effects

+ +

Sound effects are all in the "Sounds" directory. You can add or remove files to most directories, and the program will use the existing files during gameplay. However, files in the root of the sound-set directory and those in the "attract" and "combo" directories must be the same name in order for the program to find them and play them appropriately.

+ +

Command-line options

+ +

You can run DWI with various command line options to configure some values. (Please read the FAQ for details +on how to start the program with command line options). These options are available:

+ +

+ + + + + + + + + + + + + + + +
/sdl   Starts DWI in the software-only graphics mode.
/16bpp   Runs DWI in 16-bit colour mode (SDL), or uses a 16-bit primary surface (DirectX)
/32bpp   Runs DWI in 32-bit colour modes/32-bit primary surface.
/fullscreen   Runs DWI in fullscreen mode (may need to use to start on some cards)
/window   Runs DWI in a window. Some cards won't support this so DWI will try fullscreen.
/log   Creates a 'dance.log' file that can be useful for debugging.
/anysize   In DirectX mode, this tries to make textures in any size, rather than creating textures to the nearest power-of-two value (ie. a 75x60 image is loaded into a texture that big instead of a 128x64 one). This can speed up performance on some cards and save memory, if your card can handle it.
/sw   In SDL mode, surfaces are created in regular memory (default)
/hw   In SDL mode, surfaces are created in hardware memory (can improve performance if your card can handle it).
/priority:x   can force DWI to run as a more "important" program under Windows. "1" starts it as "ABOVE NORMAL", "2" is "TIME CRITICAL". May improve performance in certain cases. (Use with caution if you're running many other processes at the same time).
/sdevice:x   tells DWI to use a given sound-device. Use "/log" and look in dance.log first for a list of available sound-devices.
/fps:xx   makes DWI try to stay at a given framerate (20..100). If you've got a fast machine, this can really save on computer cycles.
/showsm   will add songs with only SMANIAC steps to the song-select screen.
/skipsearch   will prevent DWI from searching the Songs folder at startup.
/dither:0   will turn off the dithering effect DWI uses for semi-transparent images on old videocards that can't handle them. Some users may prefer this to remove the 'speckles' in the gameplay graphics.

+ +

You can limit paging to virtual memory during gameplay (which can cause skips as Windows decides to write or retrieve data from disk) using these flags:

+ +

+ + +
/minRAM:xx   Instructs DWI to try to reserve at least this much physical memory from the Operating System. *
/maxRAM:xx   Instructs DWI to try to reserve at most this much physical memory from the Operating System. *
 
* Only works in Windows NT, 2000, and XP. Default is 16-32MB.

+ +

Use these flags to fix strange behavior in DWI...

+ +

+ + + + + + + + + + + + + +
/key:nonexclusive   affect how DirectInput is initialized. Should be paired with one of /key:fg or /key:bg
/key:exclusive  
/key:fg   affect how DirectInput is intialized.
/key:bg  
/altcombo   for reasons known to the heavens and my machine in the basement, DWI would not display the 'lives' image in Nonstop Mode, instead locking up the computer. I'm convinced this is a videocard/driver issue, as the code to draw the image is exactly the same as the code to display any other image... but oh well. Using this command line argument will tell DWI to not try to display the image and instead write "X Lives" in its place, which seemed to make it work. Strange... but the option's there in case you run into the problem too.
/v5hack   some Voodoo card drivers seem to allocate space for textures incorrectly (off by one) - this should hopefully fix the problem.
/altmovie   Uses an alternate way of drawing the background movies and visualizations for older videocards that display solid-colour textures instead.
/noshade   Prevents the extra shading effect on the song-select wheel from being added.

+ +

Testing a song

+ +

+ + + + + + + + + +
/test:...   You can start DWI in test/developer mode by using the "/test:..." command line argument. Provide the *folder* the .dwi file is in.
/style:...   use this set of steps (SINGLE, DOUBLE, SOLO). Default is SINGLE.
/level:...   use this level of steps (BASIC, ANOTHER, MANIAC, SMANIAC). Default is BASIC.
/p2   test using player 2's controls instead.
/speed:X   starts song at a given speed (1..5)
/scroll:X   starts song with given speed modifier (0.5, 0.75, 1.5, 2, 3, etc.)
/startat:<TIME>   jumps to a given time into the song (game-time). <TIME> can be given in minutes, seconds, or milliseconds. +
   ie.  /startat:1:05.5  (minutes)
+        /startat:65.5    (seconds)
+        /startat:65500   (ms)      - all the same position.
/tick:1   turns the assist click on at startup (default is off).
/dark   hides the fixed-place arrows during testing.

+ +

Example:

+ +

"DWI.exe /test:.\Songs\Development\MyNewSong /style:SINGLE /level:MANIAC /p2 /speed:4 /scroll:2 /startat:1:00"

+ +

Starts testing the .dwi file found in \songs\development\mynewsong, in SINGLE mode, with MANIAC-level steps. Player 2's controls are used, and the song's speed is set to '4'. Arrows are displayed as though the "x2" modifier was active. The song starts at the 1-minute mark.

+ +

Setting Skins

+ +

Create different sub-directories within the "Skins" folder for each skin you wish to use. So, for example: +

+     <INSTALL directory>
+        + Skins
+            + Default  (leave as-is)
+            + Skin A
+            + Skin B
+            + ...         

+ +

The filenames for each skin should be the same as in the default directory. If an image isn't found, the default is used. This way you can create skins that are relatively simple, or very elaborate ones. And you don't need to delete any of the original files. ;) There is a limit of 64 skins.

+ +

Changes will take effect when you leave the Skin Selection screen.

+ +

I do ask, however, that you keep the title of the program as "Dance With Intensity". Thank you. :)

+ +

Setting Announcer and Sound Effects

+ +

Similar to skins, just create new directories in the 'Sounds' folder for each sound set you wish to use. So, for example: +

+     <INSTALL directory>
+        + Sounds
+            + Default   (leave as-is)
+            + Jack
+            + Jill
+            + ...         

+ +

The tree structure for each set should be the same as is used for the "Default" directory. For example: +

    + Jill
+        + attract    - files should be named attract-00.wav, attract-01.wav, attract-02.wav
+        |              (these are the sounds used on the title screen)
+        + combo      - files should be named combo-00.wav and combo-01.wav
+        |              ("100 Combo" and "Combo stopped")
+        + danger     - a set of files played when power level at danger or zero.
+        + eval
+        |   + A
+        |   + B      - sets of files to play at the evaluation screen based on grade
+        |   + ...   
+        + good       - a set of files played when power level in the 'good' range
+        + great      - "                                           " 'great' range
+        + over
+        |   + fail   - files played at game over screen (failure)
+        |   + pass   - "                              " (cleared all stages)
+        + select
+        |   + new    - files played when #STATUS:NEW; is set in DWI file and song is selected
+        |   + song   - files played when a song is selected
+        + start
+        +   + go     - files played at "Here we go!" screen.
+        +   + ready  - files played at "Ready?" screen.
+        + warning    - a set of files played when the power gauge is in the 'warning' range.

+ +

There should not be more than 64 sound effects in a single subdirectory. There is a limit of 64 sets. Changes will take effect once you leave the Announcer/Sound Select screen. Please keep the title sound effect (attract-00.wav) as "Dance With Intensity".

+ +

Folder- and Genre- Specific Banners

+

You can make DWI display a special banner for each folder when it is highlighted on the Song-Select Screen. To do this, simply put a standard (horizontal) banner with the same name as the folder in the 'Songs' folder. (eg. a banner for 'Default Songs' would be ".\Songs\Default Songs.png").

+ +

If you have sorting by Genre on, you can have special banners for each Genre by putting banners in PNG format with the same name as the Genre referenced into ".\Genres". (eg. "Pop Music.png").

+ +

Folder-Specific Banners can also be made for Courses too. Just put a PNG file with the same name as the subfolder the CRS files are in, in the "Courses" directory.

+ +

AVI Movie Support

+

AVI movies can be played in the background while you play. See the "Background Animation" section below for more details on how this is set up. From the System Menu, you can tell DWI whether to not play AVI files at all, or set the quality level from 1 (worst) to 10 (full). The default is 5. Changing this value could affect your framerate, so play with the values to determine what works best for your system.

+ +

Random animations are picked from the ./Movies/Random folder and played in the background of songs without a defined background script if enabled in the System Options menu. This folder can be changed by a flag in the DWI file also, enabling themes.

+ +

Sonique Visualizations (SVP) Support

+

Sonique visualizations can be played in the background while you play. See the "Background Animation" section below for more details on how this is set up. From the System Menu, you can tell DWI whether to use them at all, or set the quality level from 1 (worst) to 10 (full). The default is 5. Changing this value could affect your framerate, so play with the values to determine what works best for your system.

+ +

Random visualizations are picked from the ./Vis folder and played in the background of songs without a defined background script if enabled in the System Options menu. Their behavior can often be changed by editing the 'vis.ini' file that is created after they are used in DWI, similar to in Sonique.

+ +

User Profiles

+

DWI2.40 introduced 'user profiles' - a way that multiple users can play DWI on the same machine and keep their own individual records. Setting up a new profile is easy - simply create a new subdirectory in the "Profiles" directory with the name of the user (15 characters or less), and inside that folder, put a 64x64 PNG file called 'user.png' to represent you in the game. Look at the 'Profiles/Sample User' folder for an example.

+ +

When you use a profile, DWI will create an individual records file and profile information file in the same directory that keeps track of your individual achievements.

+ +

When you get a high score, it will be saved to your own profile's records ("New Personal Best"), and, if you beat the overall high score, it will also be saved to the system records ("It's a New Record!"), with your username registered with it.

+ +

Using a user-profile also lets you track some other statistics, such as overall high scores and combos for each mode. It will also store the last-used modifiers you used (eg. 2x speed modifier, Reverse) between sessions, so you don't have to set it again each time you start a new game.

+ +

This option can be disabled in the Game Options Menu if you prefer.

+ +4. DWI FILE FORMAT + +

Steps

+ +

DWI uses step-files that are similar to the ".MSD" file format. However, there are new additions and some tags are treated slightly differently, so the extension was changed to avoid confusion. DWI files with these new additions will not work properly in other simulators.

+ +

Step-patterns are defined in the same way as .MSD files - use the numeric keypad as a reference for most patterns: +

+  7=U+L     8=U      9=U+R
+
+  4=L                6=R
+
+  1=D+L     2=D      3=D+R
+
+    (U+D = A and L+R = B)
+

+ +

A '0' indicates no step. Each character defaults to one 1/8 of a beat. Surround a series of characters with the following brackets to change the rate at which the steps come: +

+   (...)  = 1/16 steps
+   [...]  = 1/24 steps
+   {...}  = 1/64 steps
+   `...'  = 1/192 steps

+ +

6-panel (Solo) mode uses additional characters: +

+   -\---- = C
+   ----/- = D
+
+   L\---- = E
+   -\D--- = F
+   -\-U-- = G
+   -\---R = H
+
+   L---/- = I
+   --D-/- = J
+   ---U/- = K
+   ----/R = L
+
+   -\--/- = M

+ +

To do more than 2 panels at a time, you can join codes together with the "<..>" object, and they will all count as the same beat. So, to do a jump that involves Left, Right, Up-Left, and Up-Right, you could do: +

+   -\--/- = M
+   L----R = B
+   ======
+   L\--/R = <MB>  (or <LE>, <IH>, <46M>, etc.)

+ +

MSD files from other simulators will work with DWI, with a change in the 'GAP' value being the only change usually necessary. DWI calculates the 'GAP' value differently than other simulators that use the MSD format.

+ +

DWI does not support the BMS file format. There is a utility available that can convert any BMS file into DWI format. Each song only requires one DWI file for all of its steps, so if you are converting BMS files please remember that all the different difficulties of step patterns will be contained in the same DWI file.

+ +

Hold Arrows

+ +

In the DWI file format a hold arrow is signified with the ! symbol. The string 8!8 will begin an 'up' hold arrow, and the arrow will be released the next time the program encounters an 'up' arrow: by itself or combined with another arrow (7, 8, 9, A, etc.) The characters 7!4 would show both 'up' and 'left' arrows but only the left arrow would be held. The format could best be described as "show!hold".

+ +

Tags

+ +

These tags should be in every DWI file:

+ +

+ + + + +
#TITLE:...;   title of the song.
#ARTIST:...;   artist of the song.
#GAP:...;   number of milliseconds that pass before the program starts counting beats. Used to sync the steps to the music.
#BPM:...;   BPM of the music

+ +

Additionally, the following tags can be given:

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#DISPLAYTITLE:...;   provides an alternate version of the song name that can also include special characters.
#DISPLAYARTIST:...;  provides an alternate version of the artist name that can also include special characters.
+  
+ Special Characters are denoted by giving filenames in curly-brackets.
+ eg. #DISPLAYTITLE:The {kanji.png} Song;
+  
+ The extra character files should be 50 pixels high and be black-and-white. The baseline for the font should be 34 pixels from the top.
+  
#DISPLAYBPM:...;tells DWI to display the BPM on the song select screen in a user-defined way.  Options can be:
+
+*    - BPM cycles randomly
+a    - BPM stays set at 'a' value (no cycling)
+a..b - BPM cycles between 'a' and 'b' values +
#FILE:...;   path to the music file to play (eg. /music/mysongs/abc.mp3 )
+ (NB: if the file is not found, a .wav or .mp3 file in the same folder as the DWI file is used)
#MD5:...;   an MD5 string for the music file. Helps ensure that same music file is used on all systems.
#FREEZE:...;   a value of the format "BBB=sss". Indicates that at 'beat' "BBB", the motion of the arrows should stop for "sss" milliseconds. Turn on beat-display in the System menu to help determine what values to use. Multiple freezes can be given by separating them with commas.
#CHANGEBPM:...;   a value of the format "BBB=nnn". Indicates that at 'beat' "BBB", the speed of the arrows will change to reflect a new BPM of "nnn". Multiple BPM changes can be given by separating them with commas.
#STATUS:...;   can be "NEW" or "NORMAL". Changes the display of songs on the song-select screen.
#GENRE:...;   a genre to assign to the song if "sort by Genre" is selected in the System Options. Multiple Genres can be given by separating them with commas.
#CDTITLE:...;   points to a small graphic file (64x40) that will display in the song selection screen in the bottom right of the background, showing which CD the song is from. The colour of the pixel in the upper-left will be made transparent.
#SAMPLESTART:...;   the time in the music file that the preview music should start at the song-select screen. Can be given in Milliseconds (eg. 5230), Seconds (eg. 5.23), or minutes (eg. 0:05.23). Prefix the number with a "+" to factor in the GAP value.
#SAMPLELENGTH:...;   how long to play the preview music for at the song-select screen. Can be in milliseconds, seconds, or minutes.
#RANDSEED:x;   provide a number that will influence what AVIs DWI picks and their order. Will be the same animation each time if AVI filenames and count doesn't change (default is random each time).
#RANDSTART:x;   tells DWI what beat to start the animations on. Default is 32.
#RANDFOLDER:...;   tells DWI to look in another folder when choosing AVIs, allowing 'themed' folders.
#RANDLIST:...;   a list of comma-separated filenames to use in the folder.
+

+ +

Each pattern of steps for different modes have the same basic format: +

#SINGLE:BASIC:X:...;
+ ^      ^     ^ ^
+ |      |     | + step patterns.  In doubles, the left pad's steps are given first, 
+ |      |     |   then the right pad's, separated by a colon (:).
+ |      |     |
+ |      |     + difficulty rating.  Should be 1 or higher.
+ |      |
+ |      + Difficulty.  Can be one of "BASIC", "ANOTHER", "MANIAC", or "SMANIAC"
+ |
+ + Style.  Can be one of "SINGLE", "DOUBLE", "COUPLE", or "SOLO".  "COUPLE" is 
+   Battle-mode steps.

+ +

Comments can be used by using "//". Everything after this on the same line in the file will be ignored.

+ +

Background Animations, Movies, and Visualizations

+ +

DWI allows for background animations using a special script within the step-file. A script consists of static images, animated images, and/or an AVI movie. Using the script, you can create a variety of layered effects. A sample animation is described below: +

+   #BACKGROUND:
+
+     M:MOVIE:.\movies\sfx.avi STARTAT:-1.0 LAYER:0;
+     V:VIS:.\Vis\somevis.svp LAYER:0;
+     E:FILE:.\anim\equalizer.png ANIMATE:10,33 POSITION:-33,0 SPACING:40,40 LAYER:1;
+     D:FILE:.\anim\dancer-m1.png ANIMATE:24,66 SIZE:2 MULT:0,0.5,1 SPACING:30,30 LAYER:1;
+     X:LAYER:1 OFF;
+
+     SCRIPT:M.......................
+            ................E...............
+            D...............X,V...............E...............D...............
+            X,M...............E...............D...............X,V...............
+            E...............D...............X,M...............E...............
+            D...............X,V...............E...............D...............
+            X,M...............E...............D...............X;
+
+   #END;

+ +

The first part of the "BACKGROUND" definition defines the effects. Each effect is attributed to a letter or number ("a-z", "A-Z", "1-9"). The format for defining an effect is:

+ +

+ + + + + + + + + + + + + + + + + + +
The first four tags cannot be used together...
FILE:   path to a file. Either a still image, or an animation (multiple frames of animation are stacked *vertically* in the image).
MOVIE:   path to a standard Windows AVI file. Note that the movie won't play unless you have the right codecs installed in Windows. Movies are currently stretched to fill the whole screen.
VIS:   path to a Sonique Visualization plug-in (SVP). Visualizations are currently stretched to fill the whole screen and are always put on Layer 0, and no other commands will affect it.
OFF   turns off a layer, effectively making it invisible. Will not turn off layer 0.
 
LAYER:l   the layer to use (required): +
    0 - base layer.  
+        (Image/Movie is always tiled and SPACING is ignored).
+    1 - overlay layer
+    2 - overlay layer
+    3 - overlay layer
 
STARTAT:t   number of seconds into the AVI file to start at. If negative, the movie will wait that many seconds before playing. Can be decimal (eg. 1.3 = 1300ms).
MULT:r,g,b   Red, Green, and Blue pixels in the image/movie are tinted by the given amounts. This way the same image/movie can be used multiple times across DWI files and have different colours.
ANIMATE:f,n1,n2,...nF   indicates that the FILE contains multiple frames of animation. "f" is the number of frames of animation. Each following value is the number of milliseconds each frame of animation is displayed. If not enough time-values are given, the last given value is used. Ignored for MOVIE type.
MOVE:x,y   the image/movie is moved by the given number of pixels every millisecond.
SPACING:x,y   images are always tiled if they don't fill up the screen. This tag allows you to add some spacing between the images by the given number of pixels horizontally and vertically (Layer > 0)
SIZE:s   multiplies the image size by 's' in both directions. Must be a whole number.
KEEPPOS   normally when a new effect is turned on, its position is reset. This tag keeps the layer where it is, useful for keeping images moving smoothly.
KEEPTIME   (MOVIEs only) normally when a movie starts, it starts from the beginning or the time given in the "STARTAT" tag. Adding this tag will keep it playing so when that layer is enabled again, it will have kept going.

+ +

Following the effect definition, comes the actual animation script. This is a sequence of characters in a similar way as the step-patterns are given - each character normally is 1/8 of a beat, though brackets can be used to change the time-values. In this way, background animations can be syched to the steps. It is suggested that the steps for "SINGLE:BASIC" are copied to after the "SCRIPT:" tag, and then the effects be set. In this way one knows that the script will match the same length of the music.

+ +

The animations take effect as that point in the song is reached. Multiple effects can occur at the same time if they are separated with a comma. A period (.) means no new effect should take place at that point. A zero (0) turns off all effects and returns the background to the original graphic.

+ +

More Information

+ +

Please check our website for more information and links to useful resources.

+ +

5. NONSTOP MODE AND CRS FILE FORMAT

+ +

DWI uses special CRS files that should be put in subfolders of the "Courses" directory. Now courses +can be shared with others if they have the same files and directory structure as you.

+ +

CRS files are similar to DWI files in structure. The file defines the basic details about the course, such as its name and which songs should be played. Currently these tags are supported:

+ +

Required tags:

+ +

+ + + + +
#COURSE:...;   the name of the course.
#DISPLAYCOURSE:...;  alternate name of course that can include special characters. Similar to #DISPLAYTITLE and #DISPLAYARTIST in DWI files.
#SONG:...;  

defines a song in the course. This can either be a selection from the Player's Best (or Worst), a Random stage or a predefined stage. The syntax for each is given below: +

    PLAYER'S BEST/WORST STAGE:
+    #SONG:BESTx:[BASIC|ANOTHER|MANAIC|SMANIAC];
+    #SONG:WORSTx:[BASIC|ANOTHER|MANAIC|SMANIAC];
+    - choose a song with the given index 'x'.  So BEST1 is the most popular
+      song, and WORST5 is the 5th least popular song.  If the given 
+      difficulty is not available, DWI will choose the next closest difficulty.
+      Songs that are equally popular will be put in random order.
+
+    RANDOM STAGE:
+    #SONG:*:[a]|[a..b];
+    - choose a random song, with a difficulty rating equal to or between 'a' and 'b'.
+    - if only 'a' is given, 'b' is assumed to be the same as 'a'.
+
+    #SONG:*:[BASIC|ANOTHER|MANIAC|SMANAIC];
+    - choose a random song with a given difficulty level.
+
+    #SONG:folder\*:[a]|[a..b]|[BASIC|ANOTHER|MANIAC|SMANIAC];
+    - choose a random song from a given folder.
+                   
+    DEFINED STAGE:
+    #SONG:<FOLDER>\<SONG TITLE>:<DIFFICULTY>;
+    - will use a song from <FOLDER> with the given title.
+      So to play a song called "My Song", which is in 
+      './Songs/Default/mysong/mysong.dwi', on MANIAC, 
+      you would say:
+
+      #SONG:Default\My Song:MANIAC;

+ +

NB: Either the TITLE or folder the DWI file is in can be used.

+ +

In addition, modifiers can be defined for each song by adding a list of comma-separated values to the end of the #SONG line. These modifiers are the same as listed above, plus +

+     xRANDOM   - where 'x' is the number of random effects to apply.
+                 'x' can be 1 to 7.
+     AWARDx    - where 'x' is the number of lives to award after 
+                 finishing the stage.
+

+

So to play "My Song", Maniac, with 2.0x, Left, Hidden, and with one random effect, use:
+#SONG:Default\My Song:MANIAC:2.0x,LEFT,HIDDEN,1RANDOM;

+ +

Optional tags:

+ +

+ + + + +
#REPEAT:...;   can be "YES" or "NO". If set, starts course over from the beginning after last song.
#COMBO:PERFECT;   during play, the combo counter will only go up if a "PERFECT" is made.
#COMBOMODE:1;   sets how much is added to the combo counter for jumps. Can be 1 or 2.
#LIVES:4;   sets the number of 'lives' given to each player at the start of game play. After each stage is cleared, a given number of lives is added, either by a value specified by the "AWARDx" tag in the CRS file, or using the scale below: +
    Song was 6 feet or less - 1 life.
+    Song was 7 or 8 feet    - 2 lives.
+    Song was 9 feet or more - 3 lives.
+

+ +

At the course selection screen, courses that have songs without steps for the current style (SINGLE, DOUBLE, etc) will be filtered out. Courses are loaded when DWI starts.

+ +

6. LRC (LYRICS) FILE FORMAT

+

DWI can display lyrics during a song if it finds a .LRC file in the same folder as the step-file. The file should have the same file-base as the .DWI file - so, for example, if your DWI file is called "mysong.dwi", the lyrics file should be called "mysong.lrc".

+ +

This file is a simple text-file that tells the program what text to display and when. It can also define the colour the text is displayed in.

+ +

Each line starts with a tag in the format [xxxxxx]. Currently, these tags are supported:

+ +

+ + + + +
[COLOUR]   Sets the colour for the following text. After the tag, a colour value is given in hex (ie. yellow would be 0xFFFF00). Up to 10 colour values can be given, separated by commas.
[offset:xxxx]   Makes timestamps following this tag have their times adjusted by 'xxxx' milliseconds. Use to fine-tune timings for lyrics.
[MM:SS.ss]  

Sets a time. The text following the tag will be shown on the screen after this time has passed, replacing any text that was there before. To clear text, provide just a tag with no text after it.

A line-break can be defined using the pipe "|" symbol.

+

A new colour can be selected from the defined colours by using "{cX}", where "X" is a number from 0 to 9.

+

+ +

Sample LRC file:

+

[0:00.00]aye-aye-aye|aye-aye-aye|aye-aye-aye
+[0:05.30]Where's my samurai?
+[0:07.00]
+[COLOUR]0xffff00
+[0:13.50]I've been searching for a man
+[0:16.00]All across Japan.
+...etc...

+ +

7. LIMITATIONS

+ +

Partly due to the compiler and my own lack of knowledge in some areas, there are a number of limitations +imposed on the program that users should know about:

    +
  • No more than 2048 songs. +
  • No more than 64 sound effects in a single subdirectory of 'soundfx' +

+ +

If the program runs slowly on your machine, try the following:

    +
  • Install the latest DirectX 8.1 drivers. +
  • Update the video drivers for your video card. +
  • Try running the game in fullscreen mode, and/or setting your screen resolution to 16-bit mode. +
  • Lower the sound quality to Mono, 8-bit, and/or 11 or 22Khz. +
  • Lower the quality of background movies if you use them a lot. +
  • Try limiting the framerate (/fps:xx). +

+ +

8. VERSION HISTORY

+ +

v2.49.00 - May 22, 2003.
+            - NEW: Addition of "Player's Best" and "Player's Worst" to CRS file format.
+            - NEW: Expanded functionality of random song selection in CRS files.  You can now
+              choose a random song by difficulty (instead of just foot ratings), and also select a 
+              random song in a particular folder
+            - NEW: Courses are now arranged in subfolders, allowing for different groupings of 
+              courses.  One set could be for nonstop, others for challenge; or you can divide the 
+              courses up by mix or genre, etc.  You can also give each folder its own banner, like
+              in the song select interface.
+                 NOTE: You will have to move your existing courses into subfolders for them to 
+                 be recognized!
+            - NEW: #DISPLAYBPM:[xxx..xxx]|[xxx]|[*]; added, to force a certain display type on 
+              song select screen.
+            - NEW: For users with old videocards that can't display semi-transparent images, you 
+              can now turn off the dithering effect that DWI uses if you like.  Use the 
+              '/dither:0' command line argument.
+            - Tweaks to how #RANDFOLDER:...; behaves, plus program now searches folder DWI file 
+              is in for a "Movies" sub-folder, or AVIs in the same folder first before using the 
+              default /Movies/Random folder.
+            - Tweaks to banner display on Evaluation screen (for when song/course had no banner)
+            - Tweaks to record-display for courses.
+            - Tweak to beat-display in-game and in developers mode, so numbers won't 'jiggle'.
+            - BUGFIX: 'tiled images' on song-select screen (BPM, stage #, difficulty) and during 
+              gameplay on some old videocards has been fixed.  You should probably consider 
+              upgrading to a better card though anyway. ;^)
+            - BUGFIX: Can now have up to 512 courses, instead of 64.  Oops. ;)
+            - BUGFIX: "combo continuing" playing on every step past 9999 combo.  BTW, I hate you. ;)
+            - BUGFIX: Game doesn't crash on entering course-select screen after you've added new 
+              CRS files.
+            - OTHER: Other bugfixes and tweaks that I can't begin to remember. :P
+
+v2.41.00 - February 15, 2003.
+            - CHANGE: Drawing of text made more efficient and slightly more readable, through better 
+              drawing of drop-shadows.
+            - CHANGE: textures for SVP plug-ins to draw to now adjusted to nearest multiple of 2, as I 
+              suspect some assume it's supposed to be like that for efficiency reasons, and otherwise 
+              might cause problems overrunning memory.
+            - BUGFIX: DWI2.log file now created properly again.  (d'oh!!!)
+            - BUGFIX: problem drawing certain images in 32bpp SDL mode fixed (eg. BPM display, star-wipe)
+            - BUGFIX: extra 'N/A" box no longer appears in Solo mode "Select Profile" if started with P1.
+            - BUGFIX: Better freeing of music samples after gameplay, credits, and on song-select screen.
+
+v2.40.00 - February 2, 2003.
+            - NEW: Addition of "User Profiles", a system to keep user-specific records and high 
+              scores similar to the 'name entry' system from DWI1, but with more features.  Individual
+              users can tailor their own icon and (if directories are the same across systems) take 
+              their records with them between machines.  Now tracks personal high scores and overall
+              high scores, all viewable in the Records screen. (Can be disabled in Options menu if you
+              prefer not to use it).
+            - NEW: Arrow set for DWI completely redone to feature true colour-cycling arrows like the
+              arcade.  Also, arrows are drawn in last-to-first order now instead of first-to-last.
+              (NB: Thanks to uKER for the help creating the new arrow set).
+            - NEW: You can pause the game with the "Pause/Break" key.  However, like autoplay, high
+              score will not be saved.
+            - CHANGE: Folder-specific banners treated differently - now DWI looks for a PNG file with 
+              the same name as the sub-folder, in the base "Songs" folder.  Should be easier to 
+              manage the banners all in one folder now.
+            - some freeze arrow behavior tweaked.
+            - shading on song-select wheel made less dark.
+            - more details on LRC file support added to this file.
+            - style icon colours in default skin fixed (they were reversed).
+            - if you pass a song reasonably well, you'll get that cheer as the 'Cleared' text appears.
+            - BUGFIX: strange wrapping in View Records/Nonstop mode for some songs with two lines fixed.
+            - BUGFIX: Song titles and artist names with special characters on Nonstop mode now display
+              correctly
+            - BUGFIX: Timing in Developer mode after adjusting GAP fixed.  Actually tested it this time. ;)
+            - BUGFIX: Realigning the word 'Test' in developer mode.
+            - BUGFIX: /startat in developer mode is more accurrate.
+            - BUGFIX: Bonus CRS files don't 'skip' songs that are next to each other in the songlist.
+            - VARIOUS: other small tweaks I can't remember. ;)
+
+v2.30.01 - January 3, 2003.
+            - AVI and SVP decoding optimized slightly to reduce load on main game function.
+            - flag added to turn off shading on song select wheel, if desired.
+            - BUGFIX: "Game Over" back in on failing in regular mode.  Oops.
+            - BUGFIX: "NEW!" status works.  Expires after 2 weeks now.  May require songlist reset.
+            - BUGFIX: animation thread closes properly between stages.
+            - BUGFIX: steps are judged better again.  Oops x 2.
+
+v2.30.00 - January 1, 2003.
+            - NEW: Implemented Sonique Visualization Plugins (SVP) for background animations.
+            - NEW: Folder- and Genre- specific banners, plus banners for Roulette 
+                   and Title/Artist sort options.
+            - NEW: Sort by difficulty added to Song Select screen.
+            - NEW: Multiple colours on same line of lyrics possible.
+            - NEW: Can adjust the number of stages between breaks in Nonstop Mode.
+            - NEW: Ability to disable Background Scripts.
+            - NEW: Ability to set default sort method.
+            - New 'default' banners and backgrounds.
+            - Banner and Sample Start load time reduced.
+            - Sort by BPM now much faster.
+            - Paths in Background Scripts can now have spaces (use quotes around path).
+            - Addition to Background Script commands to use Visualizations (on Layer 0).
+            - Long song names with special characters now wrap.
+            - Options Screens reorganized to group some things better.
+            - Adjustments to GAP in Development mode handled properly if changed in DWI file.
+            - Ability to change method for drawing movies/etc. to older method (slower, but good
+              for old videocards that just give solid-colour images instead now).
+            - CRS files can take either title or directory now.
+            - Stage number/display now graphical, and colours can be assigned in skin CFG file.
+            - "TAB" can be used in song-titles to force line-wrap.
+            - Font updated to include missing '~' character.
+            - Song select wheel now has some extra shading.
+            - Support for semi-transparant images on older videocards improved by addition of 
+              pattern dithering instead of simply "off" or "on".
+            - BUGFIX: Missing '0's in scores during gameplay.
+            - BUGFIX: Rounding of scores to proper multiples of 10000000 on some processors.
+            - BUGFIX: Early "GOOD" judgement on a freeze arrow + jump combination fixed.
+            - BUGFIX: "New" tag treated properly again.
+            - BUGFIX: Random AVI search assumed any file was an AVI, without checking extension.
+            - BUGFIX: Skin CFG file with Hex values in uppercase read properly now.
+
+v2.20.30 - November 30, 2002.
+            - General performance improvements.
+            - Options left-over from main game removed in demo.
+            - Command-line options added for fine-tuning memory usage (WinNT/2k/XP).
+            - Time displayed in developer mode should be correct now at different speeds.
+            - Can disable lyrics from the Options menu.
+            - BUGFIX: Genre tag correctly parsed again.
+            - BUGFIX: GeForce/Detonator drivers bug fixed.
+            - BUGFIX: Corrections to Lyric file handling (timestamps, no return after last line)
+
+v2.20.10 - November 21, 2002.
+            - Lyrics now displayed in Test mode
+            - Lyrics now enabled for songs with positive GAP values
+            - SMANIAC songs selectable in extra stages even if /showsm not used.
+            - STREAM bar glows on final tally screen if you've AAA'd all songs(!)
+            - backgrounds and banners with upper-case extensions now recognised correctly
+            - in addition to PNG files, JPGs and BMPs can be used as backgrounds.
+            - "OK" flash for Reverse-scrolling arrows added
+            - Songlist.html only written if files added/updated/deleted
+
+v2.20.00 - November 20, 2002.
+            - NEW: "Final Tally" screen added if number of stages not set to "Unlimited".
+            - NEW: Timer added to developer mode.
+            - NEW: Support for lyrics during songs added through use of "LRC" files.
+            - NEW: "/skipsearch" command line argument added.
+            - Ability to reset songlist completely from Options Menu.
+            - BUGFIX: Groove Radar values calculated correctly again.
+            - BUGFIX: "Lost life" sound playing during Arcade mode removed.
+            - BUGFIX: Sample now played when combo jumps from 99..101.
+            - BUGFIX: "Skipped" notes in autoplay fixed.
+            - BUGFIX: Stream bar glows in Evaluation Screen if full combo and combo mode set 
+                      to "ORIGINAL"
+            - BUGFIX: Folders with no files in them handled better when searching for files.
+
+v2.10.00 - November 12, 2002.
+            - NEW: Songlist rebuild is now automatic and time for incremental updates has been
+                   dramatically reduced, as the whole song database does not get rebuilt from 
+                   scratch each time now.  (NB: Special thanks to uKER for his code that 
+                   implements this).
+            - NEW: Extra stages implemented - extra stages can be defined in CRS files, or 
+                   random songs are chosen automatically.
+            - NEW: Extra character support in song titles, course titles, and artist names
+                   now possible with new tags to DWI format.
+            - NEW: Various drop-shadow colours can be defined in the skin-configuration file.
+            - NEW: "Flash" added for "OK" on freeze-arrows.
+            - NEW: DWI now uses version 1.7 of the BASS sound library.
+            - NEW: "/dark" added for Developer mode.
+            - NEW: "+" modifier added to "#SAMPLESTART:" tag - the GAP value is used as a 
+                   reference.
+            - Autoplay now possible in Nonstop mode.
+            - Centre positions for combo and judgement displays adjusted.
+            - movie decoding performance improved slightly.
+            - game starts at a default of 60FPS now.  Adjust with '/fps:xx' command-line.
+            - selecting difficulty on song-select screen requires discrete button presses, so
+              it won't cycle accidentally.
+            - BUGFIX: 'empty' space below song-names on Course selection screen corrected.
+            - BUGFIX: Various graphical glitches corrected.
+            - BUGFIX: 'negative percentages' in Nonstop mode fixed.
+            - BUGFIX: 'broken freeze arrows' glitch fixed.
+            - VARIOUS: various other tweaks and fixes that I can't remember. ;)
+
+v2.03.00 - September 12, 2002.
+            - NEW: 'Global GAP' adjustment added to System Options (affects all files)
+            - NEW: Ability to reset 'Player's Best" list added to Options.
+            - NEW: Rebuilding songlist also creates 'dwi2-songlist.html', for easier reference.
+            - colour for random songs in Nonstop mode brightened.
+            - switching from a song with CHALLENGE steps to one without that set reverts to HEAVY, not LIGHT.
+            - small graphical bug with freeze arrows ending cleaned up.
+            - freeze arrow graphics updated for up-left/up-right.
+            - new Nonstop course banner to replace the old ugly one. ;) (thanks, Cave)
+            - more Q/A added to FAQ.html
+            - BUGFIX: Scoring precision improved to make 'AAA'd songs add up correctly.
+            - BUGFIX: extra 'ticks' being played with "Little" mode on.
+            - BUGFIX: 'invisible' steps being played when Autoplay was on in "Little" mode.
+            - BUGFIX: jumping to a specific spot with different speeds in Developer mode corrected.
+            - BUGFIX: starting a song with "Start" in SDL mode won't automatically take you to Options screen.
+            - BUGFIX: arrows loaded correctly when switching skins again.
+
+v2.02.00 - August 16, 2002.
+            - NEW: Freeze arrows with normal steps at same time have both arrows in 
+                   freeze-colour.
+            - NEW: Up-left and up-right arrows in Solo mode redone to match other arrows.
+            - NEW: SOLO arrow set available in Options.
+            - NEW: Rebuilding Songlist now provides information on status 
+                   instead of appearing to 'freeze'.
+            - Numeric Keypad's 'ENTER' key now re-enabled.
+            - BUGFIX: Grading system fixed ('points' value correctly calculated now).
+            - BUGFIX: Problem with 'skipped' steps not registering in Nonstop mode fixed.
+            - BUGFIX: ESCAPE handled better under new keyboard method.
+            - BUGFIX: Can now exit developer mode properly.
+            - BUGFIX: problem with REVERSE and HIDDEN in CRS files fixed.
+            - BUGFIX: locking up in some DWIs with animated backgrounds fixed.
+            - BUGFIX: jumps treated correctly again.
+
+v2.01.10 - August 12, 2002.
+            - '/showsm' will show SMANIAC-only songs on the select screen, otherwise they're hidden
+            - All keys now read using DirectInput (or SDL) instead of using old Windows interfaces.  So 
+              problems with Escape and F1..F12 should be fixed now.
+            - BUGFIX: doubling of time in Nonstop Versus mode fixed
+            - BUGFIX: lives added properly now in Nonstop Doubles and Solo modes.
+            - BUGFIX: after rebuilding songlist, starting in Single mode should behave now.
+
+v2.01.00 - August 11, 2002.
+            - NEW: Press up-left ("sort") button on Results screen to switch to percentage-display
+            - NEW: Credits screen finally added.  Thanks to all who have helped. :)
+            - NEW: Support for more than two panels at a time in a jump.  (DWI specification tweaked slightly)
+            - NEW: '/v5hack' command-line argument for some strange Voodoo card drivers.  Might
+                   fix problems on Voodoo cards if you can't get it working right.
+            - NEW: Ability to specify number of lives added after each stage in Nonstop mode.  Also changed
+                   default behavior to give back lives in relation to difficulty of song just played.
+            - Groove radar values calculated better; now Chaos gives a better value, and all values are in 
+              relation to the length of the song now (so extended-length songs don't give too-large values).
+            - Songs with only SMANIAC steps are now selectable in regular song-select screen.
+            - If current difficulty selected is 'bumped' when moving to a song that doesn't have that set of 
+              steps, it'll go back to that setting when the next song that does is selected.
+            - Wrapping of song-titles tweaked to wrap on " -", not just "-".
+            - Power bar 'sliding' behavior tweaked.
+            - In Options Menu, currently-selected item is remembered when returning from sub-menus.
+            - Maximum number of songs allowed upped to 2048.
+            - BUGFIX: going to course-select screen after rebuilding songlist should work correctly now.
+            - BUGFIX: starting a song with 'start' on a gamepad won't take you to the options screen unless
+                      you hold it now.
+            - BUGFIX: 'beat' counter behavior fixed for when a BPM-pause/freeze occurs.
+            - BUGFIX: animations should behave now when speed is altered.
+
+v2.00.52 - I released the DirectInput implementation too soon, sorry.  This should solve the
+           issues with DX mode in some operating systems, and SDL mode.
+
+v2.00.5 - August 2, 2002.
+          - I now have WindowsXP... yay... so now I can test DWI in it...
+          - 'white flashes' during video playback fixed.
+          - grading system (rounding) bug fixed... (I think...).
+          - keyboard input now uses DirectInput for most things, instead of Windows functions - 
+            should hopefully be faster and avoid some lag problems some have been experiencing.
+          - second set of keyboard inputs can be configured now.
+          - can't change sort method after choosing "ROULETTE" anymore.
+
+v2.00.3 - July 25, 2002.
+          - fixes a number of graphical problems related to songs with positive GAP values.
+          - groove radar calculations now a bit more tolerant of mistakes in files.
+          - .75x and .5x modifiers corrected in Options screen.
+          - Stealth now selectable through both methods.
+          - New freeze arrow 'flash' animation as earlier version was getting mixed reviews. ;)
+          - fixed Roulette when "Sort by Genre" is used.
+          - Difficulty tweaked slightly.
+          - Failure of stage behaves properly again.
+
+          - IMPORTANT - I meant to do this with the first release of 2.00, but forgot -
+            DWI2's configuration is stored in 'dwi2.cfg', 'dwi2.sng', 'dwi2.rec', etc.
+            IF YOU HAVE BEEN RUNNING v2.00, PLEASE RENAME 'dance.*' 'dwi2.*'.
+            Sorry for the inconvenience.
+
+v2.00.0 - July 22, 2002.
+          - Completely overhauled DWI's interface.  The 'brushed metal' look is out in favor
+            of a new, more colourful design
+          - New, more readable and stylish font
+          - optional timer on gameplay screens to hurry things up
+          - hold 'START' when selecting a song to open up a new 'select options' screen
+            ('SELECT' will still let you change options as before also).
+          - DWI2 has removed old interfaces that I feel are outdated and in the process makes 
+            it much easier to update.  At the same time, the base skin has been updated 
+            considerably. (NB: old skins will not be recognized, sorry...)
+          - Nonstop Mode now keeps track of time, percent, etc.
+          - MAX2 scoring and grading system
+          - Smooth animations for judgements, combo display
+          - New animation for song start/end
+          - Groove Radar implemented (values calculated when Songlist is rebuilt)
+          - Roulette added to song-select screen
+          - 5th/MAX-style power bars and gameplay interfaces, freeze arrows, etc.
+          - completely redone evaluation screen
+          - usernames taken out - they were a pain to put in anyway
+          - Song banners now used on song-select screen if available.  Can be horizontal or
+            old diagonal-style (backgrounds used as before if no banner found)
+          - Records screen now keeps track of Nonstop records too
+          - new option '/fps:xx' lets you set a maximum framerate (20..100); saves processor 
+            time for other applications if you've got a fast machine
+          - multiple bugs fixed.
+
+SPECIAL NOTE: DWI 2.0's skins require a file called 'dwi2-skin.cfg' to work.  This is done
+              to avoid accidentally choosing an old skin.
+              The Sounds folder is very similar, but with new samples for some things.  Users
+              upgrading from 1.7 and lower should run 'convert.bat', which does the following:
+                 1) copy all files from \eval\S to \eval\SS
+                 2) rename \eval\SS \eval\AA
+                 3) rename \eval\SSS \eval\AAA
+                 4) remove \eval\S
+                 5) move all files from \select\song to \start\ready
+                 6) remove \select\song.  (You can also delete \select\new)
+
+v1.70.0 - June 17, 2002.
+          - New method for creating Nonstop Mode courses - introduction of "CRS" file format.
+            This should allow for easier creation of Nonstop Mode courses.  See below for details.
+          - Removed all old Nonstop-mode sections.
+          - New Nonstop Course selection screen.  Banners can be given to a course.  Also allows for 
+            playing defined courses in different modes.
+          - Two people can play Nonstop mode courses at the same time.
+          - Better record keeping for Nonstop mode courses.
+          - Style Select Screen modified.  SOLO mode is now selected by pressing up/down there.
+          - New "Failed" sequence - arrows stop and fade out now instead of still scrolling.
+          - Freeze arrow behavior tweaked.
+          - Combo system can be chosen in Options Screen.
+          - New command line argument "/sdevice:x" can tell DWI what sound device to use.
+            (view dance.log to see a listing of available devices first).
+
+v1.65.5 - June 7, 2002.
+          - Added sound effect for when you lose a life in Nonstop "Combo" mode.
+          - Updated freeze arrows to behave more like MAX.
+          - Freeze-arrows don't do as much damage as they used to. ;)
+          - MAX-like combo system.
+
+v1.65.0 - May 26, 2002.
+          - Added random background animations.  Put looping AVIs into ./Movies/Random
+            and DWI will use them automatically in the backgrounds for songs with 
+            no background script.
+          - Random animations can be enabled/disabled in the System Options.
+          - Addition of four new tags to DWI files:
+             #RANDSEED:x;     - provide a number that will influence what AVIs DWI picks.
+                                Will be the same animation each time if AVI filenames and count
+                                doesn't change (default is random each time).
+             #RANDSTART:x;    - tells DWI what beat to start the animations on.  Default is 32.
+             #RANDFOLDER:...; - tells DWI to look in another folder when choosing AVIs, 
+                                allowing 'themed' folders.
+             #RANDLIST:...;   - a list of comma-separated filenames to use in the folder.
+
+          - Ability to tweak timings for judging Perfect, Great, etc. steps in System Options.
+          - New "Select Style" interface added (default now for "DWI (Second Interface)" skin).
+            Use "SelectStyle=2" under "[GENERAL]" in the 'dwi-skin.cfg' file to enable.
+          - Crowd cheers or moans during gameplay based on performance.
+          - Music loop added to "Select Style" screens.
+          - Routine for displaying background animations put into separate thread now.
+          - New command-line argument: '/priority:x' can force DWI to run as a more "important"
+            program under Windows.  "1" starts it as "ABOVE NORMAL", "2" is "TIME CRITICAL".  May
+            improve performance in certain cases.
+          - BUGFIX: Selecting an SMANIAC song after a previous one in 1st Interface fixed.
+          - Other various bugfixes that I can't remember. ;)
+
+v1.62.3 - May 6, 2002.
+          - Minor bug fixes.  Main change is a tweak to the /test: command line arguments to 
+            accommodate folders on other drives to faciliate step-file creator authors.
+
+v1.62.2 - April 18, 2002.
+          - Speed of song can now be set to faster than normal play using F3/F4 during gameplay or 
+            at song select screen (1..5..9).
+          - bug fix: BPM shift won't reset background animation.
+          - bug fix: GAP adjustment should behave better now.
+          - More developer functions added:
+              /startat:

+ +

9. FUTURE DEVELOPMENT AND THANKS

+ +

A long time was spent making this program, and I believe that this first release is fairly complete in terms of features. New features will be considered as resources and interest permit.

+ +

Special thanks go to DjDraftHorse for the announcer files - I think he did a fantastic job, very professional. Also he has been a great beta-tester and a sounding board for new ideas. Much appreciated!

+ +

Also, a huge 'thank you' to BemaniRuler for beta-testing the program and your enthusiasm for the project. He's been a great help in creating the new interfaces and I appreciate him letting me incorporate some of his graphics from his earlier skins in the release of DWI 2.0.

+ +

Thanks also to Durikkan for his help in implementing the Groove Radar - the values used are based off of his algorithm.

+ +

BBW, for putting up with my incessant programming of the simulator and my exhorting of the joys of Bemani. ;)

+ +

LagGed and the others at "The Melting Pot" for the resources available there concerning the file formats and other simulators, and his offer to host the distribution files. uKER for taking it upon himself to write some better code for song-management which I was able to implement into the main DWI code. YrevaTeneb for his writeup on how to create DWI files at the Melting Pot, and for permission to list it here. Also a special thanks to Apocalypse for his insight in getting DirectX working.

+ +

Pawwaves to those in the furry community. :^)

+ +

Enjoy...
+SimWolf.

diff --git a/Docs/SimfileFormats/KSF/_src.txt b/Docs/legacy/SimfileFormats/KSF/_src.txt similarity index 100% rename from Docs/SimfileFormats/KSF/_src.txt rename to Docs/legacy/SimfileFormats/KSF/_src.txt diff --git a/Docs/SimfileFormats/KSF/ksf-format.txt b/Docs/legacy/SimfileFormats/KSF/ksf-format.txt similarity index 100% rename from Docs/SimfileFormats/KSF/ksf-format.txt rename to Docs/legacy/SimfileFormats/KSF/ksf-format.txt diff --git a/Docs/SimfileFormats/KSF/sample.ksf b/Docs/legacy/SimfileFormats/KSF/sample.ksf similarity index 93% rename from Docs/SimfileFormats/KSF/sample.ksf rename to Docs/legacy/SimfileFormats/KSF/sample.ksf index 907b54f45d..f84ceef269 100644 --- a/Docs/SimfileFormats/KSF/sample.ksf +++ b/Docs/legacy/SimfileFormats/KSF/sample.ksf @@ -1,22 +1,22 @@ -#TITLE:***; -#BPM:150; -#STARTTIME:0; -#PLAYER:SINGLE; -#TICKCOUNT:4; -#INTROFILE:; -#SONGFILE:; -#DISCFILE:; -#TITLEFILE:; -#DIFFICULTY:; -#STEP: -1000000000000 -0100000000000 -0010000000000 -0001000000000 -0000100000000 -0040000000000 -0040000000000 -0040000000000 -0040000000000 -0000000000000 +#TITLE:***; +#BPM:150; +#STARTTIME:0; +#PLAYER:SINGLE; +#TICKCOUNT:4; +#INTROFILE:; +#SONGFILE:; +#DISCFILE:; +#TITLEFILE:; +#DIFFICULTY:; +#STEP: +1000000000000 +0100000000000 +0010000000000 +0001000000000 +0000100000000 +0040000000000 +0040000000000 +0040000000000 +0040000000000 +0000000000000 2222222222222 \ No newline at end of file diff --git a/Docs/SimfileFormats/README b/Docs/legacy/SimfileFormats/README similarity index 98% rename from Docs/SimfileFormats/README rename to Docs/legacy/SimfileFormats/README index cd2bfbade0..27a4214eef 100644 --- a/Docs/SimfileFormats/README +++ b/Docs/legacy/SimfileFormats/README @@ -1,11 +1,11 @@ -This folder contains information on various simfile formats that exist. - -BMS: Be-Music Script, typically used for beatmania files. -DWI: Son of MSD, created for the Dance With Intensity simulator. -KSF: Another son of MSD, created for the Kick it Up simulator, with extensions - added by Direct Move. -SDF: .sm derivative used in Pocket DDR. - -misc.txt describes some formats that don't have directories. -PMS: Like BMS but for pop'n music. +This folder contains information on various simfile formats that exist. + +BMS: Be-Music Script, typically used for beatmania files. +DWI: Son of MSD, created for the Dance With Intensity simulator. +KSF: Another son of MSD, created for the Kick it Up simulator, with extensions + added by Direct Move. +SDF: .sm derivative used in Pocket DDR. + +misc.txt describes some formats that don't have directories. +PMS: Like BMS but for pop'n music. Dance: pydance format; see dance-spec.txt for more information. \ No newline at end of file diff --git a/Docs/SimfileFormats/SDF/SDF.txt b/Docs/legacy/SimfileFormats/SDF/SDF.txt similarity index 100% rename from Docs/SimfileFormats/SDF/SDF.txt rename to Docs/legacy/SimfileFormats/SDF/SDF.txt diff --git a/Docs/SimfileFormats/SDF/ssc-banner.png b/Docs/legacy/SimfileFormats/SDF/ssc-banner.png similarity index 100% rename from Docs/SimfileFormats/SDF/ssc-banner.png rename to Docs/legacy/SimfileFormats/SDF/ssc-banner.png diff --git a/Docs/SimfileFormats/SDF/ssc-bg.png b/Docs/legacy/SimfileFormats/SDF/ssc-bg.png similarity index 100% rename from Docs/SimfileFormats/SDF/ssc-bg.png rename to Docs/legacy/SimfileFormats/SDF/ssc-bg.png diff --git a/Docs/SimfileFormats/SDF/test-1bpm.sdf b/Docs/legacy/SimfileFormats/SDF/test-1bpm.sdf similarity index 100% rename from Docs/SimfileFormats/SDF/test-1bpm.sdf rename to Docs/legacy/SimfileFormats/SDF/test-1bpm.sdf diff --git a/Docs/SimfileFormats/SDF/test.sdf b/Docs/legacy/SimfileFormats/SDF/test.sdf similarity index 100% rename from Docs/SimfileFormats/SDF/test.sdf rename to Docs/legacy/SimfileFormats/SDF/test.sdf diff --git a/Docs/SimfileFormats/SDF/test.sm b/Docs/legacy/SimfileFormats/SDF/test.sm similarity index 100% rename from Docs/SimfileFormats/SDF/test.sm rename to Docs/legacy/SimfileFormats/SDF/test.sm diff --git a/Docs/SimfileFormats/dance-spec.txt b/Docs/legacy/SimfileFormats/dance-spec.txt similarity index 100% rename from Docs/SimfileFormats/dance-spec.txt rename to Docs/legacy/SimfileFormats/dance-spec.txt diff --git a/Docs/SimfileFormats/misc.txt b/Docs/legacy/SimfileFormats/misc.txt similarity index 100% rename from Docs/SimfileFormats/misc.txt rename to Docs/legacy/SimfileFormats/misc.txt diff --git a/Docs/SimfileFormats/new format draft.txt b/Docs/legacy/SimfileFormats/new format draft.txt similarity index 100% rename from Docs/SimfileFormats/new format draft.txt rename to Docs/legacy/SimfileFormats/new format draft.txt diff --git a/Docs/SimfileFormats/ssc_msd5.txt b/Docs/legacy/SimfileFormats/ssc_msd5.txt similarity index 93% rename from Docs/SimfileFormats/ssc_msd5.txt rename to Docs/legacy/SimfileFormats/ssc_msd5.txt index 576dd47da3..152155987a 100644 --- a/Docs/SimfileFormats/ssc_msd5.txt +++ b/Docs/legacy/SimfileFormats/ssc_msd5.txt @@ -1,74 +1,74 @@ -// sm-ssc step chart/msd5 hacky file format doc. -// based off of .sm, which was based off of DWI's modified MSD format. -#VERSION:; -#TITLE:; -#SUBTITLE:; -#ARTIST:; -#TITLETRANSLIT:; -#SUBTITLETRANSLIT:; -#ARTISTTRANSLIT:; -#GENRE:; -#CREDIT:; -#BANNER:; -#BACKGROUND:; -#LYRICSPATH:; -#CDTITLE:; -#MUSIC:; -#INSTRUMENTTRACK:; -#MUSICLENGTH:; -#OFFSET:; -#BPMS:; -#STOPS:; -#DELAYS:; -#LABELS:; -#TIMESIGNATURES:; -#SAMPLESTART:; -#SAMPLELENGTH:; -#DISPLAYBPM:[xxx][xxx:xxx]|[*]; -#SELECTABLE:; -#LASTSECONDHINT:; -#BGCHANGES:; -#FGCHANGES:; -#KEYSOUNDS:; -#ATTACKS:; - -// stored in cache -#FIRSTSECOND:; // calculated -#LASTSECOND:; // calculated -#SONGFILENAME:; -#MUSICBYTES:; // ignored by loader -#HASMUSIC:; -#HASBANNER:; - -// begin -#NOTEDATA:; // marks a new note data section -// information from #NOTES moved here -#CHARTNAME:; -#STEPSTYPE:; -#DESCRIPTION:; -#CHARTSTYLE:; -#DIFFICULTY:; -#METER:; -#RADARVALUES:; -#CREDIT:; - -// steps-based timingdata -#OFFSET:; -#BPMS:; -#STOPS:; -#DELAYS:; -#TIMESIGNATURES:; -#TICKCOUNTS:; -#COMBOS:; -#SPEEDS:; -#SCROLLS:; -#FAKES:; -#LABELS:; -#ATTACKS:; -#DISPLAYBPM:; - -// only in cache files -#STEPFILENAME:; - -// actual step data (not in cache files) -#NOTES:; +// sm-ssc step chart/msd5 hacky file format doc. +// based off of .sm, which was based off of DWI's modified MSD format. +#VERSION:; +#TITLE:; +#SUBTITLE:; +#ARTIST:; +#TITLETRANSLIT:; +#SUBTITLETRANSLIT:; +#ARTISTTRANSLIT:; +#GENRE:; +#CREDIT:; +#BANNER:; +#BACKGROUND:; +#LYRICSPATH:; +#CDTITLE:; +#MUSIC:; +#INSTRUMENTTRACK:; +#MUSICLENGTH:; +#OFFSET:; +#BPMS:; +#STOPS:; +#DELAYS:; +#LABELS:; +#TIMESIGNATURES:; +#SAMPLESTART:; +#SAMPLELENGTH:; +#DISPLAYBPM:[xxx][xxx:xxx]|[*]; +#SELECTABLE:; +#LASTSECONDHINT:; +#BGCHANGES:; +#FGCHANGES:; +#KEYSOUNDS:; +#ATTACKS:; + +// stored in cache +#FIRSTSECOND:; // calculated +#LASTSECOND:; // calculated +#SONGFILENAME:; +#MUSICBYTES:; // ignored by loader +#HASMUSIC:; +#HASBANNER:; + +// begin +#NOTEDATA:; // marks a new note data section +// information from #NOTES moved here +#CHARTNAME:; +#STEPSTYPE:; +#DESCRIPTION:; +#CHARTSTYLE:; +#DIFFICULTY:; +#METER:; +#RADARVALUES:; +#CREDIT:; + +// steps-based timingdata +#OFFSET:; +#BPMS:; +#STOPS:; +#DELAYS:; +#TIMESIGNATURES:; +#TICKCOUNTS:; +#COMBOS:; +#SPEEDS:; +#SCROLLS:; +#FAKES:; +#LABELS:; +#ATTACKS:; +#DISPLAYBPM:; + +// only in cache files +#STEPFILENAME:; + +// actual step data (not in cache files) +#NOTES:; diff --git a/Docs/Stats.xml b/Docs/legacy/Stats.xml similarity index 100% rename from Docs/Stats.xml rename to Docs/legacy/Stats.xml diff --git a/Docs/Themerdocs/Examples/Example_Actors/ActorFrame.lua b/Docs/legacy/Themerdocs/Examples/Example_Actors/ActorFrame.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Actors/ActorFrame.lua rename to Docs/legacy/Themerdocs/Examples/Example_Actors/ActorFrame.lua diff --git a/Docs/Themerdocs/Examples/Example_Actors/ActorFrameTexture.lua b/Docs/legacy/Themerdocs/Examples/Example_Actors/ActorFrameTexture.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Actors/ActorFrameTexture.lua rename to Docs/legacy/Themerdocs/Examples/Example_Actors/ActorFrameTexture.lua diff --git a/Docs/Themerdocs/Examples/Example_Actors/ActorScroller.lua b/Docs/legacy/Themerdocs/Examples/Example_Actors/ActorScroller.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Actors/ActorScroller.lua rename to Docs/legacy/Themerdocs/Examples/Example_Actors/ActorScroller.lua diff --git a/Docs/Themerdocs/Examples/Example_Actors/BitmapText.lua b/Docs/legacy/Themerdocs/Examples/Example_Actors/BitmapText.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Actors/BitmapText.lua rename to Docs/legacy/Themerdocs/Examples/Example_Actors/BitmapText.lua diff --git a/Docs/Themerdocs/Examples/Example_Actors/Quad.lua b/Docs/legacy/Themerdocs/Examples/Example_Actors/Quad.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Actors/Quad.lua rename to Docs/legacy/Themerdocs/Examples/Example_Actors/Quad.lua diff --git a/Docs/Themerdocs/Examples/Example_Actors/RollingNumbers.lua b/Docs/legacy/Themerdocs/Examples/Example_Actors/RollingNumbers.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Actors/RollingNumbers.lua rename to Docs/legacy/Themerdocs/Examples/Example_Actors/RollingNumbers.lua diff --git a/Docs/Themerdocs/Examples/Example_Actors/Toasty.lua b/Docs/legacy/Themerdocs/Examples/Example_Actors/Toasty.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Actors/Toasty.lua rename to Docs/legacy/Themerdocs/Examples/Example_Actors/Toasty.lua diff --git a/Docs/Themerdocs/Examples/Example_Screens/ScreenHeartEntry.lua b/Docs/legacy/Themerdocs/Examples/Example_Screens/ScreenHeartEntry.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Screens/ScreenHeartEntry.lua rename to Docs/legacy/Themerdocs/Examples/Example_Screens/ScreenHeartEntry.lua diff --git a/Docs/Themerdocs/Examples/Example_Screens/ScreenMapControllers.lua b/Docs/legacy/Themerdocs/Examples/Example_Screens/ScreenMapControllers.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Screens/ScreenMapControllers.lua rename to Docs/legacy/Themerdocs/Examples/Example_Screens/ScreenMapControllers.lua diff --git a/Docs/Themerdocs/Examples/Example_Screens/ScreenOptionsExample.ini b/Docs/legacy/Themerdocs/Examples/Example_Screens/ScreenOptionsExample.ini similarity index 100% rename from Docs/Themerdocs/Examples/Example_Screens/ScreenOptionsExample.ini rename to Docs/legacy/Themerdocs/Examples/Example_Screens/ScreenOptionsExample.ini diff --git a/Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/BGAnimations/ScreenSimpleExample overlay.lua b/Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/BGAnimations/ScreenSimpleExample overlay.lua similarity index 100% rename from Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/BGAnimations/ScreenSimpleExample overlay.lua rename to Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/BGAnimations/ScreenSimpleExample overlay.lua diff --git a/Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/ThemeInfo.ini b/Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/ThemeInfo.ini similarity index 100% rename from Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/ThemeInfo.ini rename to Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/ThemeInfo.ini diff --git a/Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/metrics.ini b/Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/metrics.ini similarity index 100% rename from Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/metrics.ini rename to Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/metrics.ini diff --git a/Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/readme.txt b/Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/readme.txt similarity index 100% rename from Docs/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/readme.txt rename to Docs/legacy/Themerdocs/Examples/Example_Themes/One_Screen_Example_Theme/readme.txt diff --git a/Docs/Themerdocs/Examples/OptionRowHandlerLua.lua b/Docs/legacy/Themerdocs/Examples/OptionRowHandlerLua.lua similarity index 100% rename from Docs/Themerdocs/Examples/OptionRowHandlerLua.lua rename to Docs/legacy/Themerdocs/Examples/OptionRowHandlerLua.lua diff --git a/Docs/Themerdocs/Examples/anatomy_of_an_actor.lua b/Docs/legacy/Themerdocs/Examples/anatomy_of_an_actor.lua similarity index 100% rename from Docs/Themerdocs/Examples/anatomy_of_an_actor.lua rename to Docs/legacy/Themerdocs/Examples/anatomy_of_an_actor.lua diff --git a/Docs/Themerdocs/Noteskin elements Reference.txt b/Docs/legacy/Themerdocs/Noteskin elements Reference.txt similarity index 100% rename from Docs/Themerdocs/Noteskin elements Reference.txt rename to Docs/legacy/Themerdocs/Noteskin elements Reference.txt diff --git a/Docs/Themerdocs/ScreenAMVTest overlay.lua b/Docs/legacy/Themerdocs/ScreenAMVTest overlay.lua similarity index 100% rename from Docs/Themerdocs/ScreenAMVTest overlay.lua rename to Docs/legacy/Themerdocs/ScreenAMVTest overlay.lua diff --git a/Docs/Themerdocs/ScreenMessages.txt b/Docs/legacy/Themerdocs/ScreenMessages.txt similarity index 100% rename from Docs/Themerdocs/ScreenMessages.txt rename to Docs/legacy/Themerdocs/ScreenMessages.txt diff --git a/Docs/Themerdocs/ScreenTextEntry.txt b/Docs/legacy/Themerdocs/ScreenTextEntry.txt similarity index 100% rename from Docs/Themerdocs/ScreenTextEntry.txt rename to Docs/legacy/Themerdocs/ScreenTextEntry.txt diff --git a/Docs/Themerdocs/ThemePrefs.txt b/Docs/legacy/Themerdocs/ThemePrefs.txt similarity index 100% rename from Docs/Themerdocs/ThemePrefs.txt rename to Docs/legacy/Themerdocs/ThemePrefs.txt diff --git a/Docs/Themerdocs/ThemePrefsRows.txt b/Docs/legacy/Themerdocs/ThemePrefsRows.txt similarity index 100% rename from Docs/Themerdocs/ThemePrefsRows.txt rename to Docs/legacy/Themerdocs/ThemePrefsRows.txt diff --git a/Docs/Themerdocs/XmlToLua.txt b/Docs/legacy/Themerdocs/XmlToLua.txt similarity index 100% rename from Docs/Themerdocs/XmlToLua.txt rename to Docs/legacy/Themerdocs/XmlToLua.txt diff --git a/Docs/Themerdocs/actordef.txt b/Docs/legacy/Themerdocs/actordef.txt similarity index 100% rename from Docs/Themerdocs/actordef.txt rename to Docs/legacy/Themerdocs/actordef.txt diff --git a/Docs/Themerdocs/announcer_files.txt b/Docs/legacy/Themerdocs/announcer_files.txt similarity index 100% rename from Docs/Themerdocs/announcer_files.txt rename to Docs/legacy/Themerdocs/announcer_files.txt diff --git a/Docs/Themerdocs/calories.txt b/Docs/legacy/Themerdocs/calories.txt similarity index 100% rename from Docs/Themerdocs/calories.txt rename to Docs/legacy/Themerdocs/calories.txt diff --git a/Docs/Themerdocs/conditional_music.txt b/Docs/legacy/Themerdocs/conditional_music.txt similarity index 100% rename from Docs/Themerdocs/conditional_music.txt rename to Docs/legacy/Themerdocs/conditional_music.txt diff --git a/Docs/Themerdocs/effect_colors.txt b/Docs/legacy/Themerdocs/effect_colors.txt similarity index 100% rename from Docs/Themerdocs/effect_colors.txt rename to Docs/legacy/Themerdocs/effect_colors.txt diff --git a/Docs/Themerdocs/fontini.txt b/Docs/legacy/Themerdocs/fontini.txt similarity index 100% rename from Docs/Themerdocs/fontini.txt rename to Docs/legacy/Themerdocs/fontini.txt diff --git a/Docs/Themerdocs/gamecommands.txt b/Docs/legacy/Themerdocs/gamecommands.txt similarity index 100% rename from Docs/Themerdocs/gamecommands.txt rename to Docs/legacy/Themerdocs/gamecommands.txt diff --git a/Docs/Themerdocs/haste.txt b/Docs/legacy/Themerdocs/haste.txt similarity index 100% rename from Docs/Themerdocs/haste.txt rename to Docs/legacy/Themerdocs/haste.txt diff --git a/Docs/Themerdocs/included_scripts.txt b/Docs/legacy/Themerdocs/included_scripts.txt similarity index 100% rename from Docs/Themerdocs/included_scripts.txt rename to Docs/legacy/Themerdocs/included_scripts.txt diff --git a/Docs/Themerdocs/modslevel.txt b/Docs/legacy/Themerdocs/modslevel.txt similarity index 100% rename from Docs/Themerdocs/modslevel.txt rename to Docs/legacy/Themerdocs/modslevel.txt diff --git a/Docs/Themerdocs/moremsg.txt b/Docs/legacy/Themerdocs/moremsg.txt similarity index 100% rename from Docs/Themerdocs/moremsg.txt rename to Docs/legacy/Themerdocs/moremsg.txt diff --git a/Docs/Themerdocs/pause_menu.md b/Docs/legacy/Themerdocs/pause_menu.md similarity index 100% rename from Docs/Themerdocs/pause_menu.md rename to Docs/legacy/Themerdocs/pause_menu.md diff --git a/Docs/Themerdocs/recommended_practices.txt b/Docs/legacy/Themerdocs/recommended_practices.txt similarity index 100% rename from Docs/Themerdocs/recommended_practices.txt rename to Docs/legacy/Themerdocs/recommended_practices.txt diff --git a/Docs/Themerdocs/sm-ssc_themeguide.txt b/Docs/legacy/Themerdocs/sm-ssc_themeguide.txt similarity index 100% rename from Docs/Themerdocs/sm-ssc_themeguide.txt rename to Docs/legacy/Themerdocs/sm-ssc_themeguide.txt diff --git a/Docs/Userdocs/Keymaps_ini_format.md b/Docs/legacy/Userdocs/Keymaps_ini_format.md similarity index 100% rename from Docs/Userdocs/Keymaps_ini_format.md rename to Docs/legacy/Userdocs/Keymaps_ini_format.md diff --git a/Docs/Userdocs/bgchanges_format.txt b/Docs/legacy/Userdocs/bgchanges_format.txt similarity index 100% rename from Docs/Userdocs/bgchanges_format.txt rename to Docs/legacy/Userdocs/bgchanges_format.txt diff --git a/Docs/Userdocs/sm5_beginner.txt b/Docs/legacy/Userdocs/sm5_beginner.txt similarity index 100% rename from Docs/Userdocs/sm5_beginner.txt rename to Docs/legacy/Userdocs/sm5_beginner.txt diff --git a/Docs/credits.txt b/Docs/legacy/credits.txt similarity index 95% rename from Docs/credits.txt rename to Docs/legacy/credits.txt index 0c7e7ddd79..c5992b311d 100644 --- a/Docs/credits.txt +++ b/Docs/legacy/credits.txt @@ -1,182 +1,182 @@ -StepMania 5 credits (in no particular order) --------------------------------------------- -If you have any corrections to this list, let us know (via forums or IRC). - -==StepMania Team== -Chris Danford, Glenn Maynard, Steve Checkoway, et al - * Keeping StepMania 5 alive with changes, and providing a nice codebase for - us to work with. - -==the spinal shark collective== -AJ Kelly as freem - * (sm-ssc) Project Coordinator/Leader - * Main programming - * Various Lua scripts - * Some small theme edits here and there - * Noteskins (retro, retrobar*) - * Windows project file maintainer (mostly) - -Midiman - * Did most of the work on _fallback and default themes - * Some programming - * Noteskins (midi-*) - -shakesoda - * Programming - * Noteskins (delta, gamma, port of orbital to kb7) - * Theme edits - * Mac OS X primary maintainer - -==sm-ssc Team== -(in no particular order) - -Aldo_MX - * Code (Pump it Up delays, among others), ideas, and support. - -cerbo - * [SongManager] SetPreferredSongs() and SetPreferredCourses() Lua bindings - -Daisuke Master - * Programming - * Pump/simple and Pump/complex noteskins - * /Docs/Themerdocs/Noteskin elements Reference.txt - * Taking advantage of sm-ssc's new features :) - -FSX - * Various fixes. (see Changelogs for more details) - -Nicole Reid (okeeblow) - * Tested building sm-ssc on FreeBSD, provided fixes. - (fixes that still need to get implemented) - -Thai Pangsakulyanont (theDtTvB) - * Changes to BMS loading/playback behavior to make things work better. - -Jason Felds (Wolfman2000) - * [Player] PercentUntilColorCombo metric - * Mac OS X maintainer - * Various fixes/changes. (see Changelogs for more details) - -Devin J. Pohly (djpohly) - * Various patches/fixes - -==other contributors== -(in no particular order) - -1a2a3a2a1a - * Various beat mode fixes - -Kaox - * Pump/default noteskin - -cesarmades - * Pump/cmd-* noteskins - -David Santamaría Rogado (howl) - * Various patches (see Changelogs for more details and links) - -Kita K./D. Trucks - * default theme music - -kurisu - * Dance-threepanel gametype code (3.9; re-adapted for sm-ssc) - -v1toko - * Lead coder of StepNXA, which is where we got the original XMode code from. - -Macgravel - * Orbular noteskin (the default kb7 noteskin) - -hanubeki (@803832, formerly sy567) - * Small beginner helper fix - (http://old.stepmania.com/forums/showpost.php?p=158721&postcount=12) - * Lots of code changes from hanubeki-modified-sm-ssc: - http://code.google.com/r/hanubeki-modified-sm-ssc/ - -galopin - * Pump it Up Exceed PlayStation 2 USB dance mat support patch - (stepmania-devs mailing list 20091213 11:27 -0800 [Pacific Standard Time]) - -Henke37 - * [MovieTexture_FFMpeg] Stutter fix - (http://www.pasteall.org/11353/diff) - -corec - * [ArchHooks_Unix, MovieTexture_FFMpeg] Make sm-ssc work with system's FFMpeg. - (http://github.com/corec/cc-overlay/blob/master/games-arcade/sm-ssc/files/sm-ssc-ffmpeg-fixes-01.patch) - * [InputMapper] Enabling upper diagonal keys for Positive Gaming Impact dance mat - (http://ssc.ajworld.net/sm-ssc/bugtracker/view.php?id=137) - -gholms - * Make autogen.sh look for automake 1.11 - (http://ssc.ajworld.net/sm-ssc/bugtracker/view.php?id=140) - -juanelote - * [SongManager] GetSongGroupByIndex function - * [MusicWheel] JumpToNextGroup/JumpToPrevGroup logic modifications - -NitroX72 - * Pump/frame noteskin - -Tatsh - * A patch to fix building with system ffmpeg - (http://ssc.ajworld.net/sm-ssc/bugtracker/view.php?id=218) - -A.C (@waiei) - * Hybrid scoring mode + scoring fixes - * Various patches/fixes/bug reporting - -John_Reactor - * Polish translation - -DHalens - * Spanish translation - -桜為å°é³©/Sakurana-Kobato (@sakuraponila) - * Scoring fixes - -@Niler_jp - * Japanese translation - -Deamon007 - * Dutch translation - -cvpcs - * Updated ffmpeg support to v0.10 - -Alfred Sorenson - * Various small additions - -==the beta testers== -[SSC Beta Testing Team] -KeithD -tweak/tweak62 - -[Friends of the Devs] -And4713 -HankPeters -okeeblow -kdaymea -taiyal - -[Members of Team Step Masters (http://www.team-stepmasters.net/foro/)] -Daisuke Master -Nueel/emmanuel virus -Fye -Bijou -Nek0 -Jib -Robe -Urqui -h4m573r -Torta - -[Private Beta Wave 1.x Testers] -FSX -Sniper257 -Wolfman2000 -NitroX72 -Wanny -Tio -Cerbo -Daisuke Master +StepMania 5 credits (in no particular order) +-------------------------------------------- +If you have any corrections to this list, let us know (via forums or IRC). + +==StepMania Team== +Chris Danford, Glenn Maynard, Steve Checkoway, et al + * Keeping StepMania 5 alive with changes, and providing a nice codebase for + us to work with. + +==the spinal shark collective== +AJ Kelly as freem + * (sm-ssc) Project Coordinator/Leader + * Main programming + * Various Lua scripts + * Some small theme edits here and there + * Noteskins (retro, retrobar*) + * Windows project file maintainer (mostly) + +Midiman + * Did most of the work on _fallback and default themes + * Some programming + * Noteskins (midi-*) + +shakesoda + * Programming + * Noteskins (delta, gamma, port of orbital to kb7) + * Theme edits + * Mac OS X primary maintainer + +==sm-ssc Team== +(in no particular order) + +Aldo_MX + * Code (Pump it Up delays, among others), ideas, and support. + +cerbo + * [SongManager] SetPreferredSongs() and SetPreferredCourses() Lua bindings + +Daisuke Master + * Programming + * Pump/simple and Pump/complex noteskins + * /Docs/Themerdocs/Noteskin elements Reference.txt + * Taking advantage of sm-ssc's new features :) + +FSX + * Various fixes. (see Changelogs for more details) + +Nicole Reid (okeeblow) + * Tested building sm-ssc on FreeBSD, provided fixes. + (fixes that still need to get implemented) + +Thai Pangsakulyanont (theDtTvB) + * Changes to BMS loading/playback behavior to make things work better. + +Jason Felds (Wolfman2000) + * [Player] PercentUntilColorCombo metric + * Mac OS X maintainer + * Various fixes/changes. (see Changelogs for more details) + +Devin J. Pohly (djpohly) + * Various patches/fixes + +==other contributors== +(in no particular order) + +1a2a3a2a1a + * Various beat mode fixes + +Kaox + * Pump/default noteskin + +cesarmades + * Pump/cmd-* noteskins + +David Santamaría Rogado (howl) + * Various patches (see Changelogs for more details and links) + +Kita K./D. Trucks + * default theme music + +kurisu + * Dance-threepanel gametype code (3.9; re-adapted for sm-ssc) + +v1toko + * Lead coder of StepNXA, which is where we got the original XMode code from. + +Macgravel + * Orbular noteskin (the default kb7 noteskin) + +hanubeki (@803832, formerly sy567) + * Small beginner helper fix + (http://old.stepmania.com/forums/showpost.php?p=158721&postcount=12) + * Lots of code changes from hanubeki-modified-sm-ssc: + http://code.google.com/r/hanubeki-modified-sm-ssc/ + +galopin + * Pump it Up Exceed PlayStation 2 USB dance mat support patch + (stepmania-devs mailing list 20091213 11:27 -0800 [Pacific Standard Time]) + +Henke37 + * [MovieTexture_FFMpeg] Stutter fix + (http://www.pasteall.org/11353/diff) + +corec + * [ArchHooks_Unix, MovieTexture_FFMpeg] Make sm-ssc work with system's FFMpeg. + (http://github.com/corec/cc-overlay/blob/master/games-arcade/sm-ssc/files/sm-ssc-ffmpeg-fixes-01.patch) + * [InputMapper] Enabling upper diagonal keys for Positive Gaming Impact dance mat + (http://ssc.ajworld.net/sm-ssc/bugtracker/view.php?id=137) + +gholms + * Make autogen.sh look for automake 1.11 + (http://ssc.ajworld.net/sm-ssc/bugtracker/view.php?id=140) + +juanelote + * [SongManager] GetSongGroupByIndex function + * [MusicWheel] JumpToNextGroup/JumpToPrevGroup logic modifications + +NitroX72 + * Pump/frame noteskin + +Tatsh + * A patch to fix building with system ffmpeg + (http://ssc.ajworld.net/sm-ssc/bugtracker/view.php?id=218) + +A.C (@waiei) + * Hybrid scoring mode + scoring fixes + * Various patches/fixes/bug reporting + +John_Reactor + * Polish translation + +DHalens + * Spanish translation + +桜為å°é³©/Sakurana-Kobato (@sakuraponila) + * Scoring fixes + +@Niler_jp + * Japanese translation + +Deamon007 + * Dutch translation + +cvpcs + * Updated ffmpeg support to v0.10 + +Alfred Sorenson + * Various small additions + +==the beta testers== +[SSC Beta Testing Team] +KeithD +tweak/tweak62 + +[Friends of the Devs] +And4713 +HankPeters +okeeblow +kdaymea +taiyal + +[Members of Team Step Masters (http://www.team-stepmasters.net/foro/)] +Daisuke Master +Nueel/emmanuel virus +Fye +Bijou +Nek0 +Jib +Robe +Urqui +h4m573r +Torta + +[Private Beta Wave 1.x Testers] +FSX +Sniper257 +Wolfman2000 +NitroX72 +Wanny +Tio +Cerbo +Daisuke Master diff --git a/Docs/docpack.zip b/Docs/legacy/docpack.zip similarity index 100% rename from Docs/docpack.zip rename to Docs/legacy/docpack.zip diff --git a/Docs/license-ext/Scoring-jp.txt b/Docs/legacy/license-ext/Scoring-jp.txt similarity index 100% rename from Docs/license-ext/Scoring-jp.txt rename to Docs/legacy/license-ext/Scoring-jp.txt diff --git a/Docs/license-ext/readme b/Docs/legacy/license-ext/readme similarity index 100% rename from Docs/license-ext/readme rename to Docs/legacy/license-ext/readme diff --git a/Docs/license-ext/theme_lang-ja.txt b/Docs/legacy/license-ext/theme_lang-ja.txt similarity index 100% rename from Docs/license-ext/theme_lang-ja.txt rename to Docs/legacy/license-ext/theme_lang-ja.txt diff --git a/Docs/license-ext/vlgothic/Changelog b/Docs/legacy/license-ext/vlgothic/Changelog similarity index 100% rename from Docs/license-ext/vlgothic/Changelog rename to Docs/legacy/license-ext/vlgothic/Changelog diff --git a/Docs/license-ext/vlgothic/LICENSE b/Docs/legacy/license-ext/vlgothic/LICENSE similarity index 100% rename from Docs/license-ext/vlgothic/LICENSE rename to Docs/legacy/license-ext/vlgothic/LICENSE diff --git a/Docs/license-ext/vlgothic/LICENSE.en b/Docs/legacy/license-ext/vlgothic/LICENSE.en similarity index 100% rename from Docs/license-ext/vlgothic/LICENSE.en rename to Docs/legacy/license-ext/vlgothic/LICENSE.en diff --git a/Docs/license-ext/vlgothic/LICENSE_E.mplus b/Docs/legacy/license-ext/vlgothic/LICENSE_E.mplus similarity index 100% rename from Docs/license-ext/vlgothic/LICENSE_E.mplus rename to Docs/legacy/license-ext/vlgothic/LICENSE_E.mplus diff --git a/Docs/license-ext/vlgothic/LICENSE_J.mplus b/Docs/legacy/license-ext/vlgothic/LICENSE_J.mplus similarity index 100% rename from Docs/license-ext/vlgothic/LICENSE_J.mplus rename to Docs/legacy/license-ext/vlgothic/LICENSE_J.mplus diff --git a/Docs/license-ext/vlgothic/README b/Docs/legacy/license-ext/vlgothic/README similarity index 100% rename from Docs/license-ext/vlgothic/README rename to Docs/legacy/license-ext/vlgothic/README diff --git a/Docs/license-ext/vlgothic/README.sazanami b/Docs/legacy/license-ext/vlgothic/README.sazanami similarity index 100% rename from Docs/license-ext/vlgothic/README.sazanami rename to Docs/legacy/license-ext/vlgothic/README.sazanami diff --git a/Docs/license-ext/vlgothic/README_J.mplus b/Docs/legacy/license-ext/vlgothic/README_J.mplus similarity index 100% rename from Docs/license-ext/vlgothic/README_J.mplus rename to Docs/legacy/license-ext/vlgothic/README_J.mplus diff --git a/Docs/midiman.wishlist b/Docs/legacy/midiman.wishlist similarity index 96% rename from Docs/midiman.wishlist rename to Docs/legacy/midiman.wishlist index 16c8e5be48..ce45107164 100644 --- a/Docs/midiman.wishlist +++ b/Docs/legacy/midiman.wishlist @@ -1,25 +1,25 @@ -force gamestate variables - ex: - GAMESTATE:SetCurrentStage('Stage_2nd'); - -force preference setting through gamecommand -(completed by AJ on 20090719 using setpref,prefname,value) - ex: - Choice1="confset,BGAnimations['RandomBackgroundMode_RandomMovies']" - -gamecommand on ssmaster for custom options menu - ex: - Choice1="gamecommand;confset,blah" - hand-in-hand with gamecommand confset - -lua-return strings for audio -(completed by AJ on 20090905) - ex: ScreenSelectMusic loop music.lua -> - if GAMESTATE:GetStagesLeft() > 1 then - return "_Music normal"; - else - return "_Music last"; - end - end - +force gamestate variables + ex: + GAMESTATE:SetCurrentStage('Stage_2nd'); + +force preference setting through gamecommand +(completed by AJ on 20090719 using setpref,prefname,value) + ex: + Choice1="confset,BGAnimations['RandomBackgroundMode_RandomMovies']" + +gamecommand on ssmaster for custom options menu + ex: + Choice1="gamecommand;confset,blah" + hand-in-hand with gamecommand confset + +lua-return strings for audio +(completed by AJ on 20090905) + ex: ScreenSelectMusic loop music.lua -> + if GAMESTATE:GetStagesLeft() > 1 then + return "_Music normal"; + else + return "_Music last"; + end + end + Midi: create clone of Languages system, but different \ No newline at end of file diff --git a/Docs/old_changelog.txt b/Docs/legacy/old_changelog.txt similarity index 100% rename from Docs/old_changelog.txt rename to Docs/legacy/old_changelog.txt diff --git a/Docs/opensource_simulators.txt b/Docs/legacy/opensource_simulators.txt similarity index 100% rename from Docs/opensource_simulators.txt rename to Docs/legacy/opensource_simulators.txt diff --git a/Docs/steps.lua b/Docs/legacy/steps.lua similarity index 100% rename from Docs/steps.lua rename to Docs/legacy/steps.lua diff --git a/Docs/versioning.txt b/Docs/legacy/versioning.txt similarity index 100% rename from Docs/versioning.txt rename to Docs/legacy/versioning.txt diff --git a/README.md b/README.md index 4a24ba0c8d..2ecfe63e7d 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ -Etterna -========= +# Etterna Etterna is an advanced cross-platform rhythm game focused on keyboard play. -| Mac | Linux-clang | Linux-gcc | Windows 7 | Windows 10 | Coverity | -|-------------------|-------------------|-------------------|-------------------|-------------------|-------------------| +| Mac | Linux-clang | Linux-gcc | Windows 7 | Windows 10 | Coverity | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | --------------------------------- | --------------------------------- | ----------------------------------- | | [![build1-trav][]][build-link-travis] | [![build2-trav][]][build-link-travis] | [![build3-trav][]][build-link-travis] | [![build1-app][]][build-link-app] | [![build2-app][]][build-link-app] | [![build1-cov][]][build-link-cover] | [build1-trav]: https://travis-matrix-badges.herokuapp.com/repos/etternagame/etterna/branches/develop/1 @@ -18,40 +17,54 @@ Etterna is an advanced cross-platform rhythm game focused on keyboard play. [build-link-cover]: https://scan.coverity.com/projects/etternagame-etterna ![Discord](https://img.shields.io/discord/339597420239519755.svg) + ![Github Releases (by Release)](https://img.shields.io/github/downloads/etternagame/etterna/v0.60.0/total.svg) ## Installation + ### From Packages For those that do not wish to compile the game on their own and use a binary right away, be aware of the following issues: -* Windows users are expected to have installed the [Microsoft Visual C++ x86 Redistributable for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145) prior to running the game. For those on a 64-bit operating system, grab the x64 redistributable as well. [DirectX End-User Runtimes (June 2010)](http://www.microsoft.com/en-us/download/details.aspx?id=8109) is also required. Windows 7 is the minimum supported version. -* macOS users need to have macOS 10.6.8 or higher to run Etterna. -* Linux users should receive all they need from the package manager of their choice. +- Windows users are expected to have installed the [Microsoft Visual C++ x86 Redistributable for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145) prior to running the game. For those on a 64-bit operating system, grab the x64 redistributable as well. [DirectX End-User Runtimes (June 2010)](http://www.microsoft.com/en-us/download/details.aspx?id=8109) is also required. Windows 7 is the minimum supported version. +- macOS users need to have macOS 10.6.8 or higher to run Etterna. +- Linux users should receive all they need from the package manager of their choice. ### From Source -https://etternagame.github.io/wiki/Building-Etterna.html +https://etternagame.github.io/wiki/Building-Etterna.html ## Resources -* Website: https://etternaonline.com/ -* Discord: https://discord.gg/ZqpUjsJ -* Lua for Etterna: https://etternagame.github.io/Lua-For-Etterna/ -* Lua API Reference: https://etternagame.github.io/Lua-For-Etterna/API/Lua.xml -* ETTP docs: https://github.com/Nickito12/NodeMultiEtt/blob/master/README.md +- [Website](https://etternaonline.com/) +- [Discord](https://discord.gg/ZqpUjsJ) +- [Lua for Etterna](https://etternagame.github.io/Lua-For-Etterna/) +- [Lua API Reference](https://etternagame.github.io/Lua-For-Etterna/API/Lua.xml) +- [ETTP docs](https://github.com/Nickito12/NodeMultiEtt/blob/master/README.md) ## Licensing Terms -In short — you can do anything you like with the game (including sell products made with it), provided you *do not* claim to have created the engine yourself or remove the credits. +In short — you can do anything you like with the game (including sell products made with it), provided you _do not_ claim to have created the engine yourself or remove the credits. For specific information/legalese: -* All of the our source code is under the [MIT license](http://opensource.org/licenses/MIT). -* The [MAD library](http://www.underbit.com/products/mad/) and [FFmpeg codecs](https://www.ffmpeg.org/) when built with our code use the [GPL license](http://www.gnu.org). +- All of the our source code is under the [MIT license](http://opensource.org/licenses/MIT). +- The [MAD library](http://www.underbit.com/products/mad/) and [FFmpeg codecs](https://www.ffmpeg.org/) when built with our code use the [GPL license](http://www.gnu.org). Etterna began as a fork of https://github.com/stepmania/stepmania -## [Collaborating](https://github.com/etternagame/etterna/blob/master/Contributing.md) +## Building + +[On Building](Docs/Building.md) + +## Building Documentation + +[On Building Documentation](Docs/Building-Docs.md) + +## Collaborating + +[On Collaborating](Docs/Contributing.md) + +## Bug Reporting -## [Bug Reporting](https://github.com/etternagame/etterna/blob/master/Docs/Bugreporting.md) +[On Bug Reporting](Docs/Bugreporting.md) From d96f5804c8a31425a8a11bff2b25ee81f954ced6 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 25 Nov 2018 23:02:39 -0300 Subject: [PATCH 055/320] Remove file i forgot to remove in previous commit --- Contributing.md | 53 ------------------------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 Contributing.md diff --git a/Contributing.md b/Contributing.md deleted file mode 100644 index 2e8552c4aa..0000000000 --- a/Contributing.md +++ /dev/null @@ -1,53 +0,0 @@ -## Contributing - -Anyone is welcome to contribute! These are the areas where help is needed the most. - - * [C++](#c) - * [Lua](#lua) - * [Documentation](#documentation) - * [Translating](#translating) - * [Packaging](#packaging) - * [Graphic Design](#graphic-Design) - * [Chart Making](#chart-making) - - -### C++ - -If you have *any* experience with C++ (Or even C and wanna learn a bit of C++) your help would be much appreciated! -There's **A LOT** of things that need doing. If you don't have any specific thing you want to work on, here are some ideas: - - [GitHub Issues](https://github.com/etternagame/etterna/issues) - - [Coverity Defects](https://scan.coverity.com/projects/etternagame-etterna) (Currently these are private, you can request access with an email, we might make this public in the future) - - Cleaning up the codebase in general (There's a lot of things that would be nice to see done, like replacing usage of RString with std::string) - - If you know how to use them and see a good place for them, some usage of modern C++ features like smart pointers might be good to see in the project :) - -### Lua - -Lua is a fairly simple language. If you have experience in any other programming language, you'll probably be able to get the basics of its syntax in under an hour. https://www.lua.org/pil/contents.html is probably a good place to learn a bit. - -Lua is used in Etterna for Themes and Noteskins. - -Noteskins control the way the notes are drawed (Most noteskins have very similar logic and only different images, but noteskins have the power to do a lot more, and some take advantage of that). - -You can think of themes as the front end of the game. The way each screen is drawn, how screen branching (Changing) happens, and other things are controlled by the theme. A theme can even create new screens from scratch, catch inputs (Both mouse and keyboard), and other things. They're fairly powerful. - -Currently, there's a lack of alternative themes (To the default one, Til Death) for Etterna. [Spawncamping-Wallhack](https://github.com/ca25nada/spawncamping-wallhack) is the only complete theme that supports Etterna as far as I know. - -### Documentation - -The project is sorely lacking in documentation. The current aim is to document the Lua stuff in https://etternagame.github.io/Lua-For-Etterna/API/Lua.xml (This is forked from http://dguzek.github.io/Lua-For-SM5/API/Lua.xml, a community-made reference for SM5 Lua). We intend to get the C++ documentation done in https://etternagame.github.io/wiki/ (At first we wanted to make this page have 3 "sections": General, Lua and C++, but gave up). Then there is a general wiki with information that can be useful to end users (https://wiki.etternaonline.com/). - -### Translating - -The Til Death theme (Default) only has one translation available. In order to make others, simply copy etterna/Themes/Til Death/Languages/en.ini and translate all the right-side words (After the `=`). Also, a list of the words/text/captions/things that aren't translate-able in the theme would be useful to make them(Some of the text is hard-coded so it's not possible to translate it). - -### Packaging - -A few people have complained about the lack of packages for Linux in general. If you'd like to, you can try working on a package for your favorite distro. I've already made a more-or-less functional debian package here: https://github.com/nico-abram/etterna/tree/debian/ - -### Graphic Design - -A lot of things in the game have been done in a hurry to simply provide a basic UI so things can be used. We usually mostly care about features working. Mockups for new designs, improved gfx (Images) and other ideas are incredibly welcome. This goes for both the default theme and the website, etternaonline. If you're interested, you could ask around in the etternaonline discord. Also, concepts for completely new themes would be interesting to see (In case someone who knows how to implement one decides to work on it). - -### Chart Making - -As the content in the game is completely community-driven, new charts and packs keep the game fresh. They make old time players come back for a day. Even if it doesnt seem like much, every chart makes the game as a whole more valuable. You can get started by clicking "Editor" within the client. From 736439b73649172ed64e17eaf6bb0b71b95fd4e8 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 00:24:41 -0300 Subject: [PATCH 056/320] Remove unused folders from src --- src/{irc => ircc}/appveyor.cpp | 0 src/smpackage/ZipArchive/Linux/Makefile | 86 - .../ChangeGameSettings.cpp | 0 .../ChangeGameSettings.h | 0 .../CreateLanguageDlg.cpp | 0 .../CreateLanguageDlg.h | 0 .../EditInsallations.cpp | 0 .../EditInsallations.h | 0 .../EnterComment.cpp | 0 src/{smpackage => smpackagee}/EnterComment.h | 0 src/{smpackage => smpackagee}/EnterName.cpp | 0 src/{smpackage => smpackagee}/EnterName.h | 0 .../LanguagesDlg.cpp | 0 src/{smpackage => smpackagee}/LanguagesDlg.h | 0 src/{smpackage => smpackagee}/MainMenuDlg.cpp | 0 src/{smpackage => smpackagee}/MainMenuDlg.h | 0 .../SMPackageInstallDlg.cpp | 0 .../SMPackageInstallDlg.h | 0 .../SMPackageUtil.cpp | 0 src/{smpackage => smpackagee}/ShowComment.cpp | 0 src/{smpackage => smpackagee}/ShowComment.h | 0 .../SmpackageExportDlg.cpp | 0 .../SmpackageExportDlg.h | 0 src/{smpackage => smpackagee}/StdAfx.cpp | 0 src/{smpackage => smpackagee}/StdAfx.h | 0 src/{smpackage => smpackagee}/TreeCtrlEx.cpp | 0 src/{smpackage => smpackagee}/TreeCtrlEx.h | 0 .../UninstallOld.cpp | 0 src/{smpackage => smpackagee}/UninstallOld.h | 0 .../ZipArchive/Appnote.txt | 0 .../ZipArchive/ChangeLog.txt | 0 .../ZipArchive/License.txt | 0 .../ZipArchive/Linux/ZipFileMapping.h | 0 .../ZipArchive/Linux/ZipPathComponent.cpp | 0 .../ZipArchive/Linux/ZipPlatform.cpp | 0 .../ZipArchive/Readme.txt | 0 .../ZipArchive/StdAfx.cpp | 0 .../ZipArchive/StdAfx.h | 0 .../ZipArchive/Windows/ZipFileMapping.h | 0 .../ZipArchive/Windows/ZipPathComponent.cpp | 0 .../ZipArchive/Windows/ZipPlatform.cpp | 0 .../ZipArchive/ZipAbstractFile.h | 0 .../ZipArchive/ZipArchive-net2003.vcproj | 2570 ++++++------- .../ZipArchive/ZipArchive-net2008.vcproj | 3372 ++++++++--------- .../ZipArchive/ZipArchive.cpp | 0 .../ZipArchive/ZipArchive.dox | 442 +-- .../ZipArchive/ZipArchive.h | 0 .../ZipArchive/ZipArchive.rc | 218 +- .../ZipArchive/ZipAutoBuffer.cpp | 0 .../ZipArchive/ZipAutoBuffer.h | 0 .../ZipArchive/ZipBaseException.h | 0 .../ZipArchive/ZipCentralDir.cpp | 0 .../ZipArchive/ZipCentralDir.h | 0 .../ZipArchive/ZipCollections.h | 0 .../ZipArchive/ZipCompatibility.cpp | 0 .../ZipArchive/ZipCompatibility.h | 0 .../ZipArchive/ZipException.cpp | 0 .../ZipArchive/ZipException.h | 0 .../ZipArchive/ZipExport.h | 0 .../ZipArchive/ZipFile.cpp | 0 .../ZipArchive/ZipFile.h | 0 .../ZipArchive/ZipFileHeader.cpp | 0 .../ZipArchive/ZipFileHeader.h | 0 .../ZipArchive/ZipFileMapping.h | 0 .../ZipArchive/ZipMemFile.cpp | 0 .../ZipArchive/ZipMemFile.h | 0 .../ZipArchive/ZipPathComponent.cpp | 0 .../ZipArchive/ZipPathComponent.h | 0 .../ZipArchive/ZipPlatform.cpp | 0 .../ZipArchive/ZipPlatform.h | 0 .../ZipArchive/ZipPlatformComm.cpp | 0 .../ZipArchive/ZipStorage.cpp | 0 .../ZipArchive/ZipStorage.h | 0 .../ZipArchive/ZipString.cpp | 0 .../ZipArchive/ZipString.h | 0 .../ZipArchive/__Windows_MFC.zcfg | 2 +- .../ZipArchive/_copy_from_Win-MFC.bat | 10 +- .../ZipArchive/_copy_from_Win-STL.bat | 10 +- .../ZipArchive/_version.txt | 0 .../ZipArchive/borland.zip | Bin .../ZipArchive/faq.txt | 0 .../ZipArchive/gpl.txt | 0 .../ZipArchive/mfc/ZipBaseException.h | 0 .../ZipArchive/mfc/ZipCollections.h | 0 .../ZipArchive/mfc/ZipFile.cpp | 0 .../ZipArchive/mfc/ZipFile.h | 0 .../ZipArchive/mfc/ZipString.h | 0 .../ZipArchive/mfc/stdafx.h | 0 .../ZipArchive/resource.h | 0 .../ZipArchive/stl/ZipBaseException.h | 0 .../ZipArchive/stl/ZipCollections.h | 0 .../ZipArchive/stl/ZipFile.cpp | 0 .../ZipArchive/stl/ZipFile.h | 0 .../ZipArchive/stl/ZipString.h | 0 .../ZipArchive/stl/stdafx.h | 0 .../ZipArchive/stl/zippie/CmdLine.cpp | 0 .../ZipArchive/stl/zippie/CmdLine.h | 0 .../ZipArchive/stl/zippie/zippie.cpp | 0 .../ZipArchive/stl/zippie/zippie.dsp | 222 +- .../ZipArchive/stl/zippie/zippie.dsw | 88 +- .../ZipArchive/stl/zippie/zippie_DLL.dsp | 224 +- .../ZipArchive/stl/zippie/zippie_DLL.dsw | 118 +- .../res/smpackage.ico | Bin .../res/smpackage.rc2 | 26 +- src/{smpackage => smpackagee}/resource.h | 0 src/{smpackage => smpackagee}/smpackage.ICO | Bin src/{smpackage => smpackagee}/smpackage.clw | 642 ++-- src/{smpackage => smpackagee}/smpackage.cpp | 0 src/{smpackage => smpackagee}/smpackage.h | 0 src/{smpackage => smpackagee}/smpackage.rc | 998 ++--- src/{smpackage => smpackagee}/smpackageUtil.h | 0 src/tests/00 README | 15 - src/tests/test_audio_readers.cpp | 646 ---- src/tests/test_file_errors.cpp | 459 --- src/tests/test_file_readers.cpp | 451 --- src/tests/test_misc.cpp | 64 - src/tests/test_misc.h | 11 - src/tests/test_threads.cpp | 330 -- src/tests/test_timing_data.cpp | 161 - src/tests/test_vector.cpp | 330 -- src/update_check/check_sm5.php | 12 - src/verify_signature/cpp_cryptopp/test.cpp | 102 - .../csharp/VerifySignature.cs | 395 -- .../java/VerifySignature.java | 218 -- 124 files changed, 4471 insertions(+), 7751 deletions(-) rename src/{irc => ircc}/appveyor.cpp (100%) delete mode 100644 src/smpackage/ZipArchive/Linux/Makefile rename src/{smpackage => smpackagee}/ChangeGameSettings.cpp (100%) rename src/{smpackage => smpackagee}/ChangeGameSettings.h (100%) rename src/{smpackage => smpackagee}/CreateLanguageDlg.cpp (100%) rename src/{smpackage => smpackagee}/CreateLanguageDlg.h (100%) rename src/{smpackage => smpackagee}/EditInsallations.cpp (100%) rename src/{smpackage => smpackagee}/EditInsallations.h (100%) rename src/{smpackage => smpackagee}/EnterComment.cpp (100%) rename src/{smpackage => smpackagee}/EnterComment.h (100%) rename src/{smpackage => smpackagee}/EnterName.cpp (100%) rename src/{smpackage => smpackagee}/EnterName.h (100%) rename src/{smpackage => smpackagee}/LanguagesDlg.cpp (100%) rename src/{smpackage => smpackagee}/LanguagesDlg.h (100%) rename src/{smpackage => smpackagee}/MainMenuDlg.cpp (100%) rename src/{smpackage => smpackagee}/MainMenuDlg.h (100%) rename src/{smpackage => smpackagee}/SMPackageInstallDlg.cpp (100%) rename src/{smpackage => smpackagee}/SMPackageInstallDlg.h (100%) rename src/{smpackage => smpackagee}/SMPackageUtil.cpp (100%) rename src/{smpackage => smpackagee}/ShowComment.cpp (100%) rename src/{smpackage => smpackagee}/ShowComment.h (100%) rename src/{smpackage => smpackagee}/SmpackageExportDlg.cpp (100%) rename src/{smpackage => smpackagee}/SmpackageExportDlg.h (100%) rename src/{smpackage => smpackagee}/StdAfx.cpp (100%) rename src/{smpackage => smpackagee}/StdAfx.h (100%) rename src/{smpackage => smpackagee}/TreeCtrlEx.cpp (100%) rename src/{smpackage => smpackagee}/TreeCtrlEx.h (100%) rename src/{smpackage => smpackagee}/UninstallOld.cpp (100%) rename src/{smpackage => smpackagee}/UninstallOld.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/Appnote.txt (100%) rename src/{smpackage => smpackagee}/ZipArchive/ChangeLog.txt (100%) rename src/{smpackage => smpackagee}/ZipArchive/License.txt (100%) rename src/{smpackage => smpackagee}/ZipArchive/Linux/ZipFileMapping.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/Linux/ZipPathComponent.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/Linux/ZipPlatform.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/Readme.txt (100%) rename src/{smpackage => smpackagee}/ZipArchive/StdAfx.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/StdAfx.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/Windows/ZipFileMapping.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/Windows/ZipPathComponent.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/Windows/ZipPlatform.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipAbstractFile.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipArchive-net2003.vcproj (96%) rename src/{smpackage => smpackagee}/ZipArchive/ZipArchive-net2008.vcproj (96%) rename src/{smpackage => smpackagee}/ZipArchive/ZipArchive.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipArchive.dox (97%) rename src/{smpackage => smpackagee}/ZipArchive/ZipArchive.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipArchive.rc (95%) rename src/{smpackage => smpackagee}/ZipArchive/ZipAutoBuffer.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipAutoBuffer.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipBaseException.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipCentralDir.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipCentralDir.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipCollections.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipCompatibility.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipCompatibility.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipException.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipException.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipExport.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipFile.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipFile.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipFileHeader.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipFileHeader.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipFileMapping.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipMemFile.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipMemFile.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipPathComponent.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipPathComponent.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipPlatform.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipPlatform.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipPlatformComm.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipStorage.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipStorage.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipString.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/ZipString.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/__Windows_MFC.zcfg (92%) rename src/{smpackage => smpackagee}/ZipArchive/_copy_from_Win-MFC.bat (95%) rename src/{smpackage => smpackagee}/ZipArchive/_copy_from_Win-STL.bat (95%) rename src/{smpackage => smpackagee}/ZipArchive/_version.txt (100%) rename src/{smpackage => smpackagee}/ZipArchive/borland.zip (100%) rename src/{smpackage => smpackagee}/ZipArchive/faq.txt (100%) rename src/{smpackage => smpackagee}/ZipArchive/gpl.txt (100%) rename src/{smpackage => smpackagee}/ZipArchive/mfc/ZipBaseException.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/mfc/ZipCollections.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/mfc/ZipFile.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/mfc/ZipFile.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/mfc/ZipString.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/mfc/stdafx.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/resource.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/ZipBaseException.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/ZipCollections.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/ZipFile.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/ZipFile.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/ZipString.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/stdafx.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/zippie/CmdLine.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/zippie/CmdLine.h (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/zippie/zippie.cpp (100%) rename src/{smpackage => smpackagee}/ZipArchive/stl/zippie/zippie.dsp (97%) rename src/{smpackage => smpackagee}/ZipArchive/stl/zippie/zippie.dsw (94%) rename src/{smpackage => smpackagee}/ZipArchive/stl/zippie/zippie_DLL.dsp (97%) rename src/{smpackage => smpackagee}/ZipArchive/stl/zippie/zippie_DLL.dsw (94%) rename src/{smpackage => smpackagee}/res/smpackage.ico (100%) rename src/{smpackage => smpackagee}/res/smpackage.rc2 (96%) rename src/{smpackage => smpackagee}/resource.h (100%) rename src/{smpackage => smpackagee}/smpackage.ICO (100%) rename src/{smpackage => smpackagee}/smpackage.clw (96%) rename src/{smpackage => smpackagee}/smpackage.cpp (100%) rename src/{smpackage => smpackagee}/smpackage.h (100%) rename src/{smpackage => smpackagee}/smpackage.rc (97%) rename src/{smpackage => smpackagee}/smpackageUtil.h (100%) delete mode 100644 src/tests/00 README delete mode 100644 src/tests/test_audio_readers.cpp delete mode 100644 src/tests/test_file_errors.cpp delete mode 100644 src/tests/test_file_readers.cpp delete mode 100644 src/tests/test_misc.cpp delete mode 100644 src/tests/test_misc.h delete mode 100644 src/tests/test_threads.cpp delete mode 100644 src/tests/test_timing_data.cpp delete mode 100644 src/tests/test_vector.cpp delete mode 100644 src/update_check/check_sm5.php delete mode 100644 src/verify_signature/cpp_cryptopp/test.cpp delete mode 100644 src/verify_signature/csharp/VerifySignature.cs delete mode 100644 src/verify_signature/java/VerifySignature.java diff --git a/src/irc/appveyor.cpp b/src/ircc/appveyor.cpp similarity index 100% rename from src/irc/appveyor.cpp rename to src/ircc/appveyor.cpp diff --git a/src/smpackage/ZipArchive/Linux/Makefile b/src/smpackage/ZipArchive/Linux/Makefile deleted file mode 100644 index 3afd97a2cc..0000000000 --- a/src/smpackage/ZipArchive/Linux/Makefile +++ /dev/null @@ -1,86 +0,0 @@ -# Makefile for ZipArchive library -# Copyright (C) 2000-2003 Tadeusz Dracz -# For conditions of distribution and use, see copyright notice in License.txt -# To install to /usr/lib and /usr/include, type: -# make install -# to install to a different directory change prefix - - - -CC=g++ -CCC=cc - -#FLAGSD = -g -FLAGSD = - -ZIPARCHLIB = libziparch.a - -ZIPPIELOCATION = stl/zippie/ - -prefix = /usr -libdir = ${prefix}/lib -includedir = ${prefix}/include -zipardir = $(includedir)/ziparchive - -AR=ar rc -RANLIB=ranlib - -.SUFFIXES: .c .cpp -.c.o: - $(CCC) -c -I. -o $*.o $< -.cpp.o: - $(CC) $(FLAGSD) -c -I. $< - -OBJS = ZipArchive.o ZipAutoBuffer.o ZipCentralDir.o \ -ZipCompatibility.o ZipException.o ZipFile.o ZipFileHeader.o \ -ZipMemFile.o ZipPathComponent.o ZipPlatform.o ZipPlatformComm.o \ -ZipStorage.o ZipString.o - -#OBJSZLIB = zlib/adler32.o zlib/compress.o zlib/crc32.o zlib/uncompr.o zlib/deflate.o zlib/trees.o \ -zlib/zutil.o zlib/inflate.o zlib/infblock.o zlib/inftrees.o zlib/infcodes.o zlib/infutil.o zlib/inffast.o - -OBJSZLIB = - -$(ZIPARCHLIB): $(OBJS) $(OBJSZLIB) - $(AR) $@ $(OBJS) $(OBJSZLIB) - -@ ($(RANLIB) $@ || true) >/dev/null 2>&1 - -ZipArchive.o: ZipArchive.h -ZipAutoBuffer.o: ZipAutoBuffer.h -ZipCentralDir.o: ZipCentralDir.h -ZipCompatibility.o: ZipCompatibility.h -ZipException.o: ZipException.h -ZipFile.o: ZipFile.h -ZipFileHeader.o: ZipFileHeader.h -ZipMemFile.o: ZipMemFile.h -ZipPathComponent.o: ZipPathComponent.h -ZipPlatform.o: ZipPlatform.h -ZipStorage.o: ZipStorage.h -ZipString.o: ZipString.h - -clean: - -rm -f *.o *~ $(ZIPARCHLIB) - -zippie: - - $(CC) -I$(zipardir) $(FLAGSD) -o zippie $(ZIPPIELOCATION)zippie.cpp $(ZIPPIELOCATION)CmdLine.cpp -lz -lstdc++ -lziparch -# $(CC) -I$(zipardir) $(FLAGSD) -o zippie ZIPPIELOCATION)zippie.cpp $(ZIPPIELOCATION)CmdLine.cpp -lstdc++ -lziparch -cleanzippie: - -rm -f zippie - -install: - -@if [ ! -d $(includedir) ]; then mkdir $(includedir); fi - -@if [ ! -d $(libdir) ]; then mkdir $(libdir); fi - -@if [ ! -d $(zipardir) ]; then mkdir $(zipardir); fi - cp libziparch.a $(libdir) - chmod 755 $(libdir)/$(ZIPARCHLIB) - cp *.h $(zipardir) - chmod 644 $(zipardir)/*h - -uninstall: - rm -f $(zipardir)/*h - rm -f $(libdir)/$(ZIPARCHLIB) - rmdir $(zipardir) - - - diff --git a/src/smpackage/ChangeGameSettings.cpp b/src/smpackagee/ChangeGameSettings.cpp similarity index 100% rename from src/smpackage/ChangeGameSettings.cpp rename to src/smpackagee/ChangeGameSettings.cpp diff --git a/src/smpackage/ChangeGameSettings.h b/src/smpackagee/ChangeGameSettings.h similarity index 100% rename from src/smpackage/ChangeGameSettings.h rename to src/smpackagee/ChangeGameSettings.h diff --git a/src/smpackage/CreateLanguageDlg.cpp b/src/smpackagee/CreateLanguageDlg.cpp similarity index 100% rename from src/smpackage/CreateLanguageDlg.cpp rename to src/smpackagee/CreateLanguageDlg.cpp diff --git a/src/smpackage/CreateLanguageDlg.h b/src/smpackagee/CreateLanguageDlg.h similarity index 100% rename from src/smpackage/CreateLanguageDlg.h rename to src/smpackagee/CreateLanguageDlg.h diff --git a/src/smpackage/EditInsallations.cpp b/src/smpackagee/EditInsallations.cpp similarity index 100% rename from src/smpackage/EditInsallations.cpp rename to src/smpackagee/EditInsallations.cpp diff --git a/src/smpackage/EditInsallations.h b/src/smpackagee/EditInsallations.h similarity index 100% rename from src/smpackage/EditInsallations.h rename to src/smpackagee/EditInsallations.h diff --git a/src/smpackage/EnterComment.cpp b/src/smpackagee/EnterComment.cpp similarity index 100% rename from src/smpackage/EnterComment.cpp rename to src/smpackagee/EnterComment.cpp diff --git a/src/smpackage/EnterComment.h b/src/smpackagee/EnterComment.h similarity index 100% rename from src/smpackage/EnterComment.h rename to src/smpackagee/EnterComment.h diff --git a/src/smpackage/EnterName.cpp b/src/smpackagee/EnterName.cpp similarity index 100% rename from src/smpackage/EnterName.cpp rename to src/smpackagee/EnterName.cpp diff --git a/src/smpackage/EnterName.h b/src/smpackagee/EnterName.h similarity index 100% rename from src/smpackage/EnterName.h rename to src/smpackagee/EnterName.h diff --git a/src/smpackage/LanguagesDlg.cpp b/src/smpackagee/LanguagesDlg.cpp similarity index 100% rename from src/smpackage/LanguagesDlg.cpp rename to src/smpackagee/LanguagesDlg.cpp diff --git a/src/smpackage/LanguagesDlg.h b/src/smpackagee/LanguagesDlg.h similarity index 100% rename from src/smpackage/LanguagesDlg.h rename to src/smpackagee/LanguagesDlg.h diff --git a/src/smpackage/MainMenuDlg.cpp b/src/smpackagee/MainMenuDlg.cpp similarity index 100% rename from src/smpackage/MainMenuDlg.cpp rename to src/smpackagee/MainMenuDlg.cpp diff --git a/src/smpackage/MainMenuDlg.h b/src/smpackagee/MainMenuDlg.h similarity index 100% rename from src/smpackage/MainMenuDlg.h rename to src/smpackagee/MainMenuDlg.h diff --git a/src/smpackage/SMPackageInstallDlg.cpp b/src/smpackagee/SMPackageInstallDlg.cpp similarity index 100% rename from src/smpackage/SMPackageInstallDlg.cpp rename to src/smpackagee/SMPackageInstallDlg.cpp diff --git a/src/smpackage/SMPackageInstallDlg.h b/src/smpackagee/SMPackageInstallDlg.h similarity index 100% rename from src/smpackage/SMPackageInstallDlg.h rename to src/smpackagee/SMPackageInstallDlg.h diff --git a/src/smpackage/SMPackageUtil.cpp b/src/smpackagee/SMPackageUtil.cpp similarity index 100% rename from src/smpackage/SMPackageUtil.cpp rename to src/smpackagee/SMPackageUtil.cpp diff --git a/src/smpackage/ShowComment.cpp b/src/smpackagee/ShowComment.cpp similarity index 100% rename from src/smpackage/ShowComment.cpp rename to src/smpackagee/ShowComment.cpp diff --git a/src/smpackage/ShowComment.h b/src/smpackagee/ShowComment.h similarity index 100% rename from src/smpackage/ShowComment.h rename to src/smpackagee/ShowComment.h diff --git a/src/smpackage/SmpackageExportDlg.cpp b/src/smpackagee/SmpackageExportDlg.cpp similarity index 100% rename from src/smpackage/SmpackageExportDlg.cpp rename to src/smpackagee/SmpackageExportDlg.cpp diff --git a/src/smpackage/SmpackageExportDlg.h b/src/smpackagee/SmpackageExportDlg.h similarity index 100% rename from src/smpackage/SmpackageExportDlg.h rename to src/smpackagee/SmpackageExportDlg.h diff --git a/src/smpackage/StdAfx.cpp b/src/smpackagee/StdAfx.cpp similarity index 100% rename from src/smpackage/StdAfx.cpp rename to src/smpackagee/StdAfx.cpp diff --git a/src/smpackage/StdAfx.h b/src/smpackagee/StdAfx.h similarity index 100% rename from src/smpackage/StdAfx.h rename to src/smpackagee/StdAfx.h diff --git a/src/smpackage/TreeCtrlEx.cpp b/src/smpackagee/TreeCtrlEx.cpp similarity index 100% rename from src/smpackage/TreeCtrlEx.cpp rename to src/smpackagee/TreeCtrlEx.cpp diff --git a/src/smpackage/TreeCtrlEx.h b/src/smpackagee/TreeCtrlEx.h similarity index 100% rename from src/smpackage/TreeCtrlEx.h rename to src/smpackagee/TreeCtrlEx.h diff --git a/src/smpackage/UninstallOld.cpp b/src/smpackagee/UninstallOld.cpp similarity index 100% rename from src/smpackage/UninstallOld.cpp rename to src/smpackagee/UninstallOld.cpp diff --git a/src/smpackage/UninstallOld.h b/src/smpackagee/UninstallOld.h similarity index 100% rename from src/smpackage/UninstallOld.h rename to src/smpackagee/UninstallOld.h diff --git a/src/smpackage/ZipArchive/Appnote.txt b/src/smpackagee/ZipArchive/Appnote.txt similarity index 100% rename from src/smpackage/ZipArchive/Appnote.txt rename to src/smpackagee/ZipArchive/Appnote.txt diff --git a/src/smpackage/ZipArchive/ChangeLog.txt b/src/smpackagee/ZipArchive/ChangeLog.txt similarity index 100% rename from src/smpackage/ZipArchive/ChangeLog.txt rename to src/smpackagee/ZipArchive/ChangeLog.txt diff --git a/src/smpackage/ZipArchive/License.txt b/src/smpackagee/ZipArchive/License.txt similarity index 100% rename from src/smpackage/ZipArchive/License.txt rename to src/smpackagee/ZipArchive/License.txt diff --git a/src/smpackage/ZipArchive/Linux/ZipFileMapping.h b/src/smpackagee/ZipArchive/Linux/ZipFileMapping.h similarity index 100% rename from src/smpackage/ZipArchive/Linux/ZipFileMapping.h rename to src/smpackagee/ZipArchive/Linux/ZipFileMapping.h diff --git a/src/smpackage/ZipArchive/Linux/ZipPathComponent.cpp b/src/smpackagee/ZipArchive/Linux/ZipPathComponent.cpp similarity index 100% rename from src/smpackage/ZipArchive/Linux/ZipPathComponent.cpp rename to src/smpackagee/ZipArchive/Linux/ZipPathComponent.cpp diff --git a/src/smpackage/ZipArchive/Linux/ZipPlatform.cpp b/src/smpackagee/ZipArchive/Linux/ZipPlatform.cpp similarity index 100% rename from src/smpackage/ZipArchive/Linux/ZipPlatform.cpp rename to src/smpackagee/ZipArchive/Linux/ZipPlatform.cpp diff --git a/src/smpackage/ZipArchive/Readme.txt b/src/smpackagee/ZipArchive/Readme.txt similarity index 100% rename from src/smpackage/ZipArchive/Readme.txt rename to src/smpackagee/ZipArchive/Readme.txt diff --git a/src/smpackage/ZipArchive/StdAfx.cpp b/src/smpackagee/ZipArchive/StdAfx.cpp similarity index 100% rename from src/smpackage/ZipArchive/StdAfx.cpp rename to src/smpackagee/ZipArchive/StdAfx.cpp diff --git a/src/smpackage/ZipArchive/StdAfx.h b/src/smpackagee/ZipArchive/StdAfx.h similarity index 100% rename from src/smpackage/ZipArchive/StdAfx.h rename to src/smpackagee/ZipArchive/StdAfx.h diff --git a/src/smpackage/ZipArchive/Windows/ZipFileMapping.h b/src/smpackagee/ZipArchive/Windows/ZipFileMapping.h similarity index 100% rename from src/smpackage/ZipArchive/Windows/ZipFileMapping.h rename to src/smpackagee/ZipArchive/Windows/ZipFileMapping.h diff --git a/src/smpackage/ZipArchive/Windows/ZipPathComponent.cpp b/src/smpackagee/ZipArchive/Windows/ZipPathComponent.cpp similarity index 100% rename from src/smpackage/ZipArchive/Windows/ZipPathComponent.cpp rename to src/smpackagee/ZipArchive/Windows/ZipPathComponent.cpp diff --git a/src/smpackage/ZipArchive/Windows/ZipPlatform.cpp b/src/smpackagee/ZipArchive/Windows/ZipPlatform.cpp similarity index 100% rename from src/smpackage/ZipArchive/Windows/ZipPlatform.cpp rename to src/smpackagee/ZipArchive/Windows/ZipPlatform.cpp diff --git a/src/smpackage/ZipArchive/ZipAbstractFile.h b/src/smpackagee/ZipArchive/ZipAbstractFile.h similarity index 100% rename from src/smpackage/ZipArchive/ZipAbstractFile.h rename to src/smpackagee/ZipArchive/ZipAbstractFile.h diff --git a/src/smpackage/ZipArchive/ZipArchive-net2003.vcproj b/src/smpackagee/ZipArchive/ZipArchive-net2003.vcproj similarity index 96% rename from src/smpackage/ZipArchive/ZipArchive-net2003.vcproj rename to src/smpackagee/ZipArchive/ZipArchive-net2003.vcproj index 0770070d68..174388a48a 100644 --- a/src/smpackage/ZipArchive/ZipArchive-net2003.vcproj +++ b/src/smpackagee/ZipArchive/ZipArchive-net2003.vcproj @@ -1,1285 +1,1285 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/smpackage/ZipArchive/ZipArchive-net2008.vcproj b/src/smpackagee/ZipArchive/ZipArchive-net2008.vcproj similarity index 96% rename from src/smpackage/ZipArchive/ZipArchive-net2008.vcproj rename to src/smpackagee/ZipArchive/ZipArchive-net2008.vcproj index dc15524a56..1874a384db 100644 --- a/src/smpackage/ZipArchive/ZipArchive-net2008.vcproj +++ b/src/smpackagee/ZipArchive/ZipArchive-net2008.vcproj @@ -1,1686 +1,1686 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/smpackage/ZipArchive/ZipArchive.cpp b/src/smpackagee/ZipArchive/ZipArchive.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipArchive.cpp rename to src/smpackagee/ZipArchive/ZipArchive.cpp diff --git a/src/smpackage/ZipArchive/ZipArchive.dox b/src/smpackagee/ZipArchive/ZipArchive.dox similarity index 97% rename from src/smpackage/ZipArchive/ZipArchive.dox rename to src/smpackagee/ZipArchive/ZipArchive.dox index 4fe506a5e8..394c02ddcb 100644 --- a/src/smpackage/ZipArchive/ZipArchive.dox +++ b/src/smpackagee/ZipArchive/ZipArchive.dox @@ -1,221 +1,221 @@ -# Doxyfile 1.3.2 - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = ZipArchive -PROJECT_NUMBER = -OUTPUT_DIRECTORY = .\Doc -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = YES -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = NO -STRIP_FROM_PATH = $(PWD)/ -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -SHORT_NAMES = NO -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -JAVADOC_AUTOBRIEF = YES -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -TAB_SIZE = 1 -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ALIASES = -ENABLED_SECTIONS = YES -MAX_INITIALIZER_LINES = 30 -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -SHOW_USED_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = NO -WARN_IF_DOC_ERROR = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = .\ZipArchive.h \ - .\ZipAutoBuffer.h \ - .\ZipCentralDir.h \ - .\ZipCompatibility.h \ - .\ZipException.h \ - .\ZipFileHeader.h \ - .\ZipPlatform.h \ - .\ZipMemFile.h \ - .\ZipPathComponent.h \ - .\ZipStorage.h \ - .\changelog.txt \ - .\faq.txt \ - .\License.txt \ - .\gpl.txt \ - .\Readme.txt -FILE_PATTERNS = -RECURSIVE = NO -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -VERBATIM_HEADERS = YES -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = CZip -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = . -HTML_FILE_EXTENSION = .html -HTML_HEADER = "c:\Program Files\Doxygen\header.html" -HTML_FOOTER = "c:\Program Files\Doxygen\footer.html" -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = YES -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = YES -BINARY_TOC = YES -TOC_EXPAND = YES -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = NO -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = YES -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = NO -ALLEXTERNALS = YES -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = NO -UML_LOOK = YES -TEMPLATE_RELATIONS = YES -INCLUDE_GRAPH = NO -INCLUDED_BY_GRAPH = NO -CALL_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DOT_IMAGE_FORMAT = gif -DOT_PATH = "c:/Program Files/ATT/Graphviz/bin/" -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 0 -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO -CGI_NAME = search.cgi -CGI_URL = -DOC_URL = -DOC_ABSPATH = -BIN_ABSPATH = /usr/local/bin/ -EXT_DOC_PATHS = +# Doxyfile 1.3.2 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = ZipArchive +PROJECT_NUMBER = +OUTPUT_DIRECTORY = .\Doc +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = YES +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = $(PWD)/ +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 1 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +ENABLED_SECTIONS = YES +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = NO +WARN_IF_DOC_ERROR = YES +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = .\ZipArchive.h \ + .\ZipAutoBuffer.h \ + .\ZipCentralDir.h \ + .\ZipCompatibility.h \ + .\ZipException.h \ + .\ZipFileHeader.h \ + .\ZipPlatform.h \ + .\ZipMemFile.h \ + .\ZipPathComponent.h \ + .\ZipStorage.h \ + .\changelog.txt \ + .\faq.txt \ + .\License.txt \ + .\gpl.txt \ + .\Readme.txt +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = CZip +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = . +HTML_FILE_EXTENSION = .html +HTML_HEADER = "c:\Program Files\Doxygen\header.html" +HTML_FOOTER = "c:\Program Files\Doxygen\footer.html" +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = YES +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = YES +BINARY_TOC = YES +TOC_EXPAND = YES +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = NO +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = YES +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = NO +ALLEXTERNALS = YES +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = NO +UML_LOOK = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = gif +DOT_PATH = "c:/Program Files/ATT/Graphviz/bin/" +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 0 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = search.cgi +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = /usr/local/bin/ +EXT_DOC_PATHS = diff --git a/src/smpackage/ZipArchive/ZipArchive.h b/src/smpackagee/ZipArchive/ZipArchive.h similarity index 100% rename from src/smpackage/ZipArchive/ZipArchive.h rename to src/smpackagee/ZipArchive/ZipArchive.h diff --git a/src/smpackage/ZipArchive/ZipArchive.rc b/src/smpackagee/ZipArchive/ZipArchive.rc similarity index 95% rename from src/smpackage/ZipArchive/ZipArchive.rc rename to src/smpackagee/ZipArchive/ZipArchive.rc index 7ac09bb6cc..6d9ca8bc5b 100644 --- a/src/smpackage/ZipArchive/ZipArchive.rc +++ b/src/smpackagee/ZipArchive/ZipArchive.rc @@ -1,109 +1,109 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Polish resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK) -#ifdef _WIN32 -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT -#pragma code_page(1250) -#endif //_WIN32 - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,3,0,0 - PRODUCTVERSION 2,3,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "http://www.artpol-software.com\0" - VALUE "CompanyName", "Artpol Software\0" - VALUE "FileDescription", "ZipArchive - zip compression library\0" - VALUE "FileVersion", "2.3\0" - VALUE "InternalName", "ZipArchive\0" - VALUE "LegalCopyright", "Copyright © 2000 - 2003 Tadeusz Dracz\0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "ZipArchive.dll\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", " ZipArchive library\0" - VALUE "ProductVersion", "2, 3, 0, 0\0" - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // Polish resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Polish resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK) +#ifdef _WIN32 +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 2,3,0,0 + PRODUCTVERSION 2,3,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "http://www.artpol-software.com\0" + VALUE "CompanyName", "Artpol Software\0" + VALUE "FileDescription", "ZipArchive - zip compression library\0" + VALUE "FileVersion", "2.3\0" + VALUE "InternalName", "ZipArchive\0" + VALUE "LegalCopyright", "Copyright © 2000 - 2003 Tadeusz Dracz\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "ZipArchive.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", " ZipArchive library\0" + VALUE "ProductVersion", "2, 3, 0, 0\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // Polish resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/smpackage/ZipArchive/ZipAutoBuffer.cpp b/src/smpackagee/ZipArchive/ZipAutoBuffer.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipAutoBuffer.cpp rename to src/smpackagee/ZipArchive/ZipAutoBuffer.cpp diff --git a/src/smpackage/ZipArchive/ZipAutoBuffer.h b/src/smpackagee/ZipArchive/ZipAutoBuffer.h similarity index 100% rename from src/smpackage/ZipArchive/ZipAutoBuffer.h rename to src/smpackagee/ZipArchive/ZipAutoBuffer.h diff --git a/src/smpackage/ZipArchive/ZipBaseException.h b/src/smpackagee/ZipArchive/ZipBaseException.h similarity index 100% rename from src/smpackage/ZipArchive/ZipBaseException.h rename to src/smpackagee/ZipArchive/ZipBaseException.h diff --git a/src/smpackage/ZipArchive/ZipCentralDir.cpp b/src/smpackagee/ZipArchive/ZipCentralDir.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipCentralDir.cpp rename to src/smpackagee/ZipArchive/ZipCentralDir.cpp diff --git a/src/smpackage/ZipArchive/ZipCentralDir.h b/src/smpackagee/ZipArchive/ZipCentralDir.h similarity index 100% rename from src/smpackage/ZipArchive/ZipCentralDir.h rename to src/smpackagee/ZipArchive/ZipCentralDir.h diff --git a/src/smpackage/ZipArchive/ZipCollections.h b/src/smpackagee/ZipArchive/ZipCollections.h similarity index 100% rename from src/smpackage/ZipArchive/ZipCollections.h rename to src/smpackagee/ZipArchive/ZipCollections.h diff --git a/src/smpackage/ZipArchive/ZipCompatibility.cpp b/src/smpackagee/ZipArchive/ZipCompatibility.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipCompatibility.cpp rename to src/smpackagee/ZipArchive/ZipCompatibility.cpp diff --git a/src/smpackage/ZipArchive/ZipCompatibility.h b/src/smpackagee/ZipArchive/ZipCompatibility.h similarity index 100% rename from src/smpackage/ZipArchive/ZipCompatibility.h rename to src/smpackagee/ZipArchive/ZipCompatibility.h diff --git a/src/smpackage/ZipArchive/ZipException.cpp b/src/smpackagee/ZipArchive/ZipException.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipException.cpp rename to src/smpackagee/ZipArchive/ZipException.cpp diff --git a/src/smpackage/ZipArchive/ZipException.h b/src/smpackagee/ZipArchive/ZipException.h similarity index 100% rename from src/smpackage/ZipArchive/ZipException.h rename to src/smpackagee/ZipArchive/ZipException.h diff --git a/src/smpackage/ZipArchive/ZipExport.h b/src/smpackagee/ZipArchive/ZipExport.h similarity index 100% rename from src/smpackage/ZipArchive/ZipExport.h rename to src/smpackagee/ZipArchive/ZipExport.h diff --git a/src/smpackage/ZipArchive/ZipFile.cpp b/src/smpackagee/ZipArchive/ZipFile.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipFile.cpp rename to src/smpackagee/ZipArchive/ZipFile.cpp diff --git a/src/smpackage/ZipArchive/ZipFile.h b/src/smpackagee/ZipArchive/ZipFile.h similarity index 100% rename from src/smpackage/ZipArchive/ZipFile.h rename to src/smpackagee/ZipArchive/ZipFile.h diff --git a/src/smpackage/ZipArchive/ZipFileHeader.cpp b/src/smpackagee/ZipArchive/ZipFileHeader.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipFileHeader.cpp rename to src/smpackagee/ZipArchive/ZipFileHeader.cpp diff --git a/src/smpackage/ZipArchive/ZipFileHeader.h b/src/smpackagee/ZipArchive/ZipFileHeader.h similarity index 100% rename from src/smpackage/ZipArchive/ZipFileHeader.h rename to src/smpackagee/ZipArchive/ZipFileHeader.h diff --git a/src/smpackage/ZipArchive/ZipFileMapping.h b/src/smpackagee/ZipArchive/ZipFileMapping.h similarity index 100% rename from src/smpackage/ZipArchive/ZipFileMapping.h rename to src/smpackagee/ZipArchive/ZipFileMapping.h diff --git a/src/smpackage/ZipArchive/ZipMemFile.cpp b/src/smpackagee/ZipArchive/ZipMemFile.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipMemFile.cpp rename to src/smpackagee/ZipArchive/ZipMemFile.cpp diff --git a/src/smpackage/ZipArchive/ZipMemFile.h b/src/smpackagee/ZipArchive/ZipMemFile.h similarity index 100% rename from src/smpackage/ZipArchive/ZipMemFile.h rename to src/smpackagee/ZipArchive/ZipMemFile.h diff --git a/src/smpackage/ZipArchive/ZipPathComponent.cpp b/src/smpackagee/ZipArchive/ZipPathComponent.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipPathComponent.cpp rename to src/smpackagee/ZipArchive/ZipPathComponent.cpp diff --git a/src/smpackage/ZipArchive/ZipPathComponent.h b/src/smpackagee/ZipArchive/ZipPathComponent.h similarity index 100% rename from src/smpackage/ZipArchive/ZipPathComponent.h rename to src/smpackagee/ZipArchive/ZipPathComponent.h diff --git a/src/smpackage/ZipArchive/ZipPlatform.cpp b/src/smpackagee/ZipArchive/ZipPlatform.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipPlatform.cpp rename to src/smpackagee/ZipArchive/ZipPlatform.cpp diff --git a/src/smpackage/ZipArchive/ZipPlatform.h b/src/smpackagee/ZipArchive/ZipPlatform.h similarity index 100% rename from src/smpackage/ZipArchive/ZipPlatform.h rename to src/smpackagee/ZipArchive/ZipPlatform.h diff --git a/src/smpackage/ZipArchive/ZipPlatformComm.cpp b/src/smpackagee/ZipArchive/ZipPlatformComm.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipPlatformComm.cpp rename to src/smpackagee/ZipArchive/ZipPlatformComm.cpp diff --git a/src/smpackage/ZipArchive/ZipStorage.cpp b/src/smpackagee/ZipArchive/ZipStorage.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipStorage.cpp rename to src/smpackagee/ZipArchive/ZipStorage.cpp diff --git a/src/smpackage/ZipArchive/ZipStorage.h b/src/smpackagee/ZipArchive/ZipStorage.h similarity index 100% rename from src/smpackage/ZipArchive/ZipStorage.h rename to src/smpackagee/ZipArchive/ZipStorage.h diff --git a/src/smpackage/ZipArchive/ZipString.cpp b/src/smpackagee/ZipArchive/ZipString.cpp similarity index 100% rename from src/smpackage/ZipArchive/ZipString.cpp rename to src/smpackagee/ZipArchive/ZipString.cpp diff --git a/src/smpackage/ZipArchive/ZipString.h b/src/smpackagee/ZipArchive/ZipString.h similarity index 100% rename from src/smpackage/ZipArchive/ZipString.h rename to src/smpackagee/ZipArchive/ZipString.h diff --git a/src/smpackage/ZipArchive/__Windows_MFC.zcfg b/src/smpackagee/ZipArchive/__Windows_MFC.zcfg similarity index 92% rename from src/smpackage/ZipArchive/__Windows_MFC.zcfg rename to src/smpackagee/ZipArchive/__Windows_MFC.zcfg index e00a2183a5..dc711df027 100644 --- a/src/smpackage/ZipArchive/__Windows_MFC.zcfg +++ b/src/smpackagee/ZipArchive/__Windows_MFC.zcfg @@ -1 +1 @@ -Windows MFC +Windows MFC diff --git a/src/smpackage/ZipArchive/_copy_from_Win-MFC.bat b/src/smpackagee/ZipArchive/_copy_from_Win-MFC.bat similarity index 95% rename from src/smpackage/ZipArchive/_copy_from_Win-MFC.bat rename to src/smpackagee/ZipArchive/_copy_from_Win-MFC.bat index 855f39f5b2..adac7df4d9 100644 --- a/src/smpackage/ZipArchive/_copy_from_Win-MFC.bat +++ b/src/smpackagee/ZipArchive/_copy_from_Win-MFC.bat @@ -1,5 +1,5 @@ -@echo off -copy Windows\*.* *.* -copy mfc\*.* *.* -del __*.zcfg -echo Windows MFC > __Windows_MFC.zcfg +@echo off +copy Windows\*.* *.* +copy mfc\*.* *.* +del __*.zcfg +echo Windows MFC > __Windows_MFC.zcfg diff --git a/src/smpackage/ZipArchive/_copy_from_Win-STL.bat b/src/smpackagee/ZipArchive/_copy_from_Win-STL.bat similarity index 95% rename from src/smpackage/ZipArchive/_copy_from_Win-STL.bat rename to src/smpackagee/ZipArchive/_copy_from_Win-STL.bat index 89ed06bb89..88f426740b 100644 --- a/src/smpackage/ZipArchive/_copy_from_Win-STL.bat +++ b/src/smpackagee/ZipArchive/_copy_from_Win-STL.bat @@ -1,5 +1,5 @@ -@echo off -copy Windows\*.* *.* -copy stl\*.* *.* -del __*.zcfg -echo Windows STL > __Windows_STL.zcfg +@echo off +copy Windows\*.* *.* +copy stl\*.* *.* +del __*.zcfg +echo Windows STL > __Windows_STL.zcfg diff --git a/src/smpackage/ZipArchive/_version.txt b/src/smpackagee/ZipArchive/_version.txt similarity index 100% rename from src/smpackage/ZipArchive/_version.txt rename to src/smpackagee/ZipArchive/_version.txt diff --git a/src/smpackage/ZipArchive/borland.zip b/src/smpackagee/ZipArchive/borland.zip similarity index 100% rename from src/smpackage/ZipArchive/borland.zip rename to src/smpackagee/ZipArchive/borland.zip diff --git a/src/smpackage/ZipArchive/faq.txt b/src/smpackagee/ZipArchive/faq.txt similarity index 100% rename from src/smpackage/ZipArchive/faq.txt rename to src/smpackagee/ZipArchive/faq.txt diff --git a/src/smpackage/ZipArchive/gpl.txt b/src/smpackagee/ZipArchive/gpl.txt similarity index 100% rename from src/smpackage/ZipArchive/gpl.txt rename to src/smpackagee/ZipArchive/gpl.txt diff --git a/src/smpackage/ZipArchive/mfc/ZipBaseException.h b/src/smpackagee/ZipArchive/mfc/ZipBaseException.h similarity index 100% rename from src/smpackage/ZipArchive/mfc/ZipBaseException.h rename to src/smpackagee/ZipArchive/mfc/ZipBaseException.h diff --git a/src/smpackage/ZipArchive/mfc/ZipCollections.h b/src/smpackagee/ZipArchive/mfc/ZipCollections.h similarity index 100% rename from src/smpackage/ZipArchive/mfc/ZipCollections.h rename to src/smpackagee/ZipArchive/mfc/ZipCollections.h diff --git a/src/smpackage/ZipArchive/mfc/ZipFile.cpp b/src/smpackagee/ZipArchive/mfc/ZipFile.cpp similarity index 100% rename from src/smpackage/ZipArchive/mfc/ZipFile.cpp rename to src/smpackagee/ZipArchive/mfc/ZipFile.cpp diff --git a/src/smpackage/ZipArchive/mfc/ZipFile.h b/src/smpackagee/ZipArchive/mfc/ZipFile.h similarity index 100% rename from src/smpackage/ZipArchive/mfc/ZipFile.h rename to src/smpackagee/ZipArchive/mfc/ZipFile.h diff --git a/src/smpackage/ZipArchive/mfc/ZipString.h b/src/smpackagee/ZipArchive/mfc/ZipString.h similarity index 100% rename from src/smpackage/ZipArchive/mfc/ZipString.h rename to src/smpackagee/ZipArchive/mfc/ZipString.h diff --git a/src/smpackage/ZipArchive/mfc/stdafx.h b/src/smpackagee/ZipArchive/mfc/stdafx.h similarity index 100% rename from src/smpackage/ZipArchive/mfc/stdafx.h rename to src/smpackagee/ZipArchive/mfc/stdafx.h diff --git a/src/smpackage/ZipArchive/resource.h b/src/smpackagee/ZipArchive/resource.h similarity index 100% rename from src/smpackage/ZipArchive/resource.h rename to src/smpackagee/ZipArchive/resource.h diff --git a/src/smpackage/ZipArchive/stl/ZipBaseException.h b/src/smpackagee/ZipArchive/stl/ZipBaseException.h similarity index 100% rename from src/smpackage/ZipArchive/stl/ZipBaseException.h rename to src/smpackagee/ZipArchive/stl/ZipBaseException.h diff --git a/src/smpackage/ZipArchive/stl/ZipCollections.h b/src/smpackagee/ZipArchive/stl/ZipCollections.h similarity index 100% rename from src/smpackage/ZipArchive/stl/ZipCollections.h rename to src/smpackagee/ZipArchive/stl/ZipCollections.h diff --git a/src/smpackage/ZipArchive/stl/ZipFile.cpp b/src/smpackagee/ZipArchive/stl/ZipFile.cpp similarity index 100% rename from src/smpackage/ZipArchive/stl/ZipFile.cpp rename to src/smpackagee/ZipArchive/stl/ZipFile.cpp diff --git a/src/smpackage/ZipArchive/stl/ZipFile.h b/src/smpackagee/ZipArchive/stl/ZipFile.h similarity index 100% rename from src/smpackage/ZipArchive/stl/ZipFile.h rename to src/smpackagee/ZipArchive/stl/ZipFile.h diff --git a/src/smpackage/ZipArchive/stl/ZipString.h b/src/smpackagee/ZipArchive/stl/ZipString.h similarity index 100% rename from src/smpackage/ZipArchive/stl/ZipString.h rename to src/smpackagee/ZipArchive/stl/ZipString.h diff --git a/src/smpackage/ZipArchive/stl/stdafx.h b/src/smpackagee/ZipArchive/stl/stdafx.h similarity index 100% rename from src/smpackage/ZipArchive/stl/stdafx.h rename to src/smpackagee/ZipArchive/stl/stdafx.h diff --git a/src/smpackage/ZipArchive/stl/zippie/CmdLine.cpp b/src/smpackagee/ZipArchive/stl/zippie/CmdLine.cpp similarity index 100% rename from src/smpackage/ZipArchive/stl/zippie/CmdLine.cpp rename to src/smpackagee/ZipArchive/stl/zippie/CmdLine.cpp diff --git a/src/smpackage/ZipArchive/stl/zippie/CmdLine.h b/src/smpackagee/ZipArchive/stl/zippie/CmdLine.h similarity index 100% rename from src/smpackage/ZipArchive/stl/zippie/CmdLine.h rename to src/smpackagee/ZipArchive/stl/zippie/CmdLine.h diff --git a/src/smpackage/ZipArchive/stl/zippie/zippie.cpp b/src/smpackagee/ZipArchive/stl/zippie/zippie.cpp similarity index 100% rename from src/smpackage/ZipArchive/stl/zippie/zippie.cpp rename to src/smpackagee/ZipArchive/stl/zippie/zippie.cpp diff --git a/src/smpackage/ZipArchive/stl/zippie/zippie.dsp b/src/smpackagee/ZipArchive/stl/zippie/zippie.dsp similarity index 97% rename from src/smpackage/ZipArchive/stl/zippie/zippie.dsp rename to src/smpackagee/ZipArchive/stl/zippie/zippie.dsp index 0405e14370..288dc3bfb6 100644 --- a/src/smpackage/ZipArchive/stl/zippie/zippie.dsp +++ b/src/smpackagee/ZipArchive/stl/zippie/zippie.dsp @@ -1,111 +1,111 @@ -# Microsoft Developer Studio Project File - Name="zippie" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=zippie - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "zippie.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "zippie.mak" CFG="zippie - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "zippie - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "zippie - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName ""$/zippie", BGAAAAAA" -# PROP Scc_LocalPath "." -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "zippie - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "NDEBUG" -# ADD RSC /l 0x415 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "zippie - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "_DEBUG" -# ADD RSC /l 0x415 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "zippie - Win32 Release" -# Name "zippie - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\CmdLine.cpp -# End Source File -# Begin Source File - -SOURCE=.\zippie.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\CmdLine.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="zippie" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=zippie - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "zippie.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "zippie.mak" CFG="zippie - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "zippie - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "zippie - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName ""$/zippie", BGAAAAAA" +# PROP Scc_LocalPath "." +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "zippie - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x415 /d "NDEBUG" +# ADD RSC /l 0x415 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "zippie - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x415 /d "_DEBUG" +# ADD RSC /l 0x415 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "zippie - Win32 Release" +# Name "zippie - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\CmdLine.cpp +# End Source File +# Begin Source File + +SOURCE=.\zippie.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\CmdLine.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/src/smpackage/ZipArchive/stl/zippie/zippie.dsw b/src/smpackagee/ZipArchive/stl/zippie/zippie.dsw similarity index 94% rename from src/smpackage/ZipArchive/stl/zippie/zippie.dsw rename to src/smpackagee/ZipArchive/stl/zippie/zippie.dsw index 60781cfa09..032bc18743 100644 --- a/src/smpackage/ZipArchive/stl/zippie/zippie.dsw +++ b/src/smpackagee/ZipArchive/stl/zippie/zippie.dsw @@ -1,44 +1,44 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "ZipArchive"="..\..\ZipArchive_STL.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "zippie"=".\zippie.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name ZipArchive - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ZipArchive"="..\..\ZipArchive_STL.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "zippie"=".\zippie.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ZipArchive + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/smpackage/ZipArchive/stl/zippie/zippie_DLL.dsp b/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsp similarity index 97% rename from src/smpackage/ZipArchive/stl/zippie/zippie_DLL.dsp rename to src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsp index 695e782fbe..6af7af75a5 100644 --- a/src/smpackage/ZipArchive/stl/zippie/zippie_DLL.dsp +++ b/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsp @@ -1,112 +1,112 @@ -# Microsoft Developer Studio Project File - Name="zippie" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=zippie - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "zippie_DLL.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "zippie_DLL.mak" CFG="zippie - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "zippie - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "zippie - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName ""$/zippie", BGAAAAAA" -# PROP Scc_LocalPath "." -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "zippie - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ZIP_HAS_DLL" /FD /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "NDEBUG" -# ADD RSC /l 0x415 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "zippie - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ZIP_HAS_DLL" /FR /FD /GZ /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "_DEBUG" -# ADD RSC /l 0x415 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "zippie - Win32 Release" -# Name "zippie - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\CmdLine.cpp -# End Source File -# Begin Source File - -SOURCE=.\zippie.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\CmdLine.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project +# Microsoft Developer Studio Project File - Name="zippie" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=zippie - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "zippie_DLL.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "zippie_DLL.mak" CFG="zippie - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "zippie - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "zippie - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName ""$/zippie", BGAAAAAA" +# PROP Scc_LocalPath "." +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "zippie - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ZIP_HAS_DLL" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x415 /d "NDEBUG" +# ADD RSC /l 0x415 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "zippie - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ZIP_HAS_DLL" /FR /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x415 /d "_DEBUG" +# ADD RSC /l 0x415 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "zippie - Win32 Release" +# Name "zippie - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\CmdLine.cpp +# End Source File +# Begin Source File + +SOURCE=.\zippie.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\CmdLine.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/src/smpackage/ZipArchive/stl/zippie/zippie_DLL.dsw b/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsw similarity index 94% rename from src/smpackage/ZipArchive/stl/zippie/zippie_DLL.dsw rename to src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsw index 6227d073b4..c78c2339c5 100644 --- a/src/smpackage/ZipArchive/stl/zippie/zippie_DLL.dsw +++ b/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsw @@ -1,59 +1,59 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "ZipArchive"="..\..\ZipArchive_STL_DLL.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name zlib - End Project Dependency -}}} - -############################################################################### - -Project: "zippie"=".\zippie_DLL.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name ZipArchive - End Project Dependency -}}} - -############################################################################### - -Project: "zlib"="..\..\zlib\zlib.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ZipArchive"="..\..\ZipArchive_STL_DLL.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "zippie"=".\zippie_DLL.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name ZipArchive + End Project Dependency +}}} + +############################################################################### + +Project: "zlib"="..\..\zlib\zlib.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/src/smpackage/res/smpackage.ico b/src/smpackagee/res/smpackage.ico similarity index 100% rename from src/smpackage/res/smpackage.ico rename to src/smpackagee/res/smpackage.ico diff --git a/src/smpackage/res/smpackage.rc2 b/src/smpackagee/res/smpackage.rc2 similarity index 96% rename from src/smpackage/res/smpackage.rc2 rename to src/smpackagee/res/smpackage.rc2 index a74b918e89..50a7391dbf 100644 --- a/src/smpackage/res/smpackage.rc2 +++ b/src/smpackagee/res/smpackage.rc2 @@ -1,13 +1,13 @@ -// -// SMPACKAGE.RC2 - resources Microsoft Visual C++ does not edit directly -// - -#ifdef APSTUDIO_INVOKED - #error this file is not editable by Microsoft Visual C++ -#endif //APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// Add manually edited resources here... - -///////////////////////////////////////////////////////////////////////////// +// +// SMPACKAGE.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/src/smpackage/resource.h b/src/smpackagee/resource.h similarity index 100% rename from src/smpackage/resource.h rename to src/smpackagee/resource.h diff --git a/src/smpackage/smpackage.ICO b/src/smpackagee/smpackage.ICO similarity index 100% rename from src/smpackage/smpackage.ICO rename to src/smpackagee/smpackage.ICO diff --git a/src/smpackage/smpackage.clw b/src/smpackagee/smpackage.clw similarity index 96% rename from src/smpackage/smpackage.clw rename to src/smpackagee/smpackage.clw index bd2520f18e..ef17bb3487 100644 --- a/src/smpackage/smpackage.clw +++ b/src/smpackagee/smpackage.clw @@ -1,321 +1,321 @@ -; CLW file contains information for the MFC ClassWizard - -[General Info] -Version=1 -LastClass=MainMenuDlg -LastTemplate=CDialog -NewFileInclude1=#include "stdafx.h" -NewFileInclude2=#include "smpackage.h" - -ClassCount=12 -Class1=CSmpackageApp -Class2=CSmpackageDlg - -ResourceCount=13 -Resource1=IDR_MAINFRAME -Resource2=IDD_ENTER_STRING -Class3=CSMPackageInstallDlg -Class4=CSmpackageExportDlg -Resource3=IDD_EXPORTER -Class5=EnterName -Resource4=IDD_EDIT_METRICS -Class6=EditInsallations -Resource5=IDD_CONVERT_THEME -Class7=MainMenuDlg -Resource6=IDD_MENU -Class8=ConvertThemeDlg -Resource7=IDD_SHOW_COMMENT -Class9=EditMetricsDlg -Resource8=IDD_ENTER_COMMENT -Resource9=IDD_DIALOG_NAME -Class10=EnterComment -Resource10=IDD_INSTALL -Class11=ShowComment -Resource11=IDD_UNINSTALL_OLD_PACKAGES -Resource12=IDD_EDIT_INSTALLATIONS -Class12=ChangeGameSettings -Resource13=IDD_CHANGE_GAME_SETTINGS - -[CLS:CSmpackageApp] -Type=0 -HeaderFile=smpackage.h -ImplementationFile=smpackage.cpp -Filter=N -LastObject=CSmpackageApp -BaseClass=CWinApp -VirtualFilter=AC - -[CLS:CSmpackageDlg] -Type=0 -HeaderFile=smpackageDlg.h -ImplementationFile=smpackageDlg.cpp -Filter=D -LastObject=CSmpackageDlg -BaseClass=CDialog -VirtualFilter=dWC - - - -[DLG:IDD_INSTALL] -Type=1 -Class=CSMPackageInstallDlg -ControlCount=10 -Control1=IDC_EDIT_MESSAGE1,edit,1342179460 -Control2=IDOK,button,1342242817 -Control3=IDCANCEL,button,1342242816 -Control4=IDC_BUTTON_BACK,button,1476460544 -Control5=IDC_STATIC,static,1342177294 -Control6=IDC_EDIT_MESSAGE3,edit,1342179460 -Control7=IDC_EDIT_MESSAGE2,edit,1352665220 -Control8=IDC_COMBO_DIR,combobox,1344339971 -Control9=IDC_BUTTON_EDIT,button,1342242816 -Control10=IDC_PROGRESS1,msctls_progress32,1082130432 - -[CLS:CSMPackageInstallDlg] -Type=0 -HeaderFile=SMPackageInstallDlg.h -ImplementationFile=SMPackageInstallDlg.cpp -BaseClass=CDialog -Filter=D -LastObject=CSMPackageInstallDlg -VirtualFilter=dWC - -[DLG:IDD_EXPORTER] -Type=1 -Class=CSmpackageExportDlg -ControlCount=10 -Control1=IDOK,button,1342242817 -Control2=IDC_BUTTON_PLAY,button,1342242816 -Control3=IDC_BUTTON_EXPORT_AS_ONE,button,1342242816 -Control4=IDC_STATIC,static,1342177294 -Control5=IDC_BUTTON_EXPORT_AS_INDIVIDUAL,button,1342242816 -Control6=IDC_TREE,SysTreeView32,1350631687 -Control7=IDC_COMBO_DIR,combobox,1344339971 -Control8=IDC_BUTTON_EDIT,button,1342242816 -Control9=IDC_STATIC,static,1342308352 -Control10=IDC_BUTTON_OPEN,button,1342242816 - -[CLS:CSmpackageExportDlg] -Type=0 -HeaderFile=SmpackageExportDlg.h -ImplementationFile=SmpackageExportDlg.cpp -BaseClass=CDialog -Filter=D -LastObject=CSmpackageExportDlg -VirtualFilter=dWC - -[CLS:EnterName] -Type=0 -HeaderFile=EnterName.h -ImplementationFile=EnterName.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=IDC_EDIT - -[DLG:IDD_EDIT_INSTALLATIONS] -Type=1 -Class=EditInsallations -ControlCount=10 -Control1=IDOK,button,1342242817 -Control2=IDCANCEL,button,1342242816 -Control3=IDC_LIST,listbox,1352728833 -Control4=IDC_EDIT,edit,1350631552 -Control5=IDC_BUTTON_ADD,button,1342242816 -Control6=IDC_BUTTON_REMOVE,button,1342242816 -Control7=IDC_BUTTON_MAKE_DEFAULT,button,1342242816 -Control8=IDC_STATIC,button,1342177287 -Control9=IDC_STATIC,button,1342177287 -Control10=IDC_STATIC,static,1342308352 - -[CLS:EditInsallations] -Type=0 -HeaderFile=EditInsallations.h -ImplementationFile=EditInsallations.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=EditInsallations - -[DLG:IDD_MENU] -Type=1 -Class=MainMenuDlg -ControlCount=20 -Control1=IDOK,button,1342242817 -Control2=IDC_STATIC,static,1342177294 -Control3=IDC_STATIC,static,1342308354 -Control4=IDC_EDIT_INSTALLATION,edit,1350633600 -Control5=IDC_STATIC,button,1342177287 -Control6=IDC_EDIT_INSTALLATIONS,button,1342242816 -Control7=IDC_STATIC,static,1342308352 -Control8=IDC_STATIC,button,1342177287 -Control9=IDC_EXPORT_PACKAGES,button,1342242816 -Control10=IDC_STATIC,static,1342308352 -Control11=IDC_STATIC,button,1342177287 -Control12=IDC_ANALYZE_ELEMENTS,button,1342242816 -Control13=IDC_STATIC,static,1342308352 -Control14=IDC_STATIC,button,1342177287 -Control15=IDC_CHANGE_API,button,1342242816 -Control16=IDC_OPEN_STEPMANIA_INI,button,1342242816 -Control17=IDC_STATIC,static,1342308352 -Control18=IDC_STATIC,button,1342177287 -Control19=IDC_CREATE_SONG,button,1342242816 -Control20=IDC_STATIC,static,1342308352 - -[CLS:MainMenuDlg] -Type=0 -HeaderFile=MainMenuDlg.h -ImplementationFile=MainMenuDlg.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=MainMenuDlg - -[DLG:IDD_CONVERT_THEME] -Type=1 -Class=ConvertThemeDlg -ControlCount=13 -Control1=IDOK,button,1342242817 -Control2=IDC_STATIC,static,1342177294 -Control3=IDC_LIST_THEMES,listbox,1352728835 -Control4=IDC_BUTTON_CONVERT,button,1476460544 -Control5=IDC_STATIC,static,1342308352 -Control6=IDC_STATIC,button,1342177287 -Control7=IDC_STATIC,static,1342308352 -Control8=IDC_BUTTON_ANALYZE,button,1476460544 -Control9=IDC_STATIC,button,1342177287 -Control10=IDC_STATIC,static,1342308352 -Control11=IDC_BUTTON_EDIT_METRICS,button,1476460544 -Control12=IDC_STATIC,static,1342308352 -Control13=IDC_BUTTON_ANALYZE_METRICS,button,1476460544 - -[CLS:ConvertThemeDlg] -Type=0 -HeaderFile=onvertThemeDlg.h -ImplementationFile=onvertThemeDlg.cpp -BaseClass=CDialog -Filter=D -LastObject=IDC_LIST_THEMES -VirtualFilter=dWC - -[DLG:IDD_EDIT_METRICS] -Type=1 -Class=EditMetricsDlg -ControlCount=11 -Control1=IDC_BUTTON_CLOSE,button,1342242816 -Control2=IDC_STATIC,static,1342177294 -Control3=IDC_EDIT_VALUE,edit,1484849220 -Control4=IDC_STATIC,static,1342308352 -Control5=IDC_EDIT_DEFAULT,edit,1350633540 -Control6=IDC_STATIC,static,1342308352 -Control7=IDC_BUTTON_OVERRIDE,button,1476460544 -Control8=IDC_BUTTON_REMOVE,button,1476460544 -Control9=IDC_TREE,SysTreeView32,1350631461 -Control10=IDC_BUTTON_SAVE,button,1342242816 -Control11=IDC_BUTTON_HELP,button,1342242816 - -[CLS:EditMetricsDlg] -Type=0 -HeaderFile=EditMetricsDlg.h -ImplementationFile=EditMetricsDlg.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=EditMetricsDlg - -[DLG:IDD_ENTER_STRING] -Type=1 -Class=EnterName -ControlCount=4 -Control1=IDC_STATIC,static,1342308352 -Control2=IDC_EDIT,edit,1350631552 -Control3=IDOK,button,1342242817 -Control4=IDCANCEL,button,1342242816 - -[DLG:IDD_ENTER_COMMENT] -Type=1 -Class=EnterComment -ControlCount=5 -Control1=65535,static,1342308352 -Control2=IDC_EDIT,edit,1350631556 -Control3=IDOK,button,1342242817 -Control4=IDCANCEL,button,1342242816 -Control5=IDC_DONTASK,button,1342242819 - -[DLG:IDD_DIALOG_NAME] -Type=1 -Class=? -ControlCount=5 -Control1=IDC_STATIC,static,1342308352 -Control2=IDC_EDIT,edit,1350631552 -Control3=IDOK,button,1342242817 -Control4=IDCANCEL,button,1342242816 -Control5=IDC_STATIC,static,1342308352 - -[CLS:EnterComment] -Type=0 -HeaderFile=EnterComment.h -ImplementationFile=EnterComment.cpp -BaseClass=CDialog -Filter=D -LastObject=IDC_EDIT -VirtualFilter=dWC - -[DLG:IDD_SHOW_COMMENT] -Type=1 -Class=ShowComment -ControlCount=4 -Control1=IDC_EDIT,edit,1350633604 -Control2=IDOK,button,1342242817 -Control3=IDCANCEL,button,1342242816 -Control4=IDC_DONTSHOW,button,1342242819 - -[CLS:ShowComment] -Type=0 -HeaderFile=ShowComment.h -ImplementationFile=ShowComment.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=IDC_DONTSHOW - -[DLG:IDD_UNINSTALL_OLD_PACKAGES] -Type=1 -Class=? -ControlCount=6 -Control1=IDOK,button,1342242817 -Control2=IDCANCEL,button,1342242816 -Control3=IDC_STATIC,static,1342308352 -Control4=IDC_PACKAGES,edit,1352730756 -Control5=IDC_BUTTON1,button,1342242816 -Control6=IDC_STATIC,static,1342308353 - -[DLG:IDD_CHANGE_GAME_SETTINGS] -Type=1 -Class=ChangeGameSettings -ControlCount=15 -Control1=IDOK,button,1342242817 -Control2=IDCANCEL,button,1342242816 -Control3=IDC_STATIC,button,1342177287 -Control4=IDC_RADIO_DEFAULT,button,1342308361 -Control5=IDC_RADIO_OPENGL,button,1342177289 -Control6=IDC_RADIO_DIRECT3D,button,1342177289 -Control7=IDC_STATIC,button,1342177287 -Control8=IDC_RADIO_SOUND_DEFAULT,button,1342308361 -Control9=IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE,button,1342177289 -Control10=IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE,button,1342177289 -Control11=IDC_RADIO_SOUND_NULL,button,1342177289 -Control12=IDC_STATIC,button,1342177287 -Control13=IDC_CHECK_LOG_TO_DISK,button,1342242819 -Control14=IDC_CHECK_SHOW_LOG_WINDOW,button,1342242819 -Control15=IDC_STATIC,static,1342308352 - -[CLS:ChangeGameSettings] -Type=0 -HeaderFile=ChangeGameSettings.h -ImplementationFile=ChangeGameSettings.cpp -BaseClass=CDialog -Filter=D -LastObject=IDCANCEL -VirtualFilter=dWC - +; CLW file contains information for the MFC ClassWizard + +[General Info] +Version=1 +LastClass=MainMenuDlg +LastTemplate=CDialog +NewFileInclude1=#include "stdafx.h" +NewFileInclude2=#include "smpackage.h" + +ClassCount=12 +Class1=CSmpackageApp +Class2=CSmpackageDlg + +ResourceCount=13 +Resource1=IDR_MAINFRAME +Resource2=IDD_ENTER_STRING +Class3=CSMPackageInstallDlg +Class4=CSmpackageExportDlg +Resource3=IDD_EXPORTER +Class5=EnterName +Resource4=IDD_EDIT_METRICS +Class6=EditInsallations +Resource5=IDD_CONVERT_THEME +Class7=MainMenuDlg +Resource6=IDD_MENU +Class8=ConvertThemeDlg +Resource7=IDD_SHOW_COMMENT +Class9=EditMetricsDlg +Resource8=IDD_ENTER_COMMENT +Resource9=IDD_DIALOG_NAME +Class10=EnterComment +Resource10=IDD_INSTALL +Class11=ShowComment +Resource11=IDD_UNINSTALL_OLD_PACKAGES +Resource12=IDD_EDIT_INSTALLATIONS +Class12=ChangeGameSettings +Resource13=IDD_CHANGE_GAME_SETTINGS + +[CLS:CSmpackageApp] +Type=0 +HeaderFile=smpackage.h +ImplementationFile=smpackage.cpp +Filter=N +LastObject=CSmpackageApp +BaseClass=CWinApp +VirtualFilter=AC + +[CLS:CSmpackageDlg] +Type=0 +HeaderFile=smpackageDlg.h +ImplementationFile=smpackageDlg.cpp +Filter=D +LastObject=CSmpackageDlg +BaseClass=CDialog +VirtualFilter=dWC + + + +[DLG:IDD_INSTALL] +Type=1 +Class=CSMPackageInstallDlg +ControlCount=10 +Control1=IDC_EDIT_MESSAGE1,edit,1342179460 +Control2=IDOK,button,1342242817 +Control3=IDCANCEL,button,1342242816 +Control4=IDC_BUTTON_BACK,button,1476460544 +Control5=IDC_STATIC,static,1342177294 +Control6=IDC_EDIT_MESSAGE3,edit,1342179460 +Control7=IDC_EDIT_MESSAGE2,edit,1352665220 +Control8=IDC_COMBO_DIR,combobox,1344339971 +Control9=IDC_BUTTON_EDIT,button,1342242816 +Control10=IDC_PROGRESS1,msctls_progress32,1082130432 + +[CLS:CSMPackageInstallDlg] +Type=0 +HeaderFile=SMPackageInstallDlg.h +ImplementationFile=SMPackageInstallDlg.cpp +BaseClass=CDialog +Filter=D +LastObject=CSMPackageInstallDlg +VirtualFilter=dWC + +[DLG:IDD_EXPORTER] +Type=1 +Class=CSmpackageExportDlg +ControlCount=10 +Control1=IDOK,button,1342242817 +Control2=IDC_BUTTON_PLAY,button,1342242816 +Control3=IDC_BUTTON_EXPORT_AS_ONE,button,1342242816 +Control4=IDC_STATIC,static,1342177294 +Control5=IDC_BUTTON_EXPORT_AS_INDIVIDUAL,button,1342242816 +Control6=IDC_TREE,SysTreeView32,1350631687 +Control7=IDC_COMBO_DIR,combobox,1344339971 +Control8=IDC_BUTTON_EDIT,button,1342242816 +Control9=IDC_STATIC,static,1342308352 +Control10=IDC_BUTTON_OPEN,button,1342242816 + +[CLS:CSmpackageExportDlg] +Type=0 +HeaderFile=SmpackageExportDlg.h +ImplementationFile=SmpackageExportDlg.cpp +BaseClass=CDialog +Filter=D +LastObject=CSmpackageExportDlg +VirtualFilter=dWC + +[CLS:EnterName] +Type=0 +HeaderFile=EnterName.h +ImplementationFile=EnterName.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=IDC_EDIT + +[DLG:IDD_EDIT_INSTALLATIONS] +Type=1 +Class=EditInsallations +ControlCount=10 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_LIST,listbox,1352728833 +Control4=IDC_EDIT,edit,1350631552 +Control5=IDC_BUTTON_ADD,button,1342242816 +Control6=IDC_BUTTON_REMOVE,button,1342242816 +Control7=IDC_BUTTON_MAKE_DEFAULT,button,1342242816 +Control8=IDC_STATIC,button,1342177287 +Control9=IDC_STATIC,button,1342177287 +Control10=IDC_STATIC,static,1342308352 + +[CLS:EditInsallations] +Type=0 +HeaderFile=EditInsallations.h +ImplementationFile=EditInsallations.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=EditInsallations + +[DLG:IDD_MENU] +Type=1 +Class=MainMenuDlg +ControlCount=20 +Control1=IDOK,button,1342242817 +Control2=IDC_STATIC,static,1342177294 +Control3=IDC_STATIC,static,1342308354 +Control4=IDC_EDIT_INSTALLATION,edit,1350633600 +Control5=IDC_STATIC,button,1342177287 +Control6=IDC_EDIT_INSTALLATIONS,button,1342242816 +Control7=IDC_STATIC,static,1342308352 +Control8=IDC_STATIC,button,1342177287 +Control9=IDC_EXPORT_PACKAGES,button,1342242816 +Control10=IDC_STATIC,static,1342308352 +Control11=IDC_STATIC,button,1342177287 +Control12=IDC_ANALYZE_ELEMENTS,button,1342242816 +Control13=IDC_STATIC,static,1342308352 +Control14=IDC_STATIC,button,1342177287 +Control15=IDC_CHANGE_API,button,1342242816 +Control16=IDC_OPEN_STEPMANIA_INI,button,1342242816 +Control17=IDC_STATIC,static,1342308352 +Control18=IDC_STATIC,button,1342177287 +Control19=IDC_CREATE_SONG,button,1342242816 +Control20=IDC_STATIC,static,1342308352 + +[CLS:MainMenuDlg] +Type=0 +HeaderFile=MainMenuDlg.h +ImplementationFile=MainMenuDlg.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=MainMenuDlg + +[DLG:IDD_CONVERT_THEME] +Type=1 +Class=ConvertThemeDlg +ControlCount=13 +Control1=IDOK,button,1342242817 +Control2=IDC_STATIC,static,1342177294 +Control3=IDC_LIST_THEMES,listbox,1352728835 +Control4=IDC_BUTTON_CONVERT,button,1476460544 +Control5=IDC_STATIC,static,1342308352 +Control6=IDC_STATIC,button,1342177287 +Control7=IDC_STATIC,static,1342308352 +Control8=IDC_BUTTON_ANALYZE,button,1476460544 +Control9=IDC_STATIC,button,1342177287 +Control10=IDC_STATIC,static,1342308352 +Control11=IDC_BUTTON_EDIT_METRICS,button,1476460544 +Control12=IDC_STATIC,static,1342308352 +Control13=IDC_BUTTON_ANALYZE_METRICS,button,1476460544 + +[CLS:ConvertThemeDlg] +Type=0 +HeaderFile=onvertThemeDlg.h +ImplementationFile=onvertThemeDlg.cpp +BaseClass=CDialog +Filter=D +LastObject=IDC_LIST_THEMES +VirtualFilter=dWC + +[DLG:IDD_EDIT_METRICS] +Type=1 +Class=EditMetricsDlg +ControlCount=11 +Control1=IDC_BUTTON_CLOSE,button,1342242816 +Control2=IDC_STATIC,static,1342177294 +Control3=IDC_EDIT_VALUE,edit,1484849220 +Control4=IDC_STATIC,static,1342308352 +Control5=IDC_EDIT_DEFAULT,edit,1350633540 +Control6=IDC_STATIC,static,1342308352 +Control7=IDC_BUTTON_OVERRIDE,button,1476460544 +Control8=IDC_BUTTON_REMOVE,button,1476460544 +Control9=IDC_TREE,SysTreeView32,1350631461 +Control10=IDC_BUTTON_SAVE,button,1342242816 +Control11=IDC_BUTTON_HELP,button,1342242816 + +[CLS:EditMetricsDlg] +Type=0 +HeaderFile=EditMetricsDlg.h +ImplementationFile=EditMetricsDlg.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=EditMetricsDlg + +[DLG:IDD_ENTER_STRING] +Type=1 +Class=EnterName +ControlCount=4 +Control1=IDC_STATIC,static,1342308352 +Control2=IDC_EDIT,edit,1350631552 +Control3=IDOK,button,1342242817 +Control4=IDCANCEL,button,1342242816 + +[DLG:IDD_ENTER_COMMENT] +Type=1 +Class=EnterComment +ControlCount=5 +Control1=65535,static,1342308352 +Control2=IDC_EDIT,edit,1350631556 +Control3=IDOK,button,1342242817 +Control4=IDCANCEL,button,1342242816 +Control5=IDC_DONTASK,button,1342242819 + +[DLG:IDD_DIALOG_NAME] +Type=1 +Class=? +ControlCount=5 +Control1=IDC_STATIC,static,1342308352 +Control2=IDC_EDIT,edit,1350631552 +Control3=IDOK,button,1342242817 +Control4=IDCANCEL,button,1342242816 +Control5=IDC_STATIC,static,1342308352 + +[CLS:EnterComment] +Type=0 +HeaderFile=EnterComment.h +ImplementationFile=EnterComment.cpp +BaseClass=CDialog +Filter=D +LastObject=IDC_EDIT +VirtualFilter=dWC + +[DLG:IDD_SHOW_COMMENT] +Type=1 +Class=ShowComment +ControlCount=4 +Control1=IDC_EDIT,edit,1350633604 +Control2=IDOK,button,1342242817 +Control3=IDCANCEL,button,1342242816 +Control4=IDC_DONTSHOW,button,1342242819 + +[CLS:ShowComment] +Type=0 +HeaderFile=ShowComment.h +ImplementationFile=ShowComment.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=IDC_DONTSHOW + +[DLG:IDD_UNINSTALL_OLD_PACKAGES] +Type=1 +Class=? +ControlCount=6 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_PACKAGES,edit,1352730756 +Control5=IDC_BUTTON1,button,1342242816 +Control6=IDC_STATIC,static,1342308353 + +[DLG:IDD_CHANGE_GAME_SETTINGS] +Type=1 +Class=ChangeGameSettings +ControlCount=15 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_STATIC,button,1342177287 +Control4=IDC_RADIO_DEFAULT,button,1342308361 +Control5=IDC_RADIO_OPENGL,button,1342177289 +Control6=IDC_RADIO_DIRECT3D,button,1342177289 +Control7=IDC_STATIC,button,1342177287 +Control8=IDC_RADIO_SOUND_DEFAULT,button,1342308361 +Control9=IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE,button,1342177289 +Control10=IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE,button,1342177289 +Control11=IDC_RADIO_SOUND_NULL,button,1342177289 +Control12=IDC_STATIC,button,1342177287 +Control13=IDC_CHECK_LOG_TO_DISK,button,1342242819 +Control14=IDC_CHECK_SHOW_LOG_WINDOW,button,1342242819 +Control15=IDC_STATIC,static,1342308352 + +[CLS:ChangeGameSettings] +Type=0 +HeaderFile=ChangeGameSettings.h +ImplementationFile=ChangeGameSettings.cpp +BaseClass=CDialog +Filter=D +LastObject=IDCANCEL +VirtualFilter=dWC + diff --git a/src/smpackage/smpackage.cpp b/src/smpackagee/smpackage.cpp similarity index 100% rename from src/smpackage/smpackage.cpp rename to src/smpackagee/smpackage.cpp diff --git a/src/smpackage/smpackage.h b/src/smpackagee/smpackage.h similarity index 100% rename from src/smpackage/smpackage.h rename to src/smpackagee/smpackage.h diff --git a/src/smpackage/smpackage.rc b/src/smpackagee/smpackage.rc similarity index 97% rename from src/smpackage/smpackage.rc rename to src/smpackagee/smpackage.rc index 9a3428c8a0..eb7dfc6c03 100644 --- a/src/smpackage/smpackage.rc +++ b/src/smpackagee/smpackage.rc @@ -1,499 +1,499 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "#define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" - "#ifdef _WIN32\r\n" - "LANGUAGE 9, 1\r\n" - "#pragma code_page(1252)\r\n" - "#endif //_WIN32\r\n" - "#include ""res\\smpackage.rc2"" // non-Microsoft Visual C++ edited resources\r\n" - "#include ""afxres.rc"" // Standard components\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAINFRAME ICON "smpackage.ICO" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_INSTALL DIALOGEX 0, 0, 332, 234 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION -CAPTION "Install a package" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - EDITTEXT IDC_EDIT_MESSAGE1,7,57,320,14,ES_MULTILINE | - ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT - WS_TABSTOP - DEFPUSHBUTTON "Finish >",IDOK,200,215,55,15 - PUSHBUTTON "Cancel",IDCANCEL,275,215,50,15 - PUSHBUTTON "< Back",IDC_BUTTON_BACK,145,215,55,15,WS_DISABLED - EDITTEXT IDC_EDIT_MESSAGE2,5,90,320,87,ES_MULTILINE | - ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | NOT - WS_TABSTOP - COMBOBOX IDC_COMBO_DIR,22,195,204,105,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Edit Installations",IDC_BUTTON_EDIT,233,194,85,14 - CONTROL "",IDC_PROGRESS1,"msctls_progress32",NOT WS_VISIBLE | - WS_BORDER,7,72,318,14 - LTEXT "You have chosen to install the package:", - IDC_STATIC_MESSAGE1,7,41,318,10 - LTEXT "This package contains the following files:", - IDC_STATIC_MESSAGE2,7,76,318,10 - LTEXT "The package will be installed in the following program folder:", - IDC_STATIC,7,181,318,10 - CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,331,33 - LTEXT "Install a package",IDC_STATIC_HEADER_TEXT,6,4,273,20 - CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,33,331,1 - ICON IDR_MAINFRAME,IDC_STATIC_ICON,295,6,21,20,0, - WS_EX_TRANSPARENT -END - -IDD_EXPORTER DIALOGEX 0, 0, 349, 222 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | - WS_VISIBLE | WS_CAPTION | WS_SYSMENU -EXSTYLE WS_EX_APPWINDOW -CAPTION "Export Packages" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - DEFPUSHBUTTON "Close",IDOK,284,201,57,14 - PUSHBUTTON "Launch Game",IDC_BUTTON_PLAY,7,200,70,15 - PUSHBUTTON "Export As One",IDC_BUTTON_EXPORT_AS_ONE,255,87,86,15 - PUSHBUTTON "Export As Individual",IDC_BUTTON_EXPORT_AS_INDIVIDUAL, - 255,120,86,15 - CONTROL "Tree2",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | - TVS_HASLINES | TVS_LINESATROOT | TVS_CHECKBOXES | - WS_BORDER | WS_TABSTOP,7,43,239,151 - COMBOBOX IDC_COMBO_DIR,16,17,229,105,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Edit Installations",IDC_BUTTON_EDIT,250,16,85,14 - PUSHBUTTON "Open Program Folder",IDC_BUTTON_OPEN,88,200,93,15 - GROUPBOX "Installation",IDC_STATIC,7,7,334,29 -END - -IDD_DIALOG_NAME DIALOGEX 0, 0, 261, 58 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Name Your Package" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - LTEXT "Enter a name for your new package:",IDC_STATIC,7,7,188, - 12 - EDITTEXT IDC_EDIT,17,20,178,13,ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,200,7,54,14 - PUSHBUTTON "Cancel",IDCANCEL,200,24,54,14 - LTEXT "Note: leave off the "".smzip"" extension",IDC_STATIC,18, - 38,179,12 -END - -IDD_EDIT_INSTALLATIONS DIALOGEX 0, 0, 243, 221 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Edit Installations" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,125,199,50,14 - PUSHBUTTON "Cancel",IDCANCEL,185,199,50,14 - LISTBOX IDC_LIST,17,30,136,80,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | - WS_TABSTOP - EDITTEXT IDC_EDIT,19,167,136,13,ES_AUTOHSCROLL - PUSHBUTTON "Add",IDC_BUTTON_ADD,165,167,50,14 - PUSHBUTTON "Remove",IDC_BUTTON_REMOVE,160,54,68,15,WS_DISABLED - PUSHBUTTON "Make Default",IDC_BUTTON_MAKE_DEFAULT,160,34,68,15, - WS_DISABLED - GROUPBOX "Add New Installation",IDC_STATIC,7,130,228,59 - GROUPBOX "Current Installations",IDC_STATIC,7,7,228,114 - LTEXT "Enter the complete path to a StepMania or DWI installation\r\ne.g. ""C:\\Program Files\\StepMania""", - IDC_STATIC,18,144,196,17 - LTEXT "The top installation is the default.",IDC_STATIC,19,17, - 196,12 -END - -IDD_MENU DIALOGEX 0, 0, 332, 284 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "StepMania Tools Main Menu" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,331,33 - LTEXT "StepMania Tools Main Menu",IDC_STATIC_HEADER_TEXT,6,4, - 273,20 - DEFPUSHBUTTON "Exit",IDOK,275,263,50,14 - GROUPBOX "Installation",IDC_STATIC,7,41,318,28 - PUSHBUTTON "Edit Installations",IDC_EDIT_INSTALLATIONS,233,49,83,15 - GROUPBOX "Create and Share",IDC_STATIC,7,176,318,78 - PUSHBUTTON "Export Packages",IDC_EXPORT_PACKAGES,14,190,91,15 - LTEXT "Create .smzip package files to share with other users.", - IDC_STATIC,109,190,213,18 - PUSHBUTTON "Create Song",IDC_CREATE_SONG,14,211,91,15 - LTEXT "Create a new song in from your favorite mp3 or ogg music file.", - IDC_STATIC,109,211,213,20 - GROUPBOX "Troubleshooting",IDC_STATIC,7,73,318,99 - PUSHBUTTON "Change Preferences",IDC_CHANGE_PREFERENCES,14,85,91,15 - PUSHBUTTON "Open Preferences",IDC_OPEN_PREFERENCES,14,127,91,15 - LTEXT "Change the graphics API, sound API, and other settings that the game will use.", - IDC_STATIC,110,85,213,18 - PUSHBUTTON "Clear Preferences",IDC_CLEAR_PREFERENCES,14,106,91,15 - PUSHBUTTON "Clear Mappings",IDC_CLEAR_KEYMAPS,14,148,91,15 - EDITTEXT IDC_EDIT_INSTALLATION,16,51,210,12,ES_AUTOHSCROLL | - ES_READONLY - LTEXT "Erase all of your keyboard and joystick mappings if you've made a mistake.", - IDC_STATIC,109,148,213,18 - PUSHBUTTON "Launch Game",IDC_BUTTON_LAUNCH_GAME,183,263,76,14 - PUSHBUTTON "Languages",IDC_LANGUAGES,14,232,91,15 - LTEXT "Create a new or manage existing language translations.", - IDC_STATIC,109,232,213,20 - LTEXT "Open the preferences file to make changes by hand.", - IDC_STATIC,109,127,213,18 - LTEXT "Clear all preferences if you've made changes and the game won't start.", - IDC_STATIC,109,106,213,18 - CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,33,331,1 - ICON IDR_MAINFRAME,IDC_STATIC_ICON,295,6,21,20,0, - WS_EX_TRANSPARENT -END - -IDD_ENTER_COMMENT DIALOGEX 0, 0, 324, 203 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Add A Comment" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - LTEXT "You can add a message to display before a user installs your package.", - IDC_STATIC,7,7,252,18 - CONTROL "Show a comment",IDC_SHOW_A_COMMENT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,19,39,185,12 - EDITTEXT IDC_EDIT,17,53,232,123,ES_MULTILINE | ES_AUTOHSCROLL - CONTROL "Don't display this dialog in the future",IDC_DONTASK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,185,145,11 - DEFPUSHBUTTON "OK",IDOK,267,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,267,24,50,14 - GROUPBOX "Package Comment",IDC_STATIC,7,29,252,152 -END - -IDD_SHOW_COMMENT DIALOGEX 0, 0, 246, 186 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Package Comment" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - EDITTEXT IDC_EDIT,7,7,232,137,ES_MULTILINE | ES_AUTOHSCROLL | - ES_READONLY - DEFPUSHBUTTON "OK",IDOK,72,165,50,14 - PUSHBUTTON "Cancel",IDCANCEL,128,165,50,14 - CONTROL "Don't display this dialog in the future",IDC_DONTSHOW, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,149,145,11 -END - -IDD_UNINSTALL_OLD_PACKAGES DIALOGEX 0, 0, 228, 152 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "Uninstall Old Packages" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "&Yes",IDOK,31,131,50,14 - PUSHBUTTON "Cancel",IDCANCEL,147,131,50,14 - LTEXT "The following packages are already installed. It is strongly recommended that they be deleted before installing this package.", - IDC_STATIC,7,7,214,27 - EDITTEXT IDC_PACKAGES,31,36,165,77,ES_MULTILINE | ES_AUTOHSCROLL | - ES_READONLY | WS_VSCROLL - PUSHBUTTON "&No",IDC_BUTTON1,87,131,49,14 - CTEXT "Delete old packages?",IDC_STATIC,31,117,166,12 -END - -IDD_CHANGE_GAME_SETTINGS DIALOGEX 0, 0, 162, 298 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Change Game Settings" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,49,276,50,14 - PUSHBUTTON "Cancel",IDCANCEL,104,276,50,14 - GROUPBOX "Graphics API",IDC_STATIC,7,7,147,66 - CONTROL "Default (recommended)",IDC_RADIO_DEFAULT,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,21,22,129,12 - CONTROL "OpenGL",IDC_RADIO_OPENGL,"Button",BS_AUTORADIOBUTTON,21, - 38,129,12 - CONTROL "Direct3D",IDC_RADIO_DIRECT3D,"Button", - BS_AUTORADIOBUTTON,21,54,129,12 - GROUPBOX "Sound API",IDC_STATIC,7,77,147,100 - CONTROL "Default (recommended)",IDC_RADIO_SOUND_DEFAULT,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,21,92,129,12 - CONTROL "DirectSound Hardware", - IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE,"Button", - BS_AUTORADIOBUTTON,21,108,129,12 - CONTROL "DirectSound Software", - IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE,"Button", - BS_AUTORADIOBUTTON,21,124,129,12 - CONTROL "WaveOut",IDC_RADIO_SOUND_WAVEOUT,"Button", - BS_AUTORADIOBUTTON,21,140,129,12 - CONTROL "Null (no sound)",IDC_RADIO_SOUND_NULL,"Button", - BS_AUTORADIOBUTTON,21,156,129,12 - GROUPBOX "Other",IDC_STATIC,7,181,147,62 - CONTROL "Log to Disk",IDC_CHECK_LOG_TO_DISK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,21,210,129,10 - CONTROL "Show Log Window",IDC_CHECK_SHOW_LOG_WINDOW,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,21,225,129,10 - LTEXT "Tip: Change these only if you experience problems when using the default settings.", - IDC_STATIC,7,247,147,26 - CONTROL "Force 60Hz Refresh",IDC_CHECK_FORCE_60HZ,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,21,195,129,10 -END - -IDD_LANGUAGES DIALOGEX 0, 0, 337, 189 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "Language Translations" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "Close",IDOK,280,168,50,14 - LTEXT "Themes",IDC_STATIC,7,7,101,10 - LTEXT "Languages",IDC_STATIC,118,7,98,10 - PUSHBUTTON "Create Language",IDC_BUTTON_CREATE,230,41,91,15 - PUSHBUTTON "Delete Language",IDC_BUTTON_DELETE,230,62,91,15 - PUSHBUTTON "Export CSV",IDC_BUTTON_EXPORT,230,83,91,15 - PUSHBUTTON "Import CSV",IDC_BUTTON_IMPORT,230,123,91,15 - LTEXT "1) Create a new language\n2) Export the theme strings to a CSV\n3) Edit the CSV using Excel or a text editor\n4) Import the CSV file back into the same language", - IDC_STATIC,7,145,258,37 - LTEXT "Selection details",IDC_STATIC,230,7,100,9 - LTEXT "Total Strings:",IDC_STATIC,221,17,89,10 - LTEXT "Need translation:",IDC_STATIC,221,28,89,10 - LTEXT "",IDC_STATIC_TOTAL_STRINGS,307,18,26,10 - LTEXT "",IDC_STATIC_NEED_TRANSLATION,307,27,26,10 - LISTBOX IDC_LIST_THEMES,7,18,102,121,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - LISTBOX IDC_LIST_LANGUAGES,116,17,100,121,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - CONTROL "Export already translated strings", - IDC_CHECK_EXPORT_ALREADY_TRANSLATED,"Button", - BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,221,100,109, - 16 - PUSHBUTTON "Check Language",IDC_CHECK_LANGUAGE,230,143,91,13 -END - -IDD_CREATE_LANGUAGE DIALOGEX 0, 0, 191, 47 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "Create Language" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,128,7,56,14 - PUSHBUTTON "Cancel",IDCANCEL,128,27,56,14 - LTEXT "Choose a language",IDC_STATIC,7,7,110,11 - COMBOBOX IDC_COMBO_LANGUAGES,17,24,100,110,CBS_DROPDOWNLIST | - CBS_SORT | WS_VSCROLL | WS_TABSTOP -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "StepMania Tools" - VALUE "FileVersion", "1, 0, 0, 1" - VALUE "InternalName", "smpackage" - VALUE "LegalCopyright", "Copyright (C) StepMania team" - VALUE "OriginalFilename", "tools.exe" - VALUE "ProductName", "StepMania Tools" - VALUE "ProductVersion", "1, 0, 0, 1" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_INSTALL, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 325 - TOPMARGIN, 7 - BOTTOMMARGIN, 227 - END - - IDD_EXPORTER, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 341 - TOPMARGIN, 7 - BOTTOMMARGIN, 215 - END - - IDD_DIALOG_NAME, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 254 - TOPMARGIN, 7 - BOTTOMMARGIN, 51 - END - - IDD_EDIT_INSTALLATIONS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 235 - TOPMARGIN, 7 - BOTTOMMARGIN, 213 - END - - IDD_MENU, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 325 - TOPMARGIN, 7 - BOTTOMMARGIN, 277 - END - - IDD_ENTER_COMMENT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 317 - TOPMARGIN, 7 - BOTTOMMARGIN, 196 - END - - IDD_SHOW_COMMENT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 239 - TOPMARGIN, 7 - BOTTOMMARGIN, 179 - END - - IDD_UNINSTALL_OLD_PACKAGES, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 221 - TOPMARGIN, 7 - BOTTOMMARGIN, 145 - END - - IDD_CHANGE_GAME_SETTINGS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 154 - TOPMARGIN, 7 - BOTTOMMARGIN, 290 - END - - IDD_LANGUAGES, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 330 - TOPMARGIN, 7 - BOTTOMMARGIN, 182 - END - - IDD_CREATE_LANGUAGE, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 184 - TOPMARGIN, 7 - BOTTOMMARGIN, 40 - END -END -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -#define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE 9, 1 -#pragma code_page(1252) -#endif //_WIN32 -#include "res\smpackage.rc2" // non-Microsoft Visual C++ edited resources -#include "afxres.rc" // Standard components -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif //_WIN32\r\n" + "#include ""res\\smpackage.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDR_MAINFRAME ICON "smpackage.ICO" + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_INSTALL DIALOGEX 0, 0, 332, 234 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION +CAPTION "Install a package" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT_MESSAGE1,7,57,320,14,ES_MULTILINE | + ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT + WS_TABSTOP + DEFPUSHBUTTON "Finish >",IDOK,200,215,55,15 + PUSHBUTTON "Cancel",IDCANCEL,275,215,50,15 + PUSHBUTTON "< Back",IDC_BUTTON_BACK,145,215,55,15,WS_DISABLED + EDITTEXT IDC_EDIT_MESSAGE2,5,90,320,87,ES_MULTILINE | + ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | NOT + WS_TABSTOP + COMBOBOX IDC_COMBO_DIR,22,195,204,105,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Edit Installations",IDC_BUTTON_EDIT,233,194,85,14 + CONTROL "",IDC_PROGRESS1,"msctls_progress32",NOT WS_VISIBLE | + WS_BORDER,7,72,318,14 + LTEXT "You have chosen to install the package:", + IDC_STATIC_MESSAGE1,7,41,318,10 + LTEXT "This package contains the following files:", + IDC_STATIC_MESSAGE2,7,76,318,10 + LTEXT "The package will be installed in the following program folder:", + IDC_STATIC,7,181,318,10 + CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,331,33 + LTEXT "Install a package",IDC_STATIC_HEADER_TEXT,6,4,273,20 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,33,331,1 + ICON IDR_MAINFRAME,IDC_STATIC_ICON,295,6,21,20,0, + WS_EX_TRANSPARENT +END + +IDD_EXPORTER DIALOGEX 0, 0, 349, 222 +STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | + WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Export Packages" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Close",IDOK,284,201,57,14 + PUSHBUTTON "Launch Game",IDC_BUTTON_PLAY,7,200,70,15 + PUSHBUTTON "Export As One",IDC_BUTTON_EXPORT_AS_ONE,255,87,86,15 + PUSHBUTTON "Export As Individual",IDC_BUTTON_EXPORT_AS_INDIVIDUAL, + 255,120,86,15 + CONTROL "Tree2",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | + TVS_HASLINES | TVS_LINESATROOT | TVS_CHECKBOXES | + WS_BORDER | WS_TABSTOP,7,43,239,151 + COMBOBOX IDC_COMBO_DIR,16,17,229,105,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Edit Installations",IDC_BUTTON_EDIT,250,16,85,14 + PUSHBUTTON "Open Program Folder",IDC_BUTTON_OPEN,88,200,93,15 + GROUPBOX "Installation",IDC_STATIC,7,7,334,29 +END + +IDD_DIALOG_NAME DIALOGEX 0, 0, 261, 58 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Name Your Package" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + LTEXT "Enter a name for your new package:",IDC_STATIC,7,7,188, + 12 + EDITTEXT IDC_EDIT,17,20,178,13,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,200,7,54,14 + PUSHBUTTON "Cancel",IDCANCEL,200,24,54,14 + LTEXT "Note: leave off the "".smzip"" extension",IDC_STATIC,18, + 38,179,12 +END + +IDD_EDIT_INSTALLATIONS DIALOGEX 0, 0, 243, 221 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Edit Installations" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,125,199,50,14 + PUSHBUTTON "Cancel",IDCANCEL,185,199,50,14 + LISTBOX IDC_LIST,17,30,136,80,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | + WS_TABSTOP + EDITTEXT IDC_EDIT,19,167,136,13,ES_AUTOHSCROLL + PUSHBUTTON "Add",IDC_BUTTON_ADD,165,167,50,14 + PUSHBUTTON "Remove",IDC_BUTTON_REMOVE,160,54,68,15,WS_DISABLED + PUSHBUTTON "Make Default",IDC_BUTTON_MAKE_DEFAULT,160,34,68,15, + WS_DISABLED + GROUPBOX "Add New Installation",IDC_STATIC,7,130,228,59 + GROUPBOX "Current Installations",IDC_STATIC,7,7,228,114 + LTEXT "Enter the complete path to a StepMania or DWI installation\r\ne.g. ""C:\\Program Files\\StepMania""", + IDC_STATIC,18,144,196,17 + LTEXT "The top installation is the default.",IDC_STATIC,19,17, + 196,12 +END + +IDD_MENU DIALOGEX 0, 0, 332, 284 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "StepMania Tools Main Menu" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,331,33 + LTEXT "StepMania Tools Main Menu",IDC_STATIC_HEADER_TEXT,6,4, + 273,20 + DEFPUSHBUTTON "Exit",IDOK,275,263,50,14 + GROUPBOX "Installation",IDC_STATIC,7,41,318,28 + PUSHBUTTON "Edit Installations",IDC_EDIT_INSTALLATIONS,233,49,83,15 + GROUPBOX "Create and Share",IDC_STATIC,7,176,318,78 + PUSHBUTTON "Export Packages",IDC_EXPORT_PACKAGES,14,190,91,15 + LTEXT "Create .smzip package files to share with other users.", + IDC_STATIC,109,190,213,18 + PUSHBUTTON "Create Song",IDC_CREATE_SONG,14,211,91,15 + LTEXT "Create a new song in from your favorite mp3 or ogg music file.", + IDC_STATIC,109,211,213,20 + GROUPBOX "Troubleshooting",IDC_STATIC,7,73,318,99 + PUSHBUTTON "Change Preferences",IDC_CHANGE_PREFERENCES,14,85,91,15 + PUSHBUTTON "Open Preferences",IDC_OPEN_PREFERENCES,14,127,91,15 + LTEXT "Change the graphics API, sound API, and other settings that the game will use.", + IDC_STATIC,110,85,213,18 + PUSHBUTTON "Clear Preferences",IDC_CLEAR_PREFERENCES,14,106,91,15 + PUSHBUTTON "Clear Mappings",IDC_CLEAR_KEYMAPS,14,148,91,15 + EDITTEXT IDC_EDIT_INSTALLATION,16,51,210,12,ES_AUTOHSCROLL | + ES_READONLY + LTEXT "Erase all of your keyboard and joystick mappings if you've made a mistake.", + IDC_STATIC,109,148,213,18 + PUSHBUTTON "Launch Game",IDC_BUTTON_LAUNCH_GAME,183,263,76,14 + PUSHBUTTON "Languages",IDC_LANGUAGES,14,232,91,15 + LTEXT "Create a new or manage existing language translations.", + IDC_STATIC,109,232,213,20 + LTEXT "Open the preferences file to make changes by hand.", + IDC_STATIC,109,127,213,18 + LTEXT "Clear all preferences if you've made changes and the game won't start.", + IDC_STATIC,109,106,213,18 + CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,33,331,1 + ICON IDR_MAINFRAME,IDC_STATIC_ICON,295,6,21,20,0, + WS_EX_TRANSPARENT +END + +IDD_ENTER_COMMENT DIALOGEX 0, 0, 324, 203 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Add A Comment" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + LTEXT "You can add a message to display before a user installs your package.", + IDC_STATIC,7,7,252,18 + CONTROL "Show a comment",IDC_SHOW_A_COMMENT,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,19,39,185,12 + EDITTEXT IDC_EDIT,17,53,232,123,ES_MULTILINE | ES_AUTOHSCROLL + CONTROL "Don't display this dialog in the future",IDC_DONTASK, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,185,145,11 + DEFPUSHBUTTON "OK",IDOK,267,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,267,24,50,14 + GROUPBOX "Package Comment",IDC_STATIC,7,29,252,152 +END + +IDD_SHOW_COMMENT DIALOGEX 0, 0, 246, 186 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Package Comment" +FONT 8, "MS Sans Serif", 0, 0, 0x1 +BEGIN + EDITTEXT IDC_EDIT,7,7,232,137,ES_MULTILINE | ES_AUTOHSCROLL | + ES_READONLY + DEFPUSHBUTTON "OK",IDOK,72,165,50,14 + PUSHBUTTON "Cancel",IDCANCEL,128,165,50,14 + CONTROL "Don't display this dialog in the future",IDC_DONTSHOW, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,149,145,11 +END + +IDD_UNINSTALL_OLD_PACKAGES DIALOGEX 0, 0, 228, 152 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Uninstall Old Packages" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "&Yes",IDOK,31,131,50,14 + PUSHBUTTON "Cancel",IDCANCEL,147,131,50,14 + LTEXT "The following packages are already installed. It is strongly recommended that they be deleted before installing this package.", + IDC_STATIC,7,7,214,27 + EDITTEXT IDC_PACKAGES,31,36,165,77,ES_MULTILINE | ES_AUTOHSCROLL | + ES_READONLY | WS_VSCROLL + PUSHBUTTON "&No",IDC_BUTTON1,87,131,49,14 + CTEXT "Delete old packages?",IDC_STATIC,31,117,166,12 +END + +IDD_CHANGE_GAME_SETTINGS DIALOGEX 0, 0, 162, 298 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Change Game Settings" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "OK",IDOK,49,276,50,14 + PUSHBUTTON "Cancel",IDCANCEL,104,276,50,14 + GROUPBOX "Graphics API",IDC_STATIC,7,7,147,66 + CONTROL "Default (recommended)",IDC_RADIO_DEFAULT,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,21,22,129,12 + CONTROL "OpenGL",IDC_RADIO_OPENGL,"Button",BS_AUTORADIOBUTTON,21, + 38,129,12 + CONTROL "Direct3D",IDC_RADIO_DIRECT3D,"Button", + BS_AUTORADIOBUTTON,21,54,129,12 + GROUPBOX "Sound API",IDC_STATIC,7,77,147,100 + CONTROL "Default (recommended)",IDC_RADIO_SOUND_DEFAULT,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,21,92,129,12 + CONTROL "DirectSound Hardware", + IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE,"Button", + BS_AUTORADIOBUTTON,21,108,129,12 + CONTROL "DirectSound Software", + IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE,"Button", + BS_AUTORADIOBUTTON,21,124,129,12 + CONTROL "WaveOut",IDC_RADIO_SOUND_WAVEOUT,"Button", + BS_AUTORADIOBUTTON,21,140,129,12 + CONTROL "Null (no sound)",IDC_RADIO_SOUND_NULL,"Button", + BS_AUTORADIOBUTTON,21,156,129,12 + GROUPBOX "Other",IDC_STATIC,7,181,147,62 + CONTROL "Log to Disk",IDC_CHECK_LOG_TO_DISK,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,21,210,129,10 + CONTROL "Show Log Window",IDC_CHECK_SHOW_LOG_WINDOW,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,21,225,129,10 + LTEXT "Tip: Change these only if you experience problems when using the default settings.", + IDC_STATIC,7,247,147,26 + CONTROL "Force 60Hz Refresh",IDC_CHECK_FORCE_60HZ,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,21,195,129,10 +END + +IDD_LANGUAGES DIALOGEX 0, 0, 337, 189 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Language Translations" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "Close",IDOK,280,168,50,14 + LTEXT "Themes",IDC_STATIC,7,7,101,10 + LTEXT "Languages",IDC_STATIC,118,7,98,10 + PUSHBUTTON "Create Language",IDC_BUTTON_CREATE,230,41,91,15 + PUSHBUTTON "Delete Language",IDC_BUTTON_DELETE,230,62,91,15 + PUSHBUTTON "Export CSV",IDC_BUTTON_EXPORT,230,83,91,15 + PUSHBUTTON "Import CSV",IDC_BUTTON_IMPORT,230,123,91,15 + LTEXT "1) Create a new language\n2) Export the theme strings to a CSV\n3) Edit the CSV using Excel or a text editor\n4) Import the CSV file back into the same language", + IDC_STATIC,7,145,258,37 + LTEXT "Selection details",IDC_STATIC,230,7,100,9 + LTEXT "Total Strings:",IDC_STATIC,221,17,89,10 + LTEXT "Need translation:",IDC_STATIC,221,28,89,10 + LTEXT "",IDC_STATIC_TOTAL_STRINGS,307,18,26,10 + LTEXT "",IDC_STATIC_NEED_TRANSLATION,307,27,26,10 + LISTBOX IDC_LIST_THEMES,7,18,102,121,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + LISTBOX IDC_LIST_LANGUAGES,116,17,100,121,LBS_SORT | + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + CONTROL "Export already translated strings", + IDC_CHECK_EXPORT_ALREADY_TRANSLATED,"Button", + BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,221,100,109, + 16 + PUSHBUTTON "Check Language",IDC_CHECK_LANGUAGE,230,143,91,13 +END + +IDD_CREATE_LANGUAGE DIALOGEX 0, 0, 191, 47 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | + WS_SYSMENU +CAPTION "Create Language" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,128,7,56,14 + PUSHBUTTON "Cancel",IDCANCEL,128,27,56,14 + LTEXT "Choose a language",IDC_STATIC,7,7,110,11 + COMBOBOX IDC_COMBO_LANGUAGES,17,24,100,110,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "FileDescription", "StepMania Tools" + VALUE "FileVersion", "1, 0, 0, 1" + VALUE "InternalName", "smpackage" + VALUE "LegalCopyright", "Copyright (C) StepMania team" + VALUE "OriginalFilename", "tools.exe" + VALUE "ProductName", "StepMania Tools" + VALUE "ProductVersion", "1, 0, 0, 1" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_INSTALL, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 325 + TOPMARGIN, 7 + BOTTOMMARGIN, 227 + END + + IDD_EXPORTER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 341 + TOPMARGIN, 7 + BOTTOMMARGIN, 215 + END + + IDD_DIALOG_NAME, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 254 + TOPMARGIN, 7 + BOTTOMMARGIN, 51 + END + + IDD_EDIT_INSTALLATIONS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 235 + TOPMARGIN, 7 + BOTTOMMARGIN, 213 + END + + IDD_MENU, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 325 + TOPMARGIN, 7 + BOTTOMMARGIN, 277 + END + + IDD_ENTER_COMMENT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 317 + TOPMARGIN, 7 + BOTTOMMARGIN, 196 + END + + IDD_SHOW_COMMENT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 239 + TOPMARGIN, 7 + BOTTOMMARGIN, 179 + END + + IDD_UNINSTALL_OLD_PACKAGES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 221 + TOPMARGIN, 7 + BOTTOMMARGIN, 145 + END + + IDD_CHANGE_GAME_SETTINGS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 154 + TOPMARGIN, 7 + BOTTOMMARGIN, 290 + END + + IDD_LANGUAGES, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 330 + TOPMARGIN, 7 + BOTTOMMARGIN, 182 + END + + IDD_CREATE_LANGUAGE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 184 + TOPMARGIN, 7 + BOTTOMMARGIN, 40 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif //_WIN32 +#include "res\smpackage.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/src/smpackage/smpackageUtil.h b/src/smpackagee/smpackageUtil.h similarity index 100% rename from src/smpackage/smpackageUtil.h rename to src/smpackagee/smpackageUtil.h diff --git a/src/tests/00 README b/src/tests/00 README deleted file mode 100644 index c647e972ea..0000000000 --- a/src/tests/00 README +++ /dev/null @@ -1,15 +0,0 @@ -This file contains test sets. - -Currently, all we have is test_audio_readers, which tests the MP3, WAV and Ogg -file readers. - -Once I create smaller test inputs, I'll commit them; the current set is about -30 megs. Until then, if you want to try this, edit the source to point it at -files you have. - -This is only compiled in the Unix build environment. - -test_vector is for testing VectorHelper against the reference scalar -code. It can be compiled using: -g++ -g -I.. ../archutils/Darwin/VectorHelper.cpp test_vector.cpp -faltivec -You can replace -faltivec with -msse2 on intel. Might requires -O3 to inline. diff --git a/src/tests/test_audio_readers.cpp b/src/tests/test_audio_readers.cpp deleted file mode 100644 index c56300968a..0000000000 --- a/src/tests/test_audio_readers.cpp +++ /dev/null @@ -1,646 +0,0 @@ -#include "global.h" -#include "RageLog.h" -#include "RageSoundReader_MP3.h" -#include "RageTimer.h" -#include "RageUtil.h" -#include "RageSoundReader_Preload.h" -#include "RageSoundReader_Resample_Good.h" - -#include "test_misc.h" -#include -#include -#include -#include - -void -ReadData(RageSoundReader* pReader, - int iFrame, /* start */ - float* pBuf, /* out */ - int iFrames) -{ - if (iFrame != -1) - pReader->SetPosition(iFrame); - int got = pReader->Read(pBuf, iFrames); - ASSERT_M(got == iFrames, ssprintf("%i, %i", got, iFrames)); -} - -void -find(const char* haystack, int hs, const char* needle, int ns) -{ - for (int i = 0; i <= hs - ns; ++i) { - if (!memcmp(haystack + i, needle, ns)) { - printf("xx %i\n", i); - return; - } - } -} - -void -dump_bin(const char* fn, const char* buf, int size) -{ - int fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC); - ASSERT(fd != -1); - write(fd, buf, size); - close(fd); -} - -void -dump(const char* fn, const int16_t* buf, int samples) -{ - FILE* f = fopen(fn, "w+"); - ASSERT(f); - - int cnt = 0; - for (int i = 0; i < samples; ++i) { - fprintf(f, "0x%04hx,", buf[i]); - if (cnt++ == 16) { - fprintf(f, "\n"); - cnt = 0; - } - } - - fclose(f); -} - -void -dump(const char* buf, int size) -{ - for (int i = 0; i < size; ++i) - printf("%-2.2x ", ((unsigned char*)buf)[i]); - printf("\n\n"); -} - -void -dump(const int16_t* buf, int samples) -{ - for (int i = 0; i < samples; ++i) - printf("0x%04hx,", buf[i]); - printf("\n"); -} - -void -dump(const float* buf, int samples) -{ - for (int i = 0; i < samples; ++i) - printf("0x%04lx,", lrintf(buf[i] * 32768)); - printf("\n"); -} - -bool -compare(const float* m1, const int16_t* m2, int iSamples) -{ - for (int i = 0; i < iSamples; ++i) { - int16_t iSample1 = lrintf(m1[i] * 32768); - if (iSample1 != m2[i]) - return false; - } - - return true; -} - -void -compare_buffers(const int16_t* expect, - const int16_t* got, - int frames, - int& NumInaccurateSamplesAtStart, - int& NumInaccurateSamples) -{ - bool InaccurateSinceStart = true; - - NumInaccurateSamplesAtStart = 0; - NumInaccurateSamples = 0; - - for (int i = 0; i < frames; ++i) { - int diff = abs(expect[i] - got[i]); - if (diff > 200) { - printf("%i\n", diff); - ++NumInaccurateSamples; - if (InaccurateSinceStart) - ++NumInaccurateSamplesAtStart; - } else - InaccurateSinceStart = false; - } -} - -bool -compare_buffers(const int16_t* expect, - const int16_t* got, - int frames, - int channels) -{ - /* - * Compare each channel separately. Try to figure out if - * the data is exactly the same, - * - * 2: either the source or dest data starts out around 0 and converges - * quickly on the other; this happens with resamplers after a seek, since - * they're missing data before the seeked position (could be fixed) - * - * When seeking, resamplers should ideally seek slightly before the - * requested position, read the extra data, feed it to the resampling - * engine, and discard the extra data. Otherwise, the resampler is starting - * with no data, and will give some low samples. (The amount of incorrect - * data depends on the window size of the resampler.) Detect if this - * happens: determine if the data starts very inaccurately and quickly - * converges. - * - * Determine if data is identical, but offset. - * - */ - - int NumInaccurateSamples; - int NumInaccurateSamplesAtStart; - compare_buffers( - expect, got, frames, NumInaccurateSamplesAtStart, NumInaccurateSamples); - - printf("%i/%i off, %i at start\n", - NumInaccurateSamples, - frames, - NumInaccurateSamplesAtStart); - return NumInaccurateSamples == 0; -} - -bool -test_read(RageSoundReader* snd, float* expected_data, int frames) -{ - int samples = frames * snd->GetNumChannels(); - float buf[samples]; - int got = snd->Read(buf, frames); - ASSERT(got == frames); - - // compare_buffers( (const int16_t *) expected_data, - // (const int16_t *) buf, - // bytes/2, - // 2 ); - - bool bMatches = true; - for (int i = 0; i < samples; ++i) - if (fabsf(buf[i] - expected_data[i]) > 0.00001f) - bMatches = false; - if (bMatches) - return true; - - dump(expected_data, min(100, samples)); - dump(buf, min(100, samples)); - return false; -} - -bool -must_be_eof(RageSoundReader* snd) -{ - float buf[16]; - int got = snd->Read(buf, 1); - return got == RageSoundReader::END_OF_FILE; -} - -const int FILTER_NONE = 0; -const int FILTER_PRELOAD = 1 << 0; -const int FILTER_RESAMPLE_FAST = 1 << 1; - -RageSoundReader* -ApplyFilters(RageSoundReader* s, int filters) -{ - if (filters & FILTER_PRELOAD) { - RageSoundReader_Preload* r = new RageSoundReader_Preload(); - if (r->Open(s)) - s = r; - else { - printf("Didn't preload\n"); - delete r; - } - } - - if (filters & FILTER_RESAMPLE_FAST) { - RageSoundReader_Resample_Good* r = - new RageSoundReader_Resample_Good(s, 10000); - s = r; - } - - return s; -} - -bool -CheckSetPositionAccurate(RageSoundReader* snd) -{ - snd->SetProperty("AccurateSync", true); - - const int one_second = snd->GetSampleRate(); - float data[one_second * snd->GetNumChannels()]; - - int iFrame = snd->GetSampleRate() * 100 / 1000; // 100ms - ReadData(snd, iFrame, data, one_second / 10); - - snd->SetPosition(iFrame * 100); - snd->SetPosition(iFrame); - if (!test_read(snd, data, one_second / 10)) { - LOG->Warn("Fail: rewind didn't work"); - return false; - } - - return true; -} - -int -FramesOfSilence(const float* data, int frames, int iChannels) -{ - int SilentFrames = 0; - while (SilentFrames < frames) { - for (int c = 0; c < iChannels; ++c) - if (fabsf(*data++) > (1 / 65536.0f)) - return SilentFrames; - ++SilentFrames; - } - return SilentFrames; -} - -/* The number of frames we compare against expected data: */ -const int TestDataSize = 2; - -/* Find "haystack" in "needle". Start looking at "expect" and move outward; - * find the closest. */ -void* -xmemsearch(const float* haystack, - size_t iHaystackSamples, - const int16_t* needle, - size_t iNeedleSamples, - int expect) -{ - if (!iNeedleSamples) - return (void*)haystack; - - const float* pHaystackEnd = haystack + iHaystackSamples; - - int out_len = 0; - while (1) { - const float* hay_early = haystack + expect - out_len; - const float* hay_late = haystack + expect + out_len; - if (hay_early >= haystack && - hay_early + iNeedleSamples < pHaystackEnd) { - if (compare(hay_early, needle, iNeedleSamples)) - return (void*)hay_early; - } - - if (hay_late >= haystack && hay_late + iNeedleSamples < pHaystackEnd) { - if (compare(hay_late, needle, iNeedleSamples)) - return (void*)hay_late; - } - - if (hay_early < haystack && hay_late + iNeedleSamples >= pHaystackEnd) - break; - - ++out_len; - } - - return NULL; -} - -struct TestFile -{ - const char* fn; - - /* The number of silent frames we expect: */ - int SilentFrames; - - /* The first two frames (four samples): */ - int16_t initial[TestDataSize * 2]; - - /* Frames of data half a second in: */ - int16_t later[TestDataSize * 2]; -}; -const int channels = 2; - -bool -RunTests(RageSoundReader* snd, const TestFile& tf) -{ - const char* fn = tf.fn; - { - float len = snd->GetLength(); - // printf("%f\n", len); - if (len < 1000.0f) { - LOG->Warn("Test file %s is too short", fn); - return false; - } - } - - /* Read the first second of the file. Do this without calling any - * seek functions. */ - const int one_second_frames = snd->GetSampleRate(); - const int one_second_samples = one_second_frames * snd->GetNumChannels(); - const int one_second_bytes = one_second_samples * sizeof(float); - float sdata[one_second_frames * snd->GetNumChannels()]; - char* data = (char*)sdata; - memset(data, 0x42, one_second_bytes); - ReadData(snd, -1, sdata, one_second_frames); - - { - /* Find out how many frames of silence we have. */ - int SilentFrames = - FramesOfSilence(sdata, one_second_frames, snd->GetNumChannels()); - - const float* InitialData = sdata + SilentFrames * snd->GetNumChannels(); - const int InitialDataSize = one_second_frames - SilentFrames; - - if (InitialDataSize < (int)sizeof(tf.initial)) { - LOG->Warn( - "Not enough (%i<%i) data to check after %i frames of silence", - InitialDataSize, - sizeof(tf.initial), - SilentFrames); - return false; - } - - bool bFailed = false; - if (SilentFrames != tf.SilentFrames) { - LOG->Trace("Expected %i silence, got %i (%i too high)", - tf.SilentFrames, - SilentFrames, - SilentFrames - tf.SilentFrames); - bFailed = true; - } - - bool Identical = !compare(InitialData, tf.initial, sizeof(tf.initial)); - if (!Identical) { - LOG->Trace("Expected data:"); - dump(tf.initial, ARRAYLEN(tf.initial)); - LOG->Trace(" "); - bFailed = true; - } - - if (bFailed) { - LOG->Trace("Got data:"); - dump(InitialData, min(16, 2 * InitialDataSize)); - } - - const int LaterOffsetFrames = one_second_frames / 2; /* half second */ - const int LaterOffsetSamples = - LaterOffsetFrames * snd->GetNumChannels(); - const float* LaterData = sdata + LaterOffsetSamples; - Identical = !compare(LaterData, tf.later, sizeof(tf.later)); - if (!Identical) { - LOG->Trace("Expected half second data:"); - dump(tf.later, ARRAYLEN(tf.later)); - LOG->Trace("Got half second data:"); - dump(LaterData, 16); - - /* See if we can find the half second data. */ - float* p = (float*)xmemsearch(sdata, - one_second_bytes, - tf.later, - sizeof(tf.later), - LaterOffsetSamples * sizeof(int16_t)); - if (p) { - int SamplesOff = p - sdata; - int FramesOff = SamplesOff / 2; - LOG->Trace("Found half second data at frame %i (wanted %i), " - "ahead by %i samples", - FramesOff, - LaterOffsetFrames, - FramesOff - LaterOffsetFrames); - } - // else - // dump( "foo", sdata, one_second/sizeof(int16_t) ); - } - } - - /* Make sure we're getting non-null data. */ - { - bool bAllNull = true; - bool bAll42 = true; - - for (int i = 0; i < one_second_bytes; ++i) { - if (data[i] != 0) - bAllNull = false; - if (data[i] != 0x42) - bAll42 = false; - } - - if (bAllNull || bAll42) { - LOG->Warn( - "'%s': sanity check failed (%i %i)", fn, bAllNull, bAll42); - return false; - } - } - - /* Read to EOF, discarding the data. */ - while (1) { - float buf[4096]; - int got = snd->Read(buf, ARRAYLEN(buf) / snd->GetNumChannels()); - if (got == RageSoundReader::END_OF_FILE) - break; - ASSERT(got >= 0); - } - - /* Now, make sure reading after an EOF returns another EOF. */ - if (!must_be_eof(snd)) { - LOG->Warn("Fail: Reading past EOF didn't EOF"); - return false; - } - - if (!must_be_eof(snd)) { - LOG->Warn("Fail: Reading past EOF twice didn't EOF"); - return false; - } - - for (int i = 0; i < 2; ++i) { - const char* szMode = i == 0 ? "accurate" : "fast"; - snd->SetProperty("AccurateSync", i == 0 ? true : false); - - /* SetPosition(0) must always reset properly. */ - int iRet = snd->SetPosition(0); - if (iRet != 1) { - LOG->Warn("Fail: SetPosition(0) (%s) returned %i, expected 1", - szMode, - iRet); - return false; - } - - if (!test_read(snd, sdata, one_second_frames)) { - LOG->Warn("Fail: SetPosition(0) (%s) didn't work", szMode); - return false; - } - - /* Make sure seeking past end of file returns 0. */ - int ret2 = snd->SetPosition(10000000); - if (ret2 != 0) { - LOG->Warn( - "Fail: SetPosition(1000000) (%s) returned %i instead of 0", - szMode, - ret2); - return false; - } - - /* Make sure that reading after a seek past EOF returns EOF. */ - if (!must_be_eof(snd)) { - LOG->Warn("Fail: SetPosition(EOF) (%s) didn't EOF", szMode); - return false; - } - } - - /* Seek to 1ms and make sure it gives us the correct data. */ - snd->SetProperty("AccurateSync", true); - int iFrame = snd->GetSampleRate() * 1 / 1000; // 1ms - snd->SetPosition(iFrame); - if (!test_read(snd, - sdata + one_second_samples * 1 / 1000, - one_second_frames * 1 / 1000)) - LOG->Warn("Fail: SetPosition(1) (accurate) didn't work"); - - /* Seek to 500ms and make sure it gives us the correct data. */ - iFrame = snd->GetSampleRate() * 500 / 1000; // 500ms - snd->SetPosition(iFrame); - if (!test_read(snd, - sdata + one_second_samples * 500 / 1000, - one_second_frames * 500 / 1000)) - LOG->Warn("Fail: seek(500) (accurate) didn't work"); - - return true; -} - -bool -test_file(const TestFile& tf, int filters) -{ - const char* fn = tf.fn; - - LOG->Trace("Testing: %s", fn); - RString error; - RageSoundReader* s = SoundReader_FileReader::OpenFile(fn, error); - s = ApplyFilters(s, filters); - - if (s == NULL) { - LOG->Trace("File '%s' failed to open: %s", fn, error.c_str()); - return false; - } - // RageSoundReader *snd = s; - RageSoundReader* snd = s->Copy(); - delete s; - - bool ret = RunTests(snd, tf); - - delete snd; - - /* - * Check SetPosition consistency: - * - * Reopen the file from scratch, seek to 100ms, read some data, do some - * operations that would result in the internal TOC being filled (seek - * to the end), then re-read the data at 100ms and make sure it's the same. - */ - - snd = SoundReader_FileReader::OpenFile(fn, error); - snd = ApplyFilters(snd, filters); - - if (snd == NULL) { - LOG->Trace("File '%s' failed to open: %s", fn, error.c_str()); - return false; - } - - if (!CheckSetPositionAccurate(snd)) - ret = false; - - delete snd; - return ret; -} - -int -main(int argc, char* argv[]) -{ - test_handle_args(argc, argv); - test_init(); - - TestFile files[] = { - /* These are all the same data, but they're encoded with different - * amounts of lossage, so the values are all similar but, unlike the - * header tests below, not identical. */ - /* { "test PCM 44100 stereo.wav", 0, - {0xfb6b,0x0076,0xf82b,0x0028}, {0xf598,0xf630,0xf2bd,0xf11d} }, { - "test ADPCM 44100 stereo.wav",0, {0xfb6b,0x0076,0xf82b,0x0028}, - {0xf6d7,0xf54f,0xf300,0xf19e} }, - // { "test ADPCM 22050 mono.wav", 1, - {0xfc2a,0xf4a8,0xf2bb,0xec98}, {0xf329,0xf1c2,0xf44f,0xff82} }, { - "test PCM8bit 44100 stereo.wav", 0, - {0xfb7b,0x0080,0xf878,0x0080}, {0xf575,0xf676,0xf272,0xf171} }, - // XXX: add MP3-in-WAV test - { "test OGG 44100 stereo.ogg", 0, - {0xfb90,0x00b6,0xf84c,0x00ec}, {0xf794,0xf6c4,0xf34e,0xf2cd} }, { - "test MP3 first frame corrupt.mp3", 2343, - {0x0001,0x0000,0x0001,0x0000}, {0xe12f,0xfe36,0xf337,0x0778} }, { - "test BASS first frame corrupt.wav", 2343, - {0x0001,0x0000,0x0001,0x0000}, {0xe12f,0xfe36,0xf337,0x0778} }, - */ - /* "BASS" is the results of decoding each MP3 with BASS's "writewav" - * program, in order to test compatibility with DWI. */ - - /* The following all contain the same data; they simply have - different tags and headers. */ - { "test MP3 44100 stereo CBR.mp3", - 592, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xef22, 0x0cd6, 0xee84, 0x0bb6 } }, - { "test MP3 44100 stereo CBR (ID3V1).mp3", - 592, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xef22, 0x0cd6, 0xee84, 0x0bb6 } }, - { "test MP3 44100 stereo CBR (ID3V2).mp3", - 592, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xef22, 0x0cd6, 0xee84, 0x0bb6 } }, - { "test MP3 44100 stereo CBR (INFO, LAME).mp3", - 1744, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xfc71, 0x23ee, 0xfb74, 0x2141 } }, - - { "test BASS 44100 stereo CBR.wav", - 592, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xef22, 0x0cd6, 0xee84, 0x0bb6 } }, - { "test BASS 44100 stereo CBR (ID3V1).wav", - 592, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xef22, 0x0cd6, 0xee84, 0x0bb6 } }, - { "test BASS 44100 stereo CBR (ID3V2).wav", - 592, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xef22, 0x0cd6, 0xee84, 0x0bb6 } }, - { "test BASS 44100 stereo CBR (INFO, LAME).wav", - 1744, - { 0x0000, 0x0001, 0x0000, 0x0001 }, - { 0xfc71, 0x23ee, 0xfb74, 0x2141 } }, - - /* The following all contain the same data; they simply have - different tags and headers. */ - { "test MP3 44100 stereo VBR (INFO, LAME).mp3", - 1774, - { 0xffff, 0x0000, 0xffff, 0x0000 }, - { 0xfe43, 0x262a, 0xfd0c, 0x22bc } }, - { "test MP3 44100 stereo VBR (XING, LAME).mp3", - 622, - { 0xffff, 0x0000, 0xffff, 0x0000 }, - { 0xef6c, 0x0cb8, 0xef10, 0x0bd2 } }, - { "test MP3 44100 stereo VBR (XING, LAME, ID3V1, ID3V2).mp3", - 622, - { 0xffff, 0x0000, 0xffff, 0x0000 }, - { 0xef6c, 0x0cb8, 0xef10, 0x0bd2 } }, - - { "test BASS 44100 stereo VBR (INFO, LAME).wav", - 1774, - { 0xffff, 0x0000, 0xffff, 0x0000 }, - { 0xfe43, 0x262a, 0xfd0c, 0x22bc } }, - { "test BASS 44100 stereo VBR (XING, LAME).wav", - 622, - { 0xffff, 0x0000, 0xffff, 0x0000 }, - { 0xef6c, 0x0cb8, 0xef10, 0x0bd2 } }, - { "test BASS 44100 stereo VBR (XING, LAME, ID3V1, ID3V2).wav", - 622, - { 0xffff, 0x0000, 0xffff, 0x0000 }, - { 0xef6c, 0x0cb8, 0xef10, 0x0bd2 } }, - { NULL, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } - }; - - for (int i = 0; files[i].fn; ++i) { - if (!test_file(files[i], 0)) - LOG->Trace(" "); - } - - test_deinit(); - exit(0); -} diff --git a/src/tests/test_file_errors.cpp b/src/tests/test_file_errors.cpp deleted file mode 100644 index 3720a2173b..0000000000 --- a/src/tests/test_file_errors.cpp +++ /dev/null @@ -1,459 +0,0 @@ -#include "global.h" -#include "PrefsManager.h" -#include "RageLog.h" -#include "RageFile.h" -#include "RageFileDriver.h" -#include "RageUtil.h" -#include "RageUtil_FileDB.h" -#include "test_misc.h" - -#include - -static RString g_TestFile; -static RString g_TestFilename; -static int g_BytesUntilError = 6; - -/* - * This driver - * 1: reads from a single "file", contained in g_TestFile, with fn - * g_TestFilename; 2: writes to the bit bucket, 3: triggers an error when - * g_BytesUntilError reaches 0. - */ -class RageFileDriverTest : public RageFileDriver -{ - public: - RageFileDriverTest(RString root); - - RageFileObj* Open(const RString& path, int mode, int& err); - bool Remove(const RString& sPath) { return false; } - bool Ready() { return true; } - - private: - RString root; -}; - -static struct FileDriverEntry_TEST : public FileDriverEntry -{ - FileDriverEntry_TEST() - : FileDriverEntry("TEST") - { - } - RageFileDriver* Create(const RString& sRoot) const - { - return new RageFileDriverTest(sRoot); - } -} const g_RegisterDriver; - -class TestFilenameDB : public FilenameDB -{ - protected: - virtual void PopulateFileSet(FileSet& fs, const RString& sPath) - { - if (sPath != ".") - return; - if (g_TestFile == "") - return; - - fs.files.clear(); - - File f; - f.SetName(g_TestFilename); - f.dir = false; - f.size = g_TestFile.size(); - f.hash = GetHashForString(g_TestFile); - fs.files.insert(f); - } - - RString root; - - public: - TestFilenameDB(RString root_) - { - root = root_; - if (root == "./") - root = ""; - } -}; - -class RageFileObjTest : public RageFileObj -{ - public: - RageFileObjTest(const RString& path); - RageFileObjTest(const RageFileObjTest& cpy); - int ReadInternal(void* buffer, size_t bytes); - int WriteInternal(const void* buffer, size_t bytes); - int Flush(); - void Rewind() { pos = 0; } - int Seek(int offset) - { - pos = min(offset, (int)g_TestFile.size()); - return pos; - } - RageFileObj* Copy() const; - RString GetDisplayPath() const { return path; } - int GetFileSize() const { return g_TestFile.size(); } - - private: - RString path; /* for Copy */ - int pos; -}; - -RageFileDriverTest::RageFileDriverTest(RString root_) - : RageFileDriver(new TestFilenameDB(root_)) - , root(root_) -{ - if (root.Right(1) != "/") - root += '/'; -} - -RageFileObjTest::RageFileObjTest(const RageFileObjTest& cpy) - : RageFileObj(cpy) -{ - path = cpy.path; - pos = cpy.pos; -} - -RageFileObj* -RageFileDriverTest::Open(const RString& path, int mode, int& err) -{ - if (path != g_TestFilename) { - err = ENOENT; - return NULL; - } - - return new RageFileObjTest(root + path); -} - -RageFileObj* -RageFileObjTest::Copy() const -{ - return new RageFileObjTest(*this); -} - -static const unsigned int BUFSIZE = 1024 * 64; -RageFileObjTest::RageFileObjTest(const RString& path_) -{ - path = path_; - pos = 0; -} - -int -RageFileObjTest::ReadInternal(void* buf, size_t bytes) -{ - bytes = min(bytes, g_TestFile.size() - pos); - - if (g_BytesUntilError != -1) { - if ((int)bytes > g_BytesUntilError) { - SetError("Fake error"); - g_BytesUntilError = -1; - return -1; - } - - g_BytesUntilError -= min(g_BytesUntilError, (int)bytes); - } - - memcpy(buf, g_TestFile.data() + pos, bytes); - pos += bytes; - return bytes; -} - -int -RageFileObjTest::WriteInternal(const void* buf, size_t bytes) -{ - if (g_BytesUntilError != -1) { - if ((int)bytes > g_BytesUntilError) { - SetError("Fake error"); - g_BytesUntilError = -1; - return -1; - } - - g_BytesUntilError -= min(g_BytesUntilError, (int)bytes); - } - - return bytes; -} - -/* - * Testing Flush() is important. Writing may buffer. That buffer will be - * flushed, at the latest, when the file is closed in the RageFile dtor. - * However, if you wait until then, there's no way to check for an error; the - * file is going away. The primary purpose of Flush() is to give the user a - * chance to check for these errors. (Flush() is only intended to flush our - * buffers; it is *not* intended to sync data to disk.) - */ -int -RageFileObjTest::Flush() -{ - if (g_BytesUntilError != -1) { - SetError("Fake error"); - g_BytesUntilError = -1; - return -1; - } - - return 0; -} - -#define Fail(s...) \ - { \ - LOG->Warn(s); \ - break; \ - } - -void -SanityCheck() -{ - /* Read sanity check. */ - do { - g_TestFile = "hello"; - g_TestFilename = "file"; - - RageFile test; - if (!test.Open("/test/file", RageFile::READ)) - Fail("Sanity check Open() failed: %s", test.GetError().c_str()); - - RString str; - int got = test.GetLine(str); - if (got <= 0) - Fail("Sanity check GetLine(): got %i", got); - - if (str != "hello") - Fail("Sanity check Read(): expected \"hello\", got \"%s\"", - str.c_str()); - } while (false); - - /* Read error sanity check. */ - do { - g_TestFile = "hello world"; - g_TestFilename = "file"; - g_BytesUntilError = 5; - - RageFile test; - if (!test.Open("/test/file", RageFile::READ)) - Fail("Sanity check 2 Open() failed: %s", test.GetError().c_str()); - - RString str; - int got = test.Read(str, 5); - if (got != 5) - Fail("Sanity check 2 Read(): got %i", got); - - if (str != "hello") - Fail("Sanity check 2 Read(): expected \"hello\", got \"%s\"", - str.c_str()); - - got = test.Read(str, 5); - if (got != -1) - Fail("Sanity check 2 GetLine(): expected -1, got %i", got); - - if (test.GetError() != "Fake error") - Fail( - "Sanity check 2 GetError(): expected \"Fake error\", got \"%s\"", - test.GetError().c_str()); - } while (false); - - /* Write error sanity check. */ - do { - g_TestFilename = "file"; - g_BytesUntilError = 5; - - RageFile test; - if (!test.Open("/test/file", RageFile::WRITE)) - Fail("Write error check Open() failed: %s", - test.GetError().c_str()); - - int wrote = test.Write("test", 4); - if (wrote != 4) - Fail("Write error check Write(): wrote %i", wrote); - - wrote = test.Write("ing", 3); - if (wrote != -1) - Fail("Write error check Write(): expected -1, got %i", wrote); - - if (test.GetError() != "Fake error") - Fail("Write error check GetError(): expected \"Fake error\", got " - "\"%s\"", - test.GetError().c_str()); - } while (false); -} - -#include "IniFile.h" -void -IniTest() -{ - g_TestFilename = "file"; - - /* Read check. */ - do { - g_TestFile = "[test]\n" - "abc=def"; - - g_BytesUntilError = -1; - - IniFile test; - if (!test.ReadFile("test/file")) - Fail("INI: ReadFile failed: %s", test.GetError().c_str()); - - RString sStr; - if (!test.GetValue("test", "abc", sStr)) - Fail("INI: GetValue failed"); - if (sStr != "def") - Fail("INI: GetValue failed: expected \"def\", got \"%s\"", - sStr.c_str()); - } while (false); - - /* Read error check. */ - do { - g_TestFile = "[test]\n" - "abc=def"; - - g_BytesUntilError = 5; - - IniFile test; - if (test.ReadFile("test/file")) - Fail("INI: ReadFile should have failed"); - - if (test.GetError() != "Fake error") - Fail("INI: ReadFile error check: wrong error return: got \"%s\"", - test.GetError().c_str()); - } while (false); - - /* Write error check. */ - do { - g_BytesUntilError = 5; - - IniFile test; - test.SetValue("foo", "bar", RString("baz")); - if (test.WriteFile("test/file")) - Fail("INI: WriteFile should have failed"); - - if (test.GetError() != "Fake error") - Fail("INI: ReadFile error check: wrong error return: got \"%s\"", - test.GetError().c_str()); - } while (false); -} - -#include "MsdFile.h" -void -MsdTest() -{ - g_TestFilename = "file"; - - /* Read check. */ - do { - g_TestFile = "#FOO;"; - - g_BytesUntilError = -1; - - MsdFile test; - if (!test.ReadFile("test/file", false)) - Fail("MSD: ReadFile failed: %s", test.GetError().c_str()); - - if (test.GetNumValues() != 1) - Fail("MSD: GetNumValues: expected 1, got %i", test.GetNumValues()); - if (test.GetNumParams(0) != 1) - Fail("MSD: GetNumParams(0): expected 1, got %i", - test.GetNumParams(0)); - RString sStr = test.GetValue(0)[0]; - if (sStr != "FOO") - Fail("MSD: GetValue failed: expected \"FOO\", got \"%s\"", - sStr.c_str()); - } while (false); - - /* Read error check. */ - do { - g_TestFile = "#FOO:BAR:BAZ;"; - g_BytesUntilError = 5; - - MsdFile test; - if (test.ReadFile("test/file", false)) - Fail("MSD: ReadFile should have failed"); - - if (test.GetError() != "Fake error") - Fail("MSD: ReadFile error check: wrong error return: got \"%s\"", - test.GetError().c_str()); - } while (false); -} - -#include "CryptManager.h" -void -CryptoTest() -{ - PREFSMAN = new PrefsManager; /* CRYPTMAN needs PREFSMAN */ - PREFSMAN->m_bSignProfileData.Set(true); - - CRYPTMAN = new CryptManager; - - g_TestFile = "hello world"; - g_TestFilename = "file"; - FlushDirCache(); - - do { - g_BytesUntilError = -1; - CRYPTMAN->SignFileToFile("test/file", "output"); - - FlushDirCache(); - - if (!CRYPTMAN->VerifyFileWithFile("test/file", "output")) - Fail("Crypto: VerifyFileWithFile failed"); - } while (false); - - /* Write error check. */ - do { - g_BytesUntilError = 5; - CRYPTMAN->SignFileToFile("test/file", "output"); - } while (false); - - /* Read error check. */ - do { - g_BytesUntilError = 5; - CRYPTMAN->SignFileToFile("output", "test/file"); - } while (false); - - delete PREFSMAN; - delete CRYPTMAN; -} - -int -main(int argc, char* argv[]) -{ - test_handle_args(argc, argv); - - test_init(); - - /* Setup. */ - FILEMAN->Mount("TEST", ".", "/test"); - - SanityCheck(); - - IniTest(); - MsdTest(); - CryptoTest(); - - test_deinit(); - - exit(0); -} - -/* - * Copyright (c) 2004 Glenn Maynard - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/tests/test_file_readers.cpp b/src/tests/test_file_readers.cpp deleted file mode 100644 index f0abbfd255..0000000000 --- a/src/tests/test_file_readers.cpp +++ /dev/null @@ -1,451 +0,0 @@ -#include "global.h" -#include "RageLog.h" -#include "RageFile.h" -#include "RageUtil.h" -#include "RageUtil_FileDB.h" -#include "test_misc.h" - -bool CreateTestFiles = false; - -void -CreateBinaryTestFile(RageFile& f, int size) -{ - char c = 0; - while (size--) { - f.Write(ssprintf("%c", c)); - ++c; - } -} - -void -CreateBinaryTestFile(RString fn, int size) -{ - RageFile f; - f.Open(fn, RageFile::WRITE); - CreateBinaryTestFile(f, size); - f.Close(); - - if (!f.Open(fn)) { - LOG->Warn("CreateBinaryTestFile: error reopening %s: %s", - fn.c_str(), - f.GetError().c_str()); - return; - } - - int test = f.GetFileSize(); - if (test != size) - LOG->Warn( - "CreateBinaryTestFile: f.GetFileSize ret %i, exp %i", test, size); -} - -bool -CheckData(const RString& buf, int offset) -{ - char c = offset % 256; - - for (unsigned i = 0; i < buf.size(); ++i) { - if (buf[i] != c) - return false; - ++c; - } - return true; -} - -int -TestBinaryRead(RageFile& test, - int size, - bool AllowEOF, - int ExpectedFilePos, - int TestDataPos) -{ - char buf[4096]; - ASSERT(size <= (int)sizeof(buf)); - int ret = test.Read(buf, size); - if (ret != size) { - if (AllowEOF) - return 0; - LOG->Warn("FAIL"); - return -1; - } - - if (!CheckData(RString(buf, ret), TestDataPos)) { - LOG->Warn("TestBinaryRead: check failed (size %i, %i,%i)", - size, - ExpectedFilePos, - TestDataPos); - return -1; - } - - if (test.Tell() != ExpectedFilePos + ret) { - LOG->Warn( - "Simple Tell() failed (got %i, expected %i)", test.Tell(), ret); - return -1; - } - return 1; -} - -RString -MakeTextTestLine(int line, int size) -{ - RString ret = ssprintf("%02i", line); - ret.append(RString(size - ret.size(), 'x')); - return ret; -} - -bool -CheckTextData(const RString& buf, int LineSize, int size) -{ - return buf == MakeTextTestLine(LineSize, size); -} - -void -TestText(int LineSize, bool DOS) -{ - const unsigned NumLines = 50; - - RString filename = "test.text"; - if (DOS) - filename += ".DOS"; - filename += ssprintf(".%i", LineSize); - if (CreateTestFiles) { - RageFile f; - f.Open(filename, RageFile::WRITE); - - for (unsigned line = 0; line < NumLines; ++line) { - const RString TestLine = MakeTextTestLine(line, LineSize); - f.Write(TestLine); - if (DOS) - f.Write("\r"); - f.Write("\n"); - } - - /* Write a binary test block at the end. */ - CreateBinaryTestFile(f, 4096); - - /* Write a text line, with no NL. */ - f.Write("final"); - - return; - } - - RageFile test; - if (!test.Open(filename)) { - LOG->Warn( - "Open \"%s\" failed: %s", filename.c_str(), test.GetError().c_str()); - exit(1); - } - - int ExpectedPos = 0; - for (unsigned line = 0; line < NumLines; ++line) { - RString buf; - if (test.GetLine(buf) <= 0) { - LOG->Warn("Text read failure, line %i, size %i, DOS %i", - line, - LineSize, - DOS); - return; - } - - /* If we successfully got data, we should not be at EOF. */ - if (test.AtEOF()) { - LOG->Warn("Unexpected EOF in text read, line %i, size %i, DOS %i", - line, - LineSize, - DOS); - return; - } - - if (!CheckTextData(buf, line, LineSize)) { - LOG->Warn("Text read check failure, line %i, size %i, DOS %i: '%s'", - line, - LineSize, - DOS, - buf.c_str()); - return; - } - ExpectedPos += buf.size() + 1; - if (DOS) - ++ExpectedPos; - } - if (ExpectedPos != test.Tell()) { - LOG->Warn("Text read pos failure, size %i, DOS %i: exp %i, got %i", - LineSize, - DOS, - ExpectedPos, - test.Tell()); - return; - } - - /* Test the binary block. Do it in a couple reads, to force it to read from - * the buffer and the file more than once. */ - TestBinaryRead(test, 1024, true, test.Tell(), 1024 * 0); - TestBinaryRead(test, 1024, true, test.Tell(), 1024 * 1); - TestBinaryRead(test, 1024, true, test.Tell(), 1024 * 2); - TestBinaryRead(test, 1024, true, test.Tell(), 1024 * 3); - - { - RString buf; - if (test.GetLine(buf) <= 0) { - LOG->Warn("Unexpected EOF in final line read, DOS %i", DOS); - return; - } - - if (buf != "final") { - LOG->Warn( - "Final text read check failure, DOS %i: '%s'", DOS, buf.c_str()); - return; - } - if (test.AtEOF()) { - LOG->Warn("Unexpected EOF (2) in final text read, DOS %i", DOS); - return; - } - } - - { - RString buf; - if (test.GetLine(buf) != 0) { - LOG->Warn("Expected EOF in final text read, but didn't get it"); - return; - } - - if (!test.AtEOF()) { - LOG->Warn("Expected EOF (2) in final text read, but didn't get it"); - return; - } - } -} - -void -TestText() -{ - /* Test with these line sizes. The internal buffer size is 256, so test - * line sizes around there carefully. */ - int sizes[] = { 4, 7, 100, 200, 254, 255, 256, 257, 258, 500, -1 }; - - for (int s = 0; sizes[s] != -1; ++s) { - TestText(sizes[s], false); - TestText(sizes[s], true); - } -} - -void -TestSeek(bool relative) -{ - const RString TestLine = "Hello World\n"; - /* Print a couple kb of text. Make sure this is big enough that the binary - * test data after it won't start in the buffer; if that happens, the seek - * will be optimized out. */ - RString junk; - for (int lines = 0; lines < 128; ++lines) - junk += "XXXXXXXXX\n"; - - if (CreateTestFiles) { - /* Output a line of text, followed by some junk, followed by binary - * test data. */ - RageFile f; - f.Open("test.seek", RageFile::WRITE); - f.Write(TestLine); - f.Write(junk); - CreateBinaryTestFile(f, 1024); - return; - } - - /* Read the line of text. This will result in some of the junk being - * read into the buffer. */ - RageFile test; - test.Open("test.seek"); - RString line; - test.GetLine(line); - - /* Run the absolute seek test twice. */ - for (int pass = 0; pass < 2; ++pass) { - /* Seek to the binary test data. */ - if (relative && pass > 0) - break; - - int ret; - if (relative) - ret = test.Seek(test.Tell() + junk.size()); - else - ret = test.Seek(TestLine.size() + junk.size()); - - if (ret != int(TestLine.size() + junk.size())) { - LOG->Warn( - "Seek(%i) failed: got %i", TestLine.size() + junk.size(), ret); - return; - } - - /* Check the binary test data (making sure we don't get any junk). */ - TestBinaryRead(test, 256, false, test.Tell(), 256 * 0); - TestBinaryRead(test, 256, false, test.Tell(), 256 * 1); - TestBinaryRead(test, 256, false, test.Tell(), 256 * 2); - TestBinaryRead(test, 256, false, test.Tell(), 256 * 3); - - /* Check EOF. */ - char c; - ret = test.Read(&c, 1); - if (ret != 0) { - LOG->Warn("Read(1) failed: got %i, expected 0", ret); - return; - } - if (!test.AtEOF()) { - LOG->Warn("AtEOF returned false, expected true"); - return; - } - } - - test.Seek(5); - if (test.AtEOF()) { - LOG->Warn("AtEOF returned true, expected false"); - return; - } - - /* Make sure a read after seeking far past EOF returns 0. */ - test.Seek(9999999); - char c; - int ret = test.Read(&c, 1); - if (ret != 0) { - LOG->Warn("Read(1) failed: got %i, expected 0", ret); - return; - } - if (!test.AtEOF()) { - LOG->Warn("AtEOF returned false, expected true"); - return; - } -} - -#include "RageFileDriverMemory.h" -#include "RageFileDriverDeflate.h" -void -CheckDeflate(RageFileObjMem& data, - int iSize, - unsigned iInputCRC, - int iBlockSize) -{ - data.Seek(0); - - RString foo2; - - RageFileObjInflate infl(&data, iSize); - infl.EnableCRC32(); - int iGot = 0; - while (iGot < iSize) { - int iRet = infl.Read(foo2, iBlockSize); - if (iRet == 0) { - LOG->Warn( - "Premature EOF (iSize %i, iBlockSize %i)", iSize, iBlockSize); - return; - } - - iGot += iRet; - } - - unsigned iOutputCRC; - if (!infl.GetCRC32(&iOutputCRC)) { - LOG->Warn("Inflate GetCRC32 failed"); - return; - } - if (iInputCRC != iOutputCRC) { - LOG->Warn("Expected CRC %08x, got %08x", iInputCRC, iOutputCRC); - return; - } - - if (iSize != iGot) { - LOG->Warn("Expected %i, got %i", iSize, iGot); - return; - } -} - -void -TestDeflate() -{ - RageFileObjMem data; - RageFileObjDeflate defl(&data); - defl.EnableCRC32(); - - int iSize = 0; - while (iSize < 1024 * 512) - iSize += defl.Write("test foo bar fah"); - defl.Flush(); - - unsigned iOutputCRC; - if (!defl.GetCRC32(&iOutputCRC)) { - LOG->Warn("Deflate GetCRC32 failed"); - return; - } - - CheckDeflate(data, iSize, iOutputCRC, 1); - CheckDeflate(data, iSize, iOutputCRC, 1024); - CheckDeflate(data, iSize, iOutputCRC, 1024 * 4); - CheckDeflate(data, iSize, iOutputCRC, iSize - 1); - CheckDeflate(data, iSize, iOutputCRC, iSize); -} - -int -main(int argc, char* argv[]) -{ - test_handle_args(argc, argv); - - optind = 0; // force getopt to reset - while (1) { - opterr = 0; - int opt = getopt(argc, argv, "c"); - if (opt == -1) - break; - switch (opt) { - case 'c': - CreateTestFiles = true; - break; - } - } - - test_init(); - - if (GetCommandlineArgument("zlib")) { - TestDeflate(); - test_deinit(); - return 0; - } - - if (CreateTestFiles) - CreateBinaryTestFile("test.binary", 4096); - else { - /* Test binary reading. */ - RageFile test; - if (!test.Open("test.binary")) { - LOG->Warn("Open \"test.binary\" failed: %s", - test.GetError().c_str()); - exit(1); - } - - TestBinaryRead(test, 256, false, 0, 0); - - /* Test simple re-opening. */ - test.Close(); - test.Open("test.binary"); - - /* We should now be back at 0. */ - if (test.Tell() != 0) { - LOG->Warn("Simple Tell() after reopen failed (got %i, expected 0)", - test.Tell()); - exit(1); - } - - /* Test reading further, with various block sizes. */ - while (1) { - if (TestBinaryRead(test, 85, true, test.Tell(), test.Tell()) == 0) - break; - } - } - - /* Test text reading. */ - TestText(); - - /* Test seeking. */ - TestSeek(true); - TestSeek(false); - - test_deinit(); - - exit(0); -} diff --git a/src/tests/test_misc.cpp b/src/tests/test_misc.cpp deleted file mode 100644 index 63f1d23ff0..0000000000 --- a/src/tests/test_misc.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "global.h" -#include "test_misc.h" - -#include "RageFileManager.h" -#include "RageLog.h" -#include "RageUtil.h" -#include "arch/ArchHooks/ArchHooks.h" - -RString g_Driver = "dir", g_Root = "."; - -RString argv0; - -void -test_handle_args(int argc, char* argv[]) -{ - SetCommandlineArguments(argc, argv); - argv0 = argv[0]; - - while (1) { - opterr = 0; - int opt = getopt(argc, argv, "cd:r:h"); - if (opt == -1) - break; - switch (opt) { - case 'd': - g_Driver = optarg; - break; - case 'r': - g_Root = optarg; - break; - - case 'h': - printf("options:\n"); - printf(" -c: create test files\n"); - printf( - " -d driver: choose file driver to test (default \"Dir\")\n"); - printf(" -r root: set file driver root (default \".\")\n"); - exit(1); - } - } -} - -void -test_init() -{ - HOOKS = ArchHooks::Create(); - HOOKS->Init(); - - FILEMAN = new RageFileManager(argv0); - FILEMAN->Mount(g_Driver, g_Root, "/"); - - LOG = new RageLog; - LOG->SetLogToDisk(false); - LOG->SetShowLogOutput(true); - LOG->SetFlushing(true); -} - -void -test_deinit() -{ - delete LOG; - delete FILEMAN; - delete HOOKS; -} diff --git a/src/tests/test_misc.h b/src/tests/test_misc.h deleted file mode 100644 index 7a09f813b8..0000000000 --- a/src/tests/test_misc.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef TEST_HELPERS_H -#define TEST_HELPERS_H - -void -test_handle_args(int argc, char* argv[]); -void -test_init(); -void -test_deinit(); - -#endif diff --git a/src/tests/test_threads.cpp b/src/tests/test_threads.cpp deleted file mode 100644 index e26d4f0854..0000000000 --- a/src/tests/test_threads.cpp +++ /dev/null @@ -1,330 +0,0 @@ -#include "global.h" -#include "RageLog.h" -#include "RageUtil.h" -#include "RageThreads.h" -#include "archutils/Unix/Backtrace.h" -#include "archutils/Unix/BacktraceNames.h" -#include "test_misc.h" - -#include -#include "archutils/Common/PthreadHelpers.h" - -/* These are volatile, so writes to them aren't optimized. */ -volatile uint64_t g_ThreadId = (uint64_t)-1; -volatile int g_Counter = 0; -volatile bool g_Finish = false; - -void -TestSuspendIncrLoop() -{ - while (!g_Finish) - ++g_Counter; -} - -int -TestSuspendThread(void* p) -{ - printf("Test thread started\n"); - - g_ThreadId = GetCurrentThreadId(); - TestSuspendIncrLoop(); - - return 0; -} - -void -test_suspend_threadid(uint64_t ThreadId) -{ - /* Wait for g_Counter to increment a bit. */ - usleep(100000); - - /* Stop the thread. */ - SuspendThread(ThreadId); - - int OldCounter = g_Counter; - - /* Wait a while. g_Counter shouldn't change. */ - usleep(100000); - - ASSERT(g_Counter == OldCounter); - - /* Start it again, and wait. */ - ResumeThread(ThreadId); - usleep(100000); - - /* g_Counter should change. */ - ASSERT(g_Counter != OldCounter); - - /* Stop all other threads. */ - RageThread::HaltAllThreads(); - - OldCounter = g_Counter; - - /* Wait a while. g_Counter shouldn't change. */ - usleep(100000); - ASSERT(g_Counter == OldCounter); - - /* Start it again, and wait. */ - RageThread::ResumeAllThreads(); - usleep(100000); - - /* g_Counter should change. */ - ASSERT(g_Counter != OldCounter); -} - -/* Test whether suspending a child thread works. */ -void -test_suspend_secondary_thread() -{ - ASSERT(!g_Finish); - ASSERT(g_ThreadId == (uint64_t)-1); - - RageThread testing; - testing.SetName("TestSuspend"); - testing.Create(TestSuspendThread, NULL); - - while (g_ThreadId == (uint64_t)-1) - ; - - test_suspend_threadid(g_ThreadId); - - g_Finish = true; - testing.Wait(); - g_Finish = false; - g_ThreadId = (uint64_t)-1; -} - -int -TestSuspendMainThread(void* p) -{ - ASSERT(!g_Finish); - - printf("Test thread started\n"); - - ASSERT(g_ThreadId != (uint64_t)-1); - test_suspend_threadid(g_ThreadId); - g_Finish = true; - - return 0; -} - -/* Test whether suspending the main thread works. */ -void -test_suspend_main_thread() -{ - ASSERT(!g_Finish); - ASSERT(g_ThreadId == (uint64_t)-1); - - g_ThreadId = GetCurrentThreadId(); - - RageThread testing; - testing.SetName("TestSuspend"); - testing.Create(TestSuspendMainThread, NULL); - - TestSuspendIncrLoop(); - - testing.Wait(); - g_Finish = false; - g_ThreadId = (uint64_t)-1; -} - -/* Run a second function, so we have two symbols to search for. */ -void -TestBacktraceThreadLoop() __attribute__((__noinline__)); -void -TestBacktraceThreadLoop() -{ - g_ThreadId = GetCurrentThreadId(); - while (!g_Finish) - ; -} - -int -TestBacktraceThread(void* p) __attribute__((__noinline__)); -int -TestBacktraceThread(void* p) -{ - TestBacktraceThreadLoop(); - return 0; -} - -bool -test_thread_backtrace(int ThreadId, const void* expect1, const void* expect2) -{ - BacktraceContext ctx; - int ret = GetThreadBacktraceContext(ThreadId, &ctx); - ASSERT(ret); - - const void* BacktracePointers[1024]; - GetBacktrace(BacktracePointers, 1024, &ctx); - - ResumeThread(ThreadId); - - bool bFound1 = false, bFound2 = false; - for (int i = 0; BacktracePointers[i]; ++i) { - BacktraceNames bn; - bn.FromAddr(BacktracePointers[i]); - - // printf("want %p, %p: %p, %p\n", expect1, expect2, - // bn.Address-bn.Offset, BacktracePointers[i] ); printf(" - //%s\n", bn.Format().c_str() ); - - /* bn.Address is the current address; Offset is the distance to the - * beginning of the symbol, so bn.Address-bn.Offset is the actual - * symbol. */ - if (bn.Address - bn.Offset == (int)expect1) - bFound1 = true; - if (bn.Address - bn.Offset == (int)expect2) - bFound2 = true; - } - - return bFound1 && bFound2; -} - -void -test_backtracing_secondary_thread() -{ - ASSERT(!g_Finish); - - RageThread testing; - testing.SetName("TestBacktrace"); - testing.Create(TestBacktraceThread, NULL); - - while (g_ThreadId == (uint64_t)-1) - ; - - if (!test_thread_backtrace(g_ThreadId, - (void*)TestBacktraceThread, - (void*)TestBacktraceThreadLoop)) { - printf("test_backtracing_secondary_thread failed\n"); - exit(1); - } - - g_Finish = true; - testing.Wait(); - g_Finish = false; - g_ThreadId = (uint64_t)-1; -} - -int -TestBacktraceMainThread(void* p) -{ - printf("Test thread started\n"); - - while (g_ThreadId == (uint64_t)-1) - ; - - if (!test_thread_backtrace(g_ThreadId, - (void*)TestBacktraceThread, - (void*)TestBacktraceThreadLoop)) { - printf("test_backtracing_main_thread failed\n"); - exit(1); - } - - g_Finish = true; - - return 0; -} - -void -test_backtracing_main_thread() -{ - ASSERT(!g_Finish); - ASSERT(g_ThreadId == (uint64_t)-1); - - RageThread testing; - testing.SetName("TestBacktrace"); - testing.Create(TestBacktraceMainThread, NULL); - - TestBacktraceThread(NULL); - - testing.Wait(); - g_Finish = false; - g_ThreadId = (uint64_t)-1; -} - -static RageMutex g_Mutex("test"); - -int -TestLocksThread(void* p) -{ - printf("Test thread started\n"); - - g_ThreadId = GetCurrentThreadId(); - - while (!g_Finish) { - g_Mutex.Lock(); - ++g_Counter; - g_Mutex.Unlock(); - } - - return 0; -} - -void -test_locks() -{ - ASSERT(!g_Finish); - ASSERT(g_ThreadId == (uint64_t)-1); - - RageThread testing; - testing.SetName("TestLocks"); - testing.Create(TestLocksThread, NULL); - - while (g_ThreadId == (uint64_t)-1) - ; - - /* Stop the thread. */ - g_Mutex.Lock(); - - int OldCounter = g_Counter; - - /* Wait a while. g_Counter shouldn't change. */ - usleep(100000); - - ASSERT(g_Counter == OldCounter); - - /* Start it again, and wait. */ - g_Mutex.Unlock(); - usleep(100000); - - /* g_Counter should change. */ - ASSERT(g_Counter != OldCounter); - - g_Finish = true; - testing.Wait(); - g_Finish = false; - g_ThreadId = (uint64_t)-1; -} - -void -go() -{ - /* Test the main thread suspending a secondary thread, and vice versa. */ - test_suspend_secondary_thread(); - test_suspend_main_thread(); - - /* Test the main thread backtracing a secondary thread, and vice versa. */ - test_backtracing_secondary_thread(); - test_backtracing_main_thread(); - - test_locks(); -} - -int -main(int argc, char* argv[]) -{ - test_handle_args(argc, argv); - - test_init(); - - InitializeBacktrace(); - - printf("'%s'\n", ThreadsVersion().c_str()); - - go(); - - test_deinit(); - - exit(0); -} diff --git a/src/tests/test_timing_data.cpp b/src/tests/test_timing_data.cpp deleted file mode 100644 index 41ead479a4..0000000000 --- a/src/tests/test_timing_data.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include "global.h" -#include "RageLog.h" -#include "RageFile.h" -#include "RageUtil.h" -#include "RageUtil_FileDB.h" -#include "PrefsManager.h" -#include "RageFileManager.h" -#include "TimingData.h" - -void -run() -{ -#define CHECK(call, exp) \ - \ -{ \ - float ret = call; \ - if (call != exp) { \ - LOG->Warn("Line %i: Got %f, expected %f", __LINE__, ret, exp); \ - return; \ - } \ - \ -} - - TimingData test; - test.AddBPMSegment(BPMSegment(0, 60)); - - /* First, trivial sanity checks. */ - CHECK(test.GetBeatFromElapsedTime(60), 60.0f); - CHECK(test.GetElapsedTimeFromBeat(60), 60.0f); - - /* The first BPM segment extends backwards in time. */ - CHECK(test.GetBeatFromElapsedTime(-60), -60.0f); - CHECK(test.GetElapsedTimeFromBeat(-60), -60.0f); - - CHECK(test.GetBeatFromElapsedTime(100000), 100000.0f); - CHECK(test.GetElapsedTimeFromBeat(100000), 100000.0f); - CHECK(test.GetBeatFromElapsedTime(-100000), -100000.0f); - CHECK(test.GetElapsedTimeFromBeat(-100000), -100000.0f); - - CHECK(test.GetBPMAtBeat(0), 60.0f); - CHECK(test.GetBPMAtBeat(100000), 60.0f); - CHECK(test.GetBPMAtBeat(-100000), 60.0f); - - /* 120BPM at beat 10: */ - test.AddBPMSegment(BPMSegment(10, 120)); - CHECK(test.GetBPMAtBeat(9.99), 60.0f); - CHECK(test.GetBPMAtBeat(10), 120.0f); - - CHECK(test.GetBeatFromElapsedTime(9), 9.0f); - CHECK(test.GetBeatFromElapsedTime(10), 10.0f); - CHECK(test.GetBeatFromElapsedTime(10.5), 11.0f); - - CHECK(test.GetElapsedTimeFromBeat(9), 9.0f); - CHECK(test.GetElapsedTimeFromBeat(10), 10.0f); - CHECK(test.GetElapsedTimeFromBeat(11), 10.5f); - - /* Add a 5-second stop at beat 10. */ - test.AddStopSegment(StopSegment(10, 5)); - - /* The stop shouldn't affect GetBPMAtBeat at all. */ - CHECK(test.GetBPMAtBeat(9.99), 60.0f); - CHECK(test.GetBPMAtBeat(10), 120.0f); - - CHECK(test.GetBeatFromElapsedTime(9), 9.0f); - CHECK(test.GetBeatFromElapsedTime(10), 10.0f); - CHECK(test.GetBeatFromElapsedTime(12), 10.0f); - CHECK(test.GetBeatFromElapsedTime(14), 10.0f); - CHECK(test.GetBeatFromElapsedTime(15), 10.0f); - CHECK(test.GetBeatFromElapsedTime(15.5), 11.0f); - - CHECK(test.GetElapsedTimeFromBeat(9), 9.0f); - CHECK(test.GetElapsedTimeFromBeat(10), 10.0f); - CHECK(test.GetElapsedTimeFromBeat(11), 15.5f); - - /* Add a 2-second stop at beat 5 and a 5-second stop at beat 15. */ - test.m_StopSegments.clear(); - test.AddStopSegment(StopSegment(5, 2)); - test.AddStopSegment(StopSegment(15, 5)); - CHECK(test.GetBPMAtBeat(9.99), 60.0f); - CHECK(test.GetBPMAtBeat(10), 120.0f); - - CHECK(test.GetBeatFromElapsedTime(1), 1.0f); - CHECK(test.GetBeatFromElapsedTime(2), 2.0f); - CHECK(test.GetBeatFromElapsedTime(5), 5.0f); // stopped - CHECK(test.GetBeatFromElapsedTime(6), 5.0f); // stopped - CHECK(test.GetBeatFromElapsedTime(7), 5.0f); // stop finished - CHECK(test.GetBeatFromElapsedTime(8), 6.0f); - CHECK(test.GetBeatFromElapsedTime(12), 10.0f); // bpm changes to 120 - CHECK(test.GetBeatFromElapsedTime(13), 12.0f); - CHECK(test.GetBeatFromElapsedTime(14), 14.0f); - CHECK(test.GetBeatFromElapsedTime(14.5f), 15.0f); // stopped - CHECK(test.GetBeatFromElapsedTime(15), 15.0f); // stopped - CHECK(test.GetBeatFromElapsedTime(17), 15.0f); // stopped - CHECK(test.GetBeatFromElapsedTime(19.5f), 15.0f); // stop finished - CHECK(test.GetBeatFromElapsedTime(20), 16.0f); - - CHECK(test.GetElapsedTimeFromBeat(1), 1.0f); - CHECK(test.GetElapsedTimeFromBeat(2), 2.0f); - CHECK(test.GetElapsedTimeFromBeat(5), 5.0f); // stopped - CHECK(test.GetElapsedTimeFromBeat(6), 8.0f); - CHECK(test.GetElapsedTimeFromBeat(10), 12.0f); // bpm changes to 120 - CHECK(test.GetElapsedTimeFromBeat(12), 13.0f); - CHECK(test.GetElapsedTimeFromBeat(14), 14.0f); - CHECK(test.GetElapsedTimeFromBeat(15.0f), 14.5f); // stopped - CHECK(test.GetElapsedTimeFromBeat(16), 20.0f); - - // todo: add warp tests -aj - - RageTimer foobar; - /* We can look up the time of any given beat, then look up the beat of that - * time and get the original value. (We can't do this in reverse; the beat - * doesn't move during stop segments.) */ - int q = 0; - for (float f = -10; f < 250; f += 0.002) { - ++q; - // const float t = test.GetElapsedTimeFromBeat( f ); - const float b = test.GetBeatFromElapsedTime(f); - - /* b == f */ - - // if( fabsf(b-f) > 0.001 ) - // { - // LOG->Warn( "%f != %f", b, f ); - // return; - // } - } - LOG->Trace("... %i in %f", q, foobar.GetDeltaTime()); - - TimingData test2; - test2.AddBPMSegment(BPMSegment(0, 60)); - test2.AddStopSegment(StopSegment(0, 1)); - // test2.AddWarpSegment( WarpSegment() ); - CHECK(test2.GetBeatFromElapsedTime(-1), -1.0f); - CHECK(test2.GetBeatFromElapsedTime(0), 0.0f); - CHECK(test2.GetBeatFromElapsedTime(1), 0.0f); - CHECK(test2.GetBeatFromElapsedTime(2), 1.0f); - CHECK(test2.GetElapsedTimeFromBeat(-1), -1.0f); - CHECK(test2.GetElapsedTimeFromBeat(0), 0.0f); - CHECK(test2.GetElapsedTimeFromBeat(1), 2.0f); - CHECK(test2.GetElapsedTimeFromBeat(2), 3.0f); -} - -int -main(int argc, char* argv[]) -{ - FILEMAN = new RageFileManager(argv[0]); - FILEMAN->Mount("dir", ".", ""); - LOG = new RageLog(); - PREFSMAN = - new PrefsManager; // TimingData needs PREFSMAN; it probably shouldn't - LOG->SetShowLogOutput(true); - LOG->SetFlushing(true); - - run(); - - delete PREFSMAN; - delete LOG; - delete FILEMAN; - - exit(0); -} diff --git a/src/tests/test_vector.cpp b/src/tests/test_vector.cpp deleted file mode 100644 index 49fa54ca3b..0000000000 --- a/src/tests/test_vector.cpp +++ /dev/null @@ -1,330 +0,0 @@ -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include - -#if 0 -#error This depends on OS X and Apple's gcc. -#endif -#ifndef USE_VEC -#error Enable altivec or sse. -#endif -#define SCALE(x, l1, h1, l2, h2) \ - (((x) - (l1)) * ((h2) - (l2)) / ((h1) - (l1)) + (l2)) - -using namespace std; - -// This requires that allocated memory be 16 byte aligned. Apple's new -// (and malloc) ensures this but most others only ensure that the -// memory is type size aligned. Hack in posix_memalign. We could also -// override the global new, but that's even more hassle. -#ifdef __APPLE_CC__ -#define NEW(t, s) new t[(s)] -#define DELETE(x) delete[] x -#else -static void* pStupid; -#define NEW(t, s) (posix_memalign(&pStupid, 16, s * sizeof(t)), (t*)pStupid) -#define DELETE(x) free((x)) -#endif - -// The reference values. -static void -ScalarWrite(float* pDestBuf, const float* pSrcBuf, size_t iSize) -{ - for (unsigned iPos = 0; iPos < iSize; ++iPos) - pDestBuf[iPos] += pSrcBuf[iPos]; -} - -#if 0 -static void ScalarRead( int16_t *pDestBuf, const int32_t *pSrcBuf, unsigned iSize ) -{ - for( unsigned iPos = 0; iPos < iSize; ++iPos ) - pDestBuf[iPos] = max( -32768, min(pSrcBuf[iPos]/256, 32767) ); -} -#endif - -static void -RandBuffer(float* pBuffer, unsigned iSize) -{ - while (iSize--) - *pBuffer++ = float(rand()) / RAND_MAX; -} - -template -static void -Diagnostic(const T* pDestBuf, const T* pRefBuf, size_t size) -{ - const int num = 10; - for (int i = 0; i < num; ++i) - fprintf(stderr, "%0*x ", sizeof(T) * 2, pDestBuf[i]); - puts(""); - for (int i = 0; i < num; ++i) - fprintf(stderr, "%0*x ", sizeof(T) * 2, pRefBuf[i]); - puts(""); - for (size_t i = size - num; i < size; ++i) - fprintf(stderr, "%0*x ", sizeof(T) * 2, pDestBuf[i]); - puts(""); - for (size_t i = size - num; i < size; ++i) - fprintf(stderr, "%0*x ", sizeof(T) * 2, pRefBuf[i]); - puts(""); -} - -template<> -static void -Diagnostic(const float* pDestBuf, const float* pRefBuf, size_t size) - -{ - const int num = 10; - for (int i = 0; i < num; ++i) - fprintf(stderr, "%f ", pDestBuf[i]); - puts(""); - for (int i = 0; i < num; ++i) - fprintf(stderr, "%f ", pRefBuf[i]); - puts(""); - for (size_t i = size - num; i < size; ++i) - fprintf(stderr, "%f ", pDestBuf[i]); - puts(""); - for (size_t i = size - num; i < size; ++i) - fprintf(stderr, "%f ", pRefBuf[i]); - puts(""); -} - -static bool -TestWrite(float* pSrcBuf, float* pDestBuf, float* pRefBuf, size_t iSize) -{ - RandBuffer(pSrcBuf, iSize); - memset(pDestBuf, 0, iSize * 4); - memset(pRefBuf, 0, iSize * 4); - Vector::FastSoundWrite(pDestBuf, pSrcBuf, iSize); - ScalarWrite(pRefBuf, pSrcBuf, iSize); - return !memcmp(pRefBuf, pDestBuf, iSize * 4); -} - -static bool -CheckAlignedWrite() -{ - const size_t size = 1024; - float* pSrcBuf = NEW(float, size); - float* pDestBuf = NEW(float, size); - float* pRefBuf = NEW(float, size); - bool ret = true; - size_t s; - - // Test unaligned ends - for (int i = 0; i < 16 && ret; ++i) { - s = size - i; - ret = TestWrite(pSrcBuf, pDestBuf, pRefBuf, s); - } - if (!ret) - Diagnostic(pDestBuf, pRefBuf, s); - DELETE(pSrcBuf); - DELETE(pDestBuf); - DELETE(pRefBuf); - return ret; -} - -static bool -CheckMisalignedSrcWrite() -{ - const size_t size = 1024; - float* pSrcBuf = NEW(float, size); - float* pDestBuf = NEW(float, size); - float* pRefBuf = NEW(float, size); - bool ret = true; - - for (int j = 0; j < 8 && ret; ++j) { - size_t s; - for (int i = 0; i < 8 && ret; ++i) { - s = size - i - j; // Source buffer is shrinking. - ret = TestWrite(pSrcBuf + j, pDestBuf, pRefBuf, s); - } - if (!ret) - Diagnostic(pDestBuf, pRefBuf, s); - } - DELETE(pSrcBuf); - DELETE(pDestBuf); - DELETE(pRefBuf); - return ret; -} - -static bool -CheckMisalignedDestWrite() -{ - const size_t size = 1024; - float* pSrcBuf = NEW(float, size); - float* pDestBuf = NEW(float, size); - float* pRefBuf = NEW(float, size); - bool ret = true; - - for (int j = 0; j < 4 && ret; ++j) { - size_t s; - for (int i = 0; i < 8 && ret; ++i) { - s = size - i - j; // Dest buffer is shrinking. - ret = TestWrite(pSrcBuf, pDestBuf + j, pRefBuf + j, s); - } - if (!ret) - Diagnostic(pDestBuf + j, pRefBuf + j, s); - } - DELETE(pSrcBuf); - DELETE(pDestBuf); - DELETE(pRefBuf); - return ret; -} - -static bool -CheckMisalignedBothWrite() -{ - const size_t size = 1024; - float* pSrcBuf = NEW(float, size); - float* pDestBuf = NEW(float, size); - float* pRefBuf = NEW(float, size); - bool ret = true; - size_t s; - - for (int j = 0; j < 4 && ret; ++j) { - for (int i = 0; i < 8 && ret; ++i) { - for (int k = 0; k < 8 && ret; ++k) { - s = size - i - j - k; // Both buffers are shrinking. - ret = TestWrite(pSrcBuf + i, pDestBuf + j, pRefBuf + j, s); - } - } - if (!ret) - Diagnostic(pDestBuf + j, pRefBuf + j, s); - } - DELETE(pSrcBuf); - DELETE(pDestBuf); - DELETE(pRefBuf); - return ret; -} - -static bool -cmp(const int16_t* p1, const int16_t* p2, size_t size) -{ - return !memcmp(p1, p2, size * 2); -} - -static bool -cmp(const float* p1, const float* p2, size_t size) -{ - const float epsilon = 0.000001; - ++size; - while (--size) - if (fabs(*p1++ - *p2++) >= epsilon) - return false; - return true; -} -#if 0 -template -static bool CheckAlignedRead() -{ - const size_t size = 1024; - int32_t *pSrcBuf = NEW( int32_t, size ); - T *pDestBuf = NEW( T, size ); - T *pRefBuf = NEW( T, size ); - bool ret = true; - - for( int i = 0; i < 8; ++i ) - { - RandBuffer( pSrcBuf, size-i ); - Vector::FastSoundRead( pDestBuf, pSrcBuf, size-i ); - ScalarRead( pRefBuf, pSrcBuf, size-i ); - - if( !(ret = cmp(pRefBuf, pDestBuf, size-i)) ) - { - fprintf( stderr, "%d: \n", i ); - Diagnostic( pDestBuf, pRefBuf, size-i ); - break; - } - } - - DELETE( pSrcBuf ); - DELETE( pDestBuf ); - DELETE( pRefBuf ); - return ret; -} - -template -static bool CheckMisalignedRead() -{ - const size_t size = 1024; - int32_t *pSrcBuf = NEW( int32_t, size ); - T *pDestBuf = NEW( T, size ); - T *pRefBuf = NEW( T, size ); - bool ret = true; - - for( int j = 0; j < 8; ++j ) - { - for( int i = 0; i < 8; ++i ) - { - RandBuffer( pSrcBuf, size-i ); - Vector::FastSoundRead( pDestBuf+j, pSrcBuf, size-i-j ); - ScalarRead( pRefBuf+j, pSrcBuf, size-i-j ); - - if( !(ret = cmp(pRefBuf+j, pDestBuf+j, size-i-j)) ) - { - fprintf( stderr, "%d, %d: \n", j, i ); - Diagnostic( pDestBuf+j, pRefBuf+j, size-i-j ); - break; - } - } - } - - DELETE( pSrcBuf ); - DELETE( pDestBuf ); - DELETE( pRefBuf ); - return ret; -} -#endif - -int -main() -{ - srand(time(NULL)); - if (!Vector::CheckForVector()) { - fputs("No vector unit accessable.\n", stderr); - return 1; - } - if (!CheckAlignedWrite()) { - fputs("Failed aligned write.\n", stderr); - return 1; - } - if (!CheckMisalignedSrcWrite()) { - fputs("Failed misaligned source write.\n", stderr); - return 1; - } - if (!CheckMisalignedDestWrite()) { - fputs("Failed misaligned destination write\n", stderr); - return 1; - } - if (!CheckMisalignedBothWrite()) { - fputs("Failed misaligned source and destination write.\n", stderr); - return 1; - } -#if 0 - if( !CheckAlignedRead() ) - { - fputs( "Failed aligned read.\n", stderr ); - return 1; - } - if( !CheckAlignedRead() ) - { - fputs( "Failed aligned float read.\n", stderr ); - return 1; - } - if( !CheckMisalignedRead() ) - { - fputs( "Failed misaligned read.\n", stderr ); - return 1; - } - if( !CheckMisalignedRead() ) - { - fputs( "Failed misaligned float read.\n", stderr ); - return 1; - } -#endif - puts("Passed."); - return 0; -} diff --git a/src/update_check/check_sm5.php b/src/update_check/check_sm5.php deleted file mode 100644 index cc077a0b1a..0000000000 --- a/src/update_check/check_sm5.php +++ /dev/null @@ -1,12 +0,0 @@ - diff --git a/src/verify_signature/cpp_cryptopp/test.cpp b/src/verify_signature/cpp_cryptopp/test.cpp deleted file mode 100644 index eb8decfe05..0000000000 --- a/src/verify_signature/cpp_cryptopp/test.cpp +++ /dev/null @@ -1,102 +0,0 @@ -// Based on test.cpp from crypto++ -// Parameters: -// public_key - X.509 standard SubjectPublicKeyInfo key in binary format -// data_file - the data file whose signature to verify -// signature - the signature of data_file in binary format -// test.cpp - written and placed in the public domain by Wei Dai - -#include "sha.h" -#include "files.h" -#include "rsa.h" - -#include -#include - -#ifdef CRYPTOPP_WIN32_AVAILABLE -#include -#endif - -#if (_MSC_VER >= 1000) -#include // for the debug heap -#endif - -#if defined(__MWERKS__) && defined(macintosh) -#include -#endif - -USING_NAMESPACE(CryptoPP) -USING_NAMESPACE(std) - -bool -RSAVerifyFile(const char* pubFilename, - const char* messageFilename, - const char* signatureFilename); - -int (*AdhocTest)(int argc, char* argv[]) = NULL; - -#ifdef __BCPLUSPLUS__ -int -cmain(int argc, char* argv[]) -#elif defined(_MSC_VER) -int __cdecl main(int argc, char* argv[]) -#else -int -main(int argc, char* argv[]) -#endif -{ -#ifdef _CRTDBG_LEAK_CHECK_DF - // Turn on leak-checking - int tempflag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); - tempflag |= _CRTDBG_LEAK_CHECK_DF; - _CrtSetDbgFlag(tempflag); -#endif - -#if defined(__MWERKS__) && defined(macintosh) - argc = ccommand(&argv); -#endif - - try { - std::string command, executableName, edcFilename; - - if (argc != 4) { - cout << "\nUsage: RSAPubKeyData.exe publickey_fn data_fn " - "signature_fn" - << endl; - return -1; - } - - if (RSAVerifyFile(argv[2], argv[3], argv[4])) { - cout << "The signature is valid." << endl; - } else { - cout << "The signature is not valid." << endl; - } - return 0; - } catch (CryptoPP::Exception& e) { - cout << "\nCryptoPP::Exception caught: " << e.what() << endl; - return -1; - } catch (std::exception& e) { - cout << "\nstd::exception caught: " << e.what() << endl; - return -2; - } -} - -bool -RSAVerifyFile(const char* pubFilename, - const char* messageFilename, - const char* signatureFilename) -{ - FileSource pubFile(pubFilename, true); - RSASSA_PKCS1v15_SHA_Verifier pub(pubFile); - - FileSource signatureFile(signatureFilename, true); - if (signatureFile.MaxRetrievable() != pub.SignatureLength()) - return false; - SecByteBlock signature(pub.SignatureLength()); - signatureFile.Get(signature, signature.size()); - - VerifierFilter* verifierFilter = new VerifierFilter(pub); - verifierFilter->Put(signature, pub.SignatureLength()); - FileSource f(messageFilename, true, verifierFilter); - - return verifierFilter->GetLastResult(); -} diff --git a/src/verify_signature/csharp/VerifySignature.cs b/src/verify_signature/csharp/VerifySignature.cs deleted file mode 100644 index c4413a66e8..0000000000 --- a/src/verify_signature/csharp/VerifySignature.cs +++ /dev/null @@ -1,395 +0,0 @@ -// Based on http://www.jensign.com/VerifySignature/dotnet/JKeyNet/ -// Parameters: -// public_key - X.509 standard SubjectPublicKeyInfo key in binary format -// data_file - the data file whose signature to verify -// signature - the signature of data_file in binary format -using System; -using System.IO; -using System.Text; -using System.Security; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using System.Runtime.InteropServices; - -namespace VerifySignature -{ - - //--- P/Invoke CryptoAPI wrapper classes ----- - public class Win32 - { - - [DllImport("crypt32.dll")] - public static extern bool CryptDecodeObject( - uint CertEncodingType, - uint lpszStructType, - byte[] pbEncoded, - uint cbEncoded, - uint flags, - [In, Out] byte[] pvStructInfo, - ref uint cbStructInfo); - - - [DllImport("crypt32.dll")] - public static extern bool CryptDecodeObject( - uint CertEncodingType, - uint lpszStructType, - byte[] pbEncoded, - uint cbEncoded, - uint flags, - IntPtr pvStructInfo, - ref uint cbStructInfo); - } - - - [StructLayout(LayoutKind.Sequential)] - public struct PUBKEYBLOBHEADERS - { - public byte bType; //BLOBHEADER - public byte bVersion; //BLOBHEADER - public short reserved; //BLOBHEADER - public uint aiKeyAlg; //BLOBHEADER - public uint magic; //RSAPUBKEY - public uint bitlen; //RSAPUBKEY - public uint pubexp; //RSAPUBKEY - } - - - [StructLayout(LayoutKind.Sequential)] - public struct CERT_PUBLIC_KEY_INFO - { - public IntPtr SubjPKIAlgpszObjId; - public int SubjPKIAlgParameterscbData; - public IntPtr SubjPKIAlgParameterspbData; - public int PublicKeycbData; - public IntPtr PublicKeypbData; - public int PublicKeycUnusedBits; - } - - - public class RSAPubKeyData - { - - const uint X509_ASN_ENCODING = 0x00000001; - const uint PKCS_7_ASN_ENCODING = 0x00010000; - - const uint RSA_CSP_PUBLICKEYBLOB = 19; - const uint X509_PUBLIC_KEY_INFO = 8; - - const int AT_KEYEXCHANGE = 1; //keyspec values - const int AT_SIGNATURE = 2; - static uint ENCODING_TYPE = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING ; - - const byte PUBLICKEYBLOB = 0x06; - const byte CUR_BLOB_VERSION = 0x02; - const ushort reserved = 0x0000; - const uint CALG_RSA_KEYX = 0x0000a400; - const uint CALG_RSA_SIGN = 0x00002400; - - - private byte[] keyModulus; // big-Endian - private byte[] keyExponent; // big-Endian - private byte[] publicKeyBlob; //Microsoft PUBLICKEYBLOB format - private uint keySize; //modulus size in bits - private bool verbose = false; - - - public uint keysize - { - get{return keySize;} - } - - public byte[] keymodulus - { - get{return keyModulus;} - } - - public byte[] keyexponent - { - get{return keyExponent;} - } - - public byte[] MSpublickeyblob - { - get{return publicKeyBlob;} - } - - public static string readFile(string file) - { - string finalStr=""; - try - { - // Create an instance of StreamReader to read from a file. - // The using statement also closes the StreamReader. - using (StreamReader sr = new StreamReader(file)) - { - String line; - // Read and display lines from the file until the end of - // the file is reached. - while ((line = sr.ReadLine()) != null) - { - //Console.WriteLine(line); - finalStr = finalStr+line; - } - return finalStr; - } - } - catch (Exception e) - { - // Let the user know what went wrong. - Console.WriteLine("The file could not be read:"); - Console.WriteLine(e.Message); - } - return null; - } - - public static void Main(String[] args) - { - RSAPubKeyData orsakey = new RSAPubKeyData(); - - if(args.Length<3) - { - Console.WriteLine("\nUsage: RSAPubKeyData.exe public_key data_fn signature_fn"); - return; - } - - String publickeyfn = args[0]; - String datafn = args[1]; - String signaturefn = args[2]; - - if (!File.Exists(publickeyfn)) - { - Console.WriteLine("File '{0}' not found.", publickeyfn); - return; - } - if (!File.Exists(datafn)) - { - Console.WriteLine("File '{0}' not found.", datafn); - return; - } - if (!File.Exists(signaturefn)) - { - Console.WriteLine("File '{0}' not found.", signaturefn); - return; - } - - Console.WriteLine("\n\n-------- Trying to decode keyfile as X.509 SubjectPublicKeyInfo format --------"); - if(!orsakey.DecodeSubjectPublicKeyInfo(publickeyfn)) - { - Console.WriteLine("FAILED to decode as X.509 SubjectPublicKeyInfo"); - return; - } - - Console.WriteLine("Decoded successfully as X.509 SubjectPublicKeyInfo"); - - RSAParameters RSAKeyInfo = new RSAParameters(); - RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); - - RSAKeyInfo.Modulus = orsakey.keymodulus; - RSAKeyInfo.Exponent = orsakey.keyexponent; - RSA.ImportParameters(RSAKeyInfo); - - byte[] data = GetFileBytes(datafn); - byte[] signature = GetFileBytes(signaturefn); - - if(RSA.VerifyData(data,"SHA1",signature)) - { - Console.WriteLine("The signature is valid."); - } - else - { - Console.WriteLine("The signature is not valid."); - } - } - - - //---- RSAPublicKey, PKCS #1 format ----- - public bool DecodeRSAPublicKey(String RSAPublicKeyfile) - { - if (!File.Exists(RSAPublicKeyfile)) - return false; - byte[] encodeddata = GetFileBytes(RSAPublicKeyfile); - return DecodeRSAPublicKey(encodeddata); - } - - - - - //---- SubjectPublicKeyInfo, X.509 standard format; e.g. Java getEncoded(); OpenSSL exported etc. - // --- decode first to RSAPublicKey encoded format ---- - public bool DecodeSubjectPublicKeyInfo(String SubjectPublicKeyInfoFile) - { - if (!File.Exists(SubjectPublicKeyInfoFile)) - return false; - byte[] subjectpublickeydata = GetFileBytes(SubjectPublicKeyInfoFile); - - IntPtr pcertpublickeyinfo = IntPtr.Zero ; - uint cbytes=0; - if(Win32.CryptDecodeObject(ENCODING_TYPE, X509_PUBLIC_KEY_INFO, subjectpublickeydata, (uint)subjectpublickeydata.Length, 0, IntPtr.Zero, ref cbytes)) - { - pcertpublickeyinfo = Marshal.AllocHGlobal((int)cbytes); - Win32.CryptDecodeObject(ENCODING_TYPE, X509_PUBLIC_KEY_INFO, subjectpublickeydata, (uint)subjectpublickeydata.Length, 0, pcertpublickeyinfo, ref cbytes); - CERT_PUBLIC_KEY_INFO pkinfo = (CERT_PUBLIC_KEY_INFO) Marshal.PtrToStructure(pcertpublickeyinfo, typeof(CERT_PUBLIC_KEY_INFO) ); - IntPtr pencodeddata = pkinfo.PublicKeypbData; - int cblob = pkinfo.PublicKeycbData ; - byte[] encodeddata = new byte[cblob]; - Marshal.Copy(pencodeddata, encodeddata, 0,cblob) ; //copy bytes from IntPtr to byte[] - Marshal.FreeHGlobal(pcertpublickeyinfo) ; - return DecodeRSAPublicKey(encodeddata); - } - else - { - return false; - } - } - - - - - - //----- decode public key and extract modulus and exponent from RSAPublicKey, PKCS #1 format byte[] ---- - public bool DecodeRSAPublicKey(byte[] encodedpubkey) - { - byte[] publickeyblob ; - - uint blobbytes=0; - if(Win32.CryptDecodeObject(ENCODING_TYPE, RSA_CSP_PUBLICKEYBLOB, encodedpubkey, (uint)encodedpubkey.Length, 0, null, ref blobbytes)) - { - publickeyblob = new byte[blobbytes]; - if(Win32.CryptDecodeObject(ENCODING_TYPE, RSA_CSP_PUBLICKEYBLOB, encodedpubkey, (uint)encodedpubkey.Length, 0, publickeyblob, ref blobbytes)) - if(verbose) - showBytes("CryptoAPI publickeyblob", publickeyblob); - } - else - { - return false; - } - this.publicKeyBlob = publickeyblob; - return DecodeMSPublicKeyBlob(publickeyblob); - } - - - - //---- Microsoft PUBLICKEYBLOB format ----- - public bool DecodeMSPublicKeyBlob(String publickeyblobfile) - { - if (!File.Exists(publickeyblobfile)) - return false; - byte[] publickeyblobdata = GetFileBytes(publickeyblobfile); - return DecodeMSPublicKeyBlob(publickeyblobdata); - } - - - - //----- Microsoft PUBLICKEYBLOB format ---- - public bool DecodeMSPublicKeyBlob(byte[] publickeyblob) - { - PUBKEYBLOBHEADERS pkheaders = new PUBKEYBLOBHEADERS() ; - int headerslength = Marshal.SizeOf(pkheaders); - IntPtr buffer = Marshal.AllocHGlobal( headerslength); - Marshal.Copy( publickeyblob, 0, buffer, headerslength ); - pkheaders = (PUBKEYBLOBHEADERS) Marshal.PtrToStructure( buffer, typeof(PUBKEYBLOBHEADERS) ); - Marshal.FreeHGlobal( buffer ); - - //----- basic sanity check of PUBLICKEYBLOB fields ------------ - if(pkheaders.bType != PUBLICKEYBLOB) - return false; - if(pkheaders.bVersion != CUR_BLOB_VERSION) - return false; - if(pkheaders.aiKeyAlg != CALG_RSA_KEYX && pkheaders.aiKeyAlg != CALG_RSA_SIGN) - return false; - - if(verbose) - { - Console.WriteLine("\n ---- PUBLICKEYBLOB headers ------"); - Console.WriteLine(" btype {0}", pkheaders.bType); - Console.WriteLine(" bversion {0}", pkheaders.bVersion); - Console.WriteLine(" reserved {0}", pkheaders.reserved); - Console.WriteLine(" aiKeyAlg 0x{0:x8}", pkheaders.aiKeyAlg); - String magicstring = (new ASCIIEncoding()).GetString(BitConverter.GetBytes(pkheaders.magic)) ; - Console.WriteLine(" magic 0x{0:x8} '{1}'", pkheaders.magic, magicstring); - Console.WriteLine(" bitlen {0}", pkheaders.bitlen); - Console.WriteLine(" pubexp {0}", pkheaders.pubexp); - Console.WriteLine(" --------------------------------"); - } - //----- Get public key size in bits ------------- - this.keySize = pkheaders.bitlen; - - //----- Get public exponent ------------- - byte[] exponent = BitConverter.GetBytes(pkheaders.pubexp); //little-endian ordered - Array.Reverse(exponent); //convert to big-endian order - this.keyExponent = exponent; - if(verbose) - showBytes("\nPublic key exponent (big-endian order):", exponent); - - //----- Get modulus ------------- - int modulusbytes = (int)pkheaders.bitlen/8 ; - byte[] modulus = new byte[modulusbytes]; - try - { - Array.Copy(publickeyblob, headerslength, modulus, 0, modulusbytes); - Array.Reverse(modulus); //convert from little to big-endian ordering. - this.keyModulus = modulus; - if(verbose) - showBytes("\nPublic key modulus (big-endian order):", modulus); - } - catch(Exception) - { - Console.WriteLine("Problem getting modulus from publickeyblob"); - return false; - } - return true; - } - - - private static byte[] GetFileBytes(String filename) - { - if(!File.Exists(filename)) - return null; - Stream stream=new FileStream(filename,FileMode.Open); - int datalen = (int)stream.Length; - byte[] filebytes =new byte[datalen]; - stream.Seek(0,SeekOrigin.Begin); - stream.Read(filebytes,0,datalen); - stream.Close(); - return filebytes; - } - - - private void PutFileBytes(String outfile, byte[] data, int bytes) - { - FileStream fs = null; - if(bytes > data.Length) - { - Console.WriteLine("Too many bytes"); - return; - } - try - { - fs = new FileStream(outfile, FileMode.Create); - fs.Write(data, 0, bytes); - } - catch(Exception e) - { - Console.WriteLine(e.Message) ; - } - finally - { - fs.Close(); - } - } - - - private static void showBytes(String info, byte[] data) - { - Console.WriteLine("{0} [{1} bytes]", info, data.Length); - for(int i=1; i<=data.Length; i++) - { - Console.Write("{0:X2} ", data[i-1]) ; - if(i%16 == 0) - Console.WriteLine(); - } - Console.WriteLine(); - } - - } -} diff --git a/src/verify_signature/java/VerifySignature.java b/src/verify_signature/java/VerifySignature.java deleted file mode 100644 index ff05569977..0000000000 --- a/src/verify_signature/java/VerifySignature.java +++ /dev/null @@ -1,218 +0,0 @@ -// Based on http://www.thecodeproject.com/useritems/Porting_Java_Public_Key.asp -// Parameters: -// public_key - X.509 standard SubjectPublicKeyInfo key in binary format -// data_file - the data file whose signature to verify -// signature - the signature of data_file in binary format - -/* - * Title: RSA Security - * Description: This class generates a RSA private and public key, reinstantiates - * the keys from the corresponding key files. It also generates compatible .Net Public Key, - * which we will read later in C# program using .Net Securtiy Framework - * The reinstantiated keys are used to sign and verify the given data.

- * - * @author Shaheryar - * @version 1.0 - */ - -import java.security.*; -import java.security.spec.*; -import java.io.*; -import java.security.interfaces.*; -import java.security.cert.*; -import javax.xml.transform.stream.*; -import javax.xml.transform.dom.*; -import javax.xml.transform.*; -import org.w3c.dom.*; -import javax.xml.parsers.*; - -public class VerifySignature -{ - private KeyPairGenerator keyGen; // Key pair generator for RSA - public PrivateKey privateKey; // Private Key Class - public PublicKey publicKey; // Public Key Class - public KeyPair keypair; // KeyPair Class - private Signature sign; // Signature, used to sign the data - /* Instantiates the key paths and signature algorithm. */ - public VerifySignature() - { - try { - // Get the instance of Signature Engine. - sign = Signature.getInstance("SHA1withRSA"); - } - catch (NoSuchAlgorithmException nsa) { - System.out.println("" + nsa.getMessage()); - } - } - - /* Initialize the public and private keys. */ - private void initializePublicKey(String publickey_fn) - { - try - { - // Read key files back and decode them from BASE64 - byte[] publicKeyBytes = readKeyBytesFromFile(publickey_fn); - - // Convert back to public and private key objects - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(publicKeyBytes); - publicKey = keyFactory.generatePublic(publicKeySpec); - } - catch (IOException io) { - System.out.println( "Public/Private key file not found."+ io.getCause() ); - } - catch (InvalidKeySpecException e) { - System.out.println( "Invalid Key Specs. Not valid key files."+ e.getCause() ); - } - catch (NoSuchAlgorithmException e) { - System.out.println( "There is no such algorithm. Please check the JDK ver."+ e.getCause() ); - } - } - - /* - * Verifies the signature for the given bytes using the public key. - * @param signature Signature - * @param data Data that was signed - * @return boolean True if valid signature else false - */ - public boolean verifySignature(String publickey_fn, byte[] signature, byte[] data) - { - try - { - initializePublicKey(publickey_fn); - sign.initVerify(publicKey); - sign.update(data); - return sign.verify(signature); - } - catch (SignatureException e) { - e.printStackTrace(); - } - catch (InvalidKeyException e) { - } - - return false; - } - - /** - * Returns the contents of the file in a byte array. - * @param fileName File Name - * @return byte[] The data read from a given file as a byte array. - */ - private byte[] readKeyBytesFromFile(String fileName) throws IOException - { - File file = new File(fileName); - InputStream is = new FileInputStream(file); - - // Get the size of the file - long length = file.length(); - - // You cannot create an array using a long type. - // It needs to be an int type. - // Before converting to an int type, check - // to ensure that file is not larger than Integer.MAX_VALUE. - if (length > Integer.MAX_VALUE) { - // File is too large - } - - // Create the byte array to hold the data - byte[] bytes = new byte[ (int) length]; - - // Read in the bytes - int offset = 0; - int numRead = 0; - while (offset < bytes.length - && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) { - offset += numRead; - } - - // Ensure all the bytes have been read in - if (offset < bytes.length) { - throw new IOException("Key File Error: Could not completely read file " + file.getName()); - } - - // Close the input stream and return bytes - is.close(); - return bytes; - } - - - public static void main(String args[]) - { - VerifySignature sm = new VerifySignature(); - - /* - Uncomment next line for first time when you run the code,it will generate the keys. - Afterwards,the application will read the generated key files from the given location. - If you want to generate the key files each time, then you should keep it uncommented always. - */ - if( args.length != 3 ) - { - System.out.println("\nUsage: RSAPubKeyData.exe publickey_fn data_fn signature_fn"); - return; - } - - String publickeyfn = args[0]; - String datafn = args[1]; - String signaturefn = args[2]; - - - byte[] data = sm.readBytesFromFile(datafn); - byte[] signature = sm.readBytesFromFile(signaturefn); - - if( sm.verifySignature(publickeyfn,signature,data) ) - { - System.out.println("The signature is valid."); - } - else - { - System.out.println("The signature is not valid."); - } - } - - private byte[] readBytesFromFile(String fileName) - { - try - { - File file = new File(fileName); - InputStream is = new FileInputStream(file); - - // Get the size of the file - long length = file.length(); - - // You cannot create an array using a long type. - // It needs to be an int type. - // Before converting to an int type, check - // to ensure that file is not larger than Integer.MAX_VALUE. - if (length > Integer.MAX_VALUE) { - // File is too large - } - - // Create the byte array to hold the data - byte[] bytes = new byte[ (int) length]; - - // Read in the bytes - int offset = 0; - int numRead = 0; - while (offset < bytes.length - && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) - { - offset += numRead; - } - - // Ensure all the bytes have been read in - if (offset < bytes.length) { - throw new IOException("Key File Error: Could not completely read file " + file.getName()); - } - - // Close the input stream and return bytes - is.close(); - return bytes; - } - catch(IOException ioe) - { - System.out.println("Exception occured while writing file"+ioe.getMessage()); - } - byte[] bytes = new byte[1]; - return bytes; - } -} From b44b6d5c101f0b963fa9988d326a2676d7cde827 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 01:37:25 -0300 Subject: [PATCH 057/320] Remove two folders in src i accidentally renamed --- src/ircc/appveyor.cpp | 150 - src/smpackagee/ChangeGameSettings.cpp | 191 -- src/smpackagee/ChangeGameSettings.h | 76 - src/smpackagee/CreateLanguageDlg.cpp | 74 - src/smpackagee/CreateLanguageDlg.h | 33 - src/smpackagee/EditInsallations.cpp | 190 -- src/smpackagee/EditInsallations.h | 80 - src/smpackagee/EnterComment.cpp | 109 - src/smpackagee/EnterComment.h | 81 - src/smpackagee/EnterName.cpp | 88 - src/smpackagee/EnterName.h | 75 - src/smpackagee/LanguagesDlg.cpp | 684 ---- src/smpackagee/LanguagesDlg.h | 36 - src/smpackagee/MainMenuDlg.cpp | 335 -- src/smpackagee/MainMenuDlg.h | 85 - src/smpackagee/SMPackageInstallDlg.cpp | 469 --- src/smpackagee/SMPackageInstallDlg.h | 85 - src/smpackagee/SMPackageUtil.cpp | 302 -- src/smpackagee/ShowComment.cpp | 83 - src/smpackagee/ShowComment.h | 76 - src/smpackagee/SmpackageExportDlg.cpp | 605 ---- src/smpackagee/SmpackageExportDlg.h | 94 - src/smpackagee/StdAfx.cpp | 5 - src/smpackagee/StdAfx.h | 67 - src/smpackagee/TreeCtrlEx.cpp | 183 -- src/smpackagee/TreeCtrlEx.h | 51 - src/smpackagee/UninstallOld.cpp | 83 - src/smpackagee/UninstallOld.h | 52 - src/smpackagee/ZipArchive/Appnote.txt | 1351 -------- src/smpackagee/ZipArchive/ChangeLog.txt | 322 -- src/smpackagee/ZipArchive/License.txt | 73 - .../ZipArchive/Linux/ZipFileMapping.h | 61 - .../ZipArchive/Linux/ZipPathComponent.cpp | 87 - .../ZipArchive/Linux/ZipPlatform.cpp | 272 -- src/smpackagee/ZipArchive/Readme.txt | 645 ---- src/smpackagee/ZipArchive/StdAfx.cpp | 17 - src/smpackagee/ZipArchive/StdAfx.h | 48 - .../ZipArchive/Windows/ZipFileMapping.h | 69 - .../ZipArchive/Windows/ZipPathComponent.cpp | 72 - .../ZipArchive/Windows/ZipPlatform.cpp | 370 --- src/smpackagee/ZipArchive/ZipAbstractFile.h | 54 - .../ZipArchive/ZipArchive-net2003.vcproj | 1285 -------- .../ZipArchive/ZipArchive-net2008.vcproj | 1686 ---------- src/smpackagee/ZipArchive/ZipArchive.cpp | 2908 ----------------- src/smpackagee/ZipArchive/ZipArchive.dox | 221 -- src/smpackagee/ZipArchive/ZipArchive.h | 2070 ------------ src/smpackagee/ZipArchive/ZipArchive.rc | 109 - src/smpackagee/ZipArchive/ZipAutoBuffer.cpp | 102 - src/smpackagee/ZipArchive/ZipAutoBuffer.h | 67 - src/smpackagee/ZipArchive/ZipBaseException.h | 22 - src/smpackagee/ZipArchive/ZipCentralDir.cpp | 836 ----- src/smpackagee/ZipArchive/ZipCentralDir.h | 558 ---- src/smpackagee/ZipArchive/ZipCollections.h | 82 - .../ZipArchive/ZipCompatibility.cpp | 194 -- src/smpackagee/ZipArchive/ZipCompatibility.h | 107 - src/smpackagee/ZipArchive/ZipException.cpp | 285 -- src/smpackagee/ZipArchive/ZipException.h | 219 -- src/smpackagee/ZipArchive/ZipExport.h | 18 - src/smpackagee/ZipArchive/ZipFile.cpp | 53 - src/smpackagee/ZipArchive/ZipFile.h | 68 - src/smpackagee/ZipArchive/ZipFileHeader.cpp | 358 -- src/smpackagee/ZipArchive/ZipFileHeader.h | 344 -- src/smpackagee/ZipArchive/ZipFileMapping.h | 69 - src/smpackagee/ZipArchive/ZipMemFile.cpp | 102 - src/smpackagee/ZipArchive/ZipMemFile.h | 105 - .../ZipArchive/ZipPathComponent.cpp | 72 - src/smpackagee/ZipArchive/ZipPathComponent.h | 195 -- src/smpackagee/ZipArchive/ZipPlatform.cpp | 370 --- src/smpackagee/ZipArchive/ZipPlatform.h | 204 -- src/smpackagee/ZipArchive/ZipPlatformComm.cpp | 48 - src/smpackagee/ZipArchive/ZipStorage.cpp | 447 --- src/smpackagee/ZipArchive/ZipStorage.h | 579 ---- src/smpackagee/ZipArchive/ZipString.cpp | 28 - src/smpackagee/ZipArchive/ZipString.h | 37 - src/smpackagee/ZipArchive/__Windows_MFC.zcfg | 1 - .../ZipArchive/_copy_from_Win-MFC.bat | 5 - .../ZipArchive/_copy_from_Win-STL.bat | 5 - src/smpackagee/ZipArchive/_version.txt | 1 - src/smpackagee/ZipArchive/borland.zip | Bin 7568 -> 0 bytes src/smpackagee/ZipArchive/faq.txt | 212 -- src/smpackagee/ZipArchive/gpl.txt | 285 -- .../ZipArchive/mfc/ZipBaseException.h | 22 - .../ZipArchive/mfc/ZipCollections.h | 82 - src/smpackagee/ZipArchive/mfc/ZipFile.cpp | 53 - src/smpackagee/ZipArchive/mfc/ZipFile.h | 68 - src/smpackagee/ZipArchive/mfc/ZipString.h | 37 - src/smpackagee/ZipArchive/mfc/stdafx.h | 48 - src/smpackagee/ZipArchive/resource.h | 15 - .../ZipArchive/stl/ZipBaseException.h | 22 - .../ZipArchive/stl/ZipCollections.h | 163 - src/smpackagee/ZipArchive/stl/ZipFile.cpp | 109 - src/smpackagee/ZipArchive/stl/ZipFile.h | 115 - src/smpackagee/ZipArchive/stl/ZipString.h | 276 -- src/smpackagee/ZipArchive/stl/stdafx.h | 125 - .../ZipArchive/stl/zippie/CmdLine.cpp | 246 -- .../ZipArchive/stl/zippie/CmdLine.h | 234 -- .../ZipArchive/stl/zippie/zippie.cpp | 911 ------ .../ZipArchive/stl/zippie/zippie.dsp | 111 - .../ZipArchive/stl/zippie/zippie.dsw | 44 - .../ZipArchive/stl/zippie/zippie_DLL.dsp | 112 - .../ZipArchive/stl/zippie/zippie_DLL.dsw | 59 - src/smpackagee/res/smpackage.ico | Bin 1078 -> 0 bytes src/smpackagee/res/smpackage.rc2 | 13 - src/smpackagee/resource.h | 105 - src/smpackagee/smpackage.ICO | Bin 6006 -> 0 bytes src/smpackagee/smpackage.clw | 321 -- src/smpackagee/smpackage.cpp | 197 -- src/smpackagee/smpackage.h | 70 - src/smpackagee/smpackage.rc | 499 --- src/smpackagee/smpackageUtil.h | 85 - 110 files changed, 26382 deletions(-) delete mode 100644 src/ircc/appveyor.cpp delete mode 100644 src/smpackagee/ChangeGameSettings.cpp delete mode 100644 src/smpackagee/ChangeGameSettings.h delete mode 100644 src/smpackagee/CreateLanguageDlg.cpp delete mode 100644 src/smpackagee/CreateLanguageDlg.h delete mode 100644 src/smpackagee/EditInsallations.cpp delete mode 100644 src/smpackagee/EditInsallations.h delete mode 100644 src/smpackagee/EnterComment.cpp delete mode 100644 src/smpackagee/EnterComment.h delete mode 100644 src/smpackagee/EnterName.cpp delete mode 100644 src/smpackagee/EnterName.h delete mode 100644 src/smpackagee/LanguagesDlg.cpp delete mode 100644 src/smpackagee/LanguagesDlg.h delete mode 100644 src/smpackagee/MainMenuDlg.cpp delete mode 100644 src/smpackagee/MainMenuDlg.h delete mode 100644 src/smpackagee/SMPackageInstallDlg.cpp delete mode 100644 src/smpackagee/SMPackageInstallDlg.h delete mode 100644 src/smpackagee/SMPackageUtil.cpp delete mode 100644 src/smpackagee/ShowComment.cpp delete mode 100644 src/smpackagee/ShowComment.h delete mode 100644 src/smpackagee/SmpackageExportDlg.cpp delete mode 100644 src/smpackagee/SmpackageExportDlg.h delete mode 100644 src/smpackagee/StdAfx.cpp delete mode 100644 src/smpackagee/StdAfx.h delete mode 100644 src/smpackagee/TreeCtrlEx.cpp delete mode 100644 src/smpackagee/TreeCtrlEx.h delete mode 100644 src/smpackagee/UninstallOld.cpp delete mode 100644 src/smpackagee/UninstallOld.h delete mode 100644 src/smpackagee/ZipArchive/Appnote.txt delete mode 100644 src/smpackagee/ZipArchive/ChangeLog.txt delete mode 100644 src/smpackagee/ZipArchive/License.txt delete mode 100644 src/smpackagee/ZipArchive/Linux/ZipFileMapping.h delete mode 100644 src/smpackagee/ZipArchive/Linux/ZipPathComponent.cpp delete mode 100644 src/smpackagee/ZipArchive/Linux/ZipPlatform.cpp delete mode 100644 src/smpackagee/ZipArchive/Readme.txt delete mode 100644 src/smpackagee/ZipArchive/StdAfx.cpp delete mode 100644 src/smpackagee/ZipArchive/StdAfx.h delete mode 100644 src/smpackagee/ZipArchive/Windows/ZipFileMapping.h delete mode 100644 src/smpackagee/ZipArchive/Windows/ZipPathComponent.cpp delete mode 100644 src/smpackagee/ZipArchive/Windows/ZipPlatform.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipAbstractFile.h delete mode 100644 src/smpackagee/ZipArchive/ZipArchive-net2003.vcproj delete mode 100644 src/smpackagee/ZipArchive/ZipArchive-net2008.vcproj delete mode 100644 src/smpackagee/ZipArchive/ZipArchive.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipArchive.dox delete mode 100644 src/smpackagee/ZipArchive/ZipArchive.h delete mode 100644 src/smpackagee/ZipArchive/ZipArchive.rc delete mode 100644 src/smpackagee/ZipArchive/ZipAutoBuffer.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipAutoBuffer.h delete mode 100644 src/smpackagee/ZipArchive/ZipBaseException.h delete mode 100644 src/smpackagee/ZipArchive/ZipCentralDir.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipCentralDir.h delete mode 100644 src/smpackagee/ZipArchive/ZipCollections.h delete mode 100644 src/smpackagee/ZipArchive/ZipCompatibility.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipCompatibility.h delete mode 100644 src/smpackagee/ZipArchive/ZipException.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipException.h delete mode 100644 src/smpackagee/ZipArchive/ZipExport.h delete mode 100644 src/smpackagee/ZipArchive/ZipFile.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipFile.h delete mode 100644 src/smpackagee/ZipArchive/ZipFileHeader.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipFileHeader.h delete mode 100644 src/smpackagee/ZipArchive/ZipFileMapping.h delete mode 100644 src/smpackagee/ZipArchive/ZipMemFile.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipMemFile.h delete mode 100644 src/smpackagee/ZipArchive/ZipPathComponent.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipPathComponent.h delete mode 100644 src/smpackagee/ZipArchive/ZipPlatform.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipPlatform.h delete mode 100644 src/smpackagee/ZipArchive/ZipPlatformComm.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipStorage.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipStorage.h delete mode 100644 src/smpackagee/ZipArchive/ZipString.cpp delete mode 100644 src/smpackagee/ZipArchive/ZipString.h delete mode 100644 src/smpackagee/ZipArchive/__Windows_MFC.zcfg delete mode 100644 src/smpackagee/ZipArchive/_copy_from_Win-MFC.bat delete mode 100644 src/smpackagee/ZipArchive/_copy_from_Win-STL.bat delete mode 100644 src/smpackagee/ZipArchive/_version.txt delete mode 100644 src/smpackagee/ZipArchive/borland.zip delete mode 100644 src/smpackagee/ZipArchive/faq.txt delete mode 100644 src/smpackagee/ZipArchive/gpl.txt delete mode 100644 src/smpackagee/ZipArchive/mfc/ZipBaseException.h delete mode 100644 src/smpackagee/ZipArchive/mfc/ZipCollections.h delete mode 100644 src/smpackagee/ZipArchive/mfc/ZipFile.cpp delete mode 100644 src/smpackagee/ZipArchive/mfc/ZipFile.h delete mode 100644 src/smpackagee/ZipArchive/mfc/ZipString.h delete mode 100644 src/smpackagee/ZipArchive/mfc/stdafx.h delete mode 100644 src/smpackagee/ZipArchive/resource.h delete mode 100644 src/smpackagee/ZipArchive/stl/ZipBaseException.h delete mode 100644 src/smpackagee/ZipArchive/stl/ZipCollections.h delete mode 100644 src/smpackagee/ZipArchive/stl/ZipFile.cpp delete mode 100644 src/smpackagee/ZipArchive/stl/ZipFile.h delete mode 100644 src/smpackagee/ZipArchive/stl/ZipString.h delete mode 100644 src/smpackagee/ZipArchive/stl/stdafx.h delete mode 100644 src/smpackagee/ZipArchive/stl/zippie/CmdLine.cpp delete mode 100644 src/smpackagee/ZipArchive/stl/zippie/CmdLine.h delete mode 100644 src/smpackagee/ZipArchive/stl/zippie/zippie.cpp delete mode 100644 src/smpackagee/ZipArchive/stl/zippie/zippie.dsp delete mode 100644 src/smpackagee/ZipArchive/stl/zippie/zippie.dsw delete mode 100644 src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsp delete mode 100644 src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsw delete mode 100644 src/smpackagee/res/smpackage.ico delete mode 100644 src/smpackagee/res/smpackage.rc2 delete mode 100644 src/smpackagee/resource.h delete mode 100644 src/smpackagee/smpackage.ICO delete mode 100644 src/smpackagee/smpackage.clw delete mode 100644 src/smpackagee/smpackage.cpp delete mode 100644 src/smpackagee/smpackage.h delete mode 100644 src/smpackagee/smpackage.rc delete mode 100644 src/smpackagee/smpackageUtil.h diff --git a/src/ircc/appveyor.cpp b/src/ircc/appveyor.cpp deleted file mode 100644 index 5994f13984..0000000000 --- a/src/ircc/appveyor.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#pragma comment(lib, "ws2_32.lib") - -#include -#include -#include -#include - -char const* owner = "wolfman2000"; -char const* nick = "appveyor-sm5"; -char const* server = "irc.freenode.net"; -char const* channel = "#stepmania"; - -bool -startsWithPing(char const* buffer) -{ - return std::strncmp(buffer, "PING ", 5) == 0; -} - -int -main(int argc, char* argv[]) -{ - // The common return value. - int ret; - // Set up the buffer. - char buffer[512]; - - auto* repoName = argv[1]; - auto* repoVersion = argv[2]; - auto* repoHash = argv[3]; - auto* repoAuthor = argv[4]; - auto* repoBuildUrl = argv[5]; - auto* repoSuccess = argv[6]; - - SOCKET sock; - struct WSAData* wd = (struct WSAData*)malloc(sizeof(struct WSAData)); - ret = WSAStartup(MAKEWORD(2, 0), wd); - free(wd); - - if (ret) { - std::cout << "Error loading Windows Socket API" << std::endl; - return 1; - } - - struct addrinfo hints; - struct addrinfo* ai; - - // Ensure the hints are cleared. - memset(&hints, 0, sizeof(struct addrinfo)); - // IPv4 vs IPv6: should not matter. - hints.ai_family = AF_UNSPEC; - // IRC uses TCP sockets. - hints.ai_socktype = SOCK_STREAM; - // Be explicit about TCP. - hints.ai_protocol = IPPROTO_TCP; - - ret = getaddrinfo(server, "6667", &hints, &ai); - if (ret != 0) { - std::cout << "Problem with getting the server information!" - << std::endl; - return 2; - } - - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock == -1) { - std::cout << "Problem with setting up the socket!" << std::endl; - return 3; - } - - ret = connect(sock, ai->ai_addr, ai->ai_addrlen); - if (ret == -1) { - std::cout << "Problem with connecting to the IRC server!" << std::endl; - } - - // The server data is not needed anymore. - freeaddrinfo(ai); - - // Start some of the basic commands. - std::sprintf(buffer, "USER %s 0 * :%s\r\n", nick, owner); - send(sock, buffer, strlen(buffer), 0); - std::sprintf(buffer, "NICK %s\r\n", nick); - send(sock, buffer, strlen(buffer), 0); - - // Respect the continuous loop. - for (;;) { - // receive the bytes as we get them. - int numBytes = recv(sock, buffer, 511, 0); - if (numBytes <= 0) { - // We have quit IRC. Get out of here. - break; - } - buffer[numBytes] = '\0'; // Ensure a null terminated string. - if (startsWithPing(buffer)) { - // We MUST reply to a PING with PONG. Otherwise, we get booted off. - buffer[1] = 'O'; - send(sock, buffer, strlen(buffer), 0); - } - // System commands should have a colon. - if (buffer[0] != ':') { - continue; - } - - // Only join once we have a 001. This indicates it's safe. - if (std::strncmp(std::strchr(buffer, ' ') + 1, "001", 3)) { - std::sprintf(buffer, "JOIN %s\r\n", channel); - send(sock, buffer, strlen(buffer), 0); - continue; - } - if (std::strncmp(std::strchr(buffer, ' ') + 1, "366", 3)) { - if (std::strncmp(repoSuccess, "success", 7) == 0) { - std::sprintf(buffer, - "PRIVMSG %s :AppVeyor build report for fork %s, " - "build %s, commit %s by %s: Compiles on " - "Windows!\r\n", - channel, - repoName, - repoVersion, - repoHash, - repoAuthor); - } else { - std::sprintf(buffer, - "PRIVMSG %s :AppVeyor build report for fork %s, " - "build %s, commit %s by %s: Did not compile on " - "Windows!\r\n", - channel, - repoName, - repoVersion, - repoHash, - repoAuthor); - } - send(sock, buffer, strlen(buffer), 0); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - - std::sprintf( - buffer, "PRIVMSG %s :Build Log: %s\r\n", channel, repoBuildUrl); - send(sock, buffer, strlen(buffer), 0); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - - std::sprintf(buffer, "QUIT Bye bye now.\r\n"); - send(sock, buffer, strlen(buffer), 0); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - } - } - - closesocket(sock); - WSACleanup(); - - return 0; -} diff --git a/src/smpackagee/ChangeGameSettings.cpp b/src/smpackagee/ChangeGameSettings.cpp deleted file mode 100644 index e7a7cdcba4..0000000000 --- a/src/smpackagee/ChangeGameSettings.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// ChangeGameSettings.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "ChangeGameSettings.h" -#include "IniFile.h" -#include "SMPackageUtil.h" -#include "SpecialFiles.h" -#include ".\changegamesettings.h" -#include "archutils/Win32/DialogUtil.h" -#include "LocalizedString.h" -#include "RageUtil.h" -#include "arch/Dialog/Dialog.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// ChangeGameSettings dialog - -ChangeGameSettings::ChangeGameSettings(CWnd* pParent /*=NULL*/) - : CDialog(ChangeGameSettings::IDD, pParent) -{ - //{{AFX_DATA_INIT(ChangeGameSettings) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -void -ChangeGameSettings::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(ChangeGameSettings) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(ChangeGameSettings, CDialog) -//{{AFX_MSG_MAP(ChangeGameSettings) -//}}AFX_MSG_MAP -ON_WM_CTLCOLOR() -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// ChangeGameSettings message handlers - -BOOL -ChangeGameSettings::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - - // - // Fill the radio buttons - // - IniFile ini; - ini.ReadFile(SpecialFiles::PREFERENCES_INI_PATH); - - RString sValue; - - // video renderers - sValue = ""; - ini.GetValue("Options", "VideoRenderers", sValue); - if (sValue.CompareNoCase("opengl") == 0) - CheckDlgButton(IDC_RADIO_OPENGL, BST_CHECKED); - else if (sValue.CompareNoCase("d3d") == 0) - CheckDlgButton(IDC_RADIO_DIRECT3D, BST_CHECKED); - else - CheckDlgButton(IDC_RADIO_DEFAULT, BST_CHECKED); - - // sound drivers - sValue = ""; - ini.GetValue("Options", "SoundDrivers", sValue); - if (sValue.CompareNoCase("DirectSound") == 0) - CheckDlgButton(IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE, BST_CHECKED); - else if (sValue.CompareNoCase("DirectSound-sw") == 0) - CheckDlgButton(IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE, BST_CHECKED); - else if (sValue.CompareNoCase("WaveOut") == 0) - CheckDlgButton(IDC_RADIO_SOUND_WAVEOUT, BST_CHECKED); - else if (sValue.CompareNoCase("null") == 0) - CheckDlgButton(IDC_RADIO_SOUND_NULL, BST_CHECKED); - else - CheckDlgButton(IDC_RADIO_SOUND_DEFAULT, BST_CHECKED); - - { - int iValue = 0; - ini.GetValue("Options", "RefreshRate", iValue); - CheckDlgButton(IDC_CHECK_FORCE_60HZ, - iValue == 60 ? BST_CHECKED : BST_UNCHECKED); - } - { - bool bValue = false; - ini.GetValue("Options", "LogToDisk", bValue); - CheckDlgButton(IDC_CHECK_LOG_TO_DISK, - bValue ? BST_CHECKED : BST_UNCHECKED); - } - { - bool bValue = false; - ini.GetValue("Options", "ShowLogOutput", bValue); - CheckDlgButton(IDC_CHECK_SHOW_LOG_WINDOW, - bValue ? BST_CHECKED : BST_UNCHECKED); - } - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -static LocalizedString ERROR_WRITING_FILE("ChangeGameSettings", - "Error writing file '%s': %s"); -void -ChangeGameSettings::OnOK() -{ - // TODO: Add extra validation here - IniFile ini; - ini.ReadFile(SpecialFiles::PREFERENCES_INI_PATH); - - if (BST_CHECKED == IsDlgButtonChecked(IDC_RADIO_OPENGL)) - ini.SetValue("Options", "VideoRenderers", (RString) "opengl"); - else if (BST_CHECKED == IsDlgButtonChecked(IDC_RADIO_DIRECT3D)) - ini.SetValue("Options", "VideoRenderers", (RString) "d3d"); - else - ini.SetValue("Options", "VideoRenderers", RString()); - - if (BST_CHECKED == IsDlgButtonChecked(IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE)) - ini.SetValue("Options", "SoundDrivers", (RString) "DirectSound"); - else if (BST_CHECKED == - IsDlgButtonChecked(IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE)) - ini.SetValue("Options", "SoundDrivers", (RString) "DirectSound-sw"); - else if (BST_CHECKED == IsDlgButtonChecked(IDC_RADIO_SOUND_WAVEOUT)) - ini.SetValue("Options", "SoundDrivers", (RString) "WaveOut"); - else if (BST_CHECKED == IsDlgButtonChecked(IDC_RADIO_SOUND_NULL)) - ini.SetValue("Options", "SoundDrivers", (RString) "null"); - else - ini.SetValue("Options", "SoundDrivers", RString()); - - if (BST_CHECKED == IsDlgButtonChecked(IDC_CHECK_FORCE_60HZ)) { - ini.SetValue("Options", "RefreshRate", 60); - } else { - int iRefresh = 0; - ini.GetValue("Options", "RefreshRate", iRefresh); - if (iRefresh == 60) - ini.SetValue("Options", "RefreshRate", 0); - } - ini.SetValue("Options", - "LogToDisk", - BST_CHECKED == IsDlgButtonChecked(IDC_CHECK_LOG_TO_DISK)); - ini.SetValue("Options", - "ShowLogOutput", - BST_CHECKED == IsDlgButtonChecked(IDC_CHECK_SHOW_LOG_WINDOW)); - - if (!ini.WriteFile(SpecialFiles::PREFERENCES_INI_PATH)) { - RString sError = ssprintf(ERROR_WRITING_FILE.GetValue(), - SpecialFiles::PREFERENCES_INI_PATH.c_str(), - ini.GetError().c_str()); - Dialog::OK(sError); - } - - CDialog::OnOK(); -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/ChangeGameSettings.h b/src/smpackagee/ChangeGameSettings.h deleted file mode 100644 index 559a5e639a..0000000000 --- a/src/smpackagee/ChangeGameSettings.h +++ /dev/null @@ -1,76 +0,0 @@ -#if !defined( \ - AFX_CHANGEGAMESETTINGS_H__BFA59E6F_E70A_49A7_90A6_F04D3C321CA6__INCLUDED_) -#define AFX_CHANGEGAMESETTINGS_H__BFA59E6F_E70A_49A7_90A6_F04D3C321CA6__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ChangeGameSettings.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// ChangeGameSettings dialog - -class ChangeGameSettings : public CDialog -{ - // Construction - public: - ChangeGameSettings(CWnd* pParent = NULL); // standard constructor - - // Dialog Data - //{{AFX_DATA(ChangeGameSettings) - enum - { - IDD = IDD_CHANGE_GAME_SETTINGS - }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(ChangeGameSettings) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - // Generated message map functions - //{{AFX_MSG(ChangeGameSettings) - virtual BOOL OnInitDialog(); - virtual void OnOK(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_CHANGEGAMESETTINGS_H__BFA59E6F_E70A_49A7_90A6_F04D3C321CA6__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/CreateLanguageDlg.cpp b/src/smpackagee/CreateLanguageDlg.cpp deleted file mode 100644 index c1c545420f..0000000000 --- a/src/smpackagee/CreateLanguageDlg.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// CreateLanguageDlg.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "CreateLanguageDlg.h" -#include "Foreach.h" -#include "RageUtil.h" -#include "SMPackageUtil.h" -#include ".\createlanguagedlg.h" -#include "archutils/Win32/DialogUtil.h" -#include "archutils/Win32/ErrorStrings.h" - -// CreateLanguageDlg dialog - -IMPLEMENT_DYNAMIC(CreateLanguageDlg, CDialog) -CreateLanguageDlg::CreateLanguageDlg(CWnd* pParent /*=NULL*/) - : CDialog(CreateLanguageDlg::IDD, pParent) -{ -} - -CreateLanguageDlg::~CreateLanguageDlg() {} - -void -CreateLanguageDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Control(pDX, IDC_COMBO_LANGUAGES, m_comboLanguages); -} - -static const char* const g_aListedLanguageCodes[] = { - "ab", "af", "ar", "az", "be", "bg", "ca", "cs", "cy", "da", "de", "el", - "en", "es", "et", "eu", "fa", "fi", "fr", "ga", "gl", "ha", "he", "hi", - "hr", "hu", "hy", "id", "in", "is", "it", "iw", "ja", "kk", "kn", "ko", - "ky", "lt", "lv", "mk", "ms", "mt", "nl", "no", "pl", "ps", "pt", "rn", - "ro", "ru", "rw", "sk", "sl", "so", "sq", "sr", "sv", "sw", "te", "th", - "tr", "uk", "ur", "uz", "vi", "wo", "xh", "yo", "zh", "zu", -}; - -BOOL -CreateLanguageDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - - for (int i = 0; i < ARRAYLEN(g_aListedLanguageCodes); ++i) { - RString s = - SMPackageUtil::GetLanguageDisplayString(g_aListedLanguageCodes[i]); - RString sLanguage = ConvertUTF8ToACP(s); - m_comboLanguages.AddString(sLanguage); - } - m_comboLanguages.SetCurSel(0); - return TRUE; // return TRUE unless you set the focus to a control -} - -BEGIN_MESSAGE_MAP(CreateLanguageDlg, CDialog) -ON_BN_CLICKED(IDOK, OnBnClickedOk) -END_MESSAGE_MAP() - -void -CreateLanguageDlg::OnBnClickedOk() -{ - // TODO: Add your control notification handler code here - - int iIndex = m_comboLanguages.GetCurSel(); - ASSERT(iIndex != LB_ERR); - - m_sChosenLanguageCode = g_aListedLanguageCodes[iIndex]; - - OnOK(); -} diff --git a/src/smpackagee/CreateLanguageDlg.h b/src/smpackagee/CreateLanguageDlg.h deleted file mode 100644 index 3a928a71df..0000000000 --- a/src/smpackagee/CreateLanguageDlg.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include "afxwin.h" - -// CreateLanguageDlg dialog - -class CreateLanguageDlg : public CDialog -{ - DECLARE_DYNAMIC(CreateLanguageDlg) - - public: - CreateLanguageDlg(CWnd* pParent = NULL); // standard constructor - virtual ~CreateLanguageDlg(); - - // Dialog Data - enum - { - IDD = IDD_CREATE_LANGUAGE - }; - - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - // Generated message map functions - //{{AFX_MSG(CreateLanguageDlg) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: - CComboBox m_comboLanguages; - afx_msg void OnBnClickedOk(); - - CString m_sChosenLanguageCode; -}; diff --git a/src/smpackagee/EditInsallations.cpp b/src/smpackagee/EditInsallations.cpp deleted file mode 100644 index 1957f97685..0000000000 --- a/src/smpackagee/EditInsallations.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// EditInsallations.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "EditInsallations.h" -#include "SMPackageUtil.h" -#include "archutils/Win32/DialogUtil.h" -#include ".\editinsallations.h" -#include "LocalizedString.h" -#include "RageFileManager.h" -#include "RageUtil.h" -#include "arch/Dialog/Dialog.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// EditInsallations dialog - -EditInsallations::EditInsallations(CWnd* pParent /*=NULL*/) - : CDialog(EditInsallations::IDD, pParent) -{ - //{{AFX_DATA_INIT(EditInsallations) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -void -EditInsallations::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(EditInsallations) - DDX_Control(pDX, IDC_LIST, m_list); - DDX_Control(pDX, IDC_EDIT, m_edit); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(EditInsallations, CDialog) -//{{AFX_MSG_MAP(EditInsallations) -ON_BN_CLICKED(IDC_BUTTON_REMOVE, OnButtonRemove) -ON_BN_CLICKED(IDC_BUTTON_MAKE_DEFAULT, OnButtonMakeDefault) -ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAdd) -//}}AFX_MSG_MAP -ON_LBN_SELCHANGE(IDC_LIST, OnLbnSelchangeList) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// EditInsallations message handlers - -BOOL -EditInsallations::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - - vector vs; - SMPackageUtil::GetGameInstallDirs(vs); - for (unsigned i = 0; i < vs.size(); i++) - m_list.AddString(vs[i]); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -void -EditInsallations::OnButtonRemove() -{ - // TODO: Add your control notification handler code here - ASSERT(m_list.GetCount() > 1); // cannot remove the list item in the list - ASSERT(m_list.GetCurSel() != LB_ERR); - - m_list.DeleteString(m_list.GetCurSel()); - OnLbnSelchangeList(); -} - -void -EditInsallations::OnButtonMakeDefault() -{ - // TODO: Add your control notification handler code here - ASSERT(m_list.GetCurSel() != LB_ERR); - - CString sText; - m_list.GetText(m_list.GetCurSel(), sText); - m_list.DeleteString(m_list.GetCurSel()); - m_list.InsertString(0, sText); - m_list.SetCurSel(0); -} - -static LocalizedString YOU_MUST_TYPE_IN( - "EditInstallations", - "You must type a program directory before clicking Add."); -static LocalizedString NOT_A_VALID_INSTALLATION_DIR( - "EditInstallations", - "'%s' is not a valid installation directory."); -void -EditInsallations::OnButtonAdd() -{ - // TODO: Add your control notification handler code here - RString sNewDir; - { - CString s; - m_edit.GetWindowText(s); - sNewDir = s; - } - - if (sNewDir == "") { - Dialog::OK(YOU_MUST_TYPE_IN.GetValue()); - return; - } - - bool bAlreadyInList = false; - for (int i = 0; i < m_list.GetCount(); i++) { - CString sDir; - m_list.GetText(i, sDir); - if (sDir.CompareNoCase(sNewDir) == 0) - return; - } - - if (!SMPackageUtil::IsValidInstallDir(sNewDir)) { - Dialog::OK( - ssprintf(NOT_A_VALID_INSTALLATION_DIR.GetValue(), sNewDir.c_str())); - return; - } - - m_list.AddString(sNewDir); -} - -void -EditInsallations::OnOK() -{ - vector vs; - - for (int i = 0; i < m_list.GetCount(); i++) { - CString sDir; - m_list.GetText(i, sDir); - RString s = sDir; - vs.push_back(s); - } - SMPackageUtil::WriteGameInstallDirs(vs); - - // set the new default - vector asInstallDirs; - SMPackageUtil::GetGameInstallDirs(asInstallDirs); - FILEMAN->Remount("/", asInstallDirs[0]); - - CDialog::OnOK(); -} - -void -EditInsallations::OnLbnSelchangeList() -{ - // TODO: Add your control notification handler code here - bool bSomethingSelected = m_list.GetCurSel() != LB_ERR; - bool bMoreThanOne = m_list.GetCount() > 1; - - this->GetDlgItem(IDC_BUTTON_MAKE_DEFAULT)->EnableWindow(bSomethingSelected); - this->GetDlgItem(IDC_BUTTON_REMOVE)->EnableWindow(bMoreThanOne); -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/EditInsallations.h b/src/smpackagee/EditInsallations.h deleted file mode 100644 index 14d1815535..0000000000 --- a/src/smpackagee/EditInsallations.h +++ /dev/null @@ -1,80 +0,0 @@ -#if !defined( \ - AFX_EDITINSALLATIONS_H__CD328CB4_8E35_4B12_BCD1_ADF5CE7EABC7__INCLUDED_) -#define AFX_EDITINSALLATIONS_H__CD328CB4_8E35_4B12_BCD1_ADF5CE7EABC7__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// EditInsallations.h : header file - -///////////////////////////////////////////////////////////////////////////// -// EditInsallations dialog - -class EditInsallations : public CDialog -{ - // Construction - public: - EditInsallations(CWnd* pParent = NULL); // standard constructor - - // Dialog Data - //{{AFX_DATA(EditInsallations) - enum - { - IDD = IDD_EDIT_INSTALLATIONS - }; - CListBox m_list; - CEdit m_edit; - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(EditInsallations) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - // Generated message map functions - //{{AFX_MSG(EditInsallations) - virtual BOOL OnInitDialog(); - afx_msg void OnButtonRemove(); - afx_msg void OnButtonMakeDefault(); - afx_msg void OnButtonAdd(); - virtual void OnOK(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: - afx_msg void OnLbnSelchangeList(); -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_EDITINSALLATIONS_H__CD328CB4_8E35_4B12_BCD1_ADF5CE7EABC7__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/EnterComment.cpp b/src/smpackagee/EnterComment.cpp deleted file mode 100644 index e43f09afa4..0000000000 --- a/src/smpackagee/EnterComment.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// EnterComment.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "EnterComment.h" -#include "archutils/Win32/DialogUtil.h" -#include ".\entercomment.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// EnterComment dialog - -EnterComment::EnterComment(CWnd* pParent /*=NULL*/) - : CDialog(EnterComment::IDD, pParent) - , m_bDontAsk(FALSE) - , m_bShowAComment(FALSE) -{ - //{{AFX_DATA_INIT(EnterComment) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -void -EnterComment::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(EnterComment) - DDX_Control(pDX, IDC_EDIT, m_edit); - //}}AFX_DATA_MAP - DDX_Check(pDX, IDC_DONTASK, m_bDontAsk); - DDX_Check(pDX, IDC_SHOW_A_COMMENT, m_bShowAComment); -} - -BOOL -EnterComment::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - - OnBnClickedShowAComment(); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -BEGIN_MESSAGE_MAP(EnterComment, CDialog) -//{{AFX_MSG_MAP(EnterComment) -//}}AFX_MSG_MAP -ON_BN_CLICKED(IDC_SHOW_A_COMMENT, OnBnClickedShowAComment) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// EnterComment message handlers - -void -EnterComment::OnOK() -{ - // TODO: Add extra validation here - - UpdateData(TRUE); - - if (m_bShowAComment) - m_edit.GetWindowText(m_sEnteredComment); - - CDialog::OnOK(); -} - -void -EnterComment::OnBnClickedShowAComment() -{ - UpdateData(TRUE); - - // TODO: Add your control notification handler code here - GetDlgItem(IDC_EDIT)->EnableWindow(m_bShowAComment); -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ \ No newline at end of file diff --git a/src/smpackagee/EnterComment.h b/src/smpackagee/EnterComment.h deleted file mode 100644 index e893744069..0000000000 --- a/src/smpackagee/EnterComment.h +++ /dev/null @@ -1,81 +0,0 @@ -#include "afxwin.h" -#if !defined( \ - AFX_ENTERCOMMENT_H__DE628EA8_0FE7_4594_B2A2_47BDB283FA1E__INCLUDED_) -#define AFX_ENTERCOMMENT_H__DE628EA8_0FE7_4594_B2A2_47BDB283FA1E__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// EnterComment.h : header file - -///////////////////////////////////////////////////////////////////////////// -// EnterComment dialog - -class EnterComment : public CDialog -{ - // Construction - public: - EnterComment(CWnd* pParent = NULL); // standard constructor - - CString m_sEnteredComment; - - // Dialog Data - //{{AFX_DATA(EnterComment) - enum - { - IDD = IDD_ENTER_COMMENT - }; - CEdit m_edit; - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(EnterComment) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - // Generated message map functions - //{{AFX_MSG(EnterComment) - virtual void OnOK(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: - BOOL m_bDontAsk; - BOOL m_bShowAComment; - afx_msg void OnBnClickedShowAComment(); -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_ENTERCOMMENT_H__DE628EA8_0FE7_4594_B2A2_47BDB283FA1E__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/EnterName.cpp b/src/smpackagee/EnterName.cpp deleted file mode 100644 index a3a106b847..0000000000 --- a/src/smpackagee/EnterName.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// EnterName.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "EnterName.h" -#include "archutils/Win32/DialogUtil.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// EnterName dialog - -EnterName::EnterName(CWnd* pParent /*=NULL*/) - : CDialog(EnterName::IDD, pParent) -{ - //{{AFX_DATA_INIT(EnterName) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -void -EnterName::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(EnterName) - DDX_Control(pDX, IDC_EDIT, m_edit); - //}}AFX_DATA_MAP -} - -BOOL -EnterName::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -BEGIN_MESSAGE_MAP(EnterName, CDialog) -//{{AFX_MSG_MAP(EnterName) -//}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// EnterName message handlers - -void -EnterName::OnOK() -{ - // TODO: Add extra validation here - m_edit.GetWindowText(m_sEnteredName); - - CDialog::OnOK(); -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/EnterName.h b/src/smpackagee/EnterName.h deleted file mode 100644 index bd98b8025f..0000000000 --- a/src/smpackagee/EnterName.h +++ /dev/null @@ -1,75 +0,0 @@ -#if !defined(AFX_ENTERNAME_H__0AB99274_EB79_4A25_B95C_627E0A99C6BA__INCLUDED_) -#define AFX_ENTERNAME_H__0AB99274_EB79_4A25_B95C_627E0A99C6BA__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// EnterName.h : header file - -///////////////////////////////////////////////////////////////////////////// -// EnterName dialog - -class EnterName : public CDialog -{ - // Construction - public: - EnterName(CWnd* pParent = NULL); // standard constructor - - CString m_sEnteredName; - - // Dialog Data - //{{AFX_DATA(EnterName) - enum - { - IDD = IDD_DIALOG_NAME - }; - CEdit m_edit; - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(EnterName) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - // Generated message map functions - //{{AFX_MSG(EnterName) - virtual void OnOK(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_ENTERNAME_H__0AB99274_EB79_4A25_B95C_627E0A99C6BA__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/LanguagesDlg.cpp b/src/smpackagee/LanguagesDlg.cpp deleted file mode 100644 index d4f3872df2..0000000000 --- a/src/smpackagee/LanguagesDlg.cpp +++ /dev/null @@ -1,684 +0,0 @@ -// LanguagesDlg.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "Foreach.h" -#include "LanguagesDlg.h" -#include "SpecialFiles.h" -#include "RageUtil.h" -#include "IniFile.h" -#include "languagesdlg.h" -#include "SMPackageUtil.h" -#include "CreateLanguageDlg.h" -#include "RageFile.h" -#include "languagesdlg.h" -#include "RageFileManager.h" -#include ".\languagesdlg.h" -#include "CsvFile.h" -#include "archutils/Win32/DialogUtil.h" -#include "LocalizedString.h" -#include "arch/Dialog/Dialog.h" -#include "archutils/Win32/SpecialDirs.h" -#include "archutils/Win32/GotoURL.h" -#include "archutils/Win32/ErrorStrings.h" - -// LanguagesDlg dialog - -IMPLEMENT_DYNAMIC(LanguagesDlg, CDialog) -LanguagesDlg::LanguagesDlg(CWnd* pParent /*=NULL*/) - : CDialog(LanguagesDlg::IDD, pParent) -{ -} - -LanguagesDlg::~LanguagesDlg() {} - -void -LanguagesDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - DDX_Control(pDX, IDC_LIST_THEMES, m_listThemes); - DDX_Control(pDX, IDC_LIST_LANGUAGES, m_listLanguages); - DDX_Control(pDX, - IDC_CHECK_EXPORT_ALREADY_TRANSLATED, - m_buttonExportAlreadyTranslated); -} - -BOOL -LanguagesDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - DialogUtil::LocalizeDialogAndContents(*this); - - vector vs; - GetDirListing(SpecialFiles::THEMES_DIR + "*", vs, true); - StripCvsAndSvn(vs); - FOREACH_CONST(RString, vs, s) - m_listThemes.AddString(*s); - if (!vs.empty()) - m_listThemes.SetSel(0); - - OnSelchangeListThemes(); - - return TRUE; // return TRUE unless you set the focus to a control -} - -static RString -GetCurrentString(const CListBox& list) -{ - // TODO: Add your control notification handler code here - int iSel = list.GetCurSel(); - if (iSel == LB_ERR) - return RString(); - CString s; - list.GetText(list.GetCurSel(), s); - return RString(s); -} - -static void -SelectString(CListBox& list, const RString& sToSelect) -{ - for (int i = 0; i < list.GetCount(); i++) { - CString s; - list.GetText(i, s); - if (s == sToSelect) { - list.SetCurSel(i); - break; - } - } -} - -void -LanguagesDlg::OnSelchangeListThemes() -{ - // TODO: Add your control notification handler code here - m_listLanguages.ResetContent(); - - RString sTheme = GetCurrentString(m_listThemes); - if (!sTheme.empty()) { - RString sLanguagesDir = SpecialFiles::THEMES_DIR + sTheme + "/" + - SpecialFiles::LANGUAGES_SUBDIR; - - vector vs; - GetDirListing(sLanguagesDir + "*.ini", vs, false); - FOREACH_CONST(RString, vs, s) - { - RString sIsoCode = GetFileNameWithoutExtension(*s); - RString sLanguage = - SMPackageUtil::GetLanguageDisplayString(sIsoCode); - m_listLanguages.AddString(ConvertUTF8ToACP(sLanguage)); - } - if (!vs.empty()) - m_listLanguages.SetSel(0); - } - - OnSelchangeListLanguages(); -} - -static RString -GetLanguageFile(const RString& sTheme, const RString& sLanguage) -{ - return SpecialFiles::THEMES_DIR + sTheme + "/" + - SpecialFiles::LANGUAGES_SUBDIR + sLanguage + ".ini"; -} - -static int -GetNumValuesInIniFile(const RString& sIniFile) -{ - int count = 0; - IniFile ini; - ini.ReadFile(sIniFile); - FOREACH_CONST_Child(&ini, key) { FOREACH_CONST_Attr(key, value) count++; } - return count; -} - -static int -GetNumIntersectingIniValues(const RString& sIniFile1, const RString& sIniFile2) -{ - int count = 0; - IniFile ini1; - ini1.ReadFile(sIniFile1); - IniFile ini2; - ini2.ReadFile(sIniFile2); - FOREACH_CONST_Child(&ini1, key1) - { - const XNode* key2 = ini2.GetChild(key1->m_sName); - if (key2 == NULL) - continue; - FOREACH_CONST_Attr(key1, attr1) - { - if (key2->GetAttr(attr1->first) == NULL) - continue; - count++; - } - } - return count; -} - -void -LanguagesDlg::OnSelchangeListLanguages() -{ - // TODO: Add your control notification handler code here - int iTotalStrings = -1; - int iNeedTranslation = -1; - - RString sTheme = GetCurrentString(m_listThemes); - RString sLanguage = GetCurrentString(m_listLanguages); - - if (!sTheme.empty()) { - RString sBaseLanguageFile = - GetLanguageFile(sTheme, SpecialFiles::BASE_LANGUAGE); - iTotalStrings = GetNumValuesInIniFile(sBaseLanguageFile); - - if (!sLanguage.empty()) { - sLanguage = - SMPackageUtil::GetLanguageCodeFromDisplayString(sLanguage); - - RString sLanguageFile = GetLanguageFile(sTheme, sLanguage); - iNeedTranslation = - iTotalStrings - - GetNumIntersectingIniValues(sBaseLanguageFile, sLanguageFile); - } - } - - GetDlgItem(IDC_STATIC_TOTAL_STRINGS) - ->SetWindowText(ssprintf(iTotalStrings == -1 ? "" : "%d", iTotalStrings)); - GetDlgItem(IDC_STATIC_NEED_TRANSLATION) - ->SetWindowText( - ssprintf(iNeedTranslation == -1 ? "" : "%d", iNeedTranslation)); - - GetDlgItem(IDC_BUTTON_CREATE)->EnableWindow(!sTheme.empty()); - GetDlgItem(IDC_BUTTON_DELETE)->EnableWindow(!sLanguage.empty()); - GetDlgItem(IDC_BUTTON_EXPORT)->EnableWindow(!sLanguage.empty()); - GetDlgItem(IDC_BUTTON_IMPORT)->EnableWindow(!sLanguage.empty()); - GetDlgItem(IDC_CHECK_LANGUAGE)->EnableWindow(!sLanguage.empty()); - GetDlgItem(IDC_CHECK_EXPORT_ALREADY_TRANSLATED) - ->EnableWindow(!sLanguage.empty()); -} - -BEGIN_MESSAGE_MAP(LanguagesDlg, CDialog) -ON_LBN_SELCHANGE(IDC_LIST_THEMES, OnSelchangeListThemes) -ON_LBN_SELCHANGE(IDC_LIST_LANGUAGES, OnSelchangeListLanguages) -ON_BN_CLICKED(IDC_BUTTON_CREATE, OnBnClickedButtonCreate) -ON_BN_CLICKED(IDC_BUTTON_DELETE, OnBnClickedButtonDelete) -ON_BN_CLICKED(IDC_BUTTON_EXPORT, OnBnClickedButtonExport) -ON_BN_CLICKED(IDC_BUTTON_IMPORT, OnBnClickedButtonImport) -ON_BN_CLICKED(IDC_CHECK_LANGUAGE, OnBnClickedCheckLanguage) -END_MESSAGE_MAP() - -// LanguagesDlg message handlers - -void -LanguagesDlg::OnBnClickedButtonCreate() -{ - // TODO: Add your control notification handler code here - CreateLanguageDlg dlg; - int nResponse = dlg.DoModal(); - if (nResponse != IDOK) - return; - - RString sTheme = GetCurrentString(m_listThemes); - ASSERT(!sTheme.empty()); - - RString sLanguageFile = - GetLanguageFile(sTheme, RString(dlg.m_sChosenLanguageCode)); - - // create empty file - RageFile file; - file.Open(sLanguageFile, RageFile::WRITE); - file.Close(); // flush file - - OnSelchangeListThemes(); - SelectString(m_listLanguages, - SMPackageUtil::GetLanguageDisplayString( - RString(dlg.m_sChosenLanguageCode))); - OnSelchangeListLanguages(); -} - -static LocalizedString THIS_WILL_PERMANENTLY_DELETE( - "LanguagesDlg", - "This will permanently delete '%s'. Continue?"); -void -LanguagesDlg::OnBnClickedButtonDelete() -{ - // TODO: Add your control notification handler code here - RString sTheme = GetCurrentString(m_listThemes); - ASSERT(!sTheme.empty()); - RString sLanguage = GetCurrentString(m_listLanguages); - ASSERT(!sLanguage.empty()); - sLanguage = SMPackageUtil::GetLanguageCodeFromDisplayString(sLanguage); - - RString sLanguageFile = GetLanguageFile(sTheme, sLanguage); - - RString sMessage = - ssprintf(THIS_WILL_PERMANENTLY_DELETE.GetValue(), sLanguageFile.c_str()); - Dialog::Result ret = Dialog::AbortRetry(sMessage); - if (ret != Dialog::retry) - return; - - FILEMAN->Remove(sLanguageFile); - - OnSelchangeListThemes(); -} - -struct TranslationLine -{ - RString sSection, sID, sBaseLanguage, sCurrentLanguage; -}; - -static LocalizedString FAILED_TO_SAVE("LanguagesDlg", "Failed to save '%s'."); -static LocalizedString THERE_ARE_NO_STRINGS_TO_EXPORT( - "LanguagesDlg", - "There are no strings to export for this language."); -static LocalizedString EXPORTED_TO_YOUR_DESKTOP( - "LanguagesDlg", - "Exported to your Desktop as '%s'."); -void -LanguagesDlg::OnBnClickedButtonExport() -{ - // TODO: Add your control notification handler code here - RString sTheme = GetCurrentString(m_listThemes); - ASSERT(!sTheme.empty()); - RString sLanguage = GetCurrentString(m_listLanguages); - ASSERT(!sLanguage.empty()); - sLanguage = SMPackageUtil::GetLanguageCodeFromDisplayString(sLanguage); - - RString sBaseLanguageFile = - GetLanguageFile(sTheme, SpecialFiles::BASE_LANGUAGE); - RString sLanguageFile = GetLanguageFile(sTheme, sLanguage); - - bool bExportAlreadyTranslated = - !!m_buttonExportAlreadyTranslated.GetCheck(); - - CsvFile csv; - IniFile ini1; - ini1.ReadFile(sBaseLanguageFile); - IniFile ini2; - ini2.ReadFile(sLanguageFile); - int iNumExpored = 0; - - vector vs; - vs.push_back("Section"); - vs.push_back("ID"); - vs.push_back("Base Language Value"); - vs.push_back("Localized Value"); - csv.m_vvs.push_back(vs); - - FOREACH_CONST_Child(&ini1, key) - { - FOREACH_CONST_Attr(key, value) - { - TranslationLine tl; - tl.sSection = key->m_sName; - tl.sID = value->first; - tl.sBaseLanguage = value->second->GetValue(); - ini2.GetValue(tl.sSection, tl.sID, tl.sCurrentLanguage); - - // don't export empty strings - RString sBaseLanguageTrimmed = tl.sBaseLanguage; - TrimLeft(sBaseLanguageTrimmed, " "); - TrimRight(sBaseLanguageTrimmed, " "); - if (sBaseLanguageTrimmed.empty()) - continue; - - bool bAlreadyTranslated = !tl.sCurrentLanguage.empty(); - if (!bAlreadyTranslated || bExportAlreadyTranslated) { - vector vs; - vs.push_back(tl.sSection); - vs.push_back(tl.sID); - vs.push_back(tl.sBaseLanguage); - vs.push_back(tl.sCurrentLanguage); - csv.m_vvs.push_back(vs); - iNumExpored++; - } - } - } - - RageFileOsAbsolute file; - RString sFile = sTheme + "-" + sLanguage + ".csv"; - RString sFullFile = SpecialDirs::GetDesktopDir() + sFile; - file.Open(sFullFile, RageFile::WRITE); - if (iNumExpored == 0) { - Dialog::OK(THERE_ARE_NO_STRINGS_TO_EXPORT.GetValue()); - return; - } - - if (csv.WriteFile(file)) - Dialog::OK( - ssprintf(EXPORTED_TO_YOUR_DESKTOP.GetValue(), sFile.c_str())); - else - Dialog::OK(ssprintf(FAILED_TO_SAVE.GetValue(), sFullFile.c_str())); -} - -static LocalizedString ERROR_READING_FILE("LanguagesDlg", - "Error reading file '%s'."); -static LocalizedString ERROR_PARSING_FILE("LanguagesDlg", - "Error parsing file '%s'."); -static LocalizedString IMPORTING_THESE_STRINGS_WILL_OVERRIDE( - "LanguagesDlg", - "Importing these strings will override all data in '%s'. Continue?"); -static LocalizedString ERROR_READING("LanguagesDlg", "Error reading '%s'."); -static LocalizedString ERROR_READING_EACH_LINE_MUST_HAVE( - "LanguagesDlg", - "Error reading line '%s' from '%s': Each line must have either 3 or 4 " - "values. This row has %d values."); -static LocalizedString IMPORTED_STRINGS_INTO("LanguagesDlg", - "Imported %d strings into '%s'.\n " - "- %d were added.\n - %d were " - "modified\n - %d were unchanged\n " - "- %d empty strings were ignored"); -void -LanguagesDlg::OnBnClickedButtonImport() -{ - // TODO: Add your control notification handler code here - CFileDialog dialog(TRUE, // file open? - NULL, // default file extension - NULL, // default file name - OFN_HIDEREADONLY | OFN_NOCHANGEDIR, // flags - "CSV file (*.csv)|*.csv|||"); - int iRet = dialog.DoModal(); - RString sCsvFile = dialog.GetPathName(); - if (iRet != IDOK) - return; - - RString sTheme = GetCurrentString(m_listThemes); - ASSERT(!sTheme.empty()); - RString sLanguage = GetCurrentString(m_listLanguages); - ASSERT(!sLanguage.empty()); - sLanguage = SMPackageUtil::GetLanguageCodeFromDisplayString(sLanguage); - - RageFileOsAbsolute cvsFile; - if (!cvsFile.Open(sCsvFile)) { - Dialog::OK(ssprintf(ERROR_READING_FILE.GetValue(), sCsvFile.c_str())); - return; - } - CsvFile csv; - if (!csv.ReadFile(cvsFile)) { - Dialog::OK(ssprintf(ERROR_PARSING_FILE.GetValue(), sCsvFile.c_str())); - return; - } - - RString sLanguageFile = GetLanguageFile(sTheme, sLanguage); - - { - Dialog::Result ret = Dialog::AbortRetry( - ssprintf(IMPORTING_THESE_STRINGS_WILL_OVERRIDE.GetValue(), - sLanguageFile.c_str())); - if (ret != Dialog::retry) - return; - } - - IniFile ini; - if (!ini.ReadFile(sLanguageFile)) { - Dialog::OK(ssprintf(ERROR_READING.GetValue(), sLanguageFile.c_str())); - return; - } - - int iNumImported = 0; - int iNumAdded = 0; - int iNumModified = 0; - int iNumUnchanged = 0; - int iNumIgnored = 0; - FOREACH_CONST(CsvFile::StringVector, csv.m_vvs, line) - { - int iLineIndex = line - csv.m_vvs.begin(); - - // Skip the header row - if (iLineIndex == 0) - continue; - - TranslationLine tl; - int iNumValues = line->size(); - if (iNumValues != 3 && iNumValues != 4) { - Dialog::OK(ssprintf(ERROR_READING_EACH_LINE_MUST_HAVE.GetValue(), - join(",", *line).c_str(), - sCsvFile.c_str(), - iNumValues)); - return; - } - tl.sSection = (*line)[0]; - tl.sID = (*line)[1]; - tl.sBaseLanguage = (*line)[2]; - tl.sCurrentLanguage = iNumValues == 4 ? (*line)[3] : RString(); - - if (tl.sCurrentLanguage.empty()) { - iNumIgnored++; - } else { - RString sOldCurrentLanguage; - bool bExists = - ini.GetValue(tl.sSection, tl.sID, sOldCurrentLanguage); - if (bExists) { - if (sOldCurrentLanguage == tl.sCurrentLanguage) - iNumUnchanged++; - else - iNumModified++; - } else { - iNumAdded++; - } - - ini.SetValue(tl.sSection, tl.sID, tl.sCurrentLanguage); - iNumImported++; - } - } - - if (ini.WriteFile(sLanguageFile)) - Dialog::OK(ssprintf(IMPORTED_STRINGS_INTO.GetValue(), - iNumImported, - sLanguageFile.c_str(), - iNumAdded, - iNumModified, - iNumUnchanged, - iNumIgnored)); - else - Dialog::OK(ssprintf(FAILED_TO_SAVE.GetValue(), sLanguageFile.c_str())); - - OnSelchangeListThemes(); -} - -void -GetAllMatches(const RString& sRegex, - const RString& sString, - vector& asOut) -{ - Regex re(sRegex + "(.*)$"); - RString sMatch(sString); - while (1) { - vector asMatches; - if (!re.Compare(sMatch, asMatches)) - break; - asOut.push_back(asMatches[0]); - sMatch = asMatches[1]; - } -} - -void -DumpList(const vector& asList, RageFile& file) -{ - RString sLine; - FOREACH_CONST(RString, asList, s) - { - if (sLine.size() + s->size() > 100) { - file.PutLine(sLine); - sLine = ""; - } - - if (sLine.size()) - sLine += ", "; - else - sLine += " "; - - sLine += *s; - } - - file.PutLine(sLine); -} - -void -LanguagesDlg::OnBnClickedCheckLanguage() -{ - RString sTheme = GetCurrentString(m_listThemes); - ASSERT(!sTheme.empty()); - RString sLanguage = GetCurrentString(m_listLanguages); - ASSERT(!sLanguage.empty()); - sLanguage = SMPackageUtil::GetLanguageCodeFromDisplayString(sLanguage); - - RString sBaseLanguageFile = - GetLanguageFile(sTheme, SpecialFiles::BASE_LANGUAGE); - RString sLanguageFile = GetLanguageFile(sTheme, sLanguage); - - IniFile ini1; - ini1.ReadFile(sBaseLanguageFile); - IniFile ini2; - ini2.ReadFile(sLanguageFile); - - RageFileOsAbsolute file; - RString sFile = sTheme + "-" + sLanguage + " check.txt"; - RString sFullFile = SpecialDirs::GetDesktopDir() + sFile; - file.Open(sFullFile, RageFile::WRITE); - - { FOREACH_CONST_Child(&ini1, key){ - FOREACH_CONST_Attr(key, value){ const RString& sSection = key->m_sName; - const RString& sID = value->first; - const RString& sBaseLanguage = value->second->GetValue(); - RString sCurrentLanguage; - ini2.GetValue(sSection, sID, sCurrentLanguage); - - if (sCurrentLanguage.empty()) - continue; - - /* Check &FOO;, %{foo}, %-1.2f, %. Some mismatches here are normal, - * particularly in languages with substantially different word order rules - * than English. */ - { - RString sRegex = - "(&[A-Za-z]+;|%{[A-Za-z]+}|%[+-]?[0-9]*.?[0-9]*[sidf]|%)"; - vector asMatchesBase; - GetAllMatches(sRegex, sBaseLanguage, asMatchesBase); - - vector asMatches; - GetAllMatches(sRegex, sCurrentLanguage, asMatches); - - if (asMatchesBase.size() != asMatches.size() || - !std::equal( - asMatchesBase.begin(), asMatchesBase.end(), asMatches.begin())) { - file.PutLine( - ssprintf("Entity/substitution mismatch in section [%s] (%s):", - sSection.c_str(), - sID.c_str())); - file.PutLine(ssprintf(" %s", sCurrentLanguage.c_str())); - file.PutLine(ssprintf(" %s", sBaseLanguage.c_str())); - } - } - - /* Check "foo::bar", "foo\nbar" and double quotes. Check these - * independently of the above. */ - { - RString sRegex = "(\"|::|\\n)"; - vector asMatchesBase; - GetAllMatches(sRegex, sBaseLanguage, asMatchesBase); - - vector asMatches; - GetAllMatches(sRegex, sCurrentLanguage, asMatches); - - if (asMatchesBase.size() != asMatches.size() || - !std::equal( - asMatchesBase.begin(), asMatchesBase.end(), asMatches.begin())) { - file.PutLine( - ssprintf("Quote/line break mismatch in section [%s] (%s):", - sSection.c_str(), - sID.c_str())); - file.PutLine(ssprintf(" %s", sCurrentLanguage.c_str())); - file.PutLine(ssprintf(" %s", sBaseLanguage.c_str())); - } - } - - /* Check that both end in a period or both don't end an a period. */ - { - RString sBaseLanguage2 = sBaseLanguage; - TrimRight(sBaseLanguage2, " "); - RString sCurrentLanguage2 = sCurrentLanguage; - TrimRight(sCurrentLanguage2, " "); - - if ((sBaseLanguage2.Right(1) == ".") ^ - (sCurrentLanguage2.Right(1) == ".")) { - file.PutLine(ssprintf("Period mismatch in section [%s] (%s):", - sSection.c_str(), - sID.c_str())); - file.PutLine(ssprintf(" %s", sCurrentLanguage.c_str())); - file.PutLine(ssprintf(" %s", sBaseLanguage.c_str())); - } - } -} -} -} - -{ FOREACH_CONST_Child(&ini2, key){ - FOREACH_CONST_Attr(key, value){ const RString& sSection = key->m_sName; -const RString& sID = value->first; -const RString& sCurrentLanguage = value->second->GetValue(); -if (utf8_is_valid(sCurrentLanguage)) - continue; - -/* The text isn't valid UTF-8. We don't know what encoding it is; guess that - * it's ISO-8859-1 and convert it so it'll display correctly and can be pasted - * into the file. Don't include the original text: if we include multiple - * encodings in the resulting text file, editors won't understand the encoding - * of the file and will pick one arbitrarily. */ -file.PutLine(ssprintf("Incorrect encoding in section [%s]:", sSection.c_str())); -wstring wsConverted = ConvertCodepageToWString(sCurrentLanguage, 1252); -RString sConverted = WStringToRString(wsConverted); -file.PutLine(ssprintf("%s=%s", sID.c_str(), sConverted.c_str())); -} -} -} - -{ FOREACH_CONST_Child(&ini2, key){ vector asList; -const RString& sSection = key->m_sName; -FOREACH_CONST_Attr(key, value) -{ - const RString& sID = value->first; - RString sCurrentLanguage; - if (ini1.GetValue(sSection, sID, sCurrentLanguage)) - continue; - - asList.push_back(sID); -} -if (!asList.empty()) { - file.PutLine( - ssprintf("Obsolete translation in section [%s]:", sSection.c_str())); - DumpList(asList, file); -} -} -} - -{ - FOREACH_CONST_Child(&ini1, key) - { - vector asList; - const RString& sSection = key->m_sName; - FOREACH_CONST_Attr(key, value) - { - const RString& sID = value->first; - const RString& sBaseText = value->second->GetValue(); - if (sBaseText.empty()) - continue; - RString sCurrentLanguage; - if (ini2.GetValue(sSection, sID, sCurrentLanguage)) - continue; - - asList.push_back(sID); - } - if (!asList.empty()) { - file.PutLine( - ssprintf("Not translated in section [%s]:", sSection.c_str())); - DumpList(asList, file); - } - } -} - -file.Close(); - -GotoURL(ssprintf("file://%s", sFullFile.c_str())); -} diff --git a/src/smpackagee/LanguagesDlg.h b/src/smpackagee/LanguagesDlg.h deleted file mode 100644 index f2fc8df501..0000000000 --- a/src/smpackagee/LanguagesDlg.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include "afxwin.h" - -// LanguagesDlg dialog - -class LanguagesDlg : public CDialog -{ - DECLARE_DYNAMIC(LanguagesDlg) - - public: - LanguagesDlg(CWnd* pParent = NULL); // standard constructor - virtual ~LanguagesDlg(); - - // Dialog Data - enum - { - IDD = IDD_LANGUAGES - }; - - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnInitDialog(); - void OnSelchangeListThemes(); - void OnSelchangeListLanguages(); - - DECLARE_MESSAGE_MAP() - public: - CListBox m_listThemes; - CListBox m_listLanguages; - afx_msg void OnBnClickedButtonCreate(); - afx_msg void OnBnClickedButtonDelete(); - afx_msg void OnBnClickedButtonExport(); - afx_msg void OnBnClickedButtonImport(); - CButton m_buttonExportAlreadyTranslated; - afx_msg void OnBnClickedCheckLanguage(); -}; diff --git a/src/smpackagee/MainMenuDlg.cpp b/src/smpackagee/MainMenuDlg.cpp deleted file mode 100644 index fb5ed9d1ae..0000000000 --- a/src/smpackagee/MainMenuDlg.cpp +++ /dev/null @@ -1,335 +0,0 @@ -// MainMenuDlg.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "MainMenuDlg.h" -#include "EditInsallations.h" -#include "SmpackageExportDlg.h" -#include "ChangeGameSettings.h" -#include "RageUtil.h" -#include "SMPackageUtil.h" -#include "mainmenudlg.h" -#include "archutils/Win32/SpecialDirs.h" -#include "SpecialFiles.h" -#include "ProductInfo.h" -#include "mainmenudlg.h" -#include "LanguagesDlg.h" -#include ".\mainmenudlg.h" -#include "archutils/Win32/DialogUtil.h" -#include "LocalizedString.h" -#include "RageFileManager.h" -#include "arch/Dialog/Dialog.h" -#include "archutils/Win32/ErrorStrings.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// MainMenuDlg dialog - -MainMenuDlg::MainMenuDlg(CWnd* pParent /*=NULL*/) - : CDialog(MainMenuDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(MainMenuDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -void -MainMenuDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(MainMenuDlg) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(MainMenuDlg, CDialog) -//{{AFX_MSG_MAP(MainMenuDlg) -ON_BN_CLICKED(IDC_EXPORT_PACKAGES, OnExportPackages) -ON_BN_CLICKED(IDC_EDIT_INSTALLATIONS, OnEditInstallations) -ON_BN_CLICKED(IDC_CREATE_SONG, OnCreateSong) -ON_BN_CLICKED(IDC_CLEAR_KEYMAPS, OnBnClickedClearKeymaps) -ON_BN_CLICKED(IDC_CHANGE_PREFERENCES, OnBnClickedChangePreferences) -ON_BN_CLICKED(IDC_OPEN_PREFERENCES, OnBnClickedOpenPreferences) -ON_BN_CLICKED(IDC_CLEAR_PREFERENCES, OnBnClickedClearPreferences) -//}}AFX_MSG_MAP -ON_BN_CLICKED(IDC_BUTTON_LAUNCH_GAME, OnBnClickedButtonLaunchGame) -ON_BN_CLICKED(IDC_LANGUAGES, OnBnClickedLanguages) -ON_WM_CTLCOLOR() -ON_WM_ERASEBKGND() -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// MainMenuDlg message handlers - -void -MainMenuDlg::OnExportPackages() -{ - // TODO: Add your control notification handler code here - CSmpackageExportDlg dlg; - dlg.DoModal(); - // if (nResponse == IDOK) -} - -void -MainMenuDlg::OnEditInstallations() -{ - // TODO: Add your control notification handler code here - EditInsallations dlg; - dlg.DoModal(); -} - -RString -GetLastErrorString() -{ - LPVOID lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - (LPTSTR)&lpMsgBuf, - 0, - NULL); - // Process any inserts in lpMsgBuf. - // ... - // Display the string. - RString s = (LPCTSTR)lpMsgBuf; - // Free the buffer. - LocalFree(lpMsgBuf); - - return s; -} - -static LocalizedString MUSIC_FILE("MainMenuDlg", "Music file"); -static LocalizedString THE_SONG_DIRECTORY_ALREADY_EXISTS("MainMenuDlg", - "The song directory " - "'%s' already exists. " - " You cannot override " - "an existing song."); -static LocalizedString FAILED_TO_COPY_MUSIC_FILE( - "MainMenuDlg", - "Failed to copy music file '%s' to '%s': %s"); -static LocalizedString FAILED_TO_CREATE_THE_SONG_FILE( - "MainMenuDlg", - "Failed to create the song file '%s'."); -static LocalizedString SUCCESS_CREATED_THE_SONG( - "MainMenuDlg", - "Success. Created the song '%s'."); -void -MainMenuDlg::OnCreateSong() -{ - // TODO: Add your control notification handler code here - ASSERT(0); - // fix compile - CFileDialog dialog( - TRUE, // file open? - NULL, // default file extension - NULL, // default file name - OFN_HIDEREADONLY | OFN_NOCHANGEDIR, // flags - ConvertUTF8ToACP(MUSIC_FILE.GetValue() + " (*.mp3;*.ogg)|*.mp3;*.ogg|||") - .c_str()); - int iRet = dialog.DoModal(); - RString sMusicFile = dialog.GetPathName(); - if (iRet != IDOK) - return; - - RString sSongDirectory = - "Songs/My Creations/" + GetFileNameWithoutExtension(sMusicFile) + "/"; - RString sNewMusicFile = sSongDirectory + Basename(sMusicFile); - - if (DoesFileExist(sSongDirectory)) { - Dialog::OK(ssprintf(THE_SONG_DIRECTORY_ALREADY_EXISTS.GetValue(), - sSongDirectory.c_str())); - return; - } - - RageFileOsAbsolute fileIn; - fileIn.Open(sMusicFile, RageFile::READ); - RageFile fileOut; - fileOut.Open(sNewMusicFile, RageFile::WRITE); - RString sError; - bool bSuccess = FileCopy(fileIn, fileOut, sError); - if (!bSuccess) { - Dialog::OK(ssprintf(FAILED_TO_COPY_MUSIC_FILE.GetValue(), - sMusicFile.c_str(), - sNewMusicFile.c_str(), - sError.c_str())); - return; - } - - // create a blank .sm file - RString sNewSongFile = sMusicFile; - SetExtension(sNewSongFile, "sm"); - RageFile file; - if (file.Open(sNewSongFile, RageFile::WRITE)) { - Dialog::OK(ssprintf(FAILED_TO_CREATE_THE_SONG_FILE.GetValue(), - sNewSongFile.c_str())); - return; - } - file.Close(); - - Dialog::OK( - ssprintf(SUCCESS_CREATED_THE_SONG.GetValue(), sSongDirectory.c_str())); -} - -BOOL -MainMenuDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - DialogUtil::SetHeaderFont(*this, IDC_STATIC_HEADER_TEXT); - - // DialogUtil::SetDlgItemHeader( *this, IDC_STATIC_HEADER_TEXT, "header" ); - - TCHAR szCurDir[MAX_PATH]; - GetCurrentDirectory(ARRAYLEN(szCurDir), szCurDir); - GetDlgItem(IDC_EDIT_INSTALLATION)->SetWindowText(szCurDir); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -static LocalizedString FAILED_TO_DELETE_FILE("MainMenuDlg", - "Failed to delete file '%s'."); -static LocalizedString IS_ALREADY_CLEARED("MainMenuDlg", - "'%s' is already cleared."); -static LocalizedString CLEARED("MainMenuDlg", "'%s' cleared"); -void -MainMenuDlg::OnBnClickedClearKeymaps() -{ - // TODO: Add your control notification handler code here - - FILEMAN->FlushDirCache(Dirname(SpecialFiles::KEYMAPS_PATH)); - if (!DoesFileExist(SpecialFiles::KEYMAPS_PATH)) { - Dialog::OK(ssprintf(IS_ALREADY_CLEARED.GetValue(), - SpecialFiles::KEYMAPS_PATH.c_str())); - return; - } - - if (!FILEMAN->Remove(SpecialFiles::KEYMAPS_PATH)) - Dialog::OK(ssprintf(FAILED_TO_DELETE_FILE.GetValue(), - SpecialFiles::KEYMAPS_PATH.c_str())); - - Dialog::OK( - ssprintf(CLEARED.GetValue(), SpecialFiles::KEYMAPS_PATH.c_str())); -} - -void -MainMenuDlg::OnBnClickedChangePreferences() -{ - // TODO: Add your control notification handler code here - ChangeGameSettings dlg; - dlg.DoModal(); -} - -static LocalizedString DOESNT_EXIST_IT_WILL_BE_CREATED( - "MainMenuDlg", - "'%s' doesn't exist. It will be created next time you start the game."); -static LocalizedString FAILED_TO_OPEN("MainMenuDlg", "Failed to open '%s': %s"); -void -MainMenuDlg::OnBnClickedOpenPreferences() -{ - // TODO: Add your control notification handler code here - // TODO: Have RageFile* do the mapping to the OS file location. - RString sPreferencesOSFile = SpecialDirs::GetAppDataDir() + PRODUCT_ID + - "/" + SpecialFiles::PREFERENCES_INI_PATH; - HINSTANCE hinst = ::ShellExecute( - this->m_hWnd, "open", sPreferencesOSFile, "", "", SW_SHOWNORMAL); - if ((int)hinst == SE_ERR_FNF) - Dialog::OK(ssprintf(DOESNT_EXIST_IT_WILL_BE_CREATED.GetValue(), - sPreferencesOSFile.c_str())); - else if ((int)hinst <= 32) - Dialog::OK(ssprintf(FAILED_TO_OPEN.GetValue(), - sPreferencesOSFile.c_str(), - GetLastErrorString().c_str())); -} - -void -MainMenuDlg::OnBnClickedClearPreferences() -{ - // TODO: Add your control notification handler code here - FILEMAN->FlushDirCache(); - if (!DoesFileExist(SpecialFiles::PREFERENCES_INI_PATH)) { - Dialog::OK(ssprintf(IS_ALREADY_CLEARED.GetValue(), - SpecialFiles::PREFERENCES_INI_PATH.c_str())); - return; - } - - if (!FILEMAN->Remove(SpecialFiles::PREFERENCES_INI_PATH)) { - Dialog::OK(ssprintf(FAILED_TO_DELETE_FILE.GetValue(), - SpecialFiles::PREFERENCES_INI_PATH.c_str())); - return; - } - - Dialog::OK( - ssprintf(CLEARED.GetValue(), SpecialFiles::PREFERENCES_INI_PATH.c_str())); -} - -void -MainMenuDlg::OnBnClickedButtonLaunchGame() -{ - // TODO: Add your control notification handler code here - if (SMPackageUtil::LaunchGame()) - exit(0); -} - -void -MainMenuDlg::OnBnClickedLanguages() -{ - // TODO: Add your control notification handler code here - LanguagesDlg dlg; - dlg.DoModal(); -} - -HBRUSH -MainMenuDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) -{ - HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); - - // TODO: Change any attributes of the DC here - switch (pWnd->GetDlgCtrlID()) { - case IDC_STATIC_HEADER_TEXT: - case IDC_STATIC_ICON: - hbr = (HBRUSH)::GetStockObject(WHITE_BRUSH); - pDC->SetBkMode(OPAQUE); - pDC->SetBkColor(RGB(255, 255, 255)); - break; - } - - // TODO: Return a different brush if the default is not desired - return hbr; -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/MainMenuDlg.h b/src/smpackagee/MainMenuDlg.h deleted file mode 100644 index d05aee1e46..0000000000 --- a/src/smpackagee/MainMenuDlg.h +++ /dev/null @@ -1,85 +0,0 @@ -#if !defined(AFX_MAINMENUDLG_H__3CED6142_18E5_4267_B678_BE5B63735C6C__INCLUDED_) -#define AFX_MAINMENUDLG_H__3CED6142_18E5_4267_B678_BE5B63735C6C__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// MainMenuDlg.h : header file - -///////////////////////////////////////////////////////////////////////////// -// MainMenuDlg dialog - -class MainMenuDlg : public CDialog -{ - // Construction - public: - MainMenuDlg(CWnd* pParent = NULL); // standard constructor - - // Dialog Data - //{{AFX_DATA(MainMenuDlg) - enum - { - IDD = IDD_MENU - }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(MainMenuDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - // Generated message map functions - //{{AFX_MSG(MainMenuDlg) - afx_msg void OnExportPackages(); - afx_msg void OnEditInstallations(); - afx_msg void OnChangeApi(); - afx_msg void OnCreateSong(); - virtual BOOL OnInitDialog(); - afx_msg void OnOpenPreferencesIni(); - afx_msg void OnBnClickedClearKeymaps(); - afx_msg void OnBnClickedChangePreferences(); - afx_msg void OnBnClickedOpenPreferences(); - afx_msg void OnBnClickedClearPreferences(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: - afx_msg void OnBnClickedButtonLaunchGame(); - afx_msg void OnBnClickedLanguages(); - afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_MAINMENUDLG_H__3CED6142_18E5_4267_B678_BE5B63735C6C__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/SMPackageInstallDlg.cpp b/src/smpackagee/SMPackageInstallDlg.cpp deleted file mode 100644 index 643247258a..0000000000 --- a/src/smpackagee/SMPackageInstallDlg.cpp +++ /dev/null @@ -1,469 +0,0 @@ -// SMPackageInstallDlg.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "SMPackageInstallDlg.h" -#include "RageUtil.h" -#include "smpackageUtil.h" -#include "EditInsallations.h" -#include "ShowComment.h" -#include "IniFile.h" -#include "UninstallOld.h" -#include -#include "RageFileManager.h" -#include "RageFileDriverZip.h" -#include "archutils/Win32/DialogUtil.h" -#include "LocalizedString.h" -#include "RageLog.h" -#include "arch/Dialog/Dialog.h" -#include "RageFileDriverDirect.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CSMPackageInstallDlg dialog - -CSMPackageInstallDlg::CSMPackageInstallDlg(RString sPackagePath, - CWnd* pParent /*=NULL*/) - : CDialog(CSMPackageInstallDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CSMPackageInstallDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - - m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); - - m_sPackagePath = sPackagePath; -} - -void -CSMPackageInstallDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CSMPackageInstallDlg) - DDX_Control(pDX, IDC_BUTTON_EDIT, m_buttonEdit); - DDX_Control(pDX, IDC_COMBO_DIR, m_comboDir); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CSMPackageInstallDlg, CDialog) -//{{AFX_MSG_MAP(CSMPackageInstallDlg) -ON_WM_PAINT() -ON_BN_CLICKED(IDC_BUTTON_EDIT, OnButtonEdit) -//}}AFX_MSG_MAP -ON_WM_CTLCOLOR() -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CSMPackageInstallDlg message handlers - -static bool -CompareStringNoCase(const RString& s1, const RString& s2) -{ - return s1.CompareNoCase(s2) < 0; -} - -void -GetSmzipFilesToExtract(RageFileDriver& zip, vector& vsOut) -{ - GetDirListingRecursive(&zip, "/", "*", vsOut); - SMPackageUtil::StripIgnoredSmzipFiles(vsOut); -} - -static LocalizedString COULD_NOT_OPEN_FILE("CSMPackageInstallDlg", - "Could not open file '%s'."); -static LocalizedString IS_NOT_A_VALID_ZIP("CSMPackageInstallDlg", - "'%s' is not a valid zip archive."); -BOOL -CSMPackageInstallDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // Set the icon for this dialog. The framework does this automatically - // when the application's main window is not a dialog - SetIcon(m_hIcon, TRUE); // Set big icon - SetIcon(m_hIcon, FALSE); // Set small icon - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - DialogUtil::SetHeaderFont(*this, IDC_STATIC_HEADER_TEXT); - - // mount the zip - RageFileOsAbsolute file; - if (!file.Open(m_sPackagePath)) { - Dialog::OK( - ssprintf(COULD_NOT_OPEN_FILE.GetValue(), m_sPackagePath.c_str())); - exit(1); // better way to abort? - } - - RageFileDriverZip zip; - if (!zip.Load(&file)) { - Dialog::OK( - ssprintf(IS_NOT_A_VALID_ZIP.GetValue(), m_sPackagePath.c_str())); - exit(1); // better way to abort? - } - - // - // Set the text of the first Edit box - // - RString sMessage1 = "\t" + m_sPackagePath; - CEdit* pEdit1 = (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE1); - pEdit1->SetWindowText(sMessage1); - - // - // Set the text of the second Edit box - // - { - vector vs; - GetSmzipFilesToExtract(zip, vs); - CEdit* pEdit2 = (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE2); - RString sText = "\t" + join("\r\n\t", vs); - pEdit2->SetWindowText(sText); - } - - RefreshInstallationList(); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -void -CSMPackageInstallDlg::OnPaint() -{ - CPaintDC dc(this); // device context for painting - - // TODO: Add your message handler code here - - if (IsIconic()) { - CPaintDC dc(this); // device context for painting - - SendMessage(WM_ICONERASEBKGND, (WPARAM)dc.GetSafeHdc(), 0); - - // Center icon in client rectangle - int cxIcon = GetSystemMetrics(SM_CXICON); - int cyIcon = GetSystemMetrics(SM_CYICON); - CRect rect; - GetClientRect(&rect); - int x = (rect.Width() - cxIcon + 1) / 2; - int y = (rect.Height() - cyIcon + 1) / 2; - - // Draw the icon - dc.DrawIcon(x, y, m_hIcon); - } else { - CDialog::OnPaint(); - } -} -#include -#include ".\smpackageinstalldlg.h" - -static bool -CheckPackages(RageFileDriverZip& fileDriver) -{ - int iErr; - RageFileBasic* pFile = fileDriver.Open("smzip.ctl", RageFile::READ, iErr); - if (pFile == NULL) - return true; - - IniFile ini; - ini.ReadFile(*pFile); - - int version = 0; - ini.GetValue("SMZIP", "Version", version); - if (version != 1) - return true; - - int cnt = 0; - ini.GetValue("Packages", "NumPackages", cnt); - - vector vsDirectories; - for (int i = 0; i < cnt; ++i) { - RString path; - if (!ini.GetValue("Packages", ssprintf("%i", i), path)) - continue; - - /* Does this directory exist? */ - if (!FILEMAN->IsADirectory(path)) - continue; - - if (!SMPackageUtil::IsValidPackageDirectory(path)) - continue; - - vsDirectories.push_back(path); - } - - if (vsDirectories.empty()) - return true; - - { - UninstallOld UninstallOldDlg; - UninstallOldDlg.m_sPackages = join("\r\n", vsDirectories); - int nResponse = UninstallOldDlg.DoModal(); - if (nResponse == IDCANCEL) - return false; // cancelled - if (nResponse == IDIGNORE) - return true; - } - - char cwd_[MAX_PATH]; - _getcwd(cwd_, MAX_PATH); - RString cwd(cwd_); - if (cwd[cwd.size() - 1] != '\\') - cwd += "\\"; - - for (int i = 0; i < (int)vsDirectories.size(); ++i) { - RString sDir = vsDirectories[i]; - sDir += "/"; - if (!DeleteRecursive(sDir)) // error deleting - { - return false; - } - } - - return true; -} - -static LocalizedString NO_INSTALLATIONS("CSMPackageInstallDlg", - "No Installations found. Exiting."); -static LocalizedString INSTALLING_PLEASE_WAIT("CSMPackageInstallDlg", - "Installing. Please wait..."); -static LocalizedString ERROR_OPENING_SOURCE_FILE( - "CSMPackageInstallDlg", - "Error opening source file '%s': %s"); -static LocalizedString ERROR_OPENING_DESTINATION_FILE( - "CSMPackageInstallDlg", - "Error opening destination file '%s': %s"); -static LocalizedString ERROR_COPYING_FILE("CSMPackageInstallDlg", - "Error copying file '%s': %s"); -static LocalizedString PACKAGE_INSTALLED_SUCCESSFULLY( - "CSMPackageInstallDlg", - "Package installed successfully!"); -void -CSMPackageInstallDlg::OnOK() -{ - // TODO: Add extra validation here - - int ProgressInit = 0; - - m_comboDir.EnableWindow(FALSE); - m_buttonEdit.EnableWindow(FALSE); - - RString sInstallDir; - { - CString s; - m_comboDir.GetWindowText(s); - sInstallDir = s; - } - - // selected install dir becomes the new default - int iSelectedInstallDirIndex = m_comboDir.GetCurSel(); - if (iSelectedInstallDirIndex == -1) { - Dialog::OK(NO_INSTALLATIONS.GetValue()); - return; - } - - SMPackageUtil::SetDefaultInstallDir(iSelectedInstallDirIndex); - - // mount the zip - RageFileOsAbsolute file; - if (!file.Open(m_sPackagePath)) { - Dialog::OK( - ssprintf(COULD_NOT_OPEN_FILE.GetValue(), m_sPackagePath.c_str())); - exit(1); // better way to abort? - } - - RageFileDriverZip zip; - if (!zip.Load(&file)) { - Dialog::OK( - ssprintf(IS_NOT_A_VALID_ZIP.GetValue(), m_sPackagePath.c_str())); - exit(1); // better way to abort? - } - - RageFileDriverDirect dir(sInstallDir); - // handle error? - - // Show comment (if any) - { - RString sComment = zip.GetGlobalComment(); - bool DontShowComment; - if (sComment != "" && - (!SMPackageUtil::GetPref("DontShowComment", DontShowComment) || - !DontShowComment)) { - ShowComment commentDlg; - commentDlg.m_sComment = sComment; - int nResponse = commentDlg.DoModal(); - if (nResponse != IDOK) - return; // cancelled - if (commentDlg.m_bDontShow) - SMPackageUtil::SetPref("DontShowComment", true); - } - } - - /* Check for installed packages that should be deleted before installing. */ - if (!CheckPackages(zip)) - return; // cancelled - - // Unzip the SMzip package into the installation folder - vector vs; - GetSmzipFilesToExtract(zip, vs); - for (unsigned i = 0; i < vs.size(); i++) { - // Throw some text up so the user has something to look at during the - // long pause. - CEdit* pEdit1 = (CEdit*)GetDlgItem(IDC_STATIC_MESSAGE1); - pEdit1->SetWindowText( - ssprintf(INSTALLING_PLEASE_WAIT.GetValue(), m_sPackagePath.c_str())); - CEdit* pEdit2 = (CEdit*)GetDlgItem(IDC_EDIT_MESSAGE2); - pEdit2->SetWindowText(""); - GetDlgItem(IDC_STATIC_MESSAGE2)->ShowWindow(SW_HIDE); - CProgressCtrl* pProgress1 = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1); - // Show the hided progress bar - if (!pProgress1->IsWindowVisible()) { - pProgress1->ShowWindow(SW_SHOWNORMAL); - } - // Initialize the progress bar and update the window 1 time (it's - // enough) - if (!ProgressInit) { - pProgress1->SetRange(0, (short)vs.size()); - pProgress1->SetStep(1); - pProgress1->SetPos(0); - SendMessage(WM_PAINT); - UpdateWindow(); // Force the silly thing to hadle WM_PAINT now! - ProgressInit = 1; - } - - Dialog::Result result; - do { - // Extract the files - const RString sFile = vs[i]; - LOG->Trace("Extracting: " + sFile); - - RString sError; - { - int iErr; - RageFileBasic* pFileFrom = - zip.Open(sFile, RageFile::READ, iErr); - if (pFileFrom == NULL) { - sError = ssprintf(ERROR_OPENING_SOURCE_FILE.GetValue(), - sFile.c_str(), - ssprintf("%d", iErr).c_str()); - goto show_error; - } - - int iError; - RageFileBasic* pFileTo = - dir.Open(sFile, RageFile::WRITE, iError); - if (pFileTo == NULL) { - sError = ssprintf(ERROR_OPENING_DESTINATION_FILE.GetValue(), - sFile.c_str(), - pFileTo->GetError().c_str()); - goto show_error; - } - - RString sErr; - if (!FileCopy(*pFileFrom, *pFileTo, sErr)) { - sError = ssprintf(ERROR_COPYING_FILE.GetValue(), - sFile.c_str(), - sErr.c_str()); - goto show_error; - } - - SAFE_DELETE(pFileFrom); - SAFE_DELETE(pFileTo); - } - - break; - - show_error: - Dialog::Result result = Dialog::AbortRetryIgnore(sError); - switch (result) { - case Dialog::abort: - exit(1); // better way to exit? - break; - case Dialog::retry: - break; - case Dialog::ignore: - // do nothing - break; - } - } while (result == Dialog::retry); - - pProgress1->StepIt(); // increase the progress bar of 1 step - } - - Dialog::OK(PACKAGE_INSTALLED_SUCCESSFULLY.GetValue()); - - // close the dialog - CDialog::OnOK(); -} - -void -CSMPackageInstallDlg::OnButtonEdit() -{ - // TODO: Add your control notification handler code here - EditInsallations dlg; - int nResponse = dlg.DoModal(); - if (nResponse == IDOK) { - RefreshInstallationList(); - } -} - -void -CSMPackageInstallDlg::RefreshInstallationList() -{ - m_comboDir.ResetContent(); - - vector asInstallDirs; - SMPackageUtil::GetGameInstallDirs(asInstallDirs); - for (unsigned i = 0; i < asInstallDirs.size(); i++) - m_comboDir.AddString(asInstallDirs[i]); - m_comboDir.SetCurSel(0); // guaranteed to be at least one item -} - -HBRUSH -CSMPackageInstallDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) -{ - HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); - - // TODO: Change any attributes of the DC here - switch (pWnd->GetDlgCtrlID()) { - case IDC_STATIC_HEADER_TEXT: - case IDC_STATIC_ICON: - hbr = (HBRUSH)::GetStockObject(WHITE_BRUSH); - pDC->SetBkMode(OPAQUE); - pDC->SetBkColor(RGB(255, 255, 255)); - break; - } - - // TODO: Return a different brush if the default is not desired - return hbr; -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/SMPackageInstallDlg.h b/src/smpackagee/SMPackageInstallDlg.h deleted file mode 100644 index fd070d4080..0000000000 --- a/src/smpackagee/SMPackageInstallDlg.h +++ /dev/null @@ -1,85 +0,0 @@ -#if !defined( \ - AFX_SMPACKAGEINSTALLDLG_H__5E362C4C_CA11_4071_A8AB_A0231E985DAF__INCLUDED_) -#define AFX_SMPACKAGEINSTALLDLG_H__5E362C4C_CA11_4071_A8AB_A0231E985DAF__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// SMPackageInstallDlg.h : header file - -///////////////////////////////////////////////////////////////////////////// -// CSMPackageInstallDlg dialog - -class CSMPackageInstallDlg : public CDialog -{ - // Construction - public: - CSMPackageInstallDlg(RString sPackagePath, - CWnd* pParent = NULL); // standard constructor - - // Dialog Data - //{{AFX_DATA(CSMPackageInstallDlg) - enum - { - IDD = IDD_INSTALL - }; - CButton m_buttonEdit; - CComboBox m_comboDir; - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CSMPackageInstallDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - void RefreshInstallationList(); - - HICON m_hIcon; - RString m_sPackagePath; - - // Generated message map functions - //{{AFX_MSG(CSMPackageInstallDlg) - virtual BOOL OnInitDialog(); - virtual void OnOK(); - afx_msg void OnPaint(); - afx_msg void OnButtonEdit(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: - afx_msg HBRUSH OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor); -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_SMPACKAGEINSTALLDLG_H__5E362C4C_CA11_4071_A8AB_A0231E985DAF__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/SMPackageUtil.cpp b/src/smpackagee/SMPackageUtil.cpp deleted file mode 100644 index 2c0bd4479d..0000000000 --- a/src/smpackagee/SMPackageUtil.cpp +++ /dev/null @@ -1,302 +0,0 @@ -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "SMPackageUtil.h" -#include "archutils/Win32/RegistryAccess.h" -#include "ProductInfo.h" -#include "RageUtil.h" -#include "RageFileManager.h" -#include "resource.h" -#include "LocalizedString.h" -#include "arch/Dialog/Dialog.h" - -static const RString SMPACKAGE_KEY = - "HKEY_LOCAL_MACHINE\\Software\\" PRODUCT_ID "\\smpackage"; -static const RString INSTALLATIONS_KEY = - "HKEY_LOCAL_MACHINE\\Software\\" PRODUCT_ID "\\smpackage\\Installations"; - -void -SMPackageUtil::WriteGameInstallDirs(const vector& asInstallDirsToWrite) -{ - RegistryAccess::CreateKey(INSTALLATIONS_KEY); - - for (unsigned i = 0; i < 100; i++) { - RString sName = ssprintf("%d", i); - RString sValue; - if (i < asInstallDirsToWrite.size()) - sValue = asInstallDirsToWrite[i]; - - RegistryAccess::SetRegValue(INSTALLATIONS_KEY, sName, sValue); - } -} - -void -SMPackageUtil::GetGameInstallDirs(vector& asInstallDirsOut) -{ - asInstallDirsOut.clear(); - - for (int i = 0; i < 100; i++) { - RString sName = ssprintf("%d", i); - - RString sPath; - if (!RegistryAccess::GetRegValue(INSTALLATIONS_KEY, sName, sPath)) - continue; - - if (sPath == "") // blank entry - continue; // skip - - if (!IsValidInstallDir(sPath)) - continue; // skip - - asInstallDirsOut.push_back(sPath); - } - - // while we're at it, write to clean up stale entries - WriteGameInstallDirs(asInstallDirsOut); -} - -void -SMPackageUtil::AddGameInstallDir(const RString& sNewInstallDir) -{ - vector asInstallDirs; - GetGameInstallDirs(asInstallDirs); - - bool bAlreadyInList = false; - for (unsigned i = 0; i < asInstallDirs.size(); i++) { - if (asInstallDirs[i].CompareNoCase(sNewInstallDir) == 0) { - bAlreadyInList = true; - break; - } - } - - if (!bAlreadyInList) - asInstallDirs.push_back(sNewInstallDir); - - WriteGameInstallDirs(asInstallDirs); -} - -void -SMPackageUtil::SetDefaultInstallDir(int iInstallDirIndex) -{ - // move the specified index to the top of the list - vector asInstallDirs; - GetGameInstallDirs(asInstallDirs); - ASSERT(iInstallDirIndex >= 0 && - iInstallDirIndex < (int)asInstallDirs.size()); - RString sDefaultInstallDir = asInstallDirs[iInstallDirIndex]; - asInstallDirs.erase(asInstallDirs.begin() + iInstallDirIndex); - asInstallDirs.insert(asInstallDirs.begin(), sDefaultInstallDir); - WriteGameInstallDirs(asInstallDirs); -} - -void -SMPackageUtil::SetDefaultInstallDir(const RString& sInstallDir) -{ - vector asInstallDirs; - GetGameInstallDirs(asInstallDirs); - - for (unsigned i = 0; i < asInstallDirs.size(); i++) { - if (asInstallDirs[i].CompareNoCase(sInstallDir) == 0) { - SetDefaultInstallDir(i); - break; - } - } -} - -bool -SMPackageUtil::IsValidInstallDir(const RString& sInstallDir) -{ - return DoesOsAbsoluteFileExist(sInstallDir + "/Songs"); -} - -bool -SMPackageUtil::GetPref(const RString& name, bool& val) -{ - return RegistryAccess::GetRegValue(SMPACKAGE_KEY, name, val); -} - -bool -SMPackageUtil::SetPref(const RString& name, bool val) -{ - return RegistryAccess::SetRegValue(SMPACKAGE_KEY, name, val); -} - -/* Get a package directory. For most paths, this is the first two components. - * For songs and note skins, this is the first three. */ -RString -SMPackageUtil::GetPackageDirectory(const RString& path) -{ - // ignore CVS/.svn files: - if (path.find("CVS") != string::npos) - return ""; - if (path.find(".svn") != string::npos) - return ""; - - vector Parts; - split(path, "\\", Parts); - - unsigned NumParts = 2; - // Songs/group/single_song, NoteSkins/gametype/single_noteskin: - if (!Parts[0].CompareNoCase("Songs") || - !Parts[0].CompareNoCase("NoteSkins")) - NumParts = 3; - if (Parts.size() < NumParts) - return ""; - - Parts.erase(Parts.begin() + NumParts, Parts.end()); - - RString ret = join("\\", Parts); - if (!IsADirectory(ret)) - return ""; - return ret; -} - -bool -SMPackageUtil::IsValidPackageDirectory(const RString& path) -{ - /* Make sure the path contains only second-level directories, and doesn't - * contain any ".", "..", "...", etc. dirs. */ - vector Parts; - split(path, "\\", Parts, true); - if (Parts.size() == 0) - return false; - - /* Make sure we're not going to "uninstall" an entire Songs subfolder. */ - unsigned NumParts = 2; - if (!Parts[0].CompareNoCase("songs")) - NumParts = 3; - if (Parts.size() < NumParts) - return false; - - /* Make sure the path doesn't contain any ".", "..", "...", etc. dirs. */ - for (unsigned i = 0; i < Parts.size(); ++i) - if (Parts[i][0] == '.') - return false; - - return true; -} - -static LocalizedString COULD_NOT_FIND("SMPackageUtil", "Could not find '%s'."); -bool -SMPackageUtil::LaunchGame() -{ - PROCESS_INFORMATION pi; - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - - RString sFile = "Program\\" PRODUCT_FAMILY ".exe"; - - BOOL bSuccess = CreateProcess(sFile, // pointer to name of executable module - NULL, // pointer to command line string - NULL, // process security attributes - NULL, // thread security attributes - false, // handle inheritance flag - 0, // creation flags - NULL, // pointer to new environment block - NULL, // pointer to current directory name - &si, // pointer to STARTUPINFO - &pi // pointer to PROCESS_INFORMATION - ); - if (!bSuccess) { - RString sError = ssprintf(COULD_NOT_FIND.GetValue(), sFile.c_str()); - Dialog::OK(sError); - return false; - } - - return true; -} - -RString -SMPackageUtil::GetLanguageDisplayString(const RString& sIsoCode) -{ - const LanguageInfo* li = GetLanguageInfo(sIsoCode); - return ssprintf( - "%s (%s)", li ? li->szIsoCode : sIsoCode.c_str(), li->szEnglishName); -} - -RString -SMPackageUtil::GetLanguageCodeFromDisplayString(const RString& sDisplayString) -{ - RString s = sDisplayString; - // strip the space and everything after - size_t iSpace = s.find(' '); - ASSERT(iSpace != s.npos); - s.erase(s.begin() + iSpace, s.end()); - return s; -} - -void -SMPackageUtil::StripIgnoredSmzipFiles(vector& vsFilesInOut) -{ - for (int i = vsFilesInOut.size() - 1; i >= 0; i--) { - const RString& sFile = vsFilesInOut[i]; - - bool bEraseThis = false; - bEraseThis |= EndsWith(sFile, "smzip.ctl"); - bEraseThis |= EndsWith(sFile, ".old"); - bEraseThis |= EndsWith(sFile, "Thumbs.db"); - bEraseThis |= EndsWith(sFile, ".DS_Store"); - bEraseThis |= (sFile.find("CVS") != string::npos); - - if (bEraseThis) - vsFilesInOut.erase(vsFilesInOut.begin() + i); - } -} - -bool -SMPackageUtil::DoesOsAbsoluteFileExist(const RString& sOsAbsoluteFile) -{ -#if defined(WIN32) - DWORD dwAttr = ::GetFileAttributes(sOsAbsoluteFile); - return bool(dwAttr != (DWORD)-1); -#endif -} - -static const RString TEMP_MOUNT_POINT = "/@package/"; - -RageFileOsAbsolute::~RageFileOsAbsolute() -{ - if (!m_sOsDir.empty()) - FILEMAN->Unmount("dir", m_sOsDir, TEMP_MOUNT_POINT); -} - -bool -RageFileOsAbsolute::Open(const RString& path, int mode) -{ - if (!m_sOsDir.empty()) - FILEMAN->Unmount("dir", m_sOsDir, TEMP_MOUNT_POINT); - - m_sOsDir = path; - size_t iStart = m_sOsDir.find_last_of("/\\"); - ASSERT(iStart != m_sOsDir.npos); - m_sOsDir.erase(m_sOsDir.begin() + iStart, m_sOsDir.end()); - - FILEMAN->Mount("dir", m_sOsDir, TEMP_MOUNT_POINT); - RString sFileName = path.Right(path.size() - m_sOsDir.size()); - return RageFile::Open(TEMP_MOUNT_POINT + sFileName, mode); -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/ShowComment.cpp b/src/smpackagee/ShowComment.cpp deleted file mode 100644 index 58391996e6..0000000000 --- a/src/smpackagee/ShowComment.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// ShowComment.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "ShowComment.h" -#include "archutils/Win32/DialogUtil.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// ShowComment dialog - -ShowComment::ShowComment(CWnd* pParent /*=NULL*/) - : CDialog(ShowComment::IDD, pParent) - , m_bDontShow(FALSE) -{ - //{{AFX_DATA_INIT(ShowComment) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -void -ShowComment::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(ShowComment) - DDX_Control(pDX, IDC_EDIT, m_edit); - //}}AFX_DATA_MAP - DDX_Check(pDX, IDC_DONTSHOW, m_bDontShow); -} - -BEGIN_MESSAGE_MAP(ShowComment, CDialog) -//{{AFX_MSG_MAP(ShowComment) -//}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// ShowComment message handlers - -BOOL -ShowComment::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - - m_edit.SetWindowText(m_sComment); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/ShowComment.h b/src/smpackagee/ShowComment.h deleted file mode 100644 index 4bcef49f99..0000000000 --- a/src/smpackagee/ShowComment.h +++ /dev/null @@ -1,76 +0,0 @@ -#if !defined(AFX_SHOWCOMMENT_H__1FA603E3_5CCD_4D9E_9EC9_88AD55A06270__INCLUDED_) -#define AFX_SHOWCOMMENT_H__1FA603E3_5CCD_4D9E_9EC9_88AD55A06270__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ShowComment.h : header file - -///////////////////////////////////////////////////////////////////////////// -// ShowComment dialog - -class ShowComment : public CDialog -{ - // Construction - public: - ShowComment(CWnd* pParent = NULL); // standard constructor - - CString m_sComment; - - // Dialog Data - //{{AFX_DATA(ShowComment) - enum - { - IDD = IDD_SHOW_COMMENT - }; - CEdit m_edit; - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(ShowComment) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - // Generated message map functions - //{{AFX_MSG(ShowComment) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: - BOOL m_bDontShow; -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_SHOWCOMMENT_H__1FA603E3_5CCD_4D9E_9EC9_88AD55A06270__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/SmpackageExportDlg.cpp b/src/smpackagee/SmpackageExportDlg.cpp deleted file mode 100644 index 8334b2b3bf..0000000000 --- a/src/smpackagee/SmpackageExportDlg.cpp +++ /dev/null @@ -1,605 +0,0 @@ -// SmpackageExportDlg.cpp : implementation file - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "SmpackageExportDlg.h" -#include "RageUtil.h" -#include "ZipArchive\ZipArchive.h" -#include "EnterName.h" -#include "EnterComment.h" -#include "smpackageUtil.h" -#include "EditInsallations.h" -#include "IniFile.h" -#include "RageFileDriverMemory.h" -#include "archutils/Win32/SpecialDirs.h" -#include "archutils/Win32/DialogUtil.h" -#include "LocalizedString.h" -#include "RageFileDriverDirect.h" -#include "arch/Dialog/Dialog.h" - -#include -#include -#include -#include ".\smpackageexportdlg.h" -using namespace std; - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CSmpackageExportDlg dialog - -CSmpackageExportDlg::CSmpackageExportDlg(CWnd* pParent /*=NULL*/) - : CDialog(CSmpackageExportDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CSmpackageExportDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -void -CSmpackageExportDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CSmpackageExportDlg) - DDX_Control(pDX, IDC_COMBO_DIR, m_comboDir); - DDX_Control( - pDX, IDC_BUTTON_EXPORT_AS_INDIVIDUAL, m_buttonExportAsIndividual); - DDX_Control(pDX, IDC_BUTTON_EXPORT_AS_ONE, m_buttonExportAsOne); - DDX_Control(pDX, IDC_TREE, m_tree); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CSmpackageExportDlg, CDialog) -//{{AFX_MSG_MAP(CSmpackageExportDlg) -ON_BN_CLICKED(IDC_BUTTON_EXPORT_AS_ONE, OnButtonExportAsOne) -ON_BN_CLICKED(IDC_BUTTON_EXPORT_AS_INDIVIDUAL, OnButtonExportAsIndividual) -ON_BN_CLICKED(IDC_BUTTON_PLAY, OnButtonPlay) -ON_BN_CLICKED(IDC_BUTTON_EDIT, OnButtonEdit) -ON_CBN_SELCHANGE(IDC_COMBO_DIR, OnSelchangeComboDir) -ON_BN_CLICKED(IDC_BUTTON_OPEN, OnButtonOpen) -//}}AFX_MSG_MAP -ON_WM_CTLCOLOR() -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CSmpackageExportDlg message handlers - -BOOL -CSmpackageExportDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - DialogUtil::LocalizeDialogAndContents(*this); - - RefreshInstallationList(); - - RefreshTree(); - - return TRUE; // return TRUE unless you set the focus to a control -} - -RString -ReplaceInvalidFileNameChars(RString sOldFileName) -{ - RString sNewFileName = sOldFileName; - const char charsToReplace[] = { ' ', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '+', '=', '[', - ']', '{', '}', '|', ':', '\"', '\\', - '<', '>', ',', '?', '/' }; - for (int i = 0; i < sizeof(charsToReplace); i++) - sNewFileName.Replace(charsToReplace[i], '_'); - return sNewFileName; -} - -static LocalizedString ERROR_ADDING_FILE("SmpackageExportDlg", - "Error adding file '%s'."); -static bool -ExportPackage(const RString& sPackageName, - const RString& sSourceInstallDir, - const vector& asDirectoriesToExport, - const RString& sComment) -{ - CZipArchive zip; - - // - // Create the package zip file - // - const RString sPackagePath = SpecialDirs::GetDesktopDir() + sPackageName; - try { - zip.Open(sPackagePath, CZipArchive::zipCreate); - } catch (CException* e) { - e->ReportError(); - zip.Close(); - e->Delete(); - return false; - } - - zip.SetGlobalComment(sComment); - - /* Find files to add to zip. */ - vector asFilePaths; - { - RageFileDriverDirect fileDriver(sSourceInstallDir); - - for (unsigned i = 0; i < asDirectoriesToExport.size(); i++) { - RString sDir = asDirectoriesToExport[i]; - if (sDir.Right(1) != "/") - sDir += "/"; - GetDirListingRecursive(&fileDriver, sDir, "*", asFilePaths); - SMPackageUtil::StripIgnoredSmzipFiles(asFilePaths); - } - } - - // Must use backslashes in the path, or else WinZip and WinRAR don't see the - // files. Not sure if this is ZipArchive's fault. - //;XXX - - { - IniFile ini; - ini.SetValue("SMZIP", "Version", 1); - - set Directories; - for (unsigned i = 0; i < asFilePaths.size(); i++) { - const RString name = - SMPackageUtil::GetPackageDirectory(asFilePaths[i]); - if (name != "") - Directories.insert(name); - } - - set::const_iterator it; - int num = 0; - for (it = Directories.begin(); it != Directories.end(); ++it) - ini.SetValue("Packages", ssprintf("%i", num++), *it); - ini.SetValue("Packages", "NumPackages", num); - - RageFileObjMem f; - ini.WriteFile(f); - RString buf = f.GetString(); - - CZipMemFile control; - control.Write(buf.GetBuffer(0), buf.size()); - - control.Seek(0, CZipAbstractFile::begin); - zip.AddNewFile(control, "smzip.ctl"); - } - - // - // Add files to zip - // - for (unsigned j = 0; j < asFilePaths.size(); j++) { - RString sFilePath = asFilePaths[j]; - - RString sExt = GetExtension(sFilePath); - bool bUseCompression = true; - if (sExt.CompareNoCase("ogv") == 0 || sExt.CompareNoCase("avi") == 0 || - sExt.CompareNoCase("mpeg") == 0 || sExt.CompareNoCase("mpg") == 0 || - sExt.CompareNoCase("mp3") == 0 || sExt.CompareNoCase("oga") == 0 || - sExt.CompareNoCase("ogg") == 0 || sExt.CompareNoCase("gif") == 0 || - sExt.CompareNoCase("jpg") == 0 || sExt.CompareNoCase("jpeg") == 0 || - sExt.CompareNoCase("png") == 0) - bUseCompression = false; - - try { - zip.AddNewFile(sSourceInstallDir + sFilePath, - sFilePath, - bUseCompression ? Z_BEST_COMPRESSION - : Z_NO_COMPRESSION, - true); - } catch (CException* e) { - Dialog::OK( - ssprintf(ERROR_ADDING_FILE.GetValue(), sFilePath.c_str())); - zip.Close(); - e->Delete(); - return false; - } - } - - zip.Close(); - return true; -} - -bool -CSmpackageExportDlg::MakeComment(RString& comment) -{ - bool DontAskForComment; - if (SMPackageUtil::GetPref("DontAskForComment", DontAskForComment) && - DontAskForComment) { - comment = ""; - return true; - } - - EnterComment commentDlg; - int nResponse = commentDlg.DoModal(); - if (nResponse != IDOK) - return false; // cancelled - - comment = commentDlg.m_sEnteredComment; - if (commentDlg.m_bDontAsk) - SMPackageUtil::SetPref("DontAskForComment", true); - - return true; -} - -static LocalizedString NO_ITEMS_ARE_CHECKED("CSmpackageExportDlg", - "No items are checked."); -static LocalizedString SUCCESSFULLY_EXPORTED( - "CSmpackageExportDlg", - "Successfully exported package '%s' to your Desktop."); -void -CSmpackageExportDlg::OnButtonExportAsOne() -{ - vector asPaths; - GetCheckedPaths(asPaths); - - if (asPaths.size() == 0) { - Dialog::OK(NO_ITEMS_ARE_CHECKED.GetValue()); - return; - } else if (asPaths.size() == 1) { - OnButtonExportAsIndividual(); - return; - } - - // Generate a package name - RString sPackageName; - EnterName nameDlg; - int nResponse = nameDlg.DoModal(); - if (nResponse != IDOK) - return; // cancelled - sPackageName = nameDlg.m_sEnteredName; - sPackageName = ReplaceInvalidFileNameChars(sPackageName + ".smzip"); - - // Generate a comment - RString sComment; - if (!MakeComment(sComment)) - return; // cancelled - - if (ExportPackage(sPackageName, GetCurrentInstallDir(), asPaths, sComment)) - Dialog::OK( - ssprintf(SUCCESSFULLY_EXPORTED.GetValue(), sPackageName.c_str())); -} - -static LocalizedString THE_FOLLOWING_PACKAGES_WERE_EXPORTED( - "CSmpackageExportDlg", - "The following packages were exported to your Desktop:"); -static LocalizedString THE_FOLLOWING_PACKAGES_FAILED( - "CSmpackageExportDlg", - "The following packages failed to export:"); -void -CSmpackageExportDlg::OnButtonExportAsIndividual() -{ - vector asPaths; - GetCheckedPaths(asPaths); - - if (asPaths.size() == 0) { - Dialog::OK(NO_ITEMS_ARE_CHECKED.GetValue()); - return; - } - - // Generate a comment - RString sComment; - if (!MakeComment(sComment)) - return; // cancelled - - vector asExportedPackages; - vector asFailedPackages; - for (unsigned i = 0; i < asPaths.size(); i++) { - // Generate a package name for every path - RString sPath = asPaths[i]; - - RString sPackageName = ReplaceInvalidFileNameChars(sPath) + ".smzip"; - - vector asPathsToExport; - asPathsToExport.push_back(sPath); - - if (ExportPackage( - sPackageName, GetCurrentInstallDir(), asPathsToExport, sComment)) - asExportedPackages.push_back(sPackageName); - else - asFailedPackages.push_back(sPackageName); - } - - RString sMessage; - if (asExportedPackages.size() > 0) - sMessage += THE_FOLLOWING_PACKAGES_WERE_EXPORTED.GetValue() + "\n\n" + - join("\n", asExportedPackages); - - if (asFailedPackages.size() > 0) { - if (!sMessage.empty()) - sMessage += "\n\n"; - sMessage += THE_FOLLOWING_PACKAGES_FAILED.GetValue() + "\n\n" + - join("\n", asFailedPackages); - } - Dialog::OK(sMessage); -} - -void -CSmpackageExportDlg::OnButtonPlay() -{ - // TODO: Add your control notification handler code here - SMPackageUtil::LaunchGame(); - exit(0); -} - -void -CSmpackageExportDlg::GetTreeItems(CArray& aItemsOut) -{ - CArray aRootsToExplore; - - // add all top-level roots - HTREEITEM item = m_tree.GetRootItem(); - while (item != NULL) { - aRootsToExplore.Add(item); - item = m_tree.GetNextSiblingItem(item); - } - - while (aRootsToExplore.GetSize() > 0) { - HTREEITEM item = aRootsToExplore[0]; - aRootsToExplore.RemoveAt(0); - aItemsOut.Add(item); - - HTREEITEM child = m_tree.GetChildItem(item); - while (child != NULL) { - aRootsToExplore.Add(child); - child = m_tree.GetNextSiblingItem(child); - } - } -} - -void -CSmpackageExportDlg::GetCheckedTreeItems( - CArray& aCheckedItemsOut) -{ - CArray aItems; - - GetTreeItems(aItems); - for (int i = 0; i < aItems.GetSize(); i++) - if (m_tree.GetCheck(aItems[i])) - aCheckedItemsOut.Add(aItems[i]); -} - -void -CSmpackageExportDlg::GetCheckedPaths(vector& aPathsOut) -{ - CArray aItems; - - GetCheckedTreeItems(aItems); - for (int i = 0; i < aItems.GetSize(); i++) { - HTREEITEM item = aItems[i]; - - RString sPath; - - while (item) { - sPath = RString((LPCTSTR)m_tree.GetItemText(item)) + '/' + sPath; - item = m_tree.GetParentItem(item); - } - - TrimRight(sPath, "/"); // strip off last slash - - aPathsOut.push_back(sPath); - } -} - -void -CSmpackageExportDlg::OnButtonEdit() -{ - // TODO: Add your control notification handler code here - EditInsallations dlg; - int nResponse = dlg.DoModal(); - if (nResponse == IDOK) { - RefreshInstallationList(); - RefreshTree(); - } -} - -void -CSmpackageExportDlg::RefreshInstallationList() -{ - m_comboDir.ResetContent(); - - vector asInstallDirs; - SMPackageUtil::GetGameInstallDirs(asInstallDirs); - for (unsigned i = 0; i < asInstallDirs.size(); i++) { - m_comboDir.AddString(asInstallDirs[i]); - } - m_comboDir.SetCurSel(0); // guaranteed to be at least one item -} - -void -CSmpackageExportDlg::OnSelchangeComboDir() -{ - // TODO: Add your control notification handler code here - RefreshTree(); -} - -RString -CSmpackageExportDlg::GetCurrentInstallDir() -{ - CString s; - m_comboDir.GetWindowText(s); - RString s2 = s; - if (s2.Right(1) != "/") - s2 += "/"; - return s2; -} - -void -CSmpackageExportDlg::RefreshTree() -{ - m_tree.DeleteAllItems(); - - RageFileDriverDirect fileDriver(GetCurrentInstallDir()); - - // Add announcers - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("Announcers"); - fileDriver.GetDirListing("Announcers/*", as1, true, false); - for (unsigned i = 0; i < as1.size(); i++) - m_tree.InsertItem(as1[i], item1); - } - - // Add characters - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("Characters"); - fileDriver.GetDirListing("Characters/*", as1, true, false); - for (unsigned i = 0; i < as1.size(); i++) - m_tree.InsertItem(as1[i], item1); - } - - // Add themes - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("Themes"); - fileDriver.GetDirListing("Themes/*", as1, true, false); - for (unsigned i = 0; i < as1.size(); i++) - m_tree.InsertItem(as1[i], item1); - } - - // Add BGAnimations - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("BGAnimations"); - fileDriver.GetDirListing("BGAnimations/*", as1, true, false); - for (unsigned i = 0; i < as1.size(); i++) - m_tree.InsertItem(as1[i], item1); - } - - // Add RandomMovies - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("RandomMovies"); - fileDriver.GetDirListing("RandomMovies/*.ogv", as1, false, false); - fileDriver.GetDirListing("RandomMovies/*.avi", as1, false, false); - fileDriver.GetDirListing("RandomMovies/*.mpg", as1, false, false); - fileDriver.GetDirListing("RandomMovies/*.mpeg", as1, false, false); - for (unsigned i = 0; i < as1.size(); i++) - m_tree.InsertItem(as1[i], item1); - } - - // Add visualizations - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("Visualizations"); - fileDriver.GetDirListing("Visualizations/*.ogv", as1, false, false); - fileDriver.GetDirListing("Visualizations/*.avi", as1, false, false); - fileDriver.GetDirListing("Visualizations/*.mpg", as1, false, false); - fileDriver.GetDirListing("Visualizations/*.mpeg", as1, false, false); - for (unsigned i = 0; i < as1.size(); i++) - m_tree.InsertItem(as1[i], item1); - } - - // Add courses - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("Courses"); - fileDriver.GetDirListing("Courses/*.crs", as1, false, false); - for (unsigned i = 0; i < as1.size(); i++) { - as1[i] = as1[i].Left(as1[i].size() - 4); // strip off ".crs" - m_tree.InsertItem(as1[i], item1); - } - } - - // - // Add NoteSkins - // - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("NoteSkins"); - fileDriver.GetDirListing("NoteSkins/*", as1, true, false); - for (unsigned i = 0; i < as1.size(); i++) { - vector as2; - HTREEITEM item2 = m_tree.InsertItem(as1[i], item1); - fileDriver.GetDirListing( - "NoteSkins/" + as1[i] + "/*", as2, true, false); - for (unsigned j = 0; j < as2.size(); j++) - m_tree.InsertItem(as2[j], item2); - } - } - - // - // Add Songs - // - { - vector as1; - HTREEITEM item1 = m_tree.InsertItem("Songs"); - fileDriver.GetDirListing("Songs/*", as1, true, false); - for (unsigned i = 0; i < as1.size(); i++) { - vector as2; - HTREEITEM item2 = m_tree.InsertItem(as1[i], item1); - fileDriver.GetDirListing( - "Songs/" + as1[i] + "/*", as2, true, false); - for (unsigned j = 0; j < as2.size(); j++) - m_tree.InsertItem(as2[j], item2); - } - } - - // Strip out any CVS/.svn items - CArray aItems; - GetTreeItems(aItems); - for (int i = 0; i < aItems.GetSize(); i++) { - if (m_tree.GetItemText(aItems[i]).CompareNoCase("CVS") == 0 || - m_tree.GetItemText(aItems[i]).CompareNoCase(".svn") == 0) - m_tree.DeleteItem(aItems[i]); - } -} - -void -CSmpackageExportDlg::OnButtonOpen() -{ - // TODO: Add your control notification handler code here - - char szCurDir[MAX_PATH]; - GetCurrentDirectory(MAX_PATH, szCurDir); - - char szCommandToExecute[MAX_PATH] = "explorer "; - strcat(szCommandToExecute, szCurDir); - - PROCESS_INFORMATION pi; - STARTUPINFO si; - ZeroMemory(&si, sizeof(si)); - - CreateProcess(NULL, // pointer to name of executable module - szCommandToExecute, // pointer to command line string - NULL, // process security attributes - NULL, // thread security attributes - false, // handle inheritance flag - 0, // creation flags - NULL, // pointer to new environment block - NULL, // pointer to current directory name - &si, // pointer to STARTUPINFO - &pi // pointer to PROCESS_INFORMATION - ); -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/SmpackageExportDlg.h b/src/smpackagee/SmpackageExportDlg.h deleted file mode 100644 index 1351700a2e..0000000000 --- a/src/smpackagee/SmpackageExportDlg.h +++ /dev/null @@ -1,94 +0,0 @@ -#if !defined( \ - AFX_SMPACKAGEEXPORTDLG_H__3E19CBFB_E8F6_4C18_B0A4_636979B80A4D__INCLUDED_) -#define AFX_SMPACKAGEEXPORTDLG_H__3E19CBFB_E8F6_4C18_B0A4_636979B80A4D__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "afxtempl.h" - -// SmpackageExportDlg.h : header file - -///////////////////////////////////////////////////////////////////////////// -// CSmpackageExportDlg dialog - -class CSmpackageExportDlg : public CDialog -{ - // Construction - public: - CSmpackageExportDlg(CWnd* pParent = NULL); // standard constructor - - // Dialog Data - //{{AFX_DATA(CSmpackageExportDlg) - enum - { - IDD = IDD_EXPORTER - }; - CComboBox m_comboDir; - CButton m_buttonExportAsIndividual; - CButton m_buttonExportAsOne; - CTreeCtrl m_tree; - //}}AFX_DATA - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CSmpackageExportDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // Implementation - protected: - void RefreshInstallationList(); - void RefreshTree(); - void GetTreeItems(CArray& aItemsOut); - void GetCheckedTreeItems(CArray& aCheckedItemsOut); - void GetCheckedPaths(vector& aCheckedItemsOut); - bool MakeComment(RString& comment); - RString GetCurrentInstallDir(); - - // Generated message map functions - //{{AFX_MSG(CSmpackageExportDlg) - virtual BOOL OnInitDialog(); - afx_msg void OnButtonExportAsOne(); - afx_msg void OnButtonExportAsIndividual(); - afx_msg void OnButtonPlay(); - afx_msg void OnButtonEdit(); - afx_msg void OnSelchangeComboDir(); - afx_msg void OnButtonOpen(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - public: -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_SMPACKAGEEXPORTDLG_H__3E19CBFB_E8F6_4C18_B0A4_636979B80A4D__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/StdAfx.cpp b/src/smpackagee/StdAfx.cpp deleted file mode 100644 index 92ba9f4701..0000000000 --- a/src/smpackagee/StdAfx.cpp +++ /dev/null @@ -1,5 +0,0 @@ -// stdafx.cpp : source file that includes just the standard includes -// smpackage.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" diff --git a/src/smpackagee/StdAfx.h b/src/smpackagee/StdAfx.h deleted file mode 100644 index f1cf81fffa..0000000000 --- a/src/smpackagee/StdAfx.h +++ /dev/null @@ -1,67 +0,0 @@ -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__D450D5ED_5C49_4A8B_B887_076F62424F1F__INCLUDED_) -#define AFX_STDAFX_H__D450D5ED_5C49_4A8B_B887_076F62424F1F__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#pragma warning(disable : 4786) // turn off broken debugger warning - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -// prevent windows includes from pulling in debug CRTs: -#if defined(_DEBUG) -#undef _DEBUG -#define RESTORE_DEBUG -#endif - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#if defined(RESTORE_DEBUG) -#undef RESTORE_DEBUG -#define _DEBUG -#endif - -#include -using namespace std; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_STDAFX_H__D450D5ED_5C49_4A8B_B887_076F62424F1F__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/TreeCtrlEx.cpp b/src/smpackagee/TreeCtrlEx.cpp deleted file mode 100644 index 0ff7fb1864..0000000000 --- a/src/smpackagee/TreeCtrlEx.cpp +++ /dev/null @@ -1,183 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// Author: Sami (M.ALSAMSAM), ittiger@ittiger.net -// -// Filename: TreeCtrlEx.cpp -// -// http : www.ittiger.net -// -////////////////////////////////////////////////////////////// -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "TreeCtrlEx.h" - -#ifdef _DEBUG -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#define new DEBUG_NEW -#endif - -////////////////////////////////// -CTreeCtrlEx::CTreeCtrlEx() {} - -CTreeCtrlEx::~CTreeCtrlEx() {} - -////////////////////////////////// -IMPLEMENT_DYNAMIC(CTreeCtrlEx, CTreeCtrl) - -BEGIN_MESSAGE_MAP(CTreeCtrlEx, CTreeCtrl) -//{{AFX_MSG_MAP(CTreeCtrlEx) -ON_WM_PAINT() -//}}AFX_MSG_MAP -END_MESSAGE_MAP() - -////////////////////////////////////////////////////////////////////// -void -CTreeCtrlEx::SetItemFont(HTREEITEM hItem, LOGFONT& logfont) -{ - Color_Font cf; - if (!m_mapColorFont.Lookup(hItem, cf)) - cf.color = (COLORREF)-1; - cf.logfont = logfont; - m_mapColorFont[hItem] = cf; -} - -////////////////////////////////////////////////////////////////////// -void -CTreeCtrlEx::SetItemBold(HTREEITEM hItem, BOOL bBold) -{ - SetItemState(hItem, bBold ? TVIS_BOLD : 0, TVIS_BOLD); -} - -////////////////////////////////////////////////////////////////////// -void -CTreeCtrlEx::SetItemColor(HTREEITEM hItem, COLORREF color) -{ - Color_Font cf; - if (!m_mapColorFont.Lookup(hItem, cf)) - cf.logfont.lfFaceName[0] = '\0'; - cf.color = color; - m_mapColorFont[hItem] = cf; -} - -////////////////////////////////////////////////////////////////////// -BOOL -CTreeCtrlEx::GetItemFont(HTREEITEM hItem, LOGFONT* plogfont) -{ - Color_Font cf; - if (!m_mapColorFont.Lookup(hItem, cf)) - return FALSE; - if (cf.logfont.lfFaceName[0] == '\0') - return FALSE; - *plogfont = cf.logfont; - return TRUE; -} - -////////////////////////////////////////////////////////////////////// -BOOL -CTreeCtrlEx::GetItemBold(HTREEITEM hItem) -{ - return GetItemState(hItem, TVIS_BOLD) & TVIS_BOLD; -} - -////////////////////////////////////////////////////////////////////// -COLORREF -CTreeCtrlEx::GetItemColor(HTREEITEM hItem) -{ - // Returns (COLORREF)-1 if color was not set - Color_Font cf; - if (!m_mapColorFont.Lookup(hItem, cf)) - return (COLORREF)-1; - return cf.color; -} - -////////////////////////////////////////////////////////////////////// -void -CTreeCtrlEx::OnPaint() -{ - CPaintDC dc(this); - - // Create a memory DC compatible with the paint DC - CDC memDC; - memDC.CreateCompatibleDC(&dc); - - CRect rcClip, rcClient; - dc.GetClipBox(&rcClip); - GetClientRect(&rcClient); - - // Select a compatible bitmap into the memory DC - CBitmap bitmap; - bitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height()); - memDC.SelectObject(&bitmap); - - // Set clip region to be same as that in paint DC - CRgn rgn; - rgn.CreateRectRgnIndirect(&rcClip); - memDC.SelectClipRgn(&rgn); - rgn.DeleteObject(); - - // First let the control do its default drawing. - CWnd::DefWindowProc(WM_PAINT, (WPARAM)memDC.m_hDC, 0); - - HTREEITEM hItem = GetFirstVisibleItem(); - - int iItemCount = GetVisibleCount() + 1; - while (hItem && iItemCount--) { - CRect rect; - - // Do not meddle with selected items or drop highlighted items - UINT selflag = TVIS_DROPHILITED | TVIS_SELECTED; - Color_Font cf; - - // if ( !(GetTreeCtrl().GetItemState( hItem, selflag ) & selflag ) - // && m_mapColorFont.Lookup( hItem, cf )) - - if ((GetItemState(hItem, selflag) & selflag) && ::GetFocus() == m_hWnd) - ; - else if (m_mapColorFont.Lookup(hItem, cf)) { - CFont* pFontDC; - CFont fontDC; - LOGFONT logfont; - - if (cf.logfont.lfFaceName[0] != '\0') - logfont = cf.logfont; - else { - // No font specified, so use window font - CFont* pFont = GetFont(); - pFont->GetLogFont(&logfont); - } - - if (GetItemBold(hItem)) - logfont.lfWeight = 700; - - fontDC.CreateFontIndirect(&logfont); - pFontDC = memDC.SelectObject(&fontDC); - - if (cf.color != (COLORREF)-1) - memDC.SetTextColor(cf.color); - else - memDC.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); - - CString sItem = GetItemText(hItem); - - GetItemRect(hItem, &rect, TRUE); - memDC.SetBkColor(GetSysColor(COLOR_WINDOW)); - memDC.TextOut(rect.left + 2, rect.top + 1, sItem); - - memDC.SelectObject(pFontDC); - } - hItem = GetNextVisibleItem(hItem); - } - - dc.BitBlt(rcClip.left, - rcClip.top, - rcClip.Width(), - rcClip.Height(), - &memDC, - rcClip.left, - rcClip.top, - SRCCOPY); - - memDC.DeleteDC(); -} diff --git a/src/smpackagee/TreeCtrlEx.h b/src/smpackagee/TreeCtrlEx.h deleted file mode 100644 index 9103fc973e..0000000000 --- a/src/smpackagee/TreeCtrlEx.h +++ /dev/null @@ -1,51 +0,0 @@ -///////////////////////////////////////////////////////////// -// -// Author: Sami (M.ALSAMSAM), ittiger@ittiger.net -// -// Filename: TreeCtrlEx.h -// -// http : www.ittiger.net -// -////////////////////////////////////////////////////////////// -#if !defined(AFX_TREECTRLEX_H__5D969ED4_7DEA_4FB5_8C1D_E12D1CCF0989__INCLUDED_) -#define AFX_TREECTRLEX_H__5D969ED4_7DEA_4FB5_8C1D_E12D1CCF0989__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include - -////////////////////////////////////////////////////////////////////// -class CTreeCtrlEx : public CTreeCtrl -{ - DECLARE_DYNAMIC(CTreeCtrlEx) - - public: - CTreeCtrlEx(); - virtual ~CTreeCtrlEx(); - - void SetItemFont(HTREEITEM, LOGFONT&); - void SetItemBold(HTREEITEM, BOOL); - void SetItemColor(HTREEITEM, COLORREF); - BOOL GetItemFont(HTREEITEM, LOGFONT*); - BOOL GetItemBold(HTREEITEM); - COLORREF GetItemColor(HTREEITEM); - - protected: - struct Color_Font - { - COLORREF color; - LOGFONT logfont; - }; - - CMap m_mapColorFont; - - protected: - //{{AFX_MSG(CTreeCtrlEx) - afx_msg void OnPaint(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -#endif // !defined(AFX_TREECTRLEX_H__5D969ED4_7DEA_4FB5_8C1D_E12D1CCF0989__INCLUDED_) diff --git a/src/smpackagee/UninstallOld.cpp b/src/smpackagee/UninstallOld.cpp deleted file mode 100644 index 9bca889888..0000000000 --- a/src/smpackagee/UninstallOld.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// UninstallOld.cpp : implementation file -// - -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "UninstallOld.h" -#include "SMPackageUtil.h" -#include "archutils/Win32/DialogUtil.h" - -// UninstallOld dialog - -UninstallOld::UninstallOld(CWnd* pParent /*=NULL*/) - : CDialog(UninstallOld::IDD, pParent) - , m_sPackages(_T("")) -{ -} - -UninstallOld::~UninstallOld() {} - -BOOL -UninstallOld::OnInitDialog() -{ - CDialog::OnInitDialog(); - - DialogUtil::LocalizeDialogAndContents(*this); - - GetDlgItem(IDC_PACKAGES)->SetWindowText(m_sPackages); - - return TRUE; // return TRUE unless you set the focus to a control -} - -BEGIN_MESSAGE_MAP(UninstallOld, CDialog) -//{{AFX_MSG_MAP(UninstallOld) -//}}AFX_MSG_MAP -ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedNo) -END_MESSAGE_MAP() - -// UninstallOld message handlers - -void -UninstallOld::OnOK() -{ - EndDialog(IDOK); -} - -void -UninstallOld::OnCancel() -{ - EndDialog(IDCANCEL); -} - -void -UninstallOld::OnBnClickedNo() -{ - EndDialog(IDIGNORE); -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/UninstallOld.h b/src/smpackagee/UninstallOld.h deleted file mode 100644 index 8d7be352da..0000000000 --- a/src/smpackagee/UninstallOld.h +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -// UninstallOld dialog - -class UninstallOld : public CDialog -{ - public: - UninstallOld(CWnd* pParent = NULL); // standard constructor - virtual ~UninstallOld(); - // Overrides - - // Dialog Data - enum - { - IDD = IDD_UNINSTALL_OLD_PACKAGES - }; - - protected: - virtual BOOL OnInitDialog(); - void OnOK(); - void OnCancel(); - - DECLARE_MESSAGE_MAP() - public: - CString m_sPackages; - afx_msg void OnBnClickedNo(); -}; - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/ZipArchive/Appnote.txt b/src/smpackagee/ZipArchive/Appnote.txt deleted file mode 100644 index ae2eeaf101..0000000000 --- a/src/smpackagee/ZipArchive/Appnote.txt +++ /dev/null @@ -1,1351 +0,0 @@ -File: APPNOTE.TXT - .ZIP File Format Specification -Version: 4.0 -Revised: 11/01/2000 - -Disclaimer ----------- - -Although PKWARE will attempt to supply current and accurate -information relating to its file formats, algorithms, and the -subject programs, the possibility of error can not be eliminated. -PKWARE therefore expressly disclaims any warranty that the -information contained in the associated materials relating to the -subject programs and/or the format of the files created or -accessed by the subject programs and/or the algorithms used by -the subject programs, or any other matter, is current, correct or -accurate as delivered. Any risk of damage due to any possible -inaccurate information is assumed by the user of the information. -Furthermore, the information relating to the subject programs -and/or the file formats created or accessed by the subject -programs and/or the algorithms used by the subject programs is -subject to change without notice. - -General Format of a .ZIP file ------------------------------ - - Files stored in arbitrary order. Large .ZIP files can span multiple - diskette media or be split into user-defined segment sizes. The - minimum user-defined segment size for a split .ZIP file is 64K. - - Overall .ZIP file format: - - [local file header 1] - [file data 1] - [data descriptor 1] - . - . - . - [local file header n] - [file data n] - [data descriptor n] - [central directory] - - - A. Local file header: - - local file header signature 4 bytes (0x04034b50) - version needed to extract 2 bytes - general purpose bit flag 2 bytes - compression method 2 bytes - last mod file time 2 bytes - last mod file date 2 bytes - crc-32 4 bytes - compressed size 4 bytes - uncompressed size 4 bytes - filename length 2 bytes - extra field length 2 bytes - - filename (variable size) - extra field (variable size) - - B. File data - - Immediately following the local header for a file - is the compressed or stored data for the file. - The series of [local file header][file data][data - descriptor] repeats for each file in the .ZIP archive. - - C. Data descriptor: - - crc-32 4 bytes - compressed size 4 bytes - uncompressed size 4 bytes - - This descriptor exists only if bit 3 of the general - purpose bit flag is set (see below). It is byte aligned - and immediately follows the last byte of compressed data. - This descriptor is used only when it was not possible to - seek in the output .ZIP file, e.g., when the output .ZIP file - was standard output or a non seekable device. - - D. Central directory structure: - - [file header 1] - . - . - . - [file header n] - [digital signature] - [end of central directory record] - - File header: - - central file header signature 4 bytes (0x02014b50) - version made by 2 bytes - version needed to extract 2 bytes - general purpose bit flag 2 bytes - compression method 2 bytes - last mod file time 2 bytes - last mod file date 2 bytes - crc-32 4 bytes - compressed size 4 bytes - uncompressed size 4 bytes - filename length 2 bytes - extra field length 2 bytes - file comment length 2 bytes - disk number start 2 bytes - internal file attributes 2 bytes - external file attributes 4 bytes - relative offset of local header 4 bytes - - filename (variable size) - extra field (variable size) - file comment (variable size) - - Digital signature: - - header signature 4 bytes (0x05054b50) - size of data 2 bytes - signature data (variable size) - - End of central directory record: - - end of central dir signature 4 bytes (0x06054b50) - number of this disk 2 bytes - number of the disk with the - start of the central directory 2 bytes - total number of entries in - the central dir on this disk 2 bytes - total number of entries in - the central dir 2 bytes - size of the central directory 4 bytes - offset of start of central - directory with respect to - the starting disk number 4 bytes - .ZIP file comment length 2 bytes - .ZIP file comment (variable size) - - E. Explanation of fields: - - version made by (2 bytes) - - The upper byte indicates the compatibility of the file - attribute information. If the external file attributes - are compatible with MS-DOS and can be read by PKZIP for - DOS version 2.04g then this value will be zero. If these - attributes are not compatible, then this value will - identify the host system on which the attributes are - compatible. Software can use this information to determine - the line record format for text files etc. The current - mappings are: - - 0 - MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) - 1 - Amiga 2 - OpenVMS - 3 - Unix 4 - VM/CMS - 5 - Atari ST 6 - OS/2 H.P.F.S. - 7 - Macintosh 8 - Z-System - 9 - CP/M 10 - Windows NTFS - 11 thru 255 - unused - - The lower byte indicates the version number of the - software used to encode the file. The value/10 - indicates the major version number, and the value - mod 10 is the minor version number. - - version needed to extract (2 bytes) - - The minimum software version needed to extract the - file, mapped as above. - - general purpose bit flag: (2 bytes) - - Bit 0: If set, indicates that the file is encrypted. - - (For Method 6 - Imploding) - Bit 1: If the compression method used was type 6, - Imploding, then this bit, if set, indicates - an 8K sliding dictionary was used. If clear, - then a 4K sliding dictionary was used. - Bit 2: If the compression method used was type 6, - Imploding, then this bit, if set, indicates - 3 Shannon-Fano trees were used to encode the - sliding dictionary output. If clear, then 2 - Shannon-Fano trees were used. - - (For Methods 8 and 9 - Deflating) - Bit 2 Bit 1 - 0 0 Normal (-en) compression option was used. - 0 1 Maximum (-exx/-ex) compression option was used. - 1 0 Fast (-ef) compression option was used. - 1 1 Super Fast (-es) compression option was used. - - Note: Bits 1 and 2 are undefined if the compression - method is any other. - - Bit 3: If this bit is set, the fields crc-32, compressed - size and uncompressed size are set to zero in the - local header. The correct values are put in the - data descriptor immediately following the compressed - data. (Note: PKZIP version 2.04g for DOS only - recognizes this bit for method 8 compression, newer - versions of PKZIP recognize this bit for any - compression method.) - - Bit 4: Reserved for use with method 8, for enhanced - deflating. - - Bit 5: If this bit is set, this indicates that the file is - compressed patched data. (Note: Requires PKZIP - version 2.70 or greater) - - Bit 6: Currently unused. - - Bit 7: Currently unused. - - Bit 8: Currently unused. - - Bit 9: Currently unused. - - Bit 10: Currently unused. - - Bit 11: Currently unused. - - Bit 12: Reserved by PKWARE for enhanced compression. - - Bit 13: Reserved by PKWARE. - - Bit 14: Reserved by PKWARE. - - Bit 15: Reserved by PKWARE. - - compression method: (2 bytes) - - (see accompanying documentation for algorithm - descriptions) - - 0 - The file is stored (no compression) - 1 - The file is Shrunk - 2 - The file is Reduced with compression factor 1 - 3 - The file is Reduced with compression factor 2 - 4 - The file is Reduced with compression factor 3 - 5 - The file is Reduced with compression factor 4 - 6 - The file is Imploded - 7 - Reserved for Tokenizing compression algorithm - 8 - The file is Deflated - 9 - Enhanced Deflating using Deflate64(tm) - 10 - PKWARE Date Compression Library Imploding - - date and time fields: (2 bytes each) - - The date and time are encoded in standard MS-DOS format. - If input came from standard input, the date and time are - those at which compression was started for this data. - - CRC-32: (4 bytes) - - The CRC-32 algorithm was generously contributed by - David Schwaderer and can be found in his excellent - book "C Programmers Guide to NetBIOS" published by - Howard W. Sams & Co. Inc. The 'magic number' for - the CRC is 0xdebb20e3. The proper CRC pre and post - conditioning is used, meaning that the CRC register - is pre-conditioned with all ones (a starting value - of 0xffffffff) and the value is post-conditioned by - taking the one's complement of the CRC residual. - If bit 3 of the general purpose flag is set, this - field is set to zero in the local header and the correct - value is put in the data descriptor and in the central - directory. - - compressed size: (4 bytes) - uncompressed size: (4 bytes) - - The size of the file compressed and uncompressed, - respectively. If bit 3 of the general purpose bit flag - is set, these fields are set to zero in the local header - and the correct values are put in the data descriptor and - in the central directory. - - filename length: (2 bytes) - extra field length: (2 bytes) - file comment length: (2 bytes) - - The length of the filename, extra field, and comment - fields respectively. The combined length of any - directory record and these three fields should not - generally exceed 65,535 bytes. If input came from standard - input, the filename length is set to zero. - - disk number start: (2 bytes) - - The number of the disk on which this file begins. - - internal file attributes: (2 bytes) - - The lowest bit of this field indicates, if set, that - the file is apparently an ASCII or text file. If not - set, that the file apparently contains binary data. - The remaining bits are unused in version 1.0. - - Bits 1 and 2 are reserved for use by PKWARE. - - external file attributes: (4 bytes) - - The mapping of the external attributes is - host-system dependent (see 'version made by'). For - MS-DOS, the low order byte is the MS-DOS directory - attribute byte. If input came from standard input, this - field is set to zero. - - relative offset of local header: (4 bytes) - - This is the offset from the start of the first disk on - which this file appears, to where the local header should - be found. - - filename: (Variable) - - The name of the file, with optional relative path. - The path stored should not contain a drive or - device letter, or a leading slash. All slashes - should be forward slashes '/' as opposed to - backwards slashes '\' for compatibility with Amiga - and Unix file systems etc. If input came from standard - input, there is no filename field. - - extra field: (Variable) - - This is for expansion. If additional information - needs to be stored for special needs or for specific - platforms, it should be stored here. Earlier versions - of the software can then safely skip this file, and - find the next file or header. This field will be 0 - length in version 1.0. - - In order to allow different programs and different types - of information to be stored in the 'extra' field in .ZIP - files, the following structure should be used for all - programs storing data in this field: - - header1+data1 + header2+data2 . . . - - Each header should consist of: - - Header ID - 2 bytes - Data Size - 2 bytes - - Note: all fields stored in Intel low-byte/high-byte order. - - The Header ID field indicates the type of data that is in - the following data block. - - Header ID's of 0 thru 31 are reserved for use by PKWARE. - The remaining ID's can be used by third party vendors for - proprietary usage. - - The current Header ID mappings defined by PKWARE are: - - 0x0007 AV Info - 0x0009 OS/2 - 0x000a NTFS - 0x000c OpenVMS - 0x000d Unix - 0x000f Patch Descriptor - 0x0014 PKCS#7 Store for X.509 Certificates - 0x0015 X.509 Certificate ID and Signature for - individual file - 0x0016 X.509 Certificate ID for Central Directory - - Several third party mappings commonly used are: - - 0x4b46 FWKCS MD5 (see below) - 0x07c8 Macintosh - 0x4341 Acorn/SparkFS - 0x4453 Windows NT security descriptor (binary ACL) - 0x4704 VM/CMS - 0x470f MVS - 0x4c41 OS/2 access control list (text ACL) - 0x4d49 Info-ZIP OpenVMS - 0x5455 extended timestamp - 0x5855 Info-ZIP Unix (original, also OS/2, NT, etc) - 0x6542 BeOS/BeBox - 0x756e ASi Unix - 0x7855 Info-ZIP Unix (new) - 0xfd4a SMS/QDOS - - The Data Size field indicates the size of the following - data block. Programs can use this value to skip to the - next header block, passing over any data blocks that are - not of interest. - - Note: As stated above, the size of the entire .ZIP file - header, including the filename, comment, and extra - field should not exceed 64K in size. - - In case two different programs should appropriate the same - Header ID value, it is strongly recommended that each - program place a unique signature of at least two bytes in - size (and preferably 4 bytes or bigger) at the start of - each data area. Every program should verify that its - unique signature is present, in addition to the Header ID - value being correct, before assuming that it is a block of - known type. - - -OS/2 Extra Field: - - The following is the layout of the OS/2 attributes "extra" - block. (Last Revision 09/05/95) - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (OS/2) 0x0009 2 bytes Tag for this "extra" block type - TSize 2 bytes Size for the following data block - BSize 4 bytes Uncompressed Block Size - CType 2 bytes Compression type - EACRC 4 bytes CRC value for uncompress block - (var) variable Compressed block - - The OS/2 extended attribute structure (FEA2LIST) is - compressed and then stored in it's entirety within this - structure. There will only ever be one "block" of data in - VarFields[]. - - -UNIX Extra Field: - - The following is the layout of the Unix "extra" block. - Note: all fields are stored in Intel low-byte/high-byte - order. - - Value Size Description - ----- ---- ----------- - (UNIX) 0x000d 2 bytes Tag for this "extra" block type - TSize 2 bytes Size for the following data block - Atime 4 bytes File last access time - Mtime 4 bytes File last modification time - Uid 2 bytes File user ID - Gid 2 bytes File group ID - (var) variable Variable length data field - - The variable length data field will contain file type - specific data. Currently the only values allowed are - the original "linked to" file names for hard or symbolic - links, and the major and minor device node numbers for - character and block device nodes. Since device nodes - cannot be either symbolic or hard links, only one set of - variable length data is stored. Link files will have the - name of the original file stored. This name is NOT NULL - terminated. Its size can be determined by checking TSize - - 12. Device entries will have eight bytes stored as two 4 - byte entries (in little endian format). The first entry - will be the major device number, and the second the minor - device number. - - - -OpenVMS Extra Field: - - The following is the layout of the OpenVMS attributes - "extra" block. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (VMS) 0x000c 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the total "extra" block - CRC 4 bytes 32-bit CRC for remainder of the block - Tag1 2 bytes OpenVMS attribute tag value #1 - Size1 2 bytes Size of attribute #1, in bytes - (var.) Size1 Attribute #1 data - . - . - . - TagN 2 bytes OpenVMS attribute tage value #N - SizeN 2 bytes Size of attribute #N, in bytes - (var.) SizeN Attribute #N data - - Rules: - - 1. There will be one or more of attributes present, which - will each be preceded by the above TagX & SizeX values. - These values are identical to the ATR$C_XXXX and - ATR$S_XXXX constants which are defined in ATR.H under - OpenVMS C. Neither of these values will ever be zero. - - 2. No word alignment or padding is performed. - - 3. A well-behaved PKZIP/OpenVMS program should never produce - more than one sub-block with the same TagX value. Also, - there will never be more than one "extra" block of type - 0x000c in a particular directory record. - - -NTFS Extra Field: - - The following is the layout of the NTFS attributes - "extra" block. (Note: At this time the Mtime, Atime - and Ctime values may be used on any WIN32 system.) - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (NTFS) 0x000a 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the total "extra" block - Reserved 4 bytes Reserved for future use - Tag1 2 bytes NTFS attribute tag value #1 - Size1 2 bytes Size of attribute #1, in bytes - (var.) Size1 Attribute #1 data - . - . - . - TagN 2 bytes NTFS attribute tage value #N - SizeN 2 bytes Size of attribute #N, in bytes - (var.) SizeN Attribute #N data - - For NTFS, values for Tag1 through TagN are as follows: - (currently only one set of attributes is defined for NTFS) - - Tag Size Description - ----- ---- ----------- - 0x0001 2 bytes Tag for attribute #1 - Size1 2 bytes Size of attribute #1, in bytes - Mtime 8 bytes File last modification time - Atime 8 bytes File last access time - Ctime 8 bytes File creation time - - -PATCH Descriptor Extra Field: - - The following is the layout of the Patch Descriptor "extra" - block. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (Patch) 0x000f 2 bytes Tag for this "extra" block type - TSize 2 bytes Size of the total "extra" block - Version 2 bytes Version of the descriptor - Flags 4 bytes Actions and reactions (see below) - OldSize 4 bytes Size of the file about to be patched - OldCRC 4 bytes 32-bit CRC of the file to be patched - NewSize 4 bytes Size of the resulting file - NewCRC 4 bytes 32-bit CRC of the resulting file - - Actions and reactions - - Bits Description - ---- ---------------- - 0 Use for autodetection - 1 Treat as selfpatch - 2-3 RESERVED - 4-5 Action (see below) - 6-7 RESERVED - 8-9 Reaction (see below) to absent file - 10-11 Reaction (see below) to newer file - 12-13 Reaction (see below) to unknown file - 14-15 RESERVED - 16-31 RESERVED - - Actions - - Action Value - ------ ----- - none 0 - add 1 - delete 2 - patch 3 - - Reactions - - Reaction Value - -------- ----- - ask 0 - skip 1 - ignore 2 - fail 3 - - -PKCS#7 Store for X.509 Certificates - - This field is contains the information about each - certificate a file is signed with. This field should only - appear in the first central directory record, and will be - ignored in any other record. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (Store) 0x0014 2 bytes Tag for this "extra" block type - SSize 2 bytes Size of the store data - SData (variable) Data about the store - - SData - Value Size Description - ----- ---- ----------- - Version 2 bytes Version number, 0x0001 for now - StoreD (variable) Actual store data - - The StoreD member is suitable for passing as the pbData - member of a CRYPT_DATA_BLOB to the CertOpenStore() function - in Microsoft's CryptoAPI. The SSize member above will be - cbData + 6, where cbData is the cbData member of the same - CRYPT_DATA_BLOB. The encoding type to pass to - CertOpenStore() should be - PKCS_7_ANS_ENCODING | X509_ASN_ENCODING. - - -X.509 Certificate ID and Signature for individual file - - This field contains the information about which certificate - in the PKCS#7 Store was used to sign the particular file. - It also contains the signature data. This field can appear - multiple times, but can only appear once per certificate. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (CID) 0x0015 2 bytes Tag for this "extra" block type - CSize 2 bytes Size of Method - Method (variable) - - Method - Value Size Description - ----- ---- ----------- - Version 2 bytes Version number, for now 0x0001 - AlgID 2 bytes Algorithm ID used for signing - IDSize 2 bytes Size of Certificate ID data - CertID (variable) Certificate ID data - SigSize 2 bytes Size of Signature data - Sig (variable) Signature data - - CertID - Value Size Description - ----- ---- ----------- - Size1 4 bytes Size of CertID, should be (IDSize - 4) - Size1 4 bytes A bug in version one causes this value - to appear twice. - IssSize 4 bytes Issuer data size - Issuer (variable) Issuer data - SerSize 4 bytes Serial Number size - Serial (variable) Serial Number data - - The Issuer and IssSize members are suitable for creating a - CRYPT_DATA_BLOB to be the Issuer member of a CERT_INFO - struct. The Serial and SerSize members would be the - SerialNumber member of the same CERT_INFO struct. This - struct would be used to find the certificate in the store - the file was signed with. Those structures are from the MS - CryptoAPI. - - Sig and SigSize are the actual signature data and size - generated by signing the file with the MS CryptoAPI using a - hash created with the given AlgID. - - -X.509 Certificate ID and Signature for central directory - - This field contains the information about which certificate - in the PKCS#7 Store was used to sign the central directory. - It should only appear with the first central directory - record, along with the store. The data structure is the - same as the CID, except that SigSize will be 0, and there - will be no Sig member. - - This field is also kept after the last central directory - record, as the signature data (ID 0x05054b50, it looks like - a central directory record of a different type). This - second copy of the data is the Signature Data member of the - record, and will have a SigSize that is non-zero, and will - have Sig data. - - Note: all fields stored in Intel low-byte/high-byte order. - - Value Size Description - ----- ---- ----------- - (CDID) 0x0016 2 bytes Tag for this "extra" block type - CSize 2 bytes Size of Method - Method (variable) - - - FWKCS MD5 Extra Field: - - The FWKCS Contents_Signature System, used in - automatically identifying files independent of filename, - optionally adds and uses an extra field to support the - rapid creation of an enhanced contents_signature: - - Header ID = 0x4b46 - Data Size = 0x0013 - Preface = 'M','D','5' - followed by 16 bytes containing the uncompressed file's - 128_bit MD5 hash(1), low byte first. - - When FWKCS revises a .ZIP file central directory to add - this extra field for a file, it also replaces the - central directory entry for that file's uncompressed - filelength with a measured value. - - FWKCS provides an option to strip this extra field, if - present, from a .ZIP file central directory. In adding - this extra field, FWKCS preserves .ZIP file Authenticity - Verification; if stripping this extra field, FWKCS - preserves all versions of AV through PKZIP version 2.04g. - - FWKCS, and FWKCS Contents_Signature System, are - trademarks of Frederick W. Kantor. - - (1) R. Rivest, RFC1321.TXT, MIT Laboratory for Computer - Science and RSA Data Security, Inc., April 1992. - ll.76-77: "The MD5 algorithm is being placed in the - public domain for review and possible adoption as a - standard." - - file comment: (Variable) - - The comment for this file. - - number of this disk: (2 bytes) - - The number of this disk, which contains central - directory end record. - - number of the disk with the start of the central - directory: (2 bytes) - - The number of the disk on which the central - directory starts. - - total number of entries in the central dir on - this disk: (2 bytes) - - The number of central directory entries on this disk. - - total number of entries in the central dir: (2 bytes) - - The total number of files in the .ZIP file. - - size of the central directory: (4 bytes) - - The size (in bytes) of the entire central directory. - - offset of start of central directory with respect to - the starting disk number: (4 bytes) - - Offset of the start of the central directory on the - disk on which the central directory starts. - - .ZIP file comment length: (2 bytes) - - The length of the comment for this .ZIP file. - - .ZIP file comment: (Variable) - - The comment for this .ZIP file. - - F. General notes: - - 1) All fields unless otherwise noted are unsigned and stored - in Intel low-byte:high-byte, low-word:high-word order. - - 2) String fields are not null terminated, since the - length is given explicitly. - - 3) Local headers should not span disk boundaries. Also, even - though the central directory can span disk boundaries, no - single record in the central directory should be split - across disks. - - 4) The entries in the central directory may not necessarily - be in the same order that files appear in the .ZIP file. - - 5) Spanned/Split archives created using PKZIP for Windows - (V2.50 or greater), PKZIP Command Line (V2.50 or greater), - or PKZIP Explorer will include a special spanning - signature as the first 4 bytes of the first segment of - the archive. This signature (0x08074b50) will be - followed immediately by the local header signature for - the first file in the archive. Spanned archives - created with this special signature are compatible with - all versions of PKZIP from PKWARE. Split archives can - only be uncompressed by other versions of PKZIP that - know how to create a split archive. - -UnShrinking - Method 1 ----------------------- - -Shrinking is a Dynamic Ziv-Lempel-Welch compression algorithm -with partial clearing. The initial code size is 9 bits, and -the maximum code size is 13 bits. Shrinking differs from -conventional Dynamic Ziv-Lempel-Welch implementations in several -respects: - -1) The code size is controlled by the compressor, and is not - automatically increased when codes larger than the current - code size are created (but not necessarily used). When - the decompressor encounters the code sequence 256 - (decimal) followed by 1, it should increase the code size - read from the input stream to the next bit size. No - blocking of the codes is performed, so the next code at - the increased size should be read from the input stream - immediately after where the previous code at the smaller - bit size was read. Again, the decompressor should not - increase the code size used until the sequence 256,1 is - encountered. - -2) When the table becomes full, total clearing is not - performed. Rather, when the compressor emits the code - sequence 256,2 (decimal), the decompressor should clear - all leaf nodes from the Ziv-Lempel tree, and continue to - use the current code size. The nodes that are cleared - from the Ziv-Lempel tree are then re-used, with the lowest - code value re-used first, and the highest code value - re-used last. The compressor can emit the sequence 256,2 - at any time. - -Expanding - Methods 2-5 ------------------------ - -The Reducing algorithm is actually a combination of two -distinct algorithms. The first algorithm compresses repeated -byte sequences, and the second algorithm takes the compressed -stream from the first algorithm and applies a probabilistic -compression method. - -The probabilistic compression stores an array of 'follower -sets' S(j), for j=0 to 255, corresponding to each possible -ASCII character. Each set contains between 0 and 32 -characters, to be denoted as S(j)[0],...,S(j)[m], where m<32. -The sets are stored at the beginning of the data area for a -Reduced file, in reverse order, with S(255) first, and S(0) -last. - -The sets are encoded as { N(j), S(j)[0],...,S(j)[N(j)-1] }, -where N(j) is the size of set S(j). N(j) can be 0, in which -case the follower set for S(j) is empty. Each N(j) value is -encoded in 6 bits, followed by N(j) eight bit character values -corresponding to S(j)[0] to S(j)[N(j)-1] respectively. If -N(j) is 0, then no values for S(j) are stored, and the value -for N(j-1) immediately follows. - -Immediately after the follower sets, is the compressed data -stream. The compressed data stream can be interpreted for the -probabilistic decompression as follows: - -let Last-Character <- 0. -loop until done - if the follower set S(Last-Character) is empty then - read 8 bits from the input stream, and copy this - value to the output stream. - otherwise if the follower set S(Last-Character) is non-empty then - read 1 bit from the input stream. - if this bit is not zero then - read 8 bits from the input stream, and copy this - value to the output stream. - otherwise if this bit is zero then - read B(N(Last-Character)) bits from the input - stream, and assign this value to I. - Copy the value of S(Last-Character)[I] to the - output stream. - - assign the last value placed on the output stream to - Last-Character. -end loop - -B(N(j)) is defined as the minimal number of bits required to -encode the value N(j)-1. - -The decompressed stream from above can then be expanded to -re-create the original file as follows: - -let State <- 0. - -loop until done - read 8 bits from the input stream into C. - case State of - 0: if C is not equal to DLE (144 decimal) then - copy C to the output stream. - otherwise if C is equal to DLE then - let State <- 1. - - 1: if C is non-zero then - let V <- C. - let Len <- L(V) - let State <- F(Len). - otherwise if C is zero then - copy the value 144 (decimal) to the output stream. - let State <- 0 - - 2: let Len <- Len + C - let State <- 3. - - 3: move backwards D(V,C) bytes in the output stream - (if this position is before the start of the output - stream, then assume that all the data before the - start of the output stream is filled with zeros). - copy Len+3 bytes from this position to the output stream. - let State <- 0. - end case -end loop - -The functions F,L, and D are dependent on the 'compression -factor', 1 through 4, and are defined as follows: - -For compression factor 1: - L(X) equals the lower 7 bits of X. - F(X) equals 2 if X equals 127 otherwise F(X) equals 3. - D(X,Y) equals the (upper 1 bit of X) * 256 + Y + 1. -For compression factor 2: - L(X) equals the lower 6 bits of X. - F(X) equals 2 if X equals 63 otherwise F(X) equals 3. - D(X,Y) equals the (upper 2 bits of X) * 256 + Y + 1. -For compression factor 3: - L(X) equals the lower 5 bits of X. - F(X) equals 2 if X equals 31 otherwise F(X) equals 3. - D(X,Y) equals the (upper 3 bits of X) * 256 + Y + 1. -For compression factor 4: - L(X) equals the lower 4 bits of X. - F(X) equals 2 if X equals 15 otherwise F(X) equals 3. - D(X,Y) equals the (upper 4 bits of X) * 256 + Y + 1. - -Imploding - Method 6 --------------------- - -The Imploding algorithm is actually a combination of two distinct -algorithms. The first algorithm compresses repeated byte -sequences using a sliding dictionary. The second algorithm is -used to compress the encoding of the sliding dictionary output, -using multiple Shannon-Fano trees. - -The Imploding algorithm can use a 4K or 8K sliding dictionary -size. The dictionary size used can be determined by bit 1 in the -general purpose flag word; a 0 bit indicates a 4K dictionary -while a 1 bit indicates an 8K dictionary. - -The Shannon-Fano trees are stored at the start of the compressed -file. The number of trees stored is defined by bit 2 in the -general purpose flag word; a 0 bit indicates two trees stored, a -1 bit indicates three trees are stored. If 3 trees are stored, -the first Shannon-Fano tree represents the encoding of the -Literal characters, the second tree represents the encoding of -the Length information, the third represents the encoding of the -Distance information. When 2 Shannon-Fano trees are stored, the -Length tree is stored first, followed by the Distance tree. - -The Literal Shannon-Fano tree, if present is used to represent -the entire ASCII character set, and contains 256 values. This -tree is used to compress any data not compressed by the sliding -dictionary algorithm. When this tree is present, the Minimum -Match Length for the sliding dictionary is 3. If this tree is -not present, the Minimum Match Length is 2. - -The Length Shannon-Fano tree is used to compress the Length part -of the (length,distance) pairs from the sliding dictionary -output. The Length tree contains 64 values, ranging from the -Minimum Match Length, to 63 plus the Minimum Match Length. - -The Distance Shannon-Fano tree is used to compress the Distance -part of the (length,distance) pairs from the sliding dictionary -output. The Distance tree contains 64 values, ranging from 0 to -63, representing the upper 6 bits of the distance value. The -distance values themselves will be between 0 and the sliding -dictionary size, either 4K or 8K. - -The Shannon-Fano trees themselves are stored in a compressed -format. The first byte of the tree data represents the number of -bytes of data representing the (compressed) Shannon-Fano tree -minus 1. The remaining bytes represent the Shannon-Fano tree -data encoded as: - - High 4 bits: Number of values at this bit length + 1. (1 - 16) - Low 4 bits: Bit Length needed to represent value + 1. (1 - 16) - -The Shannon-Fano codes can be constructed from the bit lengths -using the following algorithm: - -1) Sort the Bit Lengths in ascending order, while retaining the - order of the original lengths stored in the file. - -2) Generate the Shannon-Fano trees: - - Code <- 0 - CodeIncrement <- 0 - LastBitLength <- 0 - i <- number of Shannon-Fano codes - 1 (either 255 or 63) - - loop while i >= 0 - Code = Code + CodeIncrement - if BitLength(i) <> LastBitLength then - LastBitLength=BitLength(i) - CodeIncrement = 1 shifted left (16 - LastBitLength) - ShannonCode(i) = Code - i <- i - 1 - end loop - -3) Reverse the order of all the bits in the above ShannonCode() - vector, so that the most significant bit becomes the least - significant bit. For example, the value 0x1234 (hex) would - become 0x2C48 (hex). - -4) Restore the order of Shannon-Fano codes as originally stored - within the file. - -Example: - - This example will show the encoding of a Shannon-Fano tree - of size 8. Notice that the actual Shannon-Fano trees used - for Imploding are either 64 or 256 entries in size. - -Example: 0x02, 0x42, 0x01, 0x13 - - The first byte indicates 3 values in this table. Decoding the - bytes: - 0x42 = 5 codes of 3 bits long - 0x01 = 1 code of 2 bits long - 0x13 = 2 codes of 4 bits long - - This would generate the original bit length array of: - (3, 3, 3, 3, 3, 2, 4, 4) - - There are 8 codes in this table for the values 0 thru 7. Using - the algorithm to obtain the Shannon-Fano codes produces: - - Reversed Order Original -Val Sorted Constructed Code Value Restored Length ---- ------ ----------------- -------- -------- ------ -0: 2 1100000000000000 11 101 3 -1: 3 1010000000000000 101 001 3 -2: 3 1000000000000000 001 110 3 -3: 3 0110000000000000 110 010 3 -4: 3 0100000000000000 010 100 3 -5: 3 0010000000000000 100 11 2 -6: 4 0001000000000000 1000 1000 4 -7: 4 0000000000000000 0000 0000 4 - -The values in the Val, Order Restored and Original Length columns -now represent the Shannon-Fano encoding tree that can be used for -decoding the Shannon-Fano encoded data. How to parse the -variable length Shannon-Fano values from the data stream is beyond -the scope of this document. (See the references listed at the end of -this document for more information.) However, traditional decoding -schemes used for Huffman variable length decoding, such as the -Greenlaw algorithm, can be successfully applied. - -The compressed data stream begins immediately after the -compressed Shannon-Fano data. The compressed data stream can be -interpreted as follows: - -loop until done - read 1 bit from input stream. - - if this bit is non-zero then (encoded data is literal data) - if Literal Shannon-Fano tree is present - read and decode character using Literal Shannon-Fano tree. - otherwise - read 8 bits from input stream. - copy character to the output stream. - otherwise (encoded data is sliding dictionary match) - if 8K dictionary size - read 7 bits for offset Distance (lower 7 bits of offset). - otherwise - read 6 bits for offset Distance (lower 6 bits of offset). - - using the Distance Shannon-Fano tree, read and decode the - upper 6 bits of the Distance value. - - using the Length Shannon-Fano tree, read and decode - the Length value. - - Length <- Length + Minimum Match Length - - if Length = 63 + Minimum Match Length - read 8 bits from the input stream, - add this value to Length. - - move backwards Distance+1 bytes in the output stream, and - copy Length characters from this position to the output - stream. (if this position is before the start of the output - stream, then assume that all the data before the start of - the output stream is filled with zeros). -end loop - -Tokenizing - Method 7 --------------------- - -This method is not used by PKZIP. - -Deflating - Method 8 ------------------ - -The Deflate algorithm is similar to the Implode algorithm using -a sliding dictionary of up to 32K with secondary compression -from Huffman/Shannon-Fano codes. - -The compressed data is stored in blocks with a header describing -the block and the Huffman codes used in the data block. The header -format is as follows: - - Bit 0: Last Block bit This bit is set to 1 if this is the last - compressed block in the data. - Bits 1-2: Block type - 00 (0) - Block is stored - All stored data is byte aligned. - Skip bits until next byte, then next word = block - length, followed by the ones compliment of the block - length word. Remaining data in block is the stored - data. - - 01 (1) - Use fixed Huffman codes for literal and distance codes. - Lit Code Bits Dist Code Bits - --------- ---- --------- ---- - 0 - 143 8 0 - 31 5 - 144 - 255 9 - 256 - 279 7 - 280 - 287 8 - - Literal codes 286-287 and distance codes 30-31 are - never used but participate in the huffman construction. - - 10 (2) - Dynamic Huffman codes. (See expanding Huffman codes) - - 11 (3) - Reserved - Flag a "Error in compressed data" if seen. - -Expanding Huffman Codes ------------------------ -If the data block is stored with dynamic Huffman codes, the Huffman -codes are sent in the following compressed format: - - 5 Bits: # of Literal codes sent - 256 (256 - 286) - All other codes are never sent. - 5 Bits: # of Dist codes - 1 (1 - 32) - 4 Bits: # of Bit Length codes - 3 (3 - 19) - -The Huffman codes are sent as bit lengths and the codes are built as -described in the implode algorithm. The bit lengths themselves are -compressed with Huffman codes. There are 19 bit length codes: - - 0 - 15: Represent bit lengths of 0 - 15 - 16: Copy the previous bit length 3 - 6 times. - The next 2 bits indicate repeat length (0 = 3, ... ,3 = 6) - Example: Codes 8, 16 (+2 bits 11), 16 (+2 bits 10) will - expand to 12 bit lengths of 8 (1 + 6 + 5) - 17: Repeat a bit length of 0 for 3 - 10 times. (3 bits of length) - 18: Repeat a bit length of 0 for 11 - 138 times (7 bits of length) - -The lengths of the bit length codes are sent packed 3 bits per value -(0 - 7) in the following order: - - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - -The Huffman codes should be built as described in the Implode algorithm -except codes are assigned starting at the shortest bit length, i.e. the -shortest code should be all 0's rather than all 1's. Also, codes with -a bit length of zero do not participate in the tree construction. The -codes are then used to decode the bit lengths for the literal and -distance tables. - -The bit lengths for the literal tables are sent first with the number -of entries sent described by the 5 bits sent earlier. There are up -to 286 literal characters; the first 256 represent the respective 8 -bit character, code 256 represents the End-Of-Block code, the remaining -29 codes represent copy lengths of 3 thru 258. There are up to 30 -distance codes representing distances from 1 thru 32k as described -below. - - Length Codes - ------------ - Extra Extra Extra Extra - Code Bits Length Code Bits Lengths Code Bits Lengths Code Bits Length(s) - ---- ---- ------ ---- ---- ------- ---- ---- ------- ---- ---- --------- - 257 0 3 265 1 11,12 273 3 35-42 281 5 131-162 - 258 0 4 266 1 13,14 274 3 43-50 282 5 163-194 - 259 0 5 267 1 15,16 275 3 51-58 283 5 195-226 - 260 0 6 268 1 17,18 276 3 59-66 284 5 227-257 - 261 0 7 269 2 19-22 277 4 67-82 285 0 258 - 262 0 8 270 2 23-26 278 4 83-98 - 263 0 9 271 2 27-30 279 4 99-114 - 264 0 10 272 2 31-34 280 4 115-130 - - Distance Codes - -------------- - Extra Extra Extra Extra - Code Bits Dist Code Bits Dist Code Bits Distance Code Bits Distance - ---- ---- ---- ---- ---- ------ ---- ---- -------- ---- ---- -------- - 0 0 1 8 3 17-24 16 7 257-384 24 11 4097-6144 - 1 0 2 9 3 25-32 17 7 385-512 25 11 6145-8192 - 2 0 3 10 4 33-48 18 8 513-768 26 12 8193-12288 - 3 0 4 11 4 49-64 19 8 769-1024 27 12 12289-16384 - 4 1 5,6 12 5 65-96 20 9 1025-1536 28 13 16385-24576 - 5 1 7,8 13 5 97-128 21 9 1537-2048 29 13 24577-32768 - 6 2 9-12 14 6 129-192 22 10 2049-3072 - 7 2 13-16 15 6 193-256 23 10 3073-4096 - -The compressed data stream begins immediately after the -compressed header data. The compressed data stream can be -interpreted as follows: - -do - read header from input stream. - - if stored block - skip bits until byte aligned - read count and 1's compliment of count - copy count bytes data block - otherwise - loop until end of block code sent - decode literal character from input stream - if literal < 256 - copy character to the output stream - otherwise - if literal = end of block - break from loop - otherwise - decode distance from input stream - - move backwards distance bytes in the output stream, and - copy length characters from this position to the output - stream. - end loop -while not last block - -if data descriptor exists - skip bits until byte aligned - read crc and sizes -endif - -Decryption ----------- - -The encryption used in PKZIP was generously supplied by Roger -Schlafly. PKWARE is grateful to Mr. Schlafly for his expert -help and advice in the field of data encryption. - -PKZIP encrypts the compressed data stream. Encrypted files must -be decrypted before they can be extracted. - -Each encrypted file has an extra 12 bytes stored at the start of -the data area defining the encryption header for that file. The -encryption header is originally set to random values, and then -itself encrypted, using three, 32-bit keys. The key values are -initialized using the supplied encryption password. After each byte -is encrypted, the keys are then updated using pseudo-random number -generation techniques in combination with the same CRC-32 algorithm -used in PKZIP and described elsewhere in this document. - -The following is the basic steps required to decrypt a file: - -1) Initialize the three 32-bit keys with the password. -2) Read and decrypt the 12-byte encryption header, further - initializing the encryption keys. -3) Read and decrypt the compressed data stream using the - encryption keys. - -Step 1 - Initializing the encryption keys ------------------------------------------ - -Key(0) <- 305419896 -Key(1) <- 591751049 -Key(2) <- 878082192 - -loop for i <- 0 to length(password)-1 - update_keys(password(i)) -end loop - -Where update_keys() is defined as: - -update_keys(char): - Key(0) <- crc32(key(0),char) - Key(1) <- Key(1) + (Key(0) & 000000ffH) - Key(1) <- Key(1) * 134775813 + 1 - Key(2) <- crc32(key(2),key(1) >> 24) -end update_keys - -Where crc32(old_crc,char) is a routine that given a CRC value and a -character, returns an updated CRC value after applying the CRC-32 -algorithm described elsewhere in this document. - -Step 2 - Decrypting the encryption header ------------------------------------------ - -The purpose of this step is to further initialize the encryption -keys, based on random data, to render a plaintext attack on the -data ineffective. - -Read the 12-byte encryption header into Buffer, in locations -Buffer(0) thru Buffer(11). - -loop for i <- 0 to 11 - C <- buffer(i) ^ decrypt_byte() - update_keys(C) - buffer(i) <- C -end loop - -Where decrypt_byte() is defined as: - -unsigned char decrypt_byte() - local unsigned short temp - temp <- Key(2) | 2 - decrypt_byte <- (temp * (temp ^ 1)) >> 8 -end decrypt_byte - -After the header is decrypted, the last 1 or 2 bytes in Buffer -should be the high-order word/byte of the CRC for the file being -decrypted, stored in Intel low-byte/high-byte order. Versions of -PKZIP prior to 2.0 used a 2 byte CRC check; a 1 byte CRC check is -used on versions after 2.0. This can be used to test if the password -supplied is correct or not. - -Step 3 - Decrypting the compressed data stream ----------------------------------------------- - -The compressed data stream can be decrypted as follows: - -loop until done - read a character into C - Temp <- C ^ decrypt_byte() - update_keys(temp) - output Temp -end loop - -In addition to the above mentioned contributors to PKZIP and PKUNZIP, -I would like to extend special thanks to Robert Mahoney for suggesting -the extension .ZIP for this software. - -References: - - Fiala, Edward R., and Greene, Daniel H., "Data compression with - finite windows", Communications of the ACM, Volume 32, Number 4, - April 1989, pages 490-505. - - Held, Gilbert, "Data Compression, Techniques and Applications, - Hardware and Software Considerations", John Wiley & Sons, 1987. - - Huffman, D.A., "A method for the construction of minimum-redundancy - codes", Proceedings of the IRE, Volume 40, Number 9, September 1952, - pages 1098-1101. - - Nelson, Mark, "LZW Data Compression", Dr. Dobbs Journal, Volume 14, - Number 10, October 1989, pages 29-37. - - Nelson, Mark, "The Data Compression Book", M&T Books, 1991. - - Storer, James A., "Data Compression, Methods and Theory", - Computer Science Press, 1988 - - Welch, Terry, "A Technique for High-Performance Data Compression", - IEEE Computer, Volume 17, Number 6, June 1984, pages 8-19. - - Ziv, J. and Lempel, A., "A universal algorithm for sequential data - compression", Communications of the ACM, Volume 30, Number 6, - June 1987, pages 520-540. - - Ziv, J. and Lempel, A., "Compression of individual sequences via - variable-rate coding", IEEE Transactions on Information Theory, - Volume 24, Number 5, September 1978, pages 530-536. diff --git a/src/smpackagee/ZipArchive/ChangeLog.txt b/src/smpackagee/ZipArchive/ChangeLog.txt deleted file mode 100644 index 9f4d092f99..0000000000 --- a/src/smpackagee/ZipArchive/ChangeLog.txt +++ /dev/null @@ -1,322 +0,0 @@ -/** \page pageHist Revision history - - ver 2.3.4 (06-2003) - - Bug fixed: - - - problems with extracting some archives (very rare) (thanks to Ben Jos Walbeehm for the fix) - - problems with extracting some archives created under Linux (thanks to Jürgen Marquardt for reporting) - - small compilation errors under MSVC++ .NET (thanks to Darren Whobrey for the fixes) - - setting password in zippie (thanks to Amnon David for the fix) - - Changes: - - - CZipArchive::TestFile throws an exception now if CZipArchive::CloseFile returned -1. It makes it work as described in the documentation that an exception is thrown when the file is corrupted (thanks to Silvio Scarpati for pointing this out). - - it is now possible to add an already opened file to an archive (thanks to Kristjan Bjarnason for the change) - - ver 2.3.3 (01-2003) - - Features added: - - - CZipArchive::m_bRemoveDriveLetter option added - - Bugs fixed: - - - not extracting files from the last volume when opening an existing archive created in TDSpan mode, where the last volume filename has other extension than ".zip" - - added PKZIP_BUG_WORKAROUND definition to the zlib.h file distributed with ZipArchive library as well as to ZipArchive project files (in case the zlib library is replaced with a new version). - It deals with pkzip bug existing in some archives (thanks to Ben Jos Walbeehm for reporting). - - ver 2.3.2 (08-2002) - - Bug fixed: - - - problem with creating disk spanning archives in the STL version of the library (thanks to Luiz Rafael Culik for reporting) - - ver 2.3.1 (05-2002) - - Bug fixed: - - - using CZipMemFile::CZipMemFile(BYTE* , UINT , long ) constructor could cause memory errors (thanks to Laurent Doré) - - ver 2.3 (04-2002) (includes changes and fixes from 2.2a to 2.2c) - - Features added: - - - Visual Studio .NET compatibility - - methods CZipArchive::GetFromArchive added, which allow copying files from another archive without decompressing them - - many times requested replacing of files in the archive feature; it works with methods CZipArchive::GetFromArchive and a new - CZipArchive::AddNewFile(CZipAddNewFileInfo& ) which was introduced due to increasing parameters count - - added method CZipArchive::RenameFile which renames a file in the archive maintaining its physical position inside the archive - - projects and necessary changes for compiling ZipArchive as a DLL version (courtesy of Jonathan Reis) - see \ref subsDLL and \ref subDLLnotes -
( they are not embedded into existing ones, but made separated, since the DLL version needs separated project for zlib.dll and for the static version, - zlib library is already included in the projects to minimize linking problems with applications) - - added CZipArchive::WillBeDuplicated which lets you check quickly if the given filename would duplicate an existing one in the archive - - CZipArchive::GetCount has now an additional parameter and can return the number of files in the archive not counting the directories - - CZipArchive::Close has been given also an additional parameter (\e bUpdateTimeStamp) and can set the modification time of the zip archive to the modification time of the newest file inside the archive - - method CZipArchive::GetIndexes added - - ZipArc application updated to support renaming, replacing (as well as updating files in the archive) and getting compressed files from another archive - - Changes: - - zlib library updated to version 1.1.4 that fixes the security vulnerability in version 1.1.3 - as described in - \htmlonly - http://www.zlib.org/advisory-2002-03-11.txt - \endhtmlonly - - if the file inside the archive has the wrong date/time stamp set, then the extracted file is given the current time instead of reporting an error - - a little change in CZipArchive::PredictFileNameInZip : parameter \e bAnsiOem changed to \e bExactly (apart from the name, the meaning has also been changed) - - removed parameter bFileNameOnly from CZipArchive::DeleteFiles(const CZipStringArray &); - - Bugs fixed: - - eliminated possible errors when using CZipArchive::zipsmCheckForEff with disk-spanning mode - - reading some files created with other archivers failed occasionally in CZipFileHeader::ReadLocal (thanks to Christian von Seydlitz) - - while a file recompression (smartness level included CZipArchive::zipsmCheckForEff) if the - AutoFlush feature was enabled, there were redundant bytes added to the archive (thanks to Roman Scherzer) - - aborting extraction of multi-disk archive caused errors (thanks to Sabina Terenzi) - - some GUI fixes in ZipArc - - Known issues: - - under Windows XP, in TD disk spanning mode, when the central directory is not entirely - written on the last volume (but divided between volumes), \e SHGetFileInfo hangs up (it is used i.e. by \e CFileDialog::DoModal) - Windows probably tries to analize - zip structure, but fails becuase it is an additional feature of ZipArchive library to create multi volume archives on non-removable data storage - - ver 2.2 (10-2001) Time for global changes - - Features added: - - deleting multiple files from the archive is now way faster - the files are not - deleted separately as it was so far, but the library creates a map of holes and continuous areas and moves the data to remain in file over the holes; it means that the data is copied - only once and not for every file to delete. - - callback functions has been replaced by functional objects to make the code cleaner and to make it possible to pass more information during a callback call (see: CZipArchive::SetCallback). The same application written using the library with callback functions - and then with functional objects as callbacks (slightly modified) has proven to be circa 15% faster in the latter case (that's why it's in \e features), i.a. because only data that changes is passed to the callback method, method derived from CZipCallback::Callback can be inlined if defined inside the class declaration). Important issues: - - it affects the following functions parameters: - - CZipArchive::AddNewFile, - - CZipArchive::ExtractFile, - - CZipArchive::TestFile, - - CZipArchive::SetSpanCallback - - the meaning of the parameters passed to a callback functor is different from that what has so far been passed to the callback functions - (see CZipCallback) - - see \ref sectCallb if you're not sure how to use functors - - added callback feature when deleting files - - added callback feature when saving central directory - - added possibility to extract or delete files which filenames match the specified wildcard pattern (see CZipArchive::FindMatches) - - iterating the central directory elements speeded up (hence all the operations that iterate the central directory were speeded up, especially sorting, multiple adding, extracting, testing) - - the library now doesn't throw an exception if the platform the archive was created under is not supported, but it tries to distinguish files from directories - - CZipArchive::Flush can be called now for a disk-spanning archive in creation finalizing it then, and yet allows extracting or testing (see the function description for more) - - function CZipArchive::CloseNewFile can be called after an exception to allow to repair the archive later - - adding files with one of CZipArchive::AddNewFile functions can be safely aborted in a non-disk-spanning archive (the added data is removed from the archive) - - added function CZipException::GetErrorMessage for compatibility with MFC \c CException::GetErrorMessage - - added parameter \e bForce to CZipArchive::SetTempPath that creates the directory if it doesn't exists - - the archive created with the library under Windows can be now correctly extracted under Linux and vice versa without the need for setting the system compatibility of the files - - function CZipArchive::SetIgnoreCRC added to make possible working with the Java TM Archives (jar) - - function CZipArchive::GetFindFastIndex added - - function CZipArchive::GetCentralDirInfo added - - function CZipArchive::GetCentralDirSize added - - function CZipArchive::GetCurrentDisk added - - function CZipArchive::IsReadOnly added - - function CZipFileHeader::CompressionEfficient added - - function CZipFileHeader::GetCompressionRatio added - - \c const keywords added to functions - - TRACE messages are now easier to locate in MSVC++ (double clicking gets you directly to the code now) - - - - Changes: - - if the callback functor's method \c Callback returns \c false, - a CZipException is thrown with code CZipException::abortedAction or CZipException::abortedSafely; - - function CZipArchive::DeleteFiles(const CZipStringArray) uses now FindFast array; added \e bFileNameOnly parameter - - function CZipArchive::GetNoEntries renamed to GetCount (more standard, easier to type and easier to find at the beginning) - - the encrypted file is not recompressed again if the difference in sizes before and after compression is the - length of the encryption header - - function CZipArchive::OpenFile throws exception CZipException::badPassword if the password - was not set for the encrypted file instead of returning \c false; - - versioning shortened - - - Bugs fixed: - - CZipStorage::Flush doesn't call now m_pFile->Flush() (it has proven to slow - down the archive creation speed significantly) - it is called in different places instead - - CZipArchive::TestFile sometimes was not detecting wrong password set - - filenames in zip are now correctly converted after calling CZipArchive::Flush - - fixed value of CZipArchive::zipsmCheckForEffInMem; the bug cause the temporary file to be always created in memory - - ZipPlatform::GetDeviceFreeSpace was not working on Windows with other devices than removable (in spite of what is written in MSDN - it is sometimes needed to add slash when passing drive name to \c GetDiskFreeSpace and sometimes not). - I'm not sure if this bug concerned all Windows platforms (it was detected on Windows 2000) - - crash eliminated when the file modification time could not be retrieved (in case of an impossible value e.g. a year is 28980) - - Unix attributes corrected - - CZipArchive::ExtractFile had wrong value passed to the callback function - - ver 2.1.1 (10-2001) - - Features added: - - - Linux version at the beta stage (thanks to Luiz Rafael Culik for help) - - smart and efficient compression added to CZipArchive::AddNewFile
- i.a. optional compression to a temporary file first or to memory, in a disk spanning mode, - to see whether the file is smaller after compression and if it is not - then add it without the compression (see also CZipArchive::Smartness) - - integration of the help system with MSDN made possible (see: \ref sectHelp) - - adding a file with the user-specified filename in zip ( CZipArchive::AddNewFile(LPCTSTR , LPCTSTR , int , int , unsigned long ) ) - - adding files from memory and extracting files to memory - ( CZipArchive::AddNewFile(CZipMemFile&, LPCTSTR, int, int, unsigned long) and - CZipArchive::ExtractFile(WORD, CZipMemFile&, DWORD)) - - function CZipArchive::Flush added - increases the safety when working with zip archives (thanks to Brad Kremer for the idea) - - function CZipArchive::SetCaseSensitivity added (see the function description which functions it affects) - - function CZipArchive::PredictFileNameInZip added - - function CZipArchive::PredictExtractedFileName added - - function CZipArchive::FindFile speeded up again, the case-sensitivity parameter meaning changed, added possibility to find a filename only without a path (see the function description) - - function CZipArchive::TrimRootPath function improved - - function CZipArchive::Close allows now to write the central directory to the archive even after exception, which lets you e.g. repair the archive later - - obtaining error descriptions (English only) - see CZipException::GetErrorDescription() - - STL sample application added (a command line archiver which works for both Windows and Linux; located in \e stl/zippie) - - in TestZipDlg sample application added switch in options to allow an effective compression - - several minor enhancements - - Changes: - - - CZipPathComponent functions renamed : GetFullFileName -> GetFileName, GetFileName -> GetFileTitle, SetFileName -> SetFileTitle - - file \e __[...].zcfg is created depending on the current configuration when using scripts to copy files (see a note at \ref secCompil) - - Bugs fixed: - - - when performing a non-case-sensitive search with CZipArchive::FindFile (thanks to Kenny Prole) - - in CZipString (STL) when using a different locale than English and - non-English characters (see \ref stlNotes for info on how to set your locale in the program) - - CZipStorage::Flush call now m_pFile->Flush() as well (it might have caused a zip creation problems sometimes) - - ver 1.6.6 (08-2001) - - Features added: - - - CZipPathComponent understands now a UNC path, so it is possible to - extract files over a network (other operations over a network were - already possible) - - sample application updated to reflect previous (ver 1.6.5) and - current changes (necessary prefix added to a UNC path following - the Windows File Name Conventions : see \ref q11 "FAQ") - - - ver 1.6.5 (07-2001) - - Features added: - - - added function CZipArchive::SetRootPath that allows more flexible path - manipulations when using CZipArchive::AddNewFile and CZipArchive::ExtractFile - - ability to set the archive system compatibility to a value different - than the current system ID with the function CZipArchive::SetSystemCompatibility() - - Bugs fixed: - - - bug which caused not updating the time stamp of an extracted file - and an exception being thrown, if the file had the read-only attribute set - (thanks to Arnon Meydav) - - bugs in conversion of Unix attributes - - directories inside the archive are now recognized properly by Unix archivers - if the archive was created for Unix platform - - - ver 1.6.4 (06-2001) - - - fixed errors that made impossible using CZipMemFile class and - creation of the archives in memory - - - - ver 1.6.3 (05-2001) - - - zlib library sources incorporated into ZipArchive library projects -(eliminates most often link errors) - - - ver 1.6.2 (04-2001) - - - ZipPlatform::SetVolLabel() appends now a directory separator to the drive name (lack of it caused errors sometimes) - - added a simple protection against compiling MFC or STL version without copying the proper files first - - added several preprocessor directives for Borland compilers - - - ver 1.6.1 (03-2001) - - Features added: - - - non MFC dependent version (STL) - - porting to different platforms made easier - - possibility to read zip files created on other platforms than Windows - (correct interpretation of file/directory attributes) - - documentation generated (using - \htmlonly - Doxygen - \endhtmlonly - ) - - Changes: - - - LICENSING CHANGED - - overall tuning - - sample application updated - - ver 1.5.1 (02-2001) - - - Features added: - - - ability to reuse the archive after an exception thrown during extraction - - added progress control possibilities to CZipArchive::AddNewFile, CZipArchive::ExtractFile, CZipArchive::TestFile - - when the central directory was not located, the library throws CZipException::cdirNotFound, which allows distinguish from other exceptions (useful when we want to keep prompting the user to insert the last disk in a multi-disk spanning archive). - - - Changes: - - - CZipArchive::FindFile operation boosted ( thanks to Darin Warling) - - library name changed to ZipArchive - - the sample application updated - - Bugs fixed: - - - removed bug during extracting an encrypted file with 0 size - - fixed bug when extracting a file with an extra field in a local file header (CFileHeader::ReadLocal) - - ver 1.4.1 (01-2001) - - Disk numbering in a disk spanning archive begins now from PKBACK# 001 not PKBACK# 000 - - Adding and extracting without a full path possible in CZipArchive::AddNewFile and CZipArchive::ExtractFile. - - Several minor changes and enhancements - - Changed names for several classes. - - ver 1.3.1 (11-2000) - - - Testing the archive made easier - - Added support for password encryption and decryption. The encryption used in PKZIP was generously supplied by Roger Schlafly. - - Unicode support added - - ver 1.2.2 (08-2000) - - Bugs fixed - - ver 1.2.1 (06-2000) -\par - the code has been completely rewritten from the very beginning; - the main improvements are: - - multi-disk archive support - - creation of the disk spanning archives with the user-defined volume size - - ability to modify existing archives (add, delete files) - - modification self-extracting archives - - write buffer used for faster disk write operations - - one class for zip and unzip functions - - fast adding, deleting and extracting files with a single function call - - ver 1.1.2 (03-2000) - - international characters in filenames inside archive are now - converted in a compatible way with other archiving programs (they are stored - converted to OEM inside archive). - - ver 1.1.1 (01-2000) -\par - the first version; it is just modified code from zip.c and unzip.c files - written by Gilles Vollant and distributed with zlib library; - the modifications are as follows: - - added class' wrappers - - several bugs fixed - - several enhancements added - - MFC support added - - memory leaks eliminated when write error occurred - - automatically free used memory on destruction or exception - - modern error notification using exceptions - -*/ diff --git a/src/smpackagee/ZipArchive/License.txt b/src/smpackagee/ZipArchive/License.txt deleted file mode 100644 index ae3039860c..0000000000 --- a/src/smpackagee/ZipArchive/License.txt +++ /dev/null @@ -1,73 +0,0 @@ -/** \page pageLic Licensing information - -ZipArchive library - creation, modification and decompression of "zip" format archives
-Copyright © 2000 - 2003 Tadeusz Dracz.
-E-Mail: \htmlonly tdracz@artpol-software.com
-Web: http://www.artpol-software.com \endhtmlonly - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -
-************************************************************************* -An English version of the \ref pageGPL "GNU GPL" is in the %gpl.txt file distributed with -this project. Translations to other languages are available at: -\htmlonly -http://www.gnu.org/copyleft/gpl.html -\endhtmlonly - - -Distributing ZipArchive under GNU GPL implies ZipArchive can only be used -with software that is licensed under conditions compliant with the GPL. -Embedding in proprietary software requires an alternative license. - - -\section s1 Alternative license for use with proprietary software - - -If you want to distribute software in a commercial context that incorporates -ZipArchive and you do not want to meet the conditions of GNU GPL -(e.g. an obligation to provide a customer with the source code of your -software that uses the ZipArchive library), you need to have a commercial license. -- The commercial license provides you with the same rights as the GNU GPL, but in -addition allows you to embed ZipArchive library in proprietary software without -affecting the copyright of this software (it removes the GNU GPL obligation -to publish the source code) -- The license gives you royalty free distribution rights -- The license does not allow you to transfer these rights -- The license is granted per developer -- You won't need to purchase an additional license for the future versions of the library - - -The commercial license is available free of charge for using ZipArchive library in: -- freeware software (freeware is software that is available free of charge, but which is copyrighted by the developer, who retains the right to control its redistribution and to sell it in the future) - - excluded is software which is associated with an equipment that the same company manufactures and which has no practical usage value without the mentioned equipment (e.g. software used for maintenace of machines) - unless the equipment is free as well - - if you decide to sell the software in the future - you will need to purchase the commercial license for using the ZipArchive library, unless it is distributed in the shareware way - see below -- software distributed in the Shareware way (Shareware distribution gives users a chance to try software before buying it. If you try a Shareware program and continue using it, you are expected to register. Individual programs differ on details -- some request registration while others require it, some specify a maximum trial period. -Copyright laws apply to both Shareware and commercial software and the copyright holder retains all rights, with the exception that copying and distributing the program for evaluation purposes is encouraged, subject to certain conditions. For example, some authors require written permission before a commercial disk vendor may copy their Shareware. ) - - excluded is software which price for a single copy is higher than the price of the ZipArchive library for a single developer - -Extended Licence for HBZLIB (library for zip compression in \htmlonly Harbour\endhtmlonly)
-You can create proprietary software using hbzlib respecting the follow: -- ZipArchive library must be linked together with hbzlib -- you cannot use ZipArchive as a dynamic library (DLL), it must be linked staticaly with the software -- the commercial license for ZipArchive is free of charge, but these grants are valid only if the whole application is written with Harbour - -There is a fee for the commercial license for using the library in the software not falling into the mentioned categories. -
-It is recommended that you should print two copies of the commercial license -document after you receive it, sign them and send by post. One copy, signed by the author will be sent back to you. -Please \htmlonly contact the author or visit the Artpol Software web site \endhtmlonly to find out more. - -*/ diff --git a/src/smpackagee/ZipArchive/Linux/ZipFileMapping.h b/src/smpackagee/ZipArchive/Linux/ZipFileMapping.h deleted file mode 100644 index b16f251b95..0000000000 --- a/src/smpackagee/ZipArchive/Linux/ZipFileMapping.h +++ /dev/null @@ -1,61 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFileMapping.h $ -// $Archive: /ZipArchive_Linux/ZipFileMapping.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_) -#define AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include - -namespace ziparchv { - -struct CZipFileMapping -{ - CZipFileMapping() - { - m_iSize = 0; - m_pFileMap = NULL; - } - bool CreateMapping(CZipFile* pFile) - { - if (!pFile) - return false; - m_iSize = pFile->GetLength(); - m_pFileMap = mmap( - 0, m_iSize, PROT_READ | PROT_WRITE, MAP_SHARED, pFile->m_hFile, 0); - return (m_pFileMap != NULL); - } - void RemoveMapping() - { - - if (m_pFileMap) { - munmap(m_pFileMap, m_iSize); - m_pFileMap = NULL; - } - } - ~CZipFileMapping() { RemoveMapping(); } - char* GetMappedMemory() { return reinterpret_cast(m_pFileMap); } - - protected: - void* m_pFileMap; - size_t m_iSize; -}; -} - -#endif // !defined(AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/Linux/ZipPathComponent.cpp b/src/smpackagee/ZipArchive/Linux/ZipPathComponent.cpp deleted file mode 100644 index ed0c1c03d5..0000000000 --- a/src/smpackagee/ZipArchive/Linux/ZipPathComponent.cpp +++ /dev/null @@ -1,87 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPathComponent.cpp $ -// $Archive: /ZipArchive_Linux/ZipPathComponent.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipPathComponent.h" -#include "stdafx.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CZipPathComponent::~CZipPathComponent() {} - -void -CZipPathComponent::SetFullPath(LPCTSTR lpszFullPath) -{ - - CZipString szTempPath(lpszFullPath); - const CZipString szPrefix = _T("\\\\?\\unc\\"); - int i = -1, iLen = szPrefix.GetLength(); - if (iLen > szTempPath.GetLength()) - iLen = szTempPath.GetLength(); - CZipString szPossiblePrefix = szTempPath.Left(iLen); - szPossiblePrefix.MakeLower(); // must perform case insensitive comparison - while (++i < iLen && szPossiblePrefix[i] == szPrefix[i]) - ; - if (i == 2 || i == 4 || i == 8) // unc path, unicode path or unc path - // meeting windows file name conventions - { - m_szPrefix = szTempPath.Left(i); - szTempPath = szTempPath.Mid(i); - } else - m_szPrefix.Empty(); - - m_szDrive.Empty(); - m_szFileTitle.Empty(); - m_szDirectory.Empty(); - m_szFileExt.Empty(); - int p; - for (p = szTempPath.GetLength() - 1; p >= 0; p--) - if (szTempPath[p] == m_cSeparator) - break; - - if (p != -1) { - m_szDirectory = szTempPath.Left(p); - if (p == szTempPath.GetLength() - 1) - return; // no filename present - else - p++; - } else - p = 0; - - // p points at the beginning of the filename - m_szFileTitle = szTempPath.Mid(p); - for (p = m_szFileTitle.GetLength() - 1; p >= 0; p--) - if (m_szFileTitle[p] == _T('.')) - break; - - if (p != -1) { - m_szFileExt = m_szFileTitle.Mid(p + 1); - m_szFileTitle = m_szFileTitle.Left(p); - } -} - -CZipString -CZipPathComponent::GetNoDrive() const -{ - CZipString szPath = m_szDirectory; - CZipString szFileName = GetFileName(); - if (!szFileName.IsEmpty() && !szPath.IsEmpty()) - szPath += m_cSeparator; - - szPath += szFileName; - return szPath; -} diff --git a/src/smpackagee/ZipArchive/Linux/ZipPlatform.cpp b/src/smpackagee/ZipArchive/Linux/ZipPlatform.cpp deleted file mode 100644 index 20fd2cc067..0000000000 --- a/src/smpackagee/ZipArchive/Linux/ZipPlatform.cpp +++ /dev/null @@ -1,272 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPlatform.cpp $ -// $Archive: /ZipArchive_Linux/ZipPlatform.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipPlatform.h" -#include "ZipAutoBuffer.h" -#include "ZipException.h" -#include "ZipFileHeader.h" -#include "stdafx.h" - -#include - -#include "ZipPathComponent.h" - -#include "ZipCompatibility.h" -#include -#include -#include -#include -#include -#include - -const TCHAR CZipPathComponent::m_cSeparator = _T('/'); - -#ifndef _UTIMBUF_DEFINED -#define _utimbuf utimbuf -#endif - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// -DWORD -ZipPlatform::GetDeviceFreeSpace(LPCTSTR lpszPath) -{ - struct statfs sStats; - if (statfs(lpszPath, &sStats) == -1) - return 0; - - return sStats.f_bsize * sStats.f_bavail; -} - -bool -ZipPlatform::GetFileSize(LPCTSTR lpszFileName, DWORD& dSize) -{ - int f = open(lpszFileName, O_RDONLY); - if (f == -1) - return false; - int iSize = lseek(f, 0, SEEK_END); - close(f); - if (iSize == -1) - return false; - dSize = (DWORD)iSize; - return true; -} - -CZipString -ZipPlatform::GetTmpFileName(LPCTSTR lpszPath, DWORD iSizeNeeded) -{ - TCHAR empty[] = _T(""), prefix[] = _T("zar"); - TCHAR* buf = NULL; - CZipString tempPath; - if (lpszPath) { - // first try the user provided directory - tempPath = lpszPath; - if (ZipPlatform::GetDeviceFreeSpace(tempPath) < iSizeNeeded) - tempPath.Empty(); - else { - CZipPathComponent::AppendSeparator(tempPath); - tempPath += prefix; - tempPath += _T("XXXXXX"); - TCHAR* c = mktemp(tempPath.GetBuffer(tempPath.GetLength())); - tempPath.ReleaseBuffer(); - if (c) - return tempPath; - else - tempPath.Empty(); - } - } - - TCHAR* v = tempnam(tempPath, prefix); - tempPath = v; - free(v); - - if (!tempPath.IsEmpty()) { - CZipPathComponent zpc(tempPath); - if (ZipPlatform::GetDeviceFreeSpace(zpc.GetFilePath()) < iSizeNeeded) - return empty; - return tempPath; - } else - return empty; -} - -bool -ZipPlatform::GetCurrentDirectory(CZipString& sz) -{ - char* pBuf = getcwd(NULL, 0); - if (!pBuf) - return false; - sz = pBuf; - free(pBuf); - return true; -} - -bool -ZipPlatform::SetFileAttr(LPCTSTR lpFileName, DWORD uAttr) -{ - return chmod(lpFileName, uAttr >> 16) == 0; -} - -bool -ZipPlatform::GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr) -{ - struct stat sStats; - if (stat(lpFileName, &sStats) == -1) - return false; - uAttr = (sStats.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_IFMT)) << 16; - return true; -} - -bool -ZipPlatform::GetFileModTime(LPCTSTR lpFileName, time_t& ttime) -{ - - struct stat st; - if (stat(lpFileName, &st) != 0) - return false; - - ttime = st.st_mtime; - return ttime != -1; -} - -bool -ZipPlatform::SetFileModTime(LPCTSTR lpFileName, time_t ttime) -{ - struct utimbuf ub; - ub.actime = time(NULL); - ub.modtime = ttime == -1 - ? time(NULL) - : ttime; // if wrong file time, set it to the current - return utime(lpFileName, &ub) == 0; -} - -bool -ZipPlatform::ChangeDirectory(LPCTSTR lpDirectory) -{ - return chdir(lpDirectory) == 0; -} -int -ZipPlatform::FileExists(LPCTSTR lpszName) -{ - struct stat st; - if (stat(lpszName, &st) != 0) - return 0; - else { - if (S_ISDIR(st.st_mode)) - return -1; - else - return 1; - } -} - -ZIPINLINE bool -ZipPlatform::IsDriveRemovable(LPCTSTR lpszFilePath) -{ - // not implemmented - return true; -} - -ZIPINLINE bool -ZipPlatform::SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel) -{ - // not implemmented - return true; -} - -ZIPINLINE void -ZipPlatform::AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem) -{ - // not implemmented -} - -ZIPINLINE bool -ZipPlatform::RemoveFile(LPCTSTR lpszFileName, bool bThrow) -{ - if (unlink(lpszFileName) != 0) - if (bThrow) - CZipException::Throw(CZipException::notRemoved, lpszFileName); - else - return false; - return true; -} -ZIPINLINE bool -ZipPlatform::RenameFile(LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow) -{ - - if (rename(lpszOldName, lpszNewName) != 0) - if (bThrow) - CZipException::Throw(CZipException::notRenamed, lpszOldName); - else - return false; - return true; -} -ZIPINLINE bool -ZipPlatform::IsDirectory(DWORD uAttr) -{ - return S_ISDIR(uAttr >> 16) != 0; -} -ZIPINLINE bool -ZipPlatform::CreateDirectory(LPCTSTR lpDirectory) -{ - return mkdir(lpDirectory, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == 0; -} - -ZIPINLINE DWORD -ZipPlatform::GetDefaultAttributes() -{ - return 0x81a40000; -} - -ZIPINLINE DWORD -ZipPlatform::GetDefaultDirAttributes() -{ - return 0x41ff0010; -} - -ZIPINLINE int -ZipPlatform::GetSystemID() -{ - return ZipCompatibility::zcUnix; -} - -ZIPINLINE bool -ZipPlatform::GetSystemCaseSensitivity() -{ - return true; -} - -bool -ZipPlatform::TruncateFile(int iDes, DWORD iSize) -{ - return ftruncate(iDes, iSize) == 0; -} - -int -ZipPlatform::OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode) -{ - return open(lpszFileName, iMode, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); -} - -bool -ZipPlatform::FlushFile(int iDes) -{ - return fsync(iDes) == 0; -} - -int -ZipPlatform::GetFileSystemHandle(int iDes) -{ - return iDes; -} diff --git a/src/smpackagee/ZipArchive/Readme.txt b/src/smpackagee/ZipArchive/Readme.txt deleted file mode 100644 index 286b19deb6..0000000000 --- a/src/smpackagee/ZipArchive/Readme.txt +++ /dev/null @@ -1,645 +0,0 @@ -/* - -For conditions of distribution and use, see the copyright notice in License.txt. -Please read the documentation instead of this document -(it may be difficult to read it due to formatting tags for an automatic documentation generation). -If you do not have it, please download it from http://www.artpol-software.com/ - -*/ - -/** \mainpage ZipArchive library documentation - -\section secGen General Information - - -The ZipArchive library
-
-Copyright © 2000 - 2003 Tadeusz Dracz
-
- -\b Version: 2.3.4
-\b Date: 26-June-2003 - - -This library adds zip compression and decompression functionality to your program, allowing you to create and modify ZIP files in the compatible way with WinZip, PKZIP and other popular archivers. -Its easy and practical interface makes the library suitable for the beginners as well as for the advanced users. - -See \ref pageHist "what's new" in this version.
-To be notified about the future library updates, sign up for the \ref pageSubsc. - - -\ref pageSyst "Platforms supported:" -- Windows 9x\\Me\\NT\\2000\\XP (MFC and STL)
\ref sectVisual "Microsoft Visual C++ 6.0" (.NET compatible ), \ref sectBorl "Borland C++" - -- \ref sectLinux "Linux (STL)" - -\author Tadeusz Dracz
-E-Mail: \htmlonly tdracz@artpol-software.com \endhtmlonly
-Web Site: \htmlonly http://www.artpol-software.com \endhtmlonly - -This library uses \htmlonly the zlib library \endhtmlonly by Jean-loup Gailly and Mark Adler to perform inflate and deflate operations. - -\section sectFeat Features Summary: -- work in a compatible way with PKZIP and WinZip (apart from \ref TDSpan "TD disk spanning mode" which is specific to this library) -- create, modify, extract and test zip archives -- create and extract multi-disk archives (on non-removable disks as well) -- add file to the archive from another archive without decompressing the file (copy compressed data) (see CZipArchive::GetFromArchive) -- highly optimized deleting multiple files from the archive -- optimized replacing and renaming files in the archive -- compression from and decompression to memory, create the whole archive in memory, extract the archive from memory (see \ref sectMemory) -- password encryption and decryption supported -- possibility to create or extract self-extracting archives -- smart compression, if enabled, prevents the file in the archive to be larger after compression (see CZipArchive::Smartness) -- safe compression with CZipArchive::Flush function -- using functional objects as callback - - to provide easy disk change in a multi-disk archives - - for the progress control when adding, extracting, testing or deleting files or saving archive's central directory -- extracting and deleting using wildcard pattern matching (see CZipArchive::FindMatches) -- UNC and Windows Unicode paths recognized -- wide characters supported -- support for the Java TM Archive (jar) File Format (see CZipArchive::SetIgnoreCRC) -- can be used as a static library or DLL (necessary VC++ projects included) -- possibility to integrate help system with MSDN (see \ref sectHelp) -- easy interface -- easy transfer to other system platforms -- speedy -- well documented -- full source code provided -- sample applications provided (for the STL version located in \e stl/zippie, -the MFC version (multithreaded) is available separately) - -No software product is entirely bugless and neither is this library. If you find a bug (or suspect one), please mail me. The bugs are usually corrected within few days. Many thanks to the people that already tracked them down and submitted. - -\section secQl The Introduction - -All you need to know about the licensing: \ref pageLic . - -It's a good start to read these pages first (prior to reading the raw documentation): -- \ref pageSyst -- \ref pageGen - -Have you got a question? Maybe it's one of the \ref pageFaq "frequently asked questions". - -\ref pageHist not only shows how the development of the library went so far, but also you may find here an -interesting library feature without digging through the documentation. - -If you wish to be notified about the future library updates, sign up for the \ref pageSubsc . - - - - */ - -/** - - \page pageSyst Compilation & Integration - - \par - - \ref secCompil - - \ref winMFC - - \ref winSTL - - \ref LnxSTL - - \ref sectVisual - - \ref subsM1 - - \ref subsM2 - - \ref subsDLL - - \ref sectBorl - - \ref subExample - - \ref sectLinux - - \ref subsLnxNot - - \ref subsLnxCom - - \ref sectNotes - - \ref stlNotes - - \ref subDLLnotes - - \ref MFCsample - - - \section secCompil Compiling for different implementations and platforms - - - The files required for all the library versions are located in the program - root directory. You also need to copy additional files to the library - root directory from the two more subfolders. Depending on the configuration - these files are located in: - - - \subsection winMFC Windows MFC - \e \\Windows and \e \\mfc
- You can just execute _copy from Win-MFC.bat batch file. - - \subsection winSTL Windows STL - \e \\Windows and \e \\stl
- You can just execute _copy from Win-STL.bat batch file. - - \subsection LnxSTL Linux (STL version) - \e \\Linux and \e \\stl
- You can just execute _copy_from_Linux.sh script file - (don't forget to set executable rights before e.g. with the command: - chmod +x _copy_from_Linux.sh ). - - \note If you use one of the mentioned scripts to copy the files then for easy - orientation there will be a file \e __[...].zcfg created with the - name depending on the current configuration - - \section sectVisual Visual C++ : integrating with the project - - To add ZipArchive library functionality into your project you need to link - the library to the project. You can do this in at least two ways - (in both cases you need to include ZipArchive.h header in your sources). - - \subsection subsM1 Method 1 - - Add \e ZipArchive.lib with the proper path e.g. ..\\ZipArchive\\debug\\ZipArchive.lib to Project Settings->Link->Input->Object/library modules - and add ZipArchive library directory to the preprocessor searches ( Project Settings -> C++ -> Preprocessor -> Additional include directories ). - - \subsection subsM2 Method 2 (simpler) - - Insert Zip project into workspace and set project dependencies: your project dependent on ZipArchive project - ( Project -> Dependencies and then on the dialog that will appear - you select your project name from the combo box and check the box next to ZipArchive project name). - When you use this method, you link configurations in your project with - configurations in the ZipArchive project that have the same name in both projects. So if you need to use - for example "Static Release" configuration from ZipArchive project, you need to create one with the same name - in your application project and make sure that your project uses MFC library and run-time library in same way - ( Project->Settings->General->Microsoft Fundation Classes and Project->Settings-> c/c++ ->Code Generation->Use run-time library ). - - \subsection subsDLL DLL version - - When you're using the DLL version of the ZipArchive library, you need to define in your program ZIP_HAS_DLL (e.g. in Project Settings -> C++ -> Preprocessor -> Preprocessor definitions ). - Apart from integrating the ZipArchive library with your program (use one of the methods above), you also need to take into account zlib.lib file (use zlib/zlib.dsw to create it and add to preprocessor includes) or zlib/zlib.dsw project (insert into workspace and set ZipArchive project dependent on it)). - Files zlib.dll and ZipArchive.dll must be available for the program when running (e.g. in the program's directory). - - - - You can read about linking problems in the \ref pageFaq. - - \section sectBorl Borland C++ compatibility - The library contains a project files for Borland C++ 5.0 ( - They were created using Visual C++ Project Conversion Utility (VCTOBPR.EXE). - You can start this tool with the command Tools->Visual C++ Project Conversion Utility . - - \note Be sure to create \e Release subfolder before compiling one of these projects, - otherwise you'll get a write error. - - In case the projects provided don't work for you, you can create your own. You need to copy - to the root directory appropriate files for \ref winMFC "MFC" or \ref winSTL "STL" versions. - You may use the Borland project conversion utility. - - The library contains also \e makefiles which should work with other versions of Borland. - - - \subsection subExample Compiling the sample application - There is a Borland C++ project provided with the sample application \c ZipArc.
- To compile it you need compiled MFC version of ZipArchive library. - - \note Be sure to create \e Release subfolder first, otherwise you'll get - a write error. - - Add the library (\e ZipArchive.lib ) to the project (Project->Add To Project) and compile. - - If you wish to convert Visual C++ project using Visual C++ Project Conversion Utility then after - converting to properly compile the application you need to remove \e odbccp32.lib from the project file - and comment everything out in \e ZipArc_TLB.cpp or remove this file from the project files. - - \section sectLinux Linux platform - - \subsection subsLnxNot Notes - - - \b Usage - - When using the library under Linux you should be aware of a few things: - - after you get the system attributes with CZipFileHeader::GetSystemAttr() function, - you need to shift them right by 16 ( e.g. uAttr = header.GetSystemAttr() >> 16 ) - - the reason for that is the way the attributes are stored in the archive created under (or for) Linux. - - due to lack of implementation of ZipPlatform::IsDriveRemovable(), which has proven to be a kind of difficult to do, - the device containing the archive is always assumed to be removable; the only effect of this - is that you need to set \e iVolumeSize to a value different from 0 when opening with the function - CZipArchive::Open() the archive created in tdSpan mode. - - - \b Compiling - - - the library was tested under g++ version 2.96 - - warnings that use of the \c tempnam and \c mktemp is not safe can be ignored, because the - temporary file is created almost straight away. - - - \subsection subsLnxCom Compiling the library and liniking with the application - - First you need to copy the appropriate files (\ref LnxSTL "see above")
- - If you haven't got the zlib library already installed on your system, you can install - it using \e Makefile in the \e zlib subdirectory (type \e make and then make install ) - - only static version (you can download a full version of the zlib library from the ZipArchive library site). - If you don't want to install the zlib library, you need to include it in the ZipArchive library - ( edit the \e Makefile in the main directory and change comments, so that - OBJSZLIB is not an empty value but points to zlib library object files) - - Compile the library by typing \e make. The resulting file is a static library \e libziparch.a - - You can copy the library and the headers (if you have an appropriate rights) to \e /usr/lib and - \e /usr/include/ziparchive (you can change them in \e Makefile) with the command make install - - Now you can link the library to your application
- e.g. with the command (if the library is in the same directory)
- g++ $I. -o app app.cpp -lstdc++ -lz libziparch.a
- or if you have the library installed in the /usr subdirectories:
- g++ $I/usr/include/ziparchive -o app app.cpp -lstdc++ -lz -lziparch
- If you haven't got the zlib library installed, you need to omit the switch \e -lz in the above commands. - \anchor stlLinuxTest - - There is a test application named \e zippie.cpp (in \e stl/zippie which you can compile typing make zippie - (providing that you have installed the ZipArchive library). If you haven't got the zlib library installed, - you need to switch the comments (comment one line and uncomment another) in the \e Makefile in the section \e "zippie:". - - If you wish to uninstall the library type make uninstall - - \section sectNotes Notes - - \subsection stlNotes STL version - - [Windows only] If your locale is different from English and you wish to use non-English - characters in zip files, you need to set your locale with function - \e std::locale::global(std::locale("")) to set it to be the same as your - system locale or e.g. \e std::locale::global(std::locale("French")) - to set it to the specified value (do not use \e _T() macro here when using - Unicode); \e setlocale() function is not sufficient in this case. - - There is a sample application that compiles under Windows (MSVC) and Linux (see below - to find out \ref stlLinuxTest "how to compile it under Linux"). This sample application demonstrates most of the - ZipArchive library features and is located in \e stl/zippie. - - \subsection subDLLnotes Compiling as DLL - [Windows only] - - The project that compiles the DLL version of the ZipArchive library needs to have defined ZIP_HAS_DLL, ZIP_BUILD_DLL and also ZLIB_DLL. - - The project that uses the ZipArchive library as the DLL version need to have defined ZIP_HAS_DLL - - \subsection MFCsample MFC sample application (ZipArc) - MFC sample application using ZipArchive library is available separately. Main features: - - MDI application - - multithreaded - you can work with many zip files at one time - - shell integration (remembers the last application used to open zip files and can restore it correctly) - - drag & drop support - - detailed error reports - - you can open and modify SFX archives - - it demonstrates the use of the following functions (most of them are placed in ZipArcDoc.cpp) : - CZipArchive::AddNewFile, - CZipArchive::Close, - CZipArchive::CloseFile, - CZipArchive::CloseNewFile, - CZipArchive::DeleteFiles, - CZipArchive::EnableFindFast, - CZipArchive::ExtractFile, - CZipArchive::FindFile, - CZipArchive::FindMatches, - CZipArchive::Flush, - CZipArchive::GetArchivePath, - CZipArchive::GetCentralDirInfo, - CZipArchive::GetCentralDirSize, - CZipArchive::GetCurrentDisk, - CZipArchive::GetFileInfo, - CZipArchive::GetFindFastIndex, - CZipArchive::GetGlobalComment, - CZipArchive::GetCount, - CZipArchive::GetPassword, - CZipArchive::GetSpanMode, - CZipArchive::IsClosed, - CZipArchive::IsReadOnly, - CZipArchive::Open, - CZipArchive::RenameFile, - CZipArchive::PredictExtractedFileName, - CZipArchive::SetAdvanced, - CZipArchive::SetCallback, - CZipArchive::SetFileComment, - CZipArchive::SetGlobalComment, - CZipArchive::SetIgnoreCRC, - CZipArchive::SetPassword, - CZipArchive::SetRootPath, - CZipArchive::SetSpanCallback, - CZipArchive::SetTempPath, - CZipArchive::TestFile, - CZipArchive::WillBeDuplicated,
- CZipFileHeader::IsEncrypted, - CZipFileHeader::IsDirectory, - CZipFileHeader::GetTime, - CZipFileHeader::GetSystemCompatibility, - CZipFileHeader::GetSystemAttr, - CZipFileHeader::GetSize, - CZipFileHeader::GetFileName, - CZipFileHeader::GetEffComprSize, - CZipFileHeader::GetCompressionRatio, - CZipFileHeader::GetComment, - CZipFileHeader::CompressionEfficient, - - -*/ - - -/** - -\page pageGen General Information - -\par -\ref sectCompress -\par -\ref sectSpan -\par -\ref sectPass -\par -\ref sectSE -\par -\ref sectExc -\par -\ref sectMemory -\par -\ref sectCallb -\par -\ref sectHelp -\par - - - -\section sectCompress Compression and decompression - -There are some functions defined for fast operations on archive: CZipArchive::AddNewFile, - CZipArchive::ExtractFile, CZipArchive::DeleteFile, CZipArchive::TestFile. - You only need to call functions CZipArchive::Open - before and CZipArchive::Close - after using them. Calling CZipArchive::Close function after you've done modifying the archive is necessary -for the archive to be intact. - -\section sectSpan Multi-disk archives - -This library can create multi-disk archives in two ways (modes): - -\anchor PKSpan -- PKSpan mode. Disk spanning is performed in the compatible way with all other main zip programs. It means that: - - the archive can only be created on a removable device, - - the size of the volume is auto-detected - - the label is written to the disk - - you need to define a callback functor for changing disks and set it with CZipArchive::SetSpanCallback function. - -\anchor TDSpan -- TDSpan mode. Disk spanning is performed in the internal mode. It means that: - - the archive can be created on non-removable device as well - - you need to define the single volume size - - there is no need to set callback functor in this mode. - -\anchor convertZips -These two disk spanning modes create volumes with compatible internal structure. It means that you can easily convert the volumes created in one mode to the other one by renaming the files (in TDSpan mode each volume but last has a number as an extension). To convert the archive from TD to PKZIP compatible archive, copy each file to the removable media, giving them the extension ".zip". You should also label each disk with the appropriate label starting from "pkback# 001" -(note the space between '#' and '0'). - -There is a limited functions set available while working with multi-disk archives. Only adding is allowed when creating the archive and only extracting and testing after opening an existing one. Deleting files from these archives is not allowed at all. - -Class CZipArchive uses write buffer to make write operations as fast as possible. You can change its size with CZipArchive::SetAdvanced function (first argument). While creating a multi-disk archive, set the size of the buffer to the maximum size of the volume for the best performance. - -The popular archivers such as PKZIP and WinZip cannot operate on archive in TDSpan mode. You need to convert them to PKZIP span mode (\ref convertZips "have a look above"). Remember about copying the files to the removable media (it does not comply with Winzip, which can extract a multi-disk archive from any media but only from the fixed location on the drive). - -\section sectPass Password encryption and decryption - -This library supports creating and extracting the password protected archives. There are several issues you should be aware of when using this feature. To set the password for the file to be added or extracted call the function CZipArchive::SetPassword with the password as the argument. To clear the password call this function without arguments or with an empty string argument. The function has no effect on a closed archive and on the currently opened file (whether new or existing) inside archive. During opening the archive the password is cleared. You can set different passwords for different files inside the same archive, but remember to set it BEFORE opening the file. You cannot use ASCII characters with codes above 127 in the password, if you do so, the function CZipArchive::SetPassword returns false and the password is cleared. -You can find out what files are password encrypted by calling CZipArchive::GetFileInfo, which fills the structure CZipFileHeader with data, and then call the method ZipFileHeader::IsEncrypted. If it returns true, the file needs a password to extract. -The successful extraction of the encrypted file doesn't always mean that the password is correct. You also need to check the return value of CZipArchive::CloseFile. You could also check the size of the extracted file since it can be smaller than it should be in case of the bad password. - -\section sectSE Self extract support - -The library is capable of extracting and modifying self-extracting archives. You can create your own SFX archive as well. This is the simplest code responsible for the self-extracting: - -\code -//Windows code - -int APIENTRY WinMain(HINSTANCE hInstance, -HINSTANCE hPrevInstance, -LPSTR lpCmdLine, -int nCmdShow) -{ - CZipArchive zip; - - // get the path of the executable - TCHAR szBuff[_MAX_PATH]; - if (!::GetModuleFileName(hInstance, szBuff, _MAX_PATH)) - return -1; - - CZipString szDest; - // ... - // add some code here to get the destination directory from the user - // for example: - // CBrowseForFolder bf; - // bf.strTitle = _T("Select directory to extract files"); - // if (!bf.GetFolder(szDest)) - // return -1; - // - // class CBrowseForFolder is included in the sample application project - // remember about including the header! - zip.Open(szBuff, CZipArchive::zipOpenReadOnly); - // zipOpenReadOnly mode is necessary for self extract archives - for (WORD i = 0; i < zip.GetCount(); i++) - zip.ExtractFile(i, szDest); - - zip.Close(); - return 0; - // this code will not work for the encrypted archives since it is needed - // to get the password from the user ( a small addition to the - // existing code I suppose ) -} - -\endcode - -After compiling it and appending a zip archive to it (e.g. with the DOS command: copy /b SelfExtract.exe + ZipFile.zip FinalFile.exe ) you have a self extracting archive. - - -\section sectExc Exceptions - -The ZipArchive library mostly uses exceptions to notify about the error occured. The library throws CZipException to notify about errors specific to the internal zip file processing. In the MFC version CZipException class is derived from CException whereas in the STL version it is derived from std::exception. - -\subsection excmfc MFC version -The library throws the following exceptions inherited from \c CException: \c CMemoryException*, \c CFileExeption* and \c CZipException* (be sure to delete the object when you done with it). Handling them may be done in the following way: - -\code - -try -{ - // ... - // some operations on the ZipArchive library -} -catch (CException* e) -{ - if (e->IsKindOf( RUNTIME_CLASS( CZipException ))) - { - CZipException* p = (CZipException*) e; - //... and so on - } - else if (e->IsKindOf( RUNTIME_CLASS( CFileException ))) - { - CFileException* p = (CFileException*) e; - //... and so on - } - else - { - // the only possibility is a memory exception I suppose - //... and so on - } - e->Delete(); -} - - -\endcode - -\subsection excstl STL version -The library throws exceptions inherited from \c std::exception. In this case you should catch \c std::exception object (not a pointer to it). - -\section sectMemory Creating and extracting archives from/in memory - -With the function CZipArchive::Open(CZipMemFile&, int) you can create the archive in memory and then write to disk, e.g.: - -\code - -CZipArchive zip; -CZipMemFile mf; -// create archive in memory -zip.Open(mf, CZipArchive::zipCreate); -// ... -// add some files to archive here e.g. by calling CZipArchive::AddNewFile -// ... -zip.Close(); -// write the archive to disk -CZipFile f; -if (f.Open("c:\\temp.zip", CZipFile::modeWrite|CZipFile::modeCreate, false) -{ - int iLen = mf.GetLength(); - BYTE* b = mf.Detach(); - f.Write(b, iLen); - f.Close(); - // we must free the detached memory - free(b); -} -\endcode - -You can as well read the archive from disk and then extract files, e.g.: - -\code -CZipFile f; -if (f.Open("c:\\temp.zip", CZipFile::modeRead, false) -{ - int iLen = f.GetLength(); - BYTE* b = (BYTE*)malloc((UINT)iLen); - f.Read(b, iLen); - f.Close(); - CZipMemFile mf; - mf.Attach(b, iLen); - CZipArchive zip; - zip.Open(mf); - // ... - // extract files here from the archive e.g. by calling CZipArchive::ExtractFile - // ... - zip.Close(); -} -\endcode - -With functions CZipArchive::AddNewFile(CZipMemFile&, LPCTSTR, int, int, unsigned long) and -CZipArchive::ExtractFile(WORD, CZipMemFile&, DWORD) you can add files to archive from memory -and extract them to a memory file. Now a bit larger example: - -\code -// create the archive in memory with two files inside -CZipMemFile mf; -CZipArchive zip; -zip.Open(mf, CZipArchive::zipCreate); -zip.AddNewFile("c:\\testfile1.txt"); -zip.AddNewFile("c:\\testfile2.txt"); -zip.Close(); -//create the archive on disk and add a previously zipped file from memory -zip.Open("c:\\test.zip", CZipArchive::zipCreate); -zip.AddNewFile(mf, "File1.zip"); -zip.Close(); -// we have now zip-in-zip file on the disk, -// let's extract the embedded zip file back to memory -zip.Open("c:\\test.zip"); -// reset the contents of the CZipMemFile object -mf.SetLength(0); -zip.ExtractFile(0, mf); -zip.Close(); -// write the file from memory to disk -CZipFile f; -if (f.Open("c:\\File1.zip", CZipFile::modeWrite|CZipFile::modeCreate, false)) -{ - int iLen = mf.GetLength(); - BYTE* b = mf.Detach(); - f.Write(b, iLen); - f.Close(); - // we must free the detached memory - free(b); -} -\endcode - - -One important thing: when you operate on the archive in memory, you must ensure -that CZipMemory object will not be destroyed before calling CZipArchive::Close. -In some cases you'll need to construct the object using the \c new operator, e.g.: -\code -// ... -CZipMemFile* pmf = new CZipMemFile; -zip.Open(*pmf, CZipArchive::zipCreate); -// ... -zip.Close(); -delete pmf; -\endcode - -\section sectCallb Action progress notifications (callbacks) - -The library has the possibility to notify about the progress of the various actions (see CZipArchive::CallbackType). -To use this feature you need to define a new class derived from CZipActionCallback or from CZipSpanCallback and override -CZipCallback::Callback function. Then you need to declare an object of your class and pass its address to -function CZipArchive::SetCallback or CZipArchive::SetSpanCallback. Make sure that the object exists while the library -performs the action the functor was assigned to. -or tell the library not to use the callback (use the same functions). - - -\section sectHelp Integrating with MSDN - -If you wish to integrate the ZipArchive help system with the MSDN library you need to: -- download from -\htmlonly -the Artpol Software site -\endhtmlonly -ZipArchive HTML Help documentation or ZipArchive HTML documentation if you don't have it. -- in the latter case you need to compile the html files to the HTML Help format -with HTML Web Workshop by Microsoft (at the moment of writing available i.a. -\htmlonly -here) -\endhtmlonly -and using provided \e index.hhp file (it is at the same location as ZipArchive html help files) -- now you should have \e index.chm and \e index.chi files, rename them if you want to and put them -to the directory of your choice -- you need to download a free MSDN Integration Utility by Kirk Stowell; you can download it from -\htmlonly -the Code Project site -or from the Artpol Software site -\endhtmlonly -(Download->ZipArchive) -- use the MSDN Integration Utility for the files you have prepared -- now pressing the F1 key on the ZipArchive library method or class in the Visual Studio brings up the MSDN help; -you have also a searchable ZipArchive collection inside MSDN -\note After integrating the ZipArchive help system with the MSDN library, you need -to be patient when you use the Index for the first time, because it'll be rebuilt then which can -be a lengthy process. -*/ - -/** -\page pageSubsc ZipArchive Newsletter - -To be notified about ZipArchive library updates, enter your -e-mail into the input field below and press \e Subscribe! button. -You should receive a confirmation message then. - -\htmlonly - -
- - - - -
- - -

Privacy Policy of the ZipArchvie library Newsletter List

-
    -
  • The information you provide, will never be made available to any third party company. -
  • Only the Web Master of the Artpol Software site will have an access to the mailing list. -
  • If at anytime you wish to be removed from the mailing list, you can do it by -following the link that you will receive with every newsletter. -
- -\endhtmlonly - -*/ - \ No newline at end of file diff --git a/src/smpackagee/ZipArchive/StdAfx.cpp b/src/smpackagee/ZipArchive/StdAfx.cpp deleted file mode 100644 index fb36433f05..0000000000 --- a/src/smpackagee/ZipArchive/StdAfx.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: stdafx.cpp $ -// $Archive: /ZipArchive/stdafx.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "stdafx.h" diff --git a/src/smpackagee/ZipArchive/StdAfx.h b/src/smpackagee/ZipArchive/StdAfx.h deleted file mode 100644 index 3048192819..0000000000 --- a/src/smpackagee/ZipArchive/StdAfx.h +++ /dev/null @@ -1,48 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: stdafx.h $ -// $Archive: /ZipArchive/stdafx.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) -#define AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#if _MSC_VER < 1300 && !defined __BORLANDC__ -#define ZIPINLINE inline -#else -#define ZIPINLINE -#endif - -#if _MSC_VER >= 1300 -#define ZIP_ULONGLONG ULONGLONG -#define ZIP_LONGLONG LONGLONG -#else -#define ZIP_ULONGLONG DWORD -#define ZIP_LONGLONG LONG -#endif - -#define ZIP_ARCHIVE_MFC - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#include -#include - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/Windows/ZipFileMapping.h b/src/smpackagee/ZipArchive/Windows/ZipFileMapping.h deleted file mode 100644 index cb261b84cd..0000000000 --- a/src/smpackagee/ZipArchive/Windows/ZipFileMapping.h +++ /dev/null @@ -1,69 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFileMapping.h $ -// $Archive: /ZipArchive/ZipFileMapping.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -// -// Check the site http://www.artpol-software.com for the updated version of the -// library. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_) -#define AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "ZipFile.h" -namespace ziparchv { - -struct CZipFileMapping -{ - CZipFileMapping() - { - m_hFileMap = NULL; - m_pFileMap = NULL; - } - bool CreateMapping(CZipFile* pFile) - { - if (!pFile) - return false; - m_hFileMap = CreateFileMapping( - (*pFile), NULL, PAGE_READWRITE, 0, 0, _T("ZipArchive Mapping File")); - if (!m_hFileMap) - return false; - // Get pointer to memory representing file - m_pFileMap = MapViewOfFile(m_hFileMap, FILE_MAP_WRITE, 0, 0, 0); - return (m_pFileMap != NULL); - } - void RemoveMapping() - { - if (m_pFileMap) { - UnmapViewOfFile(m_pFileMap); - m_pFileMap = NULL; - } - if (m_hFileMap) { - CloseHandle(m_hFileMap); - m_hFileMap = NULL; - } - } - ~CZipFileMapping() { RemoveMapping(); } - char* GetMappedMemory() { return reinterpret_cast(m_pFileMap); } - - protected: - HANDLE m_hFileMap; - LPVOID m_pFileMap; -}; -} - -#endif // !defined(AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/Windows/ZipPathComponent.cpp b/src/smpackagee/ZipArchive/Windows/ZipPathComponent.cpp deleted file mode 100644 index abbaaada45..0000000000 --- a/src/smpackagee/ZipArchive/Windows/ZipPathComponent.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPathComponent.cpp $ -// $Archive: /ZipArchive/ZipPathComponent.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipPathComponent.h" -#include "stdafx.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CZipPathComponent::~CZipPathComponent() {} - -void -CZipPathComponent::SetFullPath(LPCTSTR lpszFullPath) -{ - - TCHAR szDrive[_MAX_DRIVE]; - TCHAR szDir[_MAX_DIR]; - TCHAR szFname[_MAX_FNAME]; - TCHAR szExt[_MAX_EXT]; - - CZipString szTempPath(lpszFullPath); - const CZipString szPrefix = _T("\\\\?\\unc\\"); - int i = -1, iLen = szPrefix.GetLength(); - if (iLen > szTempPath.GetLength()) - iLen = szTempPath.GetLength(); - CZipString szPossiblePrefix = szTempPath.Left(iLen); - szPossiblePrefix.MakeLower(); // must perform case insensitive comparison - while (++i < iLen && szPossiblePrefix[i] == szPrefix[i]) - ; - if (i == 2 || i == 4 || i == 8) // unc path, unicode path or unc path - // meeting windows file name conventions - { - m_szPrefix = szTempPath.Left(i); - szTempPath = szTempPath.Mid(i); - } else - m_szPrefix.Empty(); - - _tsplitpath(szTempPath, szDrive, szDir, szFname, szExt); - m_szDrive = szDrive; - m_szDirectory = szDir; - - m_szDirectory.TrimLeft(m_cSeparator); - m_szDirectory.TrimRight(m_cSeparator); - SetExtension(szExt); - m_szFileTitle = szFname; -} - -CZipString -CZipPathComponent::GetNoDrive() const -{ - CZipString szPath = m_szDirectory; - CZipString szFileName = GetFileName(); - if (!szFileName.IsEmpty() && !szPath.IsEmpty()) - szPath += m_cSeparator; - - szPath += szFileName; - return szPath; -} diff --git a/src/smpackagee/ZipArchive/Windows/ZipPlatform.cpp b/src/smpackagee/ZipArchive/Windows/ZipPlatform.cpp deleted file mode 100644 index 03d1259351..0000000000 --- a/src/smpackagee/ZipArchive/Windows/ZipPlatform.cpp +++ /dev/null @@ -1,370 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPlatform.cpp $ -// $Archive: /ZipArchive/ZipPlatform.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipPlatform.h" -#include "ZipAutoBuffer.h" -#include "ZipException.h" -#include "ZipFileHeader.h" -#include "stdafx.h" -#include - -#if defined _MSC_VER && !defined __BORLANDC__ -#include -#else -#include -#endif - -#include "ZipCompatibility.h" -#include "ZipPathComponent.h" -#include -#include -#include - -const TCHAR CZipPathComponent::m_cSeparator = _T('\\'); - -#ifndef _UTIMBUF_DEFINED -#define _utimbuf utimbuf -#endif - -DWORD -ZipPlatform::GetDeviceFreeSpace(LPCTSTR lpszPath) -{ - DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, - TotalNumberOfClusters; - CZipPathComponent zpc(lpszPath); - CZipString szDrive = zpc.GetFileDrive(); - if (!GetDiskFreeSpace(szDrive, - &SectorsPerCluster, - &BytesPerSector, - &NumberOfFreeClusters, - &TotalNumberOfClusters)) { - CZipPathComponent::AppendSeparator(szDrive); // in spite of what is - // written in MSDN it is - // sometimes needed (on - // fixed disks) - if (!GetDiskFreeSpace(szDrive, - &SectorsPerCluster, - &BytesPerSector, - &NumberOfFreeClusters, - &TotalNumberOfClusters)) - - return 0; - } - __int64 total = SectorsPerCluster * BytesPerSector * NumberOfFreeClusters; - return (DWORD)total; -} - -bool -ZipPlatform::GetFileSize(LPCTSTR lpszFileName, DWORD& dSize) -{ - HANDLE f = CreateFile(lpszFileName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - 0, - NULL); - if (!f) - return false; - DWORD dwSize; - dwSize = ::GetFileSize(f, NULL); - CloseHandle(f); - if (dwSize == 0xFFFFFFFF) - return false; - dSize = dwSize; - return true; -} - -CZipString -ZipPlatform::GetTmpFileName(LPCTSTR lpszPath, DWORD iSizeNeeded) -{ - TCHAR empty[] = _T(""); - CZipString tempPath; - bool bCheckTemp = true; - if (lpszPath) { - tempPath = lpszPath; - bCheckTemp = GetDeviceFreeSpace(tempPath) < iSizeNeeded; - } - if (bCheckTemp) { - DWORD size = GetTempPath(0, NULL); - if (size == 0) - return empty; - - GetTempPath(size, tempPath.GetBuffer(size)); - tempPath.ReleaseBuffer(); - if (GetDeviceFreeSpace(tempPath) < iSizeNeeded) { - if (!GetCurrentDirectory(tempPath) || - GetDeviceFreeSpace(tempPath) < iSizeNeeded) - return empty; - } - } - CZipString tempName; - if (!GetTempFileName(tempPath, _T("ZAR"), 0, tempName.GetBuffer(_MAX_PATH))) - return empty; - tempName.ReleaseBuffer(); - return tempName; -} - -bool -ZipPlatform::GetCurrentDirectory(CZipString& sz) -{ - DWORD i = ::GetCurrentDirectory(0, NULL); - if (!i) - return false; - TCHAR* pBuf = new TCHAR[i]; - bool b = true; - if (!::GetCurrentDirectory(i, pBuf)) - b = false; - else - sz = pBuf; - delete[] pBuf; - return b; -} - -bool -ZipPlatform::SetFileAttr(LPCTSTR lpFileName, DWORD uAttr) -{ - return ::SetFileAttributes(lpFileName, uAttr) != 0; -} - -bool -ZipPlatform::GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr) -{ - // not using MFC due to MFC bug (attr is one byte there) - DWORD temp = ::GetFileAttributes(lpFileName); - if (temp == -1) - return false; - uAttr = temp; - return true; -} - -bool -ZipPlatform::GetFileModTime(LPCTSTR lpFileName, time_t& ttime) -{ -#if defined _MSC_VER && !defined __BORLANDC__ - struct _stat st; - if (_tstat(lpFileName, &st) != 0) -#else - struct stat st; - if (stat(lpFileName, &st) != 0) -#endif - return false; - - ttime = st.st_mtime; - return ttime != -1; -} - -bool -ZipPlatform::SetFileModTime(LPCTSTR lpFileName, time_t ttime) -{ - struct _utimbuf ub; - ub.actime = time(NULL); - ub.modtime = ttime == -1 - ? time(NULL) - : ttime; // if wrong file time, set it to the current - return _tutime(lpFileName, &ub) == 0; -} - -bool -ZipPlatform::ChangeDirectory(LPCTSTR lpDirectory) -{ - return _tchdir(lpDirectory) == 0; // returns 0 if ok -} -int -ZipPlatform::FileExists(LPCTSTR lpszName) -{ - if (_taccess(lpszName, 0) == 0) { - if (DirectoryExists(lpszName)) - return -1; - return 1; - } else - return 0; -} - -ZIPINLINE bool -ZipPlatform::IsDriveRemovable(LPCTSTR lpszFilePath) -{ - CZipPathComponent zpc(lpszFilePath); - return ::GetDriveType(zpc.GetFileDrive()) == DRIVE_REMOVABLE; -} - -ZIPINLINE bool -ZipPlatform::SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel) -{ - CZipPathComponent zpc(lpszPath); - CZipString szDrive = zpc.GetFileDrive(); - CZipPathComponent::AppendSeparator(szDrive); - return ::SetVolumeLabel(szDrive, lpszLabel) != 0; -} - -ZIPINLINE void -ZipPlatform::AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem) -{ - if (bAnsiToOem) - CharToOemBuffA(buffer, buffer, buffer.GetSize()); - else - OemToCharBuffA(buffer, buffer, buffer.GetSize()); -} - -ZIPINLINE bool -ZipPlatform::RemoveFile(LPCTSTR lpszFileName, bool bThrow) -{ - if (!::DeleteFile((LPTSTR)lpszFileName)) - if (bThrow) - CZipException::Throw(CZipException::notRemoved, lpszFileName); - else - return false; - return true; -} -ZIPINLINE bool -ZipPlatform::RenameFile(LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow) -{ - if (!::MoveFile((LPTSTR)lpszOldName, (LPTSTR)lpszNewName)) - if (bThrow) - CZipException::Throw(CZipException::notRenamed, lpszOldName); - else - return false; - return true; -} -ZIPINLINE bool -ZipPlatform::IsDirectory(DWORD uAttr) -{ - return (uAttr & FILE_ATTRIBUTE_DIRECTORY) != 0; -} -ZIPINLINE bool -ZipPlatform::CreateDirectory(LPCTSTR lpDirectory) -{ - return ::CreateDirectory(lpDirectory, NULL) != 0; -} - -ZIPINLINE DWORD -ZipPlatform::GetDefaultAttributes() -{ - return 0x81a40020; // make it readable under Unix -} - -ZIPINLINE DWORD -ZipPlatform::GetDefaultDirAttributes() -{ - return 0x41ff0010; // make it readable under Unix -} - -ZIPINLINE int -ZipPlatform::GetSystemID() -{ - return ZipCompatibility::zcDosFat; -} - -ZIPINLINE bool -ZipPlatform::GetSystemCaseSensitivity() -{ - return false; -} - -#ifdef _UNICODE -int -ZipPlatform::WideToSingle(LPCTSTR lpWide, CZipAutoBuffer& szSingle) -{ - size_t wideLen = wcslen(lpWide); - if (wideLen == 0) { - szSingle.Release(); - return 0; - } - - // iLen does not include terminating character - int iLen = - WideCharToMultiByte(CP_ACP, 0, lpWide, wideLen, szSingle, 0, NULL, NULL); - if (iLen > 0) { - szSingle.Allocate(iLen, true); - iLen = WideCharToMultiByte( - CP_ACP, 0, lpWide, wideLen, szSingle, iLen, NULL, NULL); - ASSERT(iLen != 0); - } else // here it means error - { - szSingle.Release(); - iLen--; - } - return iLen; -} -int -ZipPlatform::SingleToWide(const CZipAutoBuffer& szSingle, CZipString& szWide) -{ - int singleLen = szSingle.GetSize(); - // iLen doesn't include terminating character - int iLen = MultiByteToWideChar( - CP_ACP, MB_PRECOMPOSED, szSingle.GetBuffer(), singleLen, NULL, 0); - if (iLen > 0) { - iLen = MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED, - szSingle.GetBuffer(), - singleLen, - szWide.GetBuffer(iLen), - iLen); - szWide.ReleaseBuffer(iLen); - ASSERT(iLen != 0); - } else { - szWide.Empty(); - iLen--; // return -1 - } - return iLen; -} -#endif - -#ifndef _MFC_VER -#include -#include -bool -ZipPlatform::TruncateFile(int iDes, DWORD iSize) -{ - int ret = chsize(iDes, iSize); - return ret != -1; -} - -int -ZipPlatform::OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode) -{ - switch (iShareMode) { - case (CZipFile::shareDenyWrite & CZipFile::shareDenyRead): - iShareMode = SH_DENYRW; - break; - case (CZipFile::shareDenyRead): - iShareMode = SH_DENYRD; - break; - case (CZipFile::shareDenyWrite): - iShareMode = SH_DENYWR; - break; - default: - iShareMode = SH_DENYNO; - } - return _tsopen(lpszFileName, - iMode, - iShareMode, - S_IREAD | S_IWRITE /*required only when O_CREAT mode*/); -} - -bool -ZipPlatform::FlushFile(int iDes) -{ - return _commit(iDes) == 0; -} - -int -ZipPlatform::GetFileSystemHandle(int iDes) -{ - return _get_osfhandle(iDes); -} - -#endif //_MFC_VER diff --git a/src/smpackagee/ZipArchive/ZipAbstractFile.h b/src/smpackagee/ZipArchive/ZipAbstractFile.h deleted file mode 100644 index 548674b793..0000000000 --- a/src/smpackagee/ZipArchive/ZipAbstractFile.h +++ /dev/null @@ -1,54 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipAbstractFile.h $ -// $Archive: /ZipArchive/ZipAbstractFile.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined( \ - AFX_ZIPABSTRACTFILE_H__46F247DE_21A6_4D12_AF64_B5A6B3CF4D57__INCLUDED_) -#define AFX_ZIPABSTRACTFILE_H__46F247DE_21A6_4D12_AF64_B5A6B3CF4D57__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -#include "ZipExport.h" -#include "ZipString.h" -#include "global.h" - -class ZIP_API CZipAbstractFile -{ - public: - enum - { - begin = SEEK_SET, // 0 - current = SEEK_CUR, // 1 - end = SEEK_END // 2 - }; - CZipAbstractFile() {} - virtual bool Open(LPCTSTR, UINT, bool) { return true; } - virtual void Close() = 0; - virtual void Flush() = 0; - virtual ZIP_ULONGLONG GetPosition() const = 0; - virtual ZIP_ULONGLONG Seek(ZIP_LONGLONG lOff, int nFrom) = 0; - virtual ZIP_ULONGLONG GetLength() const = 0; - virtual void SetLength(ZIP_ULONGLONG nNewLen) = 0; - virtual ZIP_ULONGLONG SeekToBegin() { return Seek(0, begin); } - virtual ZIP_ULONGLONG SeekToEnd() { return Seek(0, end); } - virtual CZipString GetFilePath() const = 0; - virtual UINT Read(void* lpBuf, UINT nCount) = 0; - virtual void Write(const void* lpBuf, UINT nCount) = 0; - virtual bool IsClosed() const = 0; - virtual ~CZipAbstractFile(){}; -}; - -#endif // !defined(AFX_ZIPABSTRACTFILE_H__46F247DE_21A6_4D12_AF64_B5A6B3CF4D57__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipArchive-net2003.vcproj b/src/smpackagee/ZipArchive/ZipArchive-net2003.vcproj deleted file mode 100644 index 174388a48a..0000000000 --- a/src/smpackagee/ZipArchive/ZipArchive-net2003.vcproj +++ /dev/null @@ -1,1285 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/smpackagee/ZipArchive/ZipArchive-net2008.vcproj b/src/smpackagee/ZipArchive/ZipArchive-net2008.vcproj deleted file mode 100644 index 1874a384db..0000000000 --- a/src/smpackagee/ZipArchive/ZipArchive-net2008.vcproj +++ /dev/null @@ -1,1686 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/smpackagee/ZipArchive/ZipArchive.cpp b/src/smpackagee/ZipArchive/ZipArchive.cpp deleted file mode 100644 index ad30d0c2f6..0000000000 --- a/src/smpackagee/ZipArchive/ZipArchive.cpp +++ /dev/null @@ -1,2908 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipArchive.cpp $ -// $Archive: /ZipArchive/ZipArchive.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipArchive.h" -#include "stdafx.h" -// #include "ZipPathComponent.h" -#include "ZipCompatibility.h" -#include "ZipPlatform.h" - -#include - -#ifndef DEF_MEM_LEVEL -#if MAX_MEM_LEVEL >= 8 -#define DEF_MEM_LEVEL 8 -#else -#define DEF_MEM_LEVEL MAX_MEM_LEVEL -#endif -#endif - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -#define ZIP_COMPR_REPL_MASK 0xffffff00 -#define ZIP_COMPR_REPL_SIGN \ - 0x0100 // first 8 bits should be 00 (reserved for compression level), next 8 - // should be different from ff (to distinguish from -1) - -const TCHAR CZipArchive::m_gszCopyright[] = { - _T("ZipArchive library Copyright 2000 - 2003 Tadeusz Dracz") -}; - -void -CZipAddNewFileInfo::Defaults() -{ - m_iSmartLevel = CZipArchive::zipsmSafeSmart; - m_iReplaceIndex = -1; - m_nBufSize = 65536; - m_iComprLevel = -1; // default -} - -CZipArchive::CZipArchive() -{ - - m_bRemoveDriveLetter = m_bDetectZlibMemoryLeaks = true; - m_bIgnoreCRC = m_bAutoFlush = false; - m_centralDir.m_pStorage = &m_storage; - m_info.m_stream.zalloc = (alloc_func)_zliballoc; - m_info.m_stream.zfree = (free_func)_zlibfree; - m_iFileOpened = nothing; - SetCaseSensitivity(ZipPlatform::GetSystemCaseSensitivity()); -} - -CZipArchive::~CZipArchive() -{ - // Close(); // cannot be here: if an exception is thrown strange things can - // happen - EmptyPtrList(); -} - -void -CZipArchive::Open(LPCTSTR szPathName, int iMode, int iVolumeSize) -{ - if (!IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive already opened.\n"), __FILE__, __LINE__); - return; - } - m_storage.Open(szPathName, iMode, iVolumeSize); - OpenInternal(iMode); -} - -void -CZipArchive::Open(CZipMemFile& mf, int iMode) -{ - if (!IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive already opened.\n"), __FILE__, __LINE__); - return; - } - if (iMode != zipOpen && iMode != zipOpenReadOnly && iMode != zipCreate) { - TRACE(_T("%s(%i) : Mode not supported.\n"), __FILE__, __LINE__); - return; - } - m_storage.Open(mf, iMode); - OpenInternal(iMode); -} - -void -CZipArchive::OpenInternal(int iMode) -{ - m_pszPassword.Release(); - m_iFileOpened = nothing; - m_centralDir.Init(); - m_iArchiveSystCompatib = ZipPlatform::GetSystemID(); - m_szRootPath.Empty(); - if ((iMode == zipOpen) || (iMode == zipOpenReadOnly)) { - m_centralDir.Read(); - // if there is at least one file, get system comp. from the first one - if (m_centralDir.IsValidIndex(0)) { - int iSystemComp = m_centralDir[0]->GetSystemCompatibility(); - if (ZipCompatibility::IsPlatformSupported(iSystemComp)) - m_iArchiveSystCompatib = iSystemComp; - } - } -} - -bool -CZipArchive::IsClosed(bool bArchive) const -{ - return bArchive ? (m_storage.GetCurrentDisk() == -1) - : (!m_storage.m_pFile || m_storage.m_pFile->IsClosed()); -} - -void -CZipArchive::ThrowError(int err, bool bZlib) -{ - if (bZlib) - err = CZipException::ZlibErrToZip(err); - CZipException::Throw( - err, IsClosed() ? _T("") : (LPCTSTR)m_storage.m_pFile->GetFilePath()); -} - -bool -CZipArchive::GetFileInfo(CZipFileHeader& fhInfo, WORD uIndex) const -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return false; - } - - if (!m_centralDir.IsValidIndex(uIndex)) - return false; - - fhInfo = *(m_centralDir[uIndex]); - m_centralDir.ConvertFileName(true, false, &fhInfo); - return true; -} - -int -CZipArchive::FindFile(LPCTSTR lpszFileName, - int iCaseSensitive, - bool bFileNameOnly) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return (int)-1; - } - bool bCS; - bool bSporadically; - switch (iCaseSensitive) { - case ffCaseSens: - bCS = true; - bSporadically = true; - break; - case ffNoCaseSens: - bCS = false; - bSporadically = true; - break; - default: - bCS = m_bCaseSensitive; - bSporadically = false; - } - return m_centralDir.FindFile( - lpszFileName, bCS, bSporadically, bFileNameOnly); -} - -bool -CZipArchive::OpenFile(WORD uIndex) -{ - if (!m_centralDir.IsValidIndex(uIndex)) { - ASSERT(FALSE); - return false; - } - if (m_storage.IsSpanMode() == 1) { - TRACE(_T("%s(%i) : You cannot extract from the span in creation.\n"), - __FILE__, - __LINE__); - return false; - } - - if (m_iFileOpened) { - TRACE(_T("%s(%i) : A file already opened.\n"), __FILE__, __LINE__); - return false; - } - - m_info.Init(); - m_centralDir.OpenFile(uIndex); - if (CurrentFile()->IsEncrypted()) { - - if (m_pszPassword.GetSize() == 0) { - TRACE(_T("%s(%i) : Password not set for the encrypted file.\n"), - __FILE__, - __LINE__); - ThrowError(CZipException::badPassword); - } - CryptInitKeys(); - if (!CryptCheck()) - ThrowError(CZipException::badPassword); - } else if (m_pszPassword.GetSize() != 0) { - TRACE(_T("%s(%i) : Password set for a not encrypted file. Ignoring ") - _T("password.\n"), - __FILE__, - __LINE__); - } - - WORD uMethod = CurrentFile()->m_uMethod; - - if ((uMethod != 0) && (uMethod != Z_DEFLATED)) - ThrowError(CZipException::badZipFile); - - if (uMethod == Z_DEFLATED) { - m_info.m_stream.opaque = m_bDetectZlibMemoryLeaks ? &m_list : 0; - int err = inflateInit2(&m_info.m_stream, -MAX_WBITS); - // * windowBits is passed < 0 to tell that there is no zlib - // header. - // * Note that in this case inflate *requires* an extra "dummy" - // byte - // * after the compressed stream in order to complete - // decompression and - // * return Z_STREAM_END. - CheckForError(err); - } - m_info.m_uComprLeft = CurrentFile()->m_uComprSize; - if (CurrentFile()->IsEncrypted()) - m_info.m_uComprLeft -= ZIPARCHIVE_ENCR_HEADER_LEN; - m_info.m_uUncomprLeft = CurrentFile()->m_uUncomprSize; - m_info.m_uCrc32 = 0; - m_info.m_stream.total_out = 0; - m_info.m_stream.avail_in = 0; - - m_iFileOpened = extract; - return true; -} - -int -CZipArchive::GetLocalExtraField(char* pBuf, int iSize) const -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return -1; - } - - if (m_iFileOpened != extract) { - TRACE( - _T("%s(%i) : A file must be opened to get the local extra field.\n"), - __FILE__, - __LINE__); - return -1; - } - - int size = m_centralDir.m_pLocalExtraField.GetSize(); - if (!pBuf || !size) - return size; - - if (iSize < size) - size = iSize; - - memcpy(pBuf, m_centralDir.m_pLocalExtraField, size); - return size; -} - -void* -CZipArchive::_zliballoc(void* opaque, UINT items, UINT size) -{ - void* p = new char[size * items]; - if (opaque) { - CZipPtrList* list = (CZipPtrList*)opaque; - list->AddTail(p); - } - return p; -} - -void -CZipArchive::_zlibfree(void* opaque, void* address) -{ - if (opaque) { - CZipPtrList* list = (CZipPtrList*)opaque; - CZipPtrListIter iter = list->Find(address); - if (list->IteratorValid(iter)) - list->RemoveAt(iter); - } - delete[](char*) address; -} - -void -CZipArchive::CheckForError(int iErr) -{ - if ((iErr == Z_OK) || (iErr == Z_NEED_DICT)) - return; - - ThrowError(iErr, true); -} - -CZipFileHeader* -CZipArchive::CurrentFile() -{ - ASSERT(m_centralDir.m_pOpenedFile); - return m_centralDir.m_pOpenedFile; -} - -DWORD -CZipArchive::ReadFile(void* pBuf, DWORD iSize) -{ - if (m_iFileOpened != extract) { - TRACE( - _T("%s(%i) : Current file must be opened.\n"), __FILE__, __LINE__); - return 0; - } - - if (!pBuf || !iSize) - return 0; - - m_info.m_stream.next_out = (Bytef*)pBuf; - m_info.m_stream.avail_out = - iSize > m_info.m_uUncomprLeft ? m_info.m_uUncomprLeft : iSize; - - DWORD iRead = 0; - - // may happen when the file is 0 sized - bool bForce = m_info.m_stream.avail_out == 0 && m_info.m_uComprLeft > 0; - while (m_info.m_stream.avail_out > 0 || - (bForce && m_info.m_uComprLeft > 0)) { - if ((m_info.m_stream.avail_in == 0) && - (m_info.m_uComprLeft >= 0)) // Also when there are zero bytes left! - { - DWORD uToRead = m_info.m_pBuffer.GetSize(); - if (m_info.m_uComprLeft < uToRead) - uToRead = m_info.m_uComprLeft; - - if (uToRead == 0) { - uToRead = 1; // Add dummy byte at end of compressed data. - } else { - m_storage.Read(m_info.m_pBuffer, uToRead, false); - CryptDecodeBuffer(uToRead); - } - - m_info.m_uComprLeft -= uToRead; - - m_info.m_stream.next_in = (Bytef*)(char*)m_info.m_pBuffer; - m_info.m_stream.avail_in = uToRead; - } - - if (CurrentFile()->m_uMethod == 0) { - DWORD uToCopy = m_info.m_stream.avail_out < m_info.m_stream.avail_in - ? m_info.m_stream.avail_out - : m_info.m_stream.avail_in; - - memcpy(m_info.m_stream.next_out, m_info.m_stream.next_in, uToCopy); - - m_info.m_uCrc32 = - crc32(m_info.m_uCrc32, m_info.m_stream.next_out, uToCopy); - - m_info.m_uUncomprLeft -= uToCopy; - m_info.m_stream.avail_in -= uToCopy; - m_info.m_stream.avail_out -= uToCopy; - m_info.m_stream.next_out += uToCopy; - m_info.m_stream.next_in += uToCopy; - m_info.m_stream.total_out += uToCopy; - iRead += uToCopy; - } else { - DWORD uTotal = m_info.m_stream.total_out; - Bytef* pOldBuf = m_info.m_stream.next_out; - int err = inflate(&m_info.m_stream, Z_SYNC_FLUSH); - DWORD uToCopy = m_info.m_stream.total_out - uTotal; - - m_info.m_uCrc32 = crc32(m_info.m_uCrc32, pOldBuf, uToCopy); - - m_info.m_uUncomprLeft -= uToCopy; - iRead += uToCopy; - - if (err == Z_STREAM_END) - return iRead; - - CheckForError(err); - } - } - - return iRead; -} - -void -CZipArchive::Close(int iAfterException, bool bUpdateTimeStamp) -{ - // if after an exception - the archive may be closed, but the file may be - // opened - if (IsClosed() && (!iAfterException || IsClosed(false))) { - TRACE( - _T("%s(%i) : ZipArchive is already closed.\n"), __FILE__, __LINE__); - return; - } - - if (m_iFileOpened == extract) - CloseFile(NULL, iAfterException != afNoException); - - if (m_iFileOpened == compress) - CloseNewFile(iAfterException != afNoException); - - if (iAfterException != afAfterException && - !IsClosed(false)) // in disk spanning when user aborts - WriteCentralDirectory(false); // we will flush in CZipStorage::Close - - time_t tNewestTime = 0; - - if (bUpdateTimeStamp) { - int iSize = m_centralDir.m_headers.GetSize(); - for (int i = 0; i < iSize; i++) { - time_t tFileInZipTime = m_centralDir[i]->GetTime(); - if (tFileInZipTime > tNewestTime) - tNewestTime = tFileInZipTime; - } - } - m_centralDir.Clear(); - CZipString szFileName = - m_storage.Close(iAfterException == afAfterException); - if (bUpdateTimeStamp && !szFileName.IsEmpty()) - ZipPlatform::SetFileModTime(szFileName, tNewestTime); -} - -void -CZipArchive::WriteCentralDirectory(bool bFlush) -{ - m_centralDir.Write(GetCallback(cbSave)); - if (bFlush) - m_storage.Flush(); -} - -void -CZipArchive::SetCallback(CZipActionCallback* pCallback, int iWhich) -{ - CallbackType cbs[] = { cbAdd, cbAddTmp, cbAddStore, - cbExtract, cbDeleteCnt, cbDelete, - cbTest, cbSave, cbGetFromArchive, - cbRename, cbReplace }; - int iCount = sizeof(cbs) / sizeof(CallbackType); - for (int i = 0; i < iCount; i++) { - CallbackType iCallback = cbs[i]; - if (iWhich & iCallback) - m_callbacks.Set(pCallback, iCallback); - } -} - -void -CZipArchive::SetAdvanced(int iWriteBuffer, - int iGeneralBuffer, - int iSearchBuffer) -{ - if (!IsClosed()) { - TRACE(_T("%s(%i) : Set this options before opening the archive.\n"), - __FILE__, - __LINE__); - return; - } - - m_storage.m_iWriteBufferSize = iWriteBuffer < 1024 ? 1024 : iWriteBuffer; - m_info.m_iBufferSize = iGeneralBuffer < 1024 ? 1024 : iGeneralBuffer; - m_centralDir.m_iBufferSize = iSearchBuffer < 1024 ? 1024 : iSearchBuffer; -} - -int -CZipArchive::CloseFile(CZipFile& file) -{ - CZipString temp = file.GetFilePath(); - file.Close(); - return CloseFile(temp); -} - -int -CZipArchive::CloseFile(LPCTSTR lpszFilePath, bool bAfterException) -{ - if (m_iFileOpened != extract) { - TRACE(_T("%s(%i) : No opened file.\n"), __FILE__, __LINE__); - return false; - } - - int iRet = 1; - if (!bAfterException) { - if (m_info.m_uUncomprLeft == 0) { - if (!m_bIgnoreCRC && m_info.m_uCrc32 != CurrentFile()->m_uCrc32) - ThrowError(CZipException::badCrc); - } else - iRet = -1; - - if (CurrentFile()->m_uMethod == Z_DEFLATED) - inflateEnd(&m_info.m_stream); - - if (lpszFilePath) { - - if (!ZipPlatform::SetFileModTime(lpszFilePath, - CurrentFile()->GetTime()) || - !ZipPlatform::SetFileAttr(lpszFilePath, - CurrentFile()->GetSystemAttr())) - iRet = -2; - } - } - - m_centralDir.CloseFile(bAfterException); - - m_iFileOpened = nothing; - m_info.ReleaseBuf(); - EmptyPtrList(); - return iRet; -} - -bool -CZipArchive::OpenNewFile(CZipFileHeader& header, - int iLevel, - LPCTSTR lpszFilePath, - DWORD uInternal) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return false; - } - - if (m_iFileOpened) { - TRACE(_T("%s(%i) : A file already opened.\n"), __FILE__, __LINE__); - return false; - } - - if (m_storage.IsSpanMode() == -1) { - TRACE(_T("%s(%i) : You cannot add files to the existing disk spannig ") - _T("archive.\n"), - __FILE__, - __LINE__); - return false; - } - - if (GetCount() == (WORD)USHRT_MAX) { - TRACE(_T("%s(%i) : Maximum file count inside archive reached.\n"), - __FILE__, - __LINE__); - return false; - } - - DWORD uAttr = 0; // ..compiler - time_t ttime; - if (lpszFilePath) { - - if (!ZipPlatform::GetFileAttr(lpszFilePath, uAttr)) - // do not continue - if the file was a directory then not - // recognizing it will cause serious errors (need uAttr to recognize - // it) - return false; - if (!ZipPlatform::GetFileModTime(lpszFilePath, ttime)) - ttime = time(NULL); - } - - m_info.Init(); - - if (lpszFilePath) { - header.SetTime(ttime); - SetFileHeaderAttr(header, uAttr); // set system compatibility as well - } else - header.SetSystemCompatibility(m_iArchiveSystCompatib); - - CZipString szFileName = header.GetFileName(); - - bool bIsDirectory = header.IsDirectory(); - if (bIsDirectory) { - int iNameLen = szFileName.GetLength(); - if (!iNameLen || - !CZipPathComponent::IsSeparator(szFileName[iNameLen - 1])) { - szFileName += CZipPathComponent::m_cSeparator; - header.SetFileName(szFileName); - } - } - - if (szFileName.IsEmpty()) { - szFileName.Format(_T("file%i"), GetCount()); - header.SetFileName(szFileName); - } - - // make sure that all slashes are correct (as the current system default) - // because AddNewFile calls InsertFindFastElement if necessary and - // the find array keeps all the files already converted to the current - // system standards we do not perform Oem->Ansi here, because who would pass - // oem values here? - // - ZipCompatibility::SlashBackslashChg(header.m_pszFileName, true); - - bool bEncrypted = m_pszPassword.GetSize() != 0; - -#ifdef _DEBUG - if (bIsDirectory && bEncrypted) - TRACE(_T("%s(%i) : Encrypting a directory. It's pointless.\n\ - Clear the password before adding a directory.\n"), - __FILE__, - __LINE__); -#endif - - int iReplaceIndex = -1; - bool bReplace = (iLevel & 0xffff) == ZIP_COMPR_REPL_SIGN; - if (bReplace) { - int iMask = ZIP_COMPR_REPL_MASK; - iReplaceIndex = (iLevel & iMask) >> 16; - iLevel = (char)(iLevel & ~iMask); - ASSERT(iLevel == 0); - } else - uInternal = 0; - - if (iLevel < -1 || iLevel > 9) - iLevel = -1; - - if (!header.PrepareData(iLevel, m_storage.IsSpanMode() == 1, bEncrypted)) - ThrowError(CZipException::tooLongFileName); - - if (bReplace) { - uInternal += header.GetSize(true); - if (header.IsEncrypted()) - uInternal += ZIPARCHIVE_ENCR_HEADER_LEN; - if (header.IsDataDescr()) - uInternal += - ZIPARCHIVE_DATADESCRIPTOR_LEN + 4; // CZipCentralDir::CloseNewFile - } - m_centralDir.AddNewFile(header, iReplaceIndex); - if (bReplace) - MakeSpaceForReplace(iReplaceIndex, uInternal, szFileName); - - // this ensures the conversion will take place anyway (must take because we - // are going to write the local header in a moment - m_centralDir.ConvertFileName(false, m_centralDir.m_bConvertAfterOpen); - - CurrentFile()->WriteLocal(m_storage); - - // we have written the local header, but if we keep filenames not converted - // in memory , we have to restore the non-converted value - if (m_centralDir.m_bConvertAfterOpen) - CurrentFile()->SetFileName(szFileName); - - if (bEncrypted) { - CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN); - // use pseudo-crc since we don't know it yet - CryptCryptHeader((long)header.m_uModTime << 16, buf); - m_storage.Write(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false); - } - - m_info.m_uComprLeft = 0; - m_info.m_stream.avail_in = (uInt)0; - m_info.m_stream.avail_out = (uInt)m_info.m_pBuffer.GetSize(); - m_info.m_stream.next_out = (Bytef*)(char*)m_info.m_pBuffer; - m_info.m_stream.total_in = 0; - m_info.m_stream.total_out = 0; - - if (bIsDirectory && (CurrentFile()->m_uMethod != 0)) - CurrentFile()->m_uMethod = 0; - - if (CurrentFile()->m_uMethod == Z_DEFLATED) { - m_info.m_stream.opaque = m_bDetectZlibMemoryLeaks ? &m_list : 0; - - int err = deflateInit2(&m_info.m_stream, - iLevel, - Z_DEFLATED, - -MAX_WBITS, - DEF_MEM_LEVEL, - Z_DEFAULT_STRATEGY); - - CheckForError(err); - } - m_iFileOpened = compress; - return true; -} - -bool -CZipArchive::ExtractFile(WORD uIndex, - LPCTSTR lpszPath, - bool bFullPath, - LPCTSTR lpszNewName, - DWORD nBufSize) -{ - - if (!nBufSize && !lpszPath) - return false; - - CZipFileHeader header; - GetFileInfo(header, - uIndex); // to ensure that slash and oem conversions take place - CZipString szFileNameInZip = (LPCTSTR)header.GetFileName(); - CZipString szFile = PredictExtractedFileName( - szFileNameInZip, lpszPath, bFullPath, lpszNewName); - CZipActionCallback* pCallback = GetCallback(cbExtract); - if (pCallback) - pCallback->Init(szFileNameInZip, szFile); - - if (header.IsDirectory()) { - if (pCallback) - pCallback->SetTotal(0); // in case of calling LeftToDo afterwards - - ZipPlatform::ForceDirectory(szFile); - ZipPlatform::SetFileAttr(szFile, header.GetSystemAttr()); - - if (pCallback) - pCallback->CallbackEnd(); - return true; - } else { - if (pCallback) - pCallback->SetTotal(header.m_uUncomprSize); - - if (!OpenFile(uIndex)) - return false; - - CZipPathComponent zpc(szFile); - ZipPlatform::ForceDirectory(zpc.GetFilePath()); - CZipFile f(szFile, - CZipFile::modeWrite | CZipFile::modeCreate | - CZipFile::shareDenyWrite); - DWORD iRead; - CZipAutoBuffer buf(nBufSize); - int iAborted = 0; - do { - iRead = ReadFile(buf, buf.GetSize()); - if (iRead) { - f.Write(buf, iRead); - if (pCallback) - if (!(*pCallback)(iRead)) { - if (iRead == buf.GetSize() && - ReadFile(buf, 1) != - 0) // test one byte if there is something left - iAborted = CZipException::abortedAction; - else - iAborted = - CZipException::abortedSafely; // we did it! - break; - } - } - } while (iRead == buf.GetSize()); - bool bRet = CloseFile(f) == 1; - if (!bRet && iAborted == CZipException::abortedSafely) - iAborted = CZipException::abortedAction; // sorry, finished, but not - // successfull - - if (pCallback) - pCallback->CallbackEnd(); - - if (iAborted) - CZipException::Throw( - iAborted, - szFile); // throw to distuingiush from other return codes - return bRet; - } -} - -bool -CZipArchive::ExtractFile(WORD uIndex, CZipMemFile& mf, DWORD nBufSize) -{ - if (!nBufSize) - return false; - - CZipFileHeader header; - GetFileInfo(header, - uIndex); // to ensure that slash and oem conversions take place - CZipActionCallback* pCallback = GetCallback(cbExtract); - if (pCallback) { - pCallback->Init(header.GetFileName()); - pCallback->SetTotal(header.m_uUncomprSize); - } - - if (header.IsDirectory() || !OpenFile(uIndex)) - return false; - - CZipAutoBuffer buf(nBufSize); - mf.SeekToEnd(); - DWORD iRead; - int iAborted = 0; - do { - iRead = ReadFile(buf, buf.GetSize()); - if (iRead) { - mf.Write(buf, iRead); - if (pCallback) - if (!(*pCallback)(iRead)) { - if (iRead == buf.GetSize() && - ReadFile(buf, 1) != - 0) // test one byte if there is something left - iAborted = CZipException::abortedAction; - else - iAborted = CZipException::abortedSafely; // we did it! - break; - } - } - } while (iRead == buf.GetSize()); - bool bRet = CloseFile() == 1; - if (!bRet && iAborted == CZipException::abortedSafely) - iAborted = - CZipException::abortedAction; // sorry, finished, but not successfull - - if (pCallback) - pCallback->CallbackEnd(); - - if (iAborted) - CZipException::Throw( - iAborted); // throw to distuingiush from other return codes - return bRet; -} - -void -CZipArchive::SetExtraField(const char* pBuf, WORD iSize) -{ - if (m_iFileOpened != compress) { - TRACE(_T("%s(%i) : A new file must be opened.\n"), __FILE__, __LINE__); - return; - } - if (!pBuf || !iSize) - return; - - CurrentFile()->m_pExtraField.Allocate(iSize); - memcpy(CurrentFile()->m_pExtraField, pBuf, iSize); -} - -bool -CZipArchive::WriteNewFile(const void* pBuf, DWORD iSize) -{ - if (m_iFileOpened != compress) { - TRACE(_T("%s(%i) : A new file must be opened.\n"), __FILE__, __LINE__); - return false; - } - - m_info.m_stream.next_in = (Bytef*)pBuf; - m_info.m_stream.avail_in = iSize; - CurrentFile()->m_uCrc32 = - crc32(CurrentFile()->m_uCrc32, (Bytef*)pBuf, iSize); - - while (m_info.m_stream.avail_in > 0) { - if (m_info.m_stream.avail_out == 0) { - CryptEncodeBuffer(); - m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); - m_info.m_uComprLeft = 0; - m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize(); - m_info.m_stream.next_out = (Bytef*)(char*)m_info.m_pBuffer; - } - - if (CurrentFile()->m_uMethod == Z_DEFLATED) { - DWORD uTotal = m_info.m_stream.total_out; - int err = deflate(&m_info.m_stream, Z_NO_FLUSH); - CheckForError(err); - m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal; - } else { - DWORD uToCopy = - (m_info.m_stream.avail_in < m_info.m_stream.avail_out) - ? m_info.m_stream.avail_in - : m_info.m_stream.avail_out; - - memcpy(m_info.m_stream.next_out, m_info.m_stream.next_in, uToCopy); - - m_info.m_stream.avail_in -= uToCopy; - m_info.m_stream.avail_out -= uToCopy; - m_info.m_stream.next_in += uToCopy; - m_info.m_stream.next_out += uToCopy; - m_info.m_stream.total_in += uToCopy; - m_info.m_stream.total_out += uToCopy; - m_info.m_uComprLeft += uToCopy; - } - } - - return true; -} - -bool -CZipArchive::CloseNewFile(bool bAfterException) -{ - if (m_iFileOpened != compress) { - TRACE(_T("%s(%i) : A new file must be opened.\n"), __FILE__, __LINE__); - return false; - } - - m_info.m_stream.avail_in = 0; - if (!bAfterException) { - int err = Z_OK; - if (CurrentFile()->m_uMethod == Z_DEFLATED) - while (err == Z_OK) { - if (m_info.m_stream.avail_out == 0) { - CryptEncodeBuffer(); - m_storage.Write( - m_info.m_pBuffer, m_info.m_uComprLeft, false); - m_info.m_uComprLeft = 0; - m_info.m_stream.avail_out = m_info.m_pBuffer.GetSize(); - m_info.m_stream.next_out = (Bytef*)(char*)m_info.m_pBuffer; - } - DWORD uTotal = m_info.m_stream.total_out; - err = deflate(&m_info.m_stream, Z_FINISH); - m_info.m_uComprLeft += m_info.m_stream.total_out - uTotal; - } - - if (err == Z_STREAM_END) - err = Z_OK; - CheckForError(err); - - if (m_info.m_uComprLeft > 0) { - CryptEncodeBuffer(); - m_storage.Write(m_info.m_pBuffer, m_info.m_uComprLeft, false); - } - - if (CurrentFile()->m_uMethod == Z_DEFLATED) { - err = deflateEnd(&m_info.m_stream); - CheckForError(err); - } - - // it may be increased by the encrypted header size - CurrentFile()->m_uComprSize += m_info.m_stream.total_out; - CurrentFile()->m_uUncomprSize = m_info.m_stream.total_in; - - m_centralDir.CloseNewFile(); - } else - m_centralDir.m_pOpenedFile = NULL; - - m_iFileOpened = nothing; - m_info.ReleaseBuf(); - EmptyPtrList(); - - if (m_bAutoFlush && !bAfterException) - Flush(); - - return true; -} - -void -CZipArchive::DeleteFile(WORD uIndex) -{ - CZipWordArray indexes; - indexes.Add(uIndex); - DeleteFiles(indexes); -} - -void -CZipArchive::GetIndexes(const CZipStringArray& aNames, CZipWordArray& aIndexes) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return; - } - int iSize = aNames.GetSize(); - for (WORD i = 0; i < iSize; i++) { - int idx = FindFile(aNames[i], ffDefault, false); - if (idx != -1) - aIndexes.Add((WORD)idx); - } -} - -void -CZipArchive::DeleteFiles(const CZipStringArray& aNames) -{ - CZipWordArray indexes; - GetIndexes(aNames, indexes); - DeleteFiles(indexes); -} - -void -CZipArchive::DeleteFiles(CZipWordArray& aIndexes) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return; - } - - if (m_storage.IsSpanMode()) { - TRACE(_T("%s(%i) : You cannot delete files from the disk spannig ") - _T("archive.\n"), - __FILE__, - __LINE__); - return; - } - - if (m_iFileOpened) { - TRACE( - _T("%s(%i) : You cannot delete files if there is a file opened.\n"), - __FILE__, - __LINE__); - return; - } - - CZipActionCallback* pCallback = GetCallback(cbDeleteCnt); - if (pCallback) - pCallback->Init(); - - int uSize = aIndexes.GetSize(); - if (!uSize) { - TRACE( - _T("%s(%i) : The indekses array is empty.\n"), __FILE__, __LINE__); - return; - } - - // remove all - that's easy so don't waste the time - if (uSize == GetCount()) { - pCallback = GetCallback(cbDelete); - if (pCallback) { - // do it right and sent the notification - pCallback->Init(); - pCallback->SetTotal(uSize); - } - - m_centralDir.RemoveFromDisk(); - m_storage.m_pFile->SetLength(m_centralDir.GetBytesBefore()); - m_centralDir.RemoveAll(); - if (m_bAutoFlush) - Flush(); - if (pCallback) - pCallback->CallbackEnd(); - return; - } - - aIndexes.Sort(true); - - CZipArray aInfo; - - int iDelIndex = 0; - - int iStep = 0; // for the compiler - if (pCallback) { - pCallback->SetTotal(GetCount()); - iStep = CZipActionCallback::m_iStep; // we don't want to wait forever - } - - int i; - int uMaxDelIndex = aIndexes[uSize - 1]; - for (i = aIndexes[0]; i < GetCount(); i++) { - CZipFileHeader* pHeader = m_centralDir[i]; - bool bDelete; - if (i <= uMaxDelIndex && i == aIndexes[iDelIndex]) { - iDelIndex++; - bDelete = true; - } else - bDelete = false; - aInfo.Add(CZipDeleteInfo(pHeader, bDelete)); - if (pCallback && (!(i % iStep))) - if (!(*pCallback)(iStep)) - ThrowError(CZipException::abortedSafely); - } - ASSERT(iDelIndex == uSize); - - uSize = aInfo.GetSize(); - if (!uSize) // it is possible - return; - - // now we start deleting (not safe to break) - pCallback = GetCallback(cbDelete); - if (pCallback) - pCallback->Init(); - - m_centralDir.RemoveFromDisk(); - - DWORD uTotalToMoveBytes = 0, uLastOffset = m_storage.m_pFile->GetLength() - - m_centralDir.GetBytesBefore(); - // count the number of bytes to move - for (i = uSize - 1; i >= 0; i--) { - const CZipDeleteInfo& di = aInfo[i]; - if (!di.m_bDelete) - uTotalToMoveBytes += uLastOffset - di.m_pHeader->m_uOffset; - uLastOffset = di.m_pHeader->m_uOffset; - } - if (pCallback) - pCallback->CallbackEnd(); - - if (pCallback) - pCallback->SetTotal(uTotalToMoveBytes); - - m_info.Init(); - - DWORD uMoveBy = 0, uOffsetStart = 0; - for (i = 0; i < uSize; i++) { - const CZipDeleteInfo& di = aInfo[i]; - - if (di.m_bDelete) { - // next hole - DWORD uTemp = di.m_pHeader->m_uOffset; - m_centralDir.RemoveFile(di.m_pHeader); // first remove - if (uOffsetStart) { - // copy the files over a previous holes - MovePackedFiles(uOffsetStart, uTemp, uMoveBy, pCallback); - uOffsetStart = 0; // never be at the beginning, because the - // first file is always to be deleted - } - if (i == uSize - 1) - uTemp = (m_storage.m_pFile->GetLength() - - m_centralDir.GetBytesBefore()) - - uTemp; - else - uTemp = aInfo[i + 1].m_pHeader->m_uOffset - uTemp; - - uMoveBy += uTemp; - } else { - if (uOffsetStart == 0) // find contiuos area to move - uOffsetStart = di.m_pHeader->m_uOffset; - di.m_pHeader->m_uOffset -= uMoveBy; - } - } - if (uOffsetStart) - MovePackedFiles(uOffsetStart, - m_storage.m_pFile->GetLength() - - m_centralDir.GetBytesBefore(), - uMoveBy, - pCallback); - - m_info.ReleaseBuf(); - if (uMoveBy) // just in case - m_storage.m_pFile->SetLength(m_storage.m_pFile->GetLength() - uMoveBy); - - if (pCallback) - pCallback->CallbackEnd(); - - if (m_bAutoFlush) - Flush(); -} - -bool -CZipArchive::AddNewFile(LPCTSTR lpszFilePath, - int iComprLevel, - bool bFullPath, - int iSmartLevel, - unsigned long nBufSize) -{ - - CZipAddNewFileInfo zanfi(lpszFilePath, bFullPath); - zanfi.m_iComprLevel = iComprLevel; - zanfi.m_iSmartLevel = zipsmSafeSmart; - zanfi.m_nBufSize = nBufSize; - return AddNewFile(zanfi); -} - -bool -CZipArchive::AddNewFile(LPCTSTR lpszFilePath, - LPCTSTR lpszFileNameInZip, - int iComprLevel, - int iSmartLevel, - unsigned long nBufSize) -{ - CZipAddNewFileInfo zanfi(lpszFilePath, lpszFileNameInZip); - zanfi.m_iComprLevel = iComprLevel; - zanfi.m_iSmartLevel = zipsmSafeSmart; - zanfi.m_nBufSize = nBufSize; - return AddNewFile(zanfi); -} - -bool -CZipArchive::AddNewFile(CZipMemFile& mf, - LPCTSTR lpszFileNameInZip, - int iComprLevel, - int iSmartLevel, - unsigned long nBufSize) -{ - CZipAddNewFileInfo zanfi(&mf, lpszFileNameInZip); - zanfi.m_iComprLevel = iComprLevel; - zanfi.m_iSmartLevel = zipsmSafeSmart; - zanfi.m_nBufSize = nBufSize; - return AddNewFile(zanfi); -} - -bool -CZipArchive::AddNewFile(CZipAddNewFileInfo& info) -{ - // no need for ASSERT and TRACE here - it will be done by OpenNewFile - - if (!m_info.m_iBufferSize) - return false; - CZipPathComponent::RemoveSeparators(info.m_szFilePath); - if (!info.m_szFilePath.IsEmpty()) // it may be empty after removing sep. - { - if (info.m_szFileNameInZip.IsEmpty()) { - CZipPathComponent zpc(info.m_szFilePath); - if (info.m_bFullPath) { - if (m_bRemoveDriveLetter) - info.m_szFileNameInZip = zpc.GetNoDrive(); - } else - info.m_szFileNameInZip = TrimRootPath(zpc); - } - } else if (!info.m_pFile) - return false; - - bool bSpan = GetSpanMode() != 0; - - // checking the iReplace index - if (!UpdateReplaceIndex(info.m_iReplaceIndex, info.m_szFileNameInZip)) - return false; - - bool bReplace = info.m_iReplaceIndex >= 0; - - DWORD uAttr; - time_t ttime; - if (info.m_pFile) { - uAttr = ZipPlatform::GetDefaultAttributes(); - ttime = time(NULL); - } else { - if (!ZipPlatform::GetFileAttr(info.m_szFilePath, uAttr)) - return false; // we don't know whether it is a file or a directory - if (!ZipPlatform::GetFileModTime(info.m_szFilePath, ttime)) - ttime = time(NULL); - } - CZipFileHeader header; - header.SetFileName(info.m_szFileNameInZip); - if (ZipPlatform::GetSystemID() != ZipCompatibility::zcUnix) - uAttr |= ZipCompatibility::ConvertToSystem( - uAttr, - ZipPlatform::GetSystemID(), - ZipCompatibility::zcUnix); // make it readable under Unix as well, - // since it stores its attributes in - // HIWORD(uAttr) - SetFileHeaderAttr(header, uAttr); - header.SetTime(ttime); - bool bInternal = (info.m_iSmartLevel & zipsmInternal01) != 0; - CZipActionCallback* pCallback = NULL; - if (!bInternal) { - pCallback = GetCallback(cbAdd); - if (pCallback) - pCallback->Init(info.m_szFileNameInZip, info.m_szFilePath); - } - - if (header.IsDirectory()) // will never be when m_pFile is not NULL, so we - // don't check it - { - ASSERT(!info.m_pFile); // should never happened - ASSERT(!bInternal); - - if (pCallback) - pCallback->SetTotal(0); // in case of calling LeftToDo afterwards - - // clear password for a directory - bool bRet = false; - CZipSmClrPass smcp; - if (info.m_iSmartLevel & zipsmCPassDir) - smcp.ClearPasswordSmartly(this); - - bRet = OpenNewFile( - header, - bReplace ? (info.m_iReplaceIndex << 16) | ZIP_COMPR_REPL_SIGN : 0); - - CloseNewFile(); - if (pCallback) - pCallback->CallbackEnd(); - - return bRet; - } - - CZipSmClrPass smcp; - bool bIsCompression = info.m_iComprLevel != 0; - bool bEff = (info.m_iSmartLevel & zipsmCheckForEff) && bIsCompression; - bool bCheckForZeroSized = - (info.m_iSmartLevel & zipsmCPFile0) && !GetPassword().IsEmpty(); - bool bCheckForSmallFiles = - (info.m_iSmartLevel & zipsmNotCompSmall) && bIsCompression; - DWORD iFileSize = DWORD(-1); - bool bNeedTempArchive = (bEff && bSpan) || (bReplace && bIsCompression); - if (bCheckForSmallFiles || bCheckForZeroSized || bNeedTempArchive) { - - if (info.m_pFile) - iFileSize = info.m_pFile->GetLength(); - else { - if (!ZipPlatform::GetFileSize(info.m_szFilePath, iFileSize) && bEff) - bEff = - false; // the file size is needed only when eff. in span mode - } - if (iFileSize != DWORD(-1)) { - if (bCheckForZeroSized && iFileSize == 0) - smcp.ClearPasswordSmartly(this); - if (bCheckForSmallFiles && iFileSize < 5) - info.m_iComprLevel = 0; - } - } - bool bEffInMem = bEff && (info.m_iSmartLevel & zipsmMemoryFlag); - CZipString szTempFileName; - if (bNeedTempArchive && - (bEffInMem || - !(szTempFileName = ZipPlatform::GetTmpFileName( - m_szTempPath.IsEmpty() ? NULL : (LPCTSTR)m_szTempPath, iFileSize)) - .IsEmpty())) { - CZipMemFile* pmf = NULL; - CZipArchive zip; - try { - // compress first to a temporary file, if ok - copy the data, if not - // - add storing - - if (bEffInMem) { - pmf = new CZipMemFile; - zip.Open(*pmf, zipCreate); - } else - zip.Open(szTempFileName, zipCreate); - zip.SetRootPath(m_szRootPath); - zip.SetPassword(GetPassword()); - zip.SetSystemCompatibility(m_iArchiveSystCompatib); - zip.SetCallback(pCallback, cbAdd); - // create a temporary file - int iTempReplaceIndex = info.m_iReplaceIndex; - info.m_iSmartLevel = zipsmLazy; - info.m_iReplaceIndex = -1; - if (!zip.AddNewFile(info)) - throw false; - info.m_iReplaceIndex = iTempReplaceIndex; - - // this may also happen when bReplace, but not in span mode - if (bEff) { - CZipFileHeader fh; - zip.GetFileInfo(fh, 0); - if (!fh.CompressionEfficient()) { - info.m_iComprLevel = 0; - info.m_iSmartLevel = zipsmInternal01; - // compression is pointless, store instead - throw AddNewFile(info); - } - } - - m_info.Init(); - throw GetFromArchive( - zip, 0, info.m_iReplaceIndex, true, GetCallback(cbAddTmp)); - } catch (bool bRet) { - - zip.Close( - !bRet); // that doesn't really matter how it will be closed - if (pmf) - delete pmf; - if (!bEffInMem) - ZipPlatform::RemoveFile(szTempFileName, false); - m_info.ReleaseBuf(); - return bRet; - } catch (...) { - zip.Close(true); - if (pmf) - delete pmf; - if (!bEffInMem) - ZipPlatform::RemoveFile(szTempFileName, false); - m_info.ReleaseBuf(); - throw; - } - } - - // try to open before adding - CZipFile f; - CZipAbstractFile* pf; - if (info.m_pFile) - pf = info.m_pFile; - else { - // cannot be shareDenyWrite - // from - // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/base/creating_and_opening_files.asp - // : If you specify the GENERIC_READ and GENERIC_WRITE access modes - // along with the FILE_SHARE_READ and FILE_SHARE_WRITE sharing modes in - // your first call to CreateFile. If you specify the GENERIC_READ and - // GENERIC_WRITE access modes and the FILE_SHARE_READ sharing mode only - // in your second call to CreateFile, the function will fail with a - // sharing violation because the read-only sharing mode specified in the - // second call conflicts with the read/write access that has been - // granted in the first call. - if (!f.Open(info.m_szFilePath, - CZipFile::modeRead | CZipFile::shareDenyNone, - false)) { - if (pCallback) - pCallback->CallbackEnd(); - return false; - } - pf = &f; - } - - ASSERT(pf); - // call init before opening (in case of exception we have the names) - iFileSize = pf->GetLength(); - - bool bRet; - if (bReplace) { - ASSERT(!bIsCompression); - bRet = OpenNewFile(header, - (info.m_iReplaceIndex << 16) | ZIP_COMPR_REPL_SIGN, - NULL, - iFileSize); - } else - bRet = OpenNewFile(header, info.m_iComprLevel); - if (!bRet) { - if (pCallback) - pCallback->CallbackEnd(); - - return false; - } - if (bInternal) { - // we do it here, because if in OpenNewFile is replacing - // then we get called cbReplace callback before and it would - // overwrite callback information written in pCallback->Init - pCallback = GetCallback(cbAddStore); - if (pCallback) - pCallback->Init(info.m_szFileNameInZip, info.m_szFilePath); - } - if (pCallback) - pCallback->SetTotal(iFileSize); - - CZipAutoBuffer buf(info.m_nBufSize); - DWORD iRead; - int iAborted = 0; - do { - iRead = pf->Read(buf, info.m_nBufSize); - if (iRead) { - WriteNewFile(buf, iRead); - if (pCallback) - if (!(*pCallback)(iRead)) { - // todo: we could remove here the bytes of the file - // partially added if not disk-spanning - if (iRead == buf.GetSize() && - pf->Read(buf, 1) != - 0) // test one byte if there is something left - { - if (!m_storage.IsSpanMode() && !bReplace) { - RemoveLast(true); - CloseNewFile(true); - iAborted = CZipException::abortedSafely; - } else - iAborted = CZipException::abortedAction; - } else { - iAborted = CZipException::abortedSafely; // we did it! - CloseNewFile(); - } - break; - } - } - - } while (iRead == buf.GetSize()); - if (!iAborted) - CloseNewFile(); - - if (pCallback) - pCallback->CallbackEnd(); - - if (iAborted) - CZipException::Throw( - iAborted); // throw to distuinguish from other return codes - - if (bEff) { - // remove the last file and add it without the compression if needed - if (!info.m_pFile) - f.Close(); - - buf.Release(); - if (RemoveLast()) { - info.m_iComprLevel = 0; - info.m_iSmartLevel = zipsmInternal01; - return AddNewFile(info); - } - } - return true; -} - -bool -CZipArchive::RemoveLast(bool bRemoveAnyway) -{ - int iIndex = GetCount() - 1; - if (iIndex < 0) - return false; - CZipFileHeader* pHeader = m_centralDir[iIndex]; - - if (!bRemoveAnyway && pHeader->CompressionEfficient()) - return false; - - m_centralDir.RemoveLastFile(pHeader, iIndex); - return true; -} - -CZipString -CZipArchive::GetArchivePath() const -{ - if (IsClosed(false)) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return _T(""); - } - return m_storage.m_pFile->GetFilePath(); -} - -CZipString -CZipArchive::GetGlobalComment() const -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return _T(""); - } - CZipString temp; - return SingleToWide(m_centralDir.m_pszComment, temp) != -1 ? (LPCTSTR)temp - : _T(""); -} - -bool -CZipArchive::SetGlobalComment(LPCTSTR lpszComment) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return false; - } - if (m_storage.IsSpanMode() == -1) { - TRACE(_T("%s(%i) : You cannot modify the global comment of the ") - _T("existing disk spanning archive.\n"), - __FILE__, - __LINE__); - return false; - } - - WideToSingle(lpszComment, m_centralDir.m_pszComment); - m_centralDir.RemoveFromDisk(); - if (m_bAutoFlush) - Flush(); - - return true; -} - -int -CZipArchive::GetCurrentDisk() const -{ - return m_storage.GetCurrentDisk() + 1; -} - -bool -CZipArchive::SetFileComment(WORD uIndex, LPCTSTR lpszComment) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return false; - } - if (m_storage.IsSpanMode() == -1) { - TRACE(_T("%s(%i) : You cannot modify the file comment in the existing ") - _T("disk spanning archive.\n"), - __FILE__, - __LINE__); - return false; - } - - if (!m_centralDir.IsValidIndex(uIndex)) { - ASSERT(FALSE); - return false; - } - m_centralDir[uIndex]->SetComment(lpszComment); - m_centralDir.RemoveFromDisk(); - if (m_bAutoFlush) - Flush(); - return true; -} - -void -CZipArchive::CryptInitKeys() -{ - ASSERT(m_pszPassword.GetSize()); - m_keys[0] = 305419896L; - m_keys[1] = 591751049L; - m_keys[2] = 878082192L; - for (DWORD i = 0; i < m_pszPassword.GetSize(); i++) - CryptUpdateKeys(m_pszPassword[i]); -} - -void -CZipArchive::CryptUpdateKeys(char c) -{ - - m_keys[0] = CryptCRC32(m_keys[0], c); - m_keys[1] += m_keys[0] & 0xff; - m_keys[1] = m_keys[1] * 134775813L + 1; - c = char(m_keys[1] >> 24); - m_keys[2] = CryptCRC32(m_keys[2], c); -} - -bool -CZipArchive::CryptCheck() -{ - CZipAutoBuffer buf(ZIPARCHIVE_ENCR_HEADER_LEN); - m_storage.Read(buf, ZIPARCHIVE_ENCR_HEADER_LEN, false); - BYTE b = 0; - for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN; i++) { - b = buf[i]; // only temporary - CryptDecode((char&)b); - } - // check the last byte - return CurrentFile()->IsDataDescr() - ? (BYTE(CurrentFile()->m_uModTime >> 8) == b) - : (BYTE(CurrentFile()->m_uCrc32 >> 24) == b); -} - -char -CZipArchive::CryptDecryptByte() -{ - int temp = (m_keys[2] & 0xffff) | 2; - return (char)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -void -CZipArchive::CryptDecode(char& c) -{ - c ^= CryptDecryptByte(); - CryptUpdateKeys(c); -} - -bool -CZipArchive::SetPassword(LPCTSTR lpszPassword) -{ - if (m_iFileOpened != nothing) { - TRACE(_T("%s(%i) : You cannot change the password when the file is ") - _T("opened.\n"), - __FILE__, - __LINE__); - return false; // it's important not to change the password when the file - // inside archive is opened - } - if (IsClosed()) { - TRACE(_T("%s(%i) : Setting the password for a closed archive has no ") - _T("effect.\n"), - __FILE__, - __LINE__); - } - if (lpszPassword) { - int iLen = WideToSingle(lpszPassword, m_pszPassword); - if (iLen == -1) - return false; - for (size_t i = 0; (int)i < iLen; i++) - if (m_pszPassword[i] <= 0) { - m_pszPassword.Release(); - TRACE(_T("%s(%i) : The password contains forbidden ") - _T("characters. Password cleared.\n"), - __FILE__, - __LINE__); - return false; - } - } else - m_pszPassword.Release(); - return true; -} - -CZipString -CZipArchive::GetPassword() const -{ - CZipString temp; - CZipArchive::SingleToWide(m_pszPassword, temp); - return temp; -} - -DWORD -CZipArchive::CryptCRC32(DWORD l, char c) -{ - const DWORD* CRC_TABLE = get_crc_table(); - return CRC_TABLE[(l ^ c) & 0xff] ^ (l >> 8); -} - -void -CZipArchive::CryptCryptHeader(long iCrc, CZipAutoBuffer& buf) -{ - CryptInitKeys(); - srand(UINT(time(NULL))); - // genereate pseudo-random sequence - char c; - for (int i = 0; i < ZIPARCHIVE_ENCR_HEADER_LEN - 2; i++) { - int t1 = rand(); - c = (char)(t1 >> 6); - if (!c) - c = (char)t1; - CryptEncode(c); - buf[i] = c; - } - c = (char)((iCrc >> 16) & 0xff); - CryptEncode(c); - buf[ZIPARCHIVE_ENCR_HEADER_LEN - 2] = c; - c = (char)((iCrc >> 24) & 0xff); - CryptEncode(c); - buf[ZIPARCHIVE_ENCR_HEADER_LEN - 1] = c; -} - -void -CZipArchive::CryptEncode(char& c) -{ - char t = CryptDecryptByte(); - CryptUpdateKeys(c); - c ^= t; -} - -void -CZipArchive::CryptEncodeBuffer() -{ - if (CurrentFile()->IsEncrypted()) - for (DWORD i = 0; i < m_info.m_uComprLeft; i++) - CryptEncode(m_info.m_pBuffer[i]); -} - -void -CZipArchive::CloseFileAfterTestFailed() -{ - if (m_iFileOpened != extract) { - TRACE(_T("%s(%i) : No file opened.\n"), __FILE__, __LINE__); - return; - } - m_info.ReleaseBuf(); - m_centralDir.Clear(false); - m_iFileOpened = nothing; -} - -bool -CZipArchive::TestFile(WORD uIndex, DWORD uBufSize) -{ - if (m_storage.IsSpanMode() == 1) { - TRACE( - _T("%s(%i) : You cannot test the spanning archive in creation.\n"), - __FILE__, - __LINE__); - return false; - } - if (!uBufSize) - return false; - - CZipFileHeader* pHeader = m_centralDir[uIndex]; - CZipActionCallback* pCallback = GetCallback(cbTest); - if (pCallback) { - pCallback->Init(m_centralDir.GetProperHeaderFileName(pHeader)); - } - - if (pHeader->IsDirectory()) { - if (pCallback) - pCallback->SetTotal(0); - - // we do not test whether the password for the encrypted directory - // is correct, since it seems to be senseless (anyway password - // encrypted directories should be avoided - it adds 12 bytes) - DWORD iSize = pHeader->m_uComprSize; - if ((iSize != 0 || iSize != pHeader->m_uUncomprSize) - // different treating compressed directories - && !(pHeader->IsEncrypted() && iSize == 12 && - !pHeader->m_uUncomprSize)) - CZipException::Throw(CZipException::dirWithSize); - - if (pCallback) - pCallback->CallbackEnd(); - - return true; - } else { - try { - if (pCallback) - pCallback->SetTotal(pHeader->m_uUncomprSize); - - if (!OpenFile(uIndex)) - return false; - CZipAutoBuffer buf(uBufSize); - DWORD iRead; - int iAborted = 0; - do { - iRead = ReadFile(buf, buf.GetSize()); - if (pCallback && iRead) - if (!(*pCallback)(iRead)) { - if (iRead == buf.GetSize() && - ReadFile(buf, 1) != - 0) // test one byte if there is something left - iAborted = CZipException::abortedAction; - else - iAborted = - CZipException::abortedSafely; // we did it! - break; - } - } while (iRead == buf.GetSize()); - bool bRet = CloseFile() != -1; - if (!bRet && iAborted == CZipException::abortedSafely) - iAborted = CZipException::abortedAction; // sorry, finished, but - // not successfull - - if (pCallback) - pCallback->CallbackEnd(); - - if (iAborted) - CZipException::Throw( - iAborted); // throw to distuingiush from other return codes - if (bRet) - return true; - else - CZipException::Throw(CZipException::badZipFile); - return false; // to satisfy the compiler and eliminate warning - } catch (...) { - CloseFileAfterTestFailed(); - throw; - } - } -} - -int -CZipArchive::WideToSingle(LPCTSTR lpWide, CZipAutoBuffer& szSingle) -{ -#ifdef _UNICODE - return ZipPlatform::WideToSingle(lpWide, szSingle); -#else - - size_t iLen = strlen(lpWide); - // if not UNICODE just copy - // iLen does not include the NULL character - szSingle.Allocate(iLen); - memcpy(szSingle, lpWide, iLen); - return iLen; -#endif -} - -int -CZipArchive::SingleToWide(const CZipAutoBuffer& szSingle, CZipString& szWide) -{ - -#ifdef _UNICODE - return ZipPlatform::SingleToWide(szSingle, szWide); -#else // if not UNICODE just copy - int singleLen = szSingle.GetSize(); - // iLen does not include the NULL character - memcpy(szWide.GetBuffer(singleLen), szSingle.GetBuffer(), singleLen); - szWide.ReleaseBuffer(singleLen); - return singleLen; -#endif -} - -void -CZipArchive::CryptDecodeBuffer(DWORD uCount) -{ - if (CurrentFile()->IsEncrypted()) - for (DWORD i = 0; i < uCount; i++) - CryptDecode(m_info.m_pBuffer[i]); -} - -void -CZipArchive::EmptyPtrList() -{ - if (m_list.GetCount()) { - // if some memory hasn't been freed due to an error in zlib, so free it - // now - CZipPtrListIter iter = m_list.GetHeadPosition(); - while (m_list.IteratorValid(iter)) - delete[](char*) m_list.GetNext(iter); - } - m_list.RemoveAll(); -} - -void -CZipArchive::SetFileHeaderAttr(CZipFileHeader& header, DWORD uAttr) -{ - header.SetSystemCompatibility(m_iArchiveSystCompatib); - header.SetSystemAttr(uAttr); -} - -void -CZipArchive::EnableFindFast(bool bEnable) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : Set it after opening the archive.\n"), - __FILE__, - __LINE__); - return; - } - m_centralDir.EnableFindFast(bEnable, m_bCaseSensitive); -} - -bool -CZipArchive::SetSystemCompatibility(int iSystemComp) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : Set it after opening the archive.\n"), - __FILE__, - __LINE__); - return false; - } - - if (m_iFileOpened == compress) { - TRACE(_T("%s(%i) : Set it before opening a file inside archive.\n"), - __FILE__, - __LINE__); - return false; - } - - if (!ZipCompatibility::IsPlatformSupported(iSystemComp)) - return false; - m_iArchiveSystCompatib = iSystemComp; - return true; -} - -void -CZipArchive::SetRootPath(LPCTSTR szPath) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : Set it after opening the archive.\n"), - __FILE__, - __LINE__); - return; - } - - if (m_iFileOpened != nothing) { - TRACE(_T("%s(%i) : Set it before opening a file inside archive.\n"), - __FILE__, - __LINE__); - return; - } - - if (szPath) { - m_szRootPath = szPath; - CZipPathComponent::RemoveSeparators(m_szRootPath); - } else - m_szRootPath.Empty(); -} - -CZipString -CZipArchive::TrimRootPath(CZipPathComponent& zpc) const -{ - if (m_szRootPath.IsEmpty()) - return zpc.GetFileName(); - CZipString szPath = zpc.GetFullPath(); - return RemovePathBeginning(m_szRootPath, szPath, m_pZipCompare) - ? szPath - : zpc.GetFileName(); -} - -bool -CZipArchive::RemovePathBeginning(LPCTSTR lpszBeginning, - CZipString& szPath, - ZIPSTRINGCOMPARE pCompareFunction) -{ - CZipString szBeginning(lpszBeginning); - CZipPathComponent::RemoveSeparators(szBeginning); - int iRootPathLength = szBeginning.GetLength(); - if (iRootPathLength && szPath.GetLength() >= iRootPathLength && - (szPath.Left(iRootPathLength).*pCompareFunction)(szBeginning) == 0) { - // the beginning is the same - if (szPath.GetLength() == iRootPathLength) { - szPath.Empty(); - return true; - } - // is the end of m_szPathRoot only a beginning of a directory name? - // check for a separator - // we know the length is larger, so we can write: - if (CZipPathComponent::IsSeparator(szPath[iRootPathLength])) { - szPath = szPath.Mid(iRootPathLength); - CZipPathComponent::RemoveSeparatorsLeft(szPath); - return true; - } - } - return false; -} - -void -CZipArchive::SetTempPath(LPCTSTR lpszPath, bool bForce) -{ - m_szTempPath = lpszPath; - if (lpszPath && bForce) - ZipPlatform::ForceDirectory(lpszPath); - CZipPathComponent::RemoveSeparators(m_szTempPath); -} - -CZipString -CZipArchive::PredictFileNameInZip(LPCTSTR lpszFilePath, - bool bFullPath, - int iWhat, - bool bExactly) const -{ - CZipString sz = lpszFilePath; - if (sz.IsEmpty()) - return _T(""); - bool bAppend; - switch (iWhat) { - case prFile: - bAppend = false; - break; - case prDir: - bAppend = true; - break; - default: - bAppend = CZipPathComponent::IsSeparator(sz[sz.GetLength() - 1]); - } - - // remove for CZipPathComponent treating last name as a file even if dir - CZipPathComponent::RemoveSeparators(sz); - CZipPathComponent zpc(sz); - - if (bFullPath) { - if (m_bRemoveDriveLetter) - sz = zpc.GetNoDrive(); - } else - sz = TrimRootPath(zpc); - - if (bAppend && !sz.IsEmpty()) - CZipPathComponent::AppendSeparator(sz); - CZipFileHeader fh; // create a temporary object to convert - fh.SetFileName(sz); - if (bExactly) { - fh.SetSystemCompatibility(m_iArchiveSystCompatib); - ZipCompatibility::FileNameUpdate(fh, false); - } else { - fh.SetSystemCompatibility( - -1); // non existing system to prevent ansi oem conversion - ZipCompatibility::FileNameUpdate(fh, - true); // update only path separators - } - - return fh.GetFileName(); -} - -CZipString -CZipArchive::PredictExtractedFileName(LPCTSTR lpszFileNameInZip, - LPCTSTR lpszPath, - bool bFullPath, - LPCTSTR lpszNewName) const -{ - CZipString szFile = lpszPath; - CZipString sz = lpszNewName ? lpszNewName : lpszFileNameInZip; - if (sz.IsEmpty()) - return szFile; - if (!szFile.IsEmpty()) - CZipPathComponent::AppendSeparator(szFile); - - // remove for CZipPathComponent treating last name as a file even if dir - CZipPathComponent::RemoveSeparators(sz); - CZipPathComponent zpc(sz); - szFile += bFullPath ? (m_bRemoveDriveLetter ? zpc.GetNoDrive() : sz) - : TrimRootPath(zpc); - return szFile; -} - -void -CZipArchive::SetAutoFlush(bool bAutoFlush) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive not yet opened.\n"), __FILE__, __LINE__); - return; - } - if (m_storage.IsSpanMode() != 0) { - TRACE( - _T("%s(%i) : Cannot set auto-flush for the disk spanning archive.\n"), - __FILE__, - __LINE__); - return; - } - m_bAutoFlush = bAutoFlush; -} - -void -CZipArchive::Flush() -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive not yet opened.\n"), __FILE__, __LINE__); - return; - } - - if (m_storage.IsSpanMode() < 0) { - TRACE(_T("%s(%i) : Cannot flush an existing disk spanning archive.\n"), - __FILE__, - __LINE__); - return; - } - WriteCentralDirectory(); - m_storage.FlushFile(); - if (m_storage.IsSpanMode() > - 0) // try to finalize disk-spanning archive without closing it - m_storage.FinalizeSpan(); -} - -void -CZipArchive::GetCentralDirInfo(CZipCentralDir::Info& info) const -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive not yet opened.\n"), __FILE__, __LINE__); - return; - } - m_centralDir.GetInfo(info); - if (GetSpanMode() > 0) - info.m_uDiskEntriesNo = m_storage.GetCurrentDisk(); -} - -bool -CZipArchive::CWildcard::IsPatternValid(LPCTSTR lpszPattern, int* iErrorType) -{ - try { - /* loop through pattern to EOS */ - while (*lpszPattern) { - /* determine pattern type */ - switch (*lpszPattern) { - /* check literal escape, it cannot be at end of pattern */ - case _T('\\'): - if (!*++lpszPattern) - throw patternEsc; - lpszPattern++; - break; - - /* the [..] construct must be well formed */ - case _T('['): - lpszPattern++; - - /* if the next character is ']' then bad pattern */ - if (*lpszPattern == _T(']')) - throw patternEmpty; - - /* if end of pattern here then bad pattern */ - if (!*lpszPattern) - throw patternClose; - - /* loop to end of [..] construct */ - while (*lpszPattern != _T(']')) { - /* check for literal escape */ - if (*lpszPattern == _T('\\')) { - lpszPattern++; - - /* if end of pattern here then bad pattern */ - if (!*lpszPattern++) - throw patternEsc; - } else - lpszPattern++; - - /* if end of pattern here then bad pattern */ - if (!*lpszPattern) - throw patternClose; - - /* if this a range */ - if (*lpszPattern == _T('-')) { - /* we must have an end of range */ - if (!*++lpszPattern || *lpszPattern == ']') - throw patternRange; - else { - - /* check for literal escape */ - if (*lpszPattern == _T('\\')) - lpszPattern++; - - /* if end of pattern here - then bad pattern */ - if (!*lpszPattern++) - throw patternEsc; - } - } - } - break; - - /* all other characters are valid pattern elements */ - case '*': - case '?': - default: - lpszPattern++; /* "normal" character */ - break; - } - } - throw patternValid; - } catch (int i) { - if (iErrorType) - *iErrorType = i; - return i == patternValid; - } -} - -bool -CZipArchive::CWildcard::IsPattern(LPCTSTR lpszPattern) -{ - while (*lpszPattern) { - switch (*lpszPattern++) { - case _T('?'): - case _T('*'): - case _T('['): - case _T('\\'): - return true; - } - } - return false; -} - -bool -CZipArchive::CWildcard::IsMatch(LPCTSTR lpszText, int* iRetCode) -{ - CZipString sz; - if (!m_bCaseSensitive) { - sz = lpszText; - sz.MakeLower(); - lpszText = (LPCTSTR)sz; - } - int i = Match((LPCTSTR)m_szPattern, lpszText); - if (iRetCode) - *iRetCode = i; - return i == matchValid; -} - -int -CZipArchive::CWildcard::MatchAfterStar(LPCTSTR p, LPCTSTR t) -{ - int iMatch = matchNone; - TCHAR nextp; - - /* pass over existing ? and * in pattern */ - - while (*p == _T('?') || *p == _T('*')) { - /* take one char for each ? and + */ - - if (*p == _T('?')) { - /* if end of text then no match */ - if (!*t++) - return matchAbort; - } - - /* move to next char in pattern */ - - p++; - } - - /* if end of pattern we have matched regardless of text left */ - - if (!*p) - return matchValid; - - /* get the next character to match which must be a literal or '[' */ - - nextp = *p; - if (nextp == _T('\\')) { - nextp = p[1]; - - /* if end of text then we have a bad pattern */ - - if (!nextp) - return matchPattern; - } - - /* Continue until we run out of text or definite result seen */ - - do { - /* a precondition for matching is that the next character - in the pattern match the next character in the text or that - the next pattern char is the beginning of a range. Increment - text pointer as we go here */ - - if (nextp == *t || nextp == _T('[')) - iMatch = Match(p, t); - - /* if the end of text is reached then no iMatch */ - - if (!*t++) - iMatch = matchAbort; - - } while (iMatch != matchValid && iMatch != matchAbort && - iMatch != matchPattern); - - /* return result */ - - return iMatch; -} - -int -CZipArchive::CWildcard::Match(LPCTSTR lpszPattern, LPCTSTR lpszText) -{ - - TCHAR range_start, range_end; /* start and end in range */ - - bool bInvert; /* is this [..] or [!..] */ - bool bMemberMatch; /* have I matched the [..] construct? */ - bool bLoop; /* should I terminate? */ - - for (; *lpszPattern; lpszPattern++, lpszText++) { - /* if this is the end of the text - then this is the end of the match */ - - if (!*lpszText) { - if (*lpszPattern == _T('*') && *++lpszPattern == _T('\0')) - return matchValid; - else - return matchAbort; - } - - /* determine and react to pattern type */ - - switch (*lpszPattern) { - case _T('?'): /* single any character match */ - break; - - case _T('*'): /* multiple any character match */ - return MatchAfterStar(lpszPattern, lpszText); - - /* [..] construct, single member/exclusion character match */ - case _T('['): { - /* move to beginning of range */ - - lpszPattern++; - - /* check if this is a member match or exclusion match */ - - bInvert = false; - if (*lpszPattern == _T('!') || *lpszPattern == _T('^')) { - bInvert = true; - lpszPattern++; - } - - /* if closing bracket here or at range start then we have a - malformed pattern */ - - if (*lpszPattern == _T(']')) - return matchPattern; - - bMemberMatch = false; - bLoop = true; - - while (bLoop) { - /* if end of construct then bLoop is done */ - - if (*lpszPattern == _T(']')) { - bLoop = false; - continue; - } - - /* matching a '!', '^', '-', '\' or a ']' */ - - if (*lpszPattern == _T('\\')) - range_start = range_end = *++lpszPattern; - else - range_start = range_end = *lpszPattern; - - /* if end of pattern then bad pattern (Missing ']') */ - - if (!*lpszPattern) - return matchPattern; - - /* check for range bar */ - if (*++lpszPattern == _T('-')) { - /* get the range end */ - - range_end = *++lpszPattern; - - /* if end of pattern or construct - then bad pattern */ - - if (range_end == _T('\0') || range_end == _T(']')) - return matchPattern; - /* special character range end */ - if (range_end == _T('\\')) { - range_end = *++lpszPattern; - - /* if end of text then - we have a bad pattern */ - if (!range_end) - return matchPattern; - } - - /* move just beyond this range */ - lpszPattern++; - } - - /* if the text character is in range then match found. - make sure the range letters have the proper - relationship to one another before comparison */ - - if (range_start < range_end) { - if (*lpszText >= range_start && - *lpszText <= range_end) { - bMemberMatch = true; - bLoop = false; - } - } else { - if (*lpszText >= range_end && - *lpszText <= range_start) { - bMemberMatch = true; - bLoop = false; - } - } - } - - /* if there was a match in an exclusion set then no match */ - /* if there was no match in a member set then no match */ - - if ((bInvert && bMemberMatch) || !(bInvert || bMemberMatch)) - return matchRange; - - /* if this is not an exclusion then skip the rest of - the [...] construct that already matched. */ - - if (bMemberMatch) { - while (*lpszPattern != _T(']')) { - /* bad pattern (Missing ']') */ - if (!*lpszPattern) - return matchPattern; - - /* skip exact match */ - if (*lpszPattern == _T('\\')) { - lpszPattern++; - - /* if end of text then - we have a bad pattern */ - - if (!*lpszPattern) - return matchPattern; - } - - /* move to next pattern char */ - - lpszPattern++; - } - } - break; - } - case _T('\\'): /* next character is quoted and must match exactly */ - - /* move pattern pointer to quoted char and fall through */ - - lpszPattern++; - - /* if end of text then we have a bad pattern */ - - if (!*lpszPattern) - return matchPattern; - - /* must match this character exactly */ - - default: - if (*lpszPattern != *lpszText) - return matchPattern; - } - } - /* if end of text not reached then the pattern fails */ - - if (*lpszText) - return matchEnd; - else - return matchValid; -} - -void -CZipArchive::FindMatches(LPCTSTR lpszPattern, - CZipWordArray& ar, - bool bFullPath) const -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return; - } - - // ar.RemoveAll(); don't do this - int iCount = GetCount(); - CWildcard wc(lpszPattern, m_bCaseSensitive); - for (int i = 0; i < iCount; i++) { - const CZipFileHeader* pHeader = m_centralDir[i]; - CZipString sz = m_centralDir.GetProperHeaderFileName(pHeader); - if (!bFullPath) { - CZipPathComponent::RemoveSeparators(sz); - CZipPathComponent zpc(sz); - sz = zpc.GetFileName(); - } - if (wc.IsMatch(sz)) - ar.Add(i); - } -} - -int -CZipArchive::WillBeDuplicated(LPCTSTR lpszFilePath, - bool bFullPath, - bool bFileNameOnly, - int iWhat) -{ - CZipString szFile; - // we predict with bExactly set to false, because FindFile converts all - // filanames anyway - if (bFileNameOnly) { - CZipPathComponent zpc(lpszFilePath); - szFile = PredictFileNameInZip(zpc.GetFileName(), false, iWhat); - } else - szFile = PredictFileNameInZip(lpszFilePath, bFullPath, iWhat); - return FindFile(szFile, ffDefault, bFileNameOnly); -} - -// it'll get up to the next file or to the end of file (bad if zip corrupted or -// not-ordered by offsett or redundant bytes added) -bool -CZipArchive::GetFromArchive(CZipArchive& zip, - WORD uIndex, - int iReplaceIndex, - bool bKeepSystComp, - CZipActionCallback* pCallback) -{ - - if (IsClosed() || zip.IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return false; - } - - if (m_iFileOpened || zip.m_iFileOpened) { - TRACE(_T("%s(%i) : You cannot get files from another archive if there ") - _T("is a file opened.\n"), - __FILE__, - __LINE__); - return false; - } - - if (zip.m_storage.IsSpanMode()) { - TRACE( - _T("%s(%i) : You cannot get files from the disk spannig archive.\n"), - __FILE__, - __LINE__); - return false; - } - - if (m_storage.IsSpanMode() == -1) { - TRACE(_T("%s(%i) : You cannot add files to the existing disk spannig ") - _T("archive.\n"), - __FILE__, - __LINE__); - return false; - } - - ASSERT(m_info.m_pBuffer.GetSize() > 0); - - bool bIsSpan = m_storage.IsSpanMode() == 1; - - CZipFileHeader fh; - if (!zip.GetFileInfo(fh, uIndex)) - return false; - CZipAbstractFile* pFile = zip.m_storage.m_pFile; - - DWORD uEndOffset; - if (uIndex < zip.GetCount() - 1) { - CZipFileHeader fhTemp; - if (!zip.GetFileInfo(fhTemp, uIndex + 1)) - return false; - uEndOffset = fhTemp.m_uOffset; - } else { - CZipCentralDir::Info info; - zip.m_centralDir.GetInfo(info); - if (info.m_bOnDisk) - uEndOffset = info.m_uOffset; - else - uEndOffset = pFile->GetLength(); - } - uEndOffset += zip.m_centralDir.GetBytesBefore(); - DWORD uStartOffset = - zip.m_centralDir.GetBytesBefore() + fh.m_uOffset + fh.GetSize(true); - DWORD uTotalToMove = uEndOffset - uStartOffset, uTotalMoved = 0; - - DWORD uPredictedSize = - fh.m_uComprSize + (fh.IsDataDescr() ? ZIPARCHIVE_DATADESCRIPTOR_LEN : 0); - if (uTotalToMove > uPredictedSize + 4 /* may be or may be not a signature*/) - uTotalToMove = uPredictedSize + 4; - else if (uTotalToMove < uPredictedSize) - ThrowError(CZipException::badZipFile); - - // conversion stuff - CZipString szFileNameConverted, szFileName; - bool bConvertSystem = - !bKeepSystComp && fh.GetSystemCompatibility() != m_iArchiveSystCompatib; - - // GetFileInfo always converts the filename regardless of - // zip.m_centralDir.m_bConvertAfterOpen value - szFileNameConverted = fh.GetFileName(); - if (bConvertSystem) { - DWORD uAttr = fh.GetSystemAttr(); - fh.SetSystemCompatibility(m_iArchiveSystCompatib); - fh.SetSystemAttr(uAttr); - } - - ZipCompatibility::FileNameUpdate(fh, false); - szFileName = fh.GetFileName(); - - bool bNeedDataDescr = bIsSpan && !fh.IsDataDescr(); - if (bNeedDataDescr) - fh.m_uFlag |= 8; // data descriptor present - - // needed by InsertFindFastElement - if (m_centralDir.IsFindFastEnabled()) - fh.SetFileName(szFileNameConverted); - - if (!UpdateReplaceIndex(iReplaceIndex, szFileNameConverted)) - return false; - - bool bReplace = iReplaceIndex >= 0; - int iCallbackType = 0; - if (pCallback) - iCallbackType = pCallback->m_iType; - - // if the same callback is applied to cbReplace, then the previous - // information about the type will be lost - CZipFileHeader* pHeader = - m_centralDir.AddNewFile(fh, iReplaceIndex); // must be converted when - // adding because of - // InsertFastElement - if (bReplace) - MakeSpaceForReplace( - iReplaceIndex, uTotalToMove + fh.GetSize(true), szFileNameConverted); - - if (pCallback) { - pCallback->m_iType = iCallbackType; - pCallback->Init(szFileNameConverted, zip.GetArchivePath()); - pCallback->SetTotal(fh.m_uComprSize); - } - - if (m_centralDir.IsFindFastEnabled()) - pHeader->SetFileName(szFileName); - - // must be written as not converted - pHeader->WriteLocal(m_storage); - - // made a correction to what was set in WriteLocal - pHeader->m_uOffset -= m_centralDir.GetBytesBefore(); - - // we keep in converted in memory - if (m_centralDir.m_bConvertAfterOpen) - pHeader->SetFileName(szFileNameConverted); - - // skip reading the local file header - - pFile->Seek(uStartOffset, CZipAbstractFile::begin); - - DWORD uPack = uTotalToMove > m_info.m_pBuffer.GetSize() - ? m_info.m_pBuffer.GetSize() - : uTotalToMove; - char* buf = (char*)m_info.m_pBuffer; - - DWORD size_read; - - int iAborted = 0; - bool bBreak = false; - if (uPack) - do { - size_read = pFile->Read(buf, uPack); - if (!size_read) - break; - if (uTotalMoved + size_read > uTotalToMove) { - size_read = uTotalToMove - uTotalMoved; - if (!size_read) // this is for protection - break; - bBreak = true; - } - - m_storage.Write(buf, size_read, false); - uTotalMoved += size_read; - if (pCallback) - if (!(*pCallback)(size_read)) { - if (uTotalToMove != uTotalMoved) { - if (!bIsSpan && !bReplace) { - m_centralDir.RemoveLastFile(); - iAborted = CZipException::abortedSafely; - } else - iAborted = CZipException::abortedAction; - } else - iAborted = CZipException::abortedSafely; // we did it! - break; - } - } while (!bBreak); - - if (iAborted) - CZipException::Throw( - iAborted); // throw to distuingiush from other return codes - - // copying from non-span to span or from span without data description to - // span so add the data descriptor - - m_centralDir.m_pOpenedFile = NULL; - if (bNeedDataDescr && uTotalMoved == uTotalToMove) { - const int iToWrite = ZIPARCHIVE_DATADESCRIPTOR_LEN + 4; - CZipAutoBuffer buf(iToWrite); - memcpy(buf, m_storage.m_gszExtHeaderSignat, 4); - pHeader->GetCrcAndSizes(buf + 4); - m_storage.Write(buf, iToWrite, true); - } - m_storage.Flush(); - if (uTotalMoved < uTotalToMove) - ThrowError(CZipException::badZipFile); - - if (pCallback) - pCallback->CallbackEnd(); - - return true; -} - -bool -CZipArchive::GetFromArchive(CZipArchive& zip, - CZipWordArray& aIndexes, - bool bKeepSystComp) -{ - aIndexes.Sort(true); - int iFiles = aIndexes.GetSize(); - m_info.Init(); - try { - for (int i = 0; i < iFiles; i++) { - int iFileIndex = aIndexes[i]; - if (!m_centralDir.IsValidIndex(iFileIndex)) - if (!GetFromArchive(zip, - iFileIndex, - -1, - bKeepSystComp, - GetCallback(cbGetFromArchive))) { - m_info.ReleaseBuf(); - return false; - } - } - } catch (...) { - m_info.ReleaseBuf(); - throw; - } - m_info.ReleaseBuf(); - if (m_bAutoFlush) - Flush(); - return true; -} -bool -CZipArchive::RenameFile(WORD uIndex, LPCTSTR lpszNewName) -{ - if (IsClosed()) { - TRACE(_T("%s(%i) : ZipArchive is closed.\n"), __FILE__, __LINE__); - return false; - } - - if (m_storage.IsSpanMode()) { - TRACE( - _T("%s(%i) : You cannot rename files in the disk spannig archive.\n"), - __FILE__, - __LINE__); - return false; - } - - if (m_iFileOpened) { - TRACE( - _T("%s(%i) : You cannot rename a file if there is a file opened.\n"), - __FILE__, - __LINE__); - return false; - } - CZipFileHeader fh, fhNew; - if (!GetFileInfo(fh, uIndex)) - return false; - CZipString szNewName(lpszNewName); - if (fh.IsDirectory()) - CZipPathComponent::AppendSeparator(szNewName); - else - CZipPathComponent::RemoveSeparators(szNewName); - if (fh.GetFileName().Collate(szNewName) == 0) - return true; - fhNew.SetSystemCompatibility(m_iArchiveSystCompatib); - - fhNew.SetFileName(szNewName); - ZipCompatibility::FileNameUpdate(fhNew, false); - ZipCompatibility::FileNameUpdate( - fh, false); // in case the conversion changes the filename size - WORD uFileNameLen = fh.GetFileNameSize(); - WORD uNewFileNameLen = fhNew.GetFileNameSize(); - int iDelta = uNewFileNameLen - uFileNameLen; - int iOffset = 0; - CZipAutoBuffer buf, *pBuf; - m_centralDir.RemoveFromDisk(); // does m_storage.Flush(); - if (iDelta != 0) { - // we need to make more or less space - - m_info.Init(); - DWORD uStartOffset = fh.m_uOffset + 30 + uFileNameLen; - DWORD uFileLen = m_storage.m_pFile->GetLength(); - DWORD uEndOffset = uFileLen - m_centralDir.GetBytesBefore(); - CZipActionCallback* pCallback = GetCallback(cbRename); - if (pCallback) { - // do it right and sent the notification - pCallback->Init(fh.GetFileName(), GetArchivePath()); - pCallback->SetTotal(uEndOffset - uStartOffset); - } - bool bForward = iDelta > 0; - if (bForward) - m_storage.m_pFile->SetLength(uFileLen + - iDelta); // ensure the seek is correct - - MovePackedFiles( - uStartOffset, uEndOffset, abs(iDelta), pCallback, bForward); - if (pCallback) - pCallback->CallbackEnd(); - - if (!bForward) - m_storage.m_pFile->SetLength(uFileLen + - iDelta); // delta < 0; shrink the file - - m_info.ReleaseBuf(); - - int iSize = GetCount(); - for (int i = uIndex + 1; i < iSize; i++) - m_centralDir[i]->m_uOffset += iDelta; - buf.Allocate(4 + uNewFileNameLen); - WORD uExtraFieldSize = fh.GetExtraFieldSize(); - memcpy(buf, &uNewFileNameLen, 2); - memcpy(buf + 2, &uExtraFieldSize, 2); // to write everything at once - memcpy(buf + 4, fhNew.m_pszFileName, uNewFileNameLen); - pBuf = &buf; - iOffset = -4; - } else - pBuf = &fhNew.m_pszFileName; - - m_storage.m_pFile->Seek(m_centralDir.GetBytesBefore() + fh.m_uOffset + 30 + - iOffset, - CZipAbstractFile::begin); - m_storage.m_pFile->Write(buf, buf.GetSize()); - m_centralDir.RenameFile(uIndex, szNewName); - if (m_bAutoFlush) - Flush(); - - return true; -} - -bool -CZipArchive::UpdateReplaceIndex(int& iReplaceIndex, LPCTSTR lpszNewFileName) -{ - if (iReplaceIndex == -2) - iReplaceIndex = FindFile(lpszNewFileName); - if (iReplaceIndex < 0) { - if (iReplaceIndex != -1) - iReplaceIndex = -1; - return true; - } - - if (GetSpanMode() != 0) { - TRACE( - _T("%s(%i) : You cannot replace files in a disk-spanning archive.\n"), - __FILE__, - __LINE__); - return false; - } - - if (!m_centralDir.IsValidIndex(iReplaceIndex)) { - TRACE(_T("%s(%i) : Not valid replace index.\n"), __FILE__, __LINE__); - return false; - } - if (iReplaceIndex == GetCount() - 1) // replacing last file in the archive - { - RemoveLast(true); - iReplaceIndex = -1; - } - return true; -} - -void -CZipArchive::MakeSpaceForReplace(int iReplaceIndex, - DWORD uTotal, - LPCTSTR lpszFileName) -{ - - ASSERT(iReplaceIndex < GetCount() - 1); - DWORD uReplaceStart = - m_storage.m_pFile->GetPosition() - m_centralDir.GetBytesBefore(); - DWORD uReplaceEnd = m_centralDir.m_headers[iReplaceIndex + 1]->m_uOffset; - DWORD uReplaceTotal = uReplaceEnd - uReplaceStart; - int iDelta = uTotal - uReplaceTotal; - - if (iDelta != 0) { - - // m_info.Init(); don't - the calling functions will - CZipActionCallback* pCallback = GetCallback(CZipArchive::cbReplace); - DWORD uFileLen = m_storage.m_pFile->GetLength(); - DWORD uUpperLimit = - uFileLen - - m_centralDir.GetBytesBefore(); // will be added in MovePackedFiles - if (pCallback) { - pCallback->Init(lpszFileName, GetArchivePath()); - pCallback->SetTotal(uUpperLimit - uReplaceEnd); - } - - bool bForward = iDelta > 0; - if (bForward) - m_storage.m_pFile->SetLength(uFileLen + - iDelta); // ensure the seek is correct - - MovePackedFiles( - uReplaceEnd, uUpperLimit, abs(iDelta), pCallback, bForward); - - if (!bForward) - m_storage.m_pFile->SetLength(uFileLen + - iDelta); // delta < 0; shrink the file - - m_storage.m_pFile->Seek(uReplaceStart, CZipAbstractFile::begin); - int iSize = m_centralDir.m_headers.GetSize(); - for (int i = iReplaceIndex + 1; i < iSize; i++) - m_centralDir.m_headers[i]->m_uOffset += iDelta; - if (pCallback) - pCallback->CallbackEnd(); - } -} - -void -CZipArchive::MovePackedFiles(DWORD uStartOffset, - DWORD uEndOffset, - DWORD uMoveBy, - CZipActionCallback* pCallback, - bool bForward) -{ - ASSERT(m_info.m_pBuffer.GetSize() > 0); - uStartOffset += m_centralDir.GetBytesBefore(); - uEndOffset += m_centralDir.GetBytesBefore(); - - DWORD uTotalToMove = uEndOffset - uStartOffset; - DWORD uPack = uTotalToMove > m_info.m_pBuffer.GetSize() - ? m_info.m_pBuffer.GetSize() - : uTotalToMove; - char* buf = (char*)m_info.m_pBuffer; - - DWORD size_read; - bool bBreak = false; - do { - - if (uEndOffset - uStartOffset < uPack) { - uPack = uEndOffset - uStartOffset; - if (!uPack) - break; - bBreak = true; - } - DWORD uPosition = bForward ? uEndOffset - uPack : uStartOffset; - - m_storage.m_pFile->Seek(uPosition, CZipAbstractFile::begin); - size_read = m_storage.m_pFile->Read(buf, uPack); - if (!size_read) - break; - - if (bForward) - uPosition += uMoveBy; - else - uPosition -= uMoveBy; - m_storage.m_pFile->Seek(uPosition, CZipAbstractFile::begin); - m_storage.m_pFile->Write(buf, size_read); - if (bForward) - uEndOffset -= size_read; - else - uStartOffset += size_read; - if (pCallback) - if (!(*pCallback)(size_read)) - ThrowError(CZipException::abortedAction); - } while (!bBreak); - - if (uEndOffset != uStartOffset) - ThrowError(CZipException::internal); -} \ No newline at end of file diff --git a/src/smpackagee/ZipArchive/ZipArchive.dox b/src/smpackagee/ZipArchive/ZipArchive.dox deleted file mode 100644 index 394c02ddcb..0000000000 --- a/src/smpackagee/ZipArchive/ZipArchive.dox +++ /dev/null @@ -1,221 +0,0 @@ -# Doxyfile 1.3.2 - -#--------------------------------------------------------------------------- -# General configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = ZipArchive -PROJECT_NUMBER = -OUTPUT_DIRECTORY = .\Doc -OUTPUT_LANGUAGE = English -USE_WINDOWS_ENCODING = YES -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = NO -STRIP_FROM_PATH = $(PWD)/ -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -SHORT_NAMES = NO -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -JAVADOC_AUTOBRIEF = YES -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -TAB_SIZE = 1 -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ALIASES = -ENABLED_SECTIONS = YES -MAX_INITIALIZER_LINES = 30 -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -SHOW_USED_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = NO -WARN_IF_DOC_ERROR = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = .\ZipArchive.h \ - .\ZipAutoBuffer.h \ - .\ZipCentralDir.h \ - .\ZipCompatibility.h \ - .\ZipException.h \ - .\ZipFileHeader.h \ - .\ZipPlatform.h \ - .\ZipMemFile.h \ - .\ZipPathComponent.h \ - .\ZipStorage.h \ - .\changelog.txt \ - .\faq.txt \ - .\License.txt \ - .\gpl.txt \ - .\Readme.txt -FILE_PATTERNS = -RECURSIVE = NO -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -VERBATIM_HEADERS = YES -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = CZip -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = . -HTML_FILE_EXTENSION = .html -HTML_HEADER = "c:\Program Files\Doxygen\header.html" -HTML_FOOTER = "c:\Program Files\Doxygen\footer.html" -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = YES -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = YES -BINARY_TOC = YES -TOC_EXPAND = YES -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = NO -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = YES -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::addtions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = NO -ALLEXTERNALS = YES -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = NO -UML_LOOK = YES -TEMPLATE_RELATIONS = YES -INCLUDE_GRAPH = NO -INCLUDED_BY_GRAPH = NO -CALL_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DOT_IMAGE_FORMAT = gif -DOT_PATH = "c:/Program Files/ATT/Graphviz/bin/" -DOTFILE_DIRS = -MAX_DOT_GRAPH_WIDTH = 1024 -MAX_DOT_GRAPH_HEIGHT = 1024 -MAX_DOT_GRAPH_DEPTH = 0 -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO -CGI_NAME = search.cgi -CGI_URL = -DOC_URL = -DOC_ABSPATH = -BIN_ABSPATH = /usr/local/bin/ -EXT_DOC_PATHS = diff --git a/src/smpackagee/ZipArchive/ZipArchive.h b/src/smpackagee/ZipArchive/ZipArchive.h deleted file mode 100644 index 9a34c3d5cc..0000000000 --- a/src/smpackagee/ZipArchive/ZipArchive.h +++ /dev/null @@ -1,2070 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipArchive.h $ -// $Archive: /ZipArchive/ZipArchive.h $ -// $Date: 2003-12-11 00:09:22 -0600 (Thu, 11 Dec 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -// -// Check the site http://www.artpol-software.com for the updated version of the -// library. -//////////////////////////////////////////////////////////////////////////////// -// -// The following information files are distributed along with this library: -// License.txt - licensing information -// gpl.txt - General Public License text -// Readme.txt - general information -// ChangeLog.txt - revision history -// faq.txt - frequently asked questions -// Appnote.txt - details on the zip format -// ( also available at -// ftp://ftp.pkware.com/appnote.zip) -// -// - -/** - * \file ZipArchive.h - * Interface for the CZipArchive class. - * - */ - -#if !defined(AFX_ZIPARCHIVE_H__A7F528A6_1872_4071_BE66_D56CC2DDE0E6__INCLUDED_) -#define AFX_ZIPARCHIVE_H__A7F528A6_1872_4071_BE66_D56CC2DDE0E6__INCLUDED_ - -/** - \namespace ziparchv - A helper namespace. - \par Members - - CZipFileMapping - -*/ - -/** - \struct CZipFileMapping ZipFileMapping.h - - Maps a file to the memory. A system-specific implementation. - Stored in ziparchv namespace. - - \c #include "ZipFileMapping.h" -*/ - -// to ensure that the correct files are copied -// (see "Compatibility" chapter in the documentation). -// Rebuild the project after copying the files. -#ifdef ZIP_ARCHIVE_MFC_PROJ -#ifndef ZIP_ARCHIVE_MFC -#error You need to copy files from the MFC subdirectory\ - to the ZipArchive root directory and rebuild the project -#endif -#elif defined ZIP_ARCHIVE_STL_PROJ -#ifndef ZIP_ARCHIVE_STL -#error You need to copy files from the STL subdirectory\ - to the ZipArchive root directory and rebuild the project -#endif -#endif // - -#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL) -#pragma warning(disable : 4251) // needs to have dll-interface to be used by - // clients of class -#pragma warning( \ - disable : 4275) // non dll-interface class used as base for dll-interface -#endif - -#ifdef __GNUC__ -#include "zlib.h" -#else -#include "../../../extern/zlib/zlib.h" -#endif - -#include "global.h" -#include "ZipAutoBuffer.h" -#include "ZipCentralDir.h" -#include "ZipException.h" -#include "ZipExport.h" -#include "ZipPathComponent.h" -#include "ZipStorage.h" -#include "ZipString.h" - -/** - Structure used as a parameter in CZipArchive::AddNewFile(CZipAddNewFileInfo& - ); Use one of constructors provided and then adjust the member variables that - are set to default values by #Defaults method. -*/ -struct ZIP_API CZipAddNewFileInfo -{ - CZipAddNewFileInfo(LPCTSTR lpszFilePath, bool bFullPath = true) - : m_szFilePath(lpszFilePath) - , m_bFullPath(bFullPath) - { - m_pFile = NULL; - Defaults(); - } - CZipAddNewFileInfo(LPCTSTR lpszFilePath, LPCTSTR lpszFileNameInZip) - : m_szFilePath(lpszFilePath) - , m_szFileNameInZip(lpszFileNameInZip) - { - m_pFile = NULL; - Defaults(); - } - CZipAddNewFileInfo(CZipAbstractFile* pFile, LPCTSTR lpszFileNameInZip) - : m_pFile(pFile) - , m_szFileNameInZip(lpszFileNameInZip) - { - Defaults(); - } - /** - the full path to the file to be added; if it is empty you need to set - #m_pFile - */ - CZipString m_szFilePath; - - /** - the file name that will be stored in the archive (if the file is a - directory, there is a path separator automatically added at the end); - #SetRootPath function has no effect on this parameter - */ - CZipString m_szFileNameInZip; - - /* - It has only the meaning when #m_szFileNameInZip is not specified and - #m_szFilePath is not empty. - - if \c true, include full path of the file inside the archive (even if - #m_szRootPath is set)
- - if \c false only the filename without a path is stored in the archive
- in this case if #m_szRootPath is set previously with #SetRootPath - and if the beginning of #m_szFilePath equals #m_szRootPath - then the filename is set to the remaining part of m_szFilePath - (you can say to m_lpszFilePath minus #m_szRootPath) - */ - bool m_bFullPath; - - /* - the compression level, see #OpenNewFile - */ - int m_iComprLevel; - - /** - the smartness level of of the library; can be one or more #Smartness - values (you can OR them);
- if zipsmCheckForEff is specified and due to it the file needs to be - reinserted into the archive without a compression and the callback - functor is specified, the callback functor's method Callback is called - with the first argument set to - DWORD (-1) (you need to remember the last argument if you need the - size of the file) - */ - int m_iSmartLevel; - - /* - the index of the existing file in the archive to be replaced by the file -being added (the new file goes into the same physical place as the old file - -the archive may of course grow or shrink as a result) - -- >= 0 the index of the file to be replaced -- -1 do not replace any file and add the new file at the end of the archive -(default) -- -2 if the new file has the same name as a file already in the archive then -replace it or add at the end of the archive if it's filename is unique; it uses -CZipArchive::FindFile with the arguments \e iCaseSensitive and \e bFileNameOnly -set to default values - - \note - - you replace files in disk-spanning archives (i.e. use a value -different from -1) - - if the space size taken by the old file is different from the space -size needed by the new file, the callback is called while moving data (see -CZipArchive::cbReplace) - - this replaces the file physically, so no information from the file -being replaced is retained (such as attributes, modification time, etc.) - - if you use an invalid index, the function will fail; if you specify -the last file in the archive to be replaced, it'll be removed and the usual -action taken - - the new file encryption does not depend on the old file encryption but -only on the current password settings (see CZipArchive::SetPassword) - - if #m_iComprLevel is not 0 then a temporary archive is created in the -temporary directory (see CZipArchive::SetTempPath) or in the memory (if you use -CZipArchive::zipsmMemoryFlag in #m_iSmartLevel) - - the most complicated scenario is when you try to replace the -file and use CZipArchive::zipsmCheckForEff flag in #m_iSmartLevel and the file -compression proves to be inefficient (you can use the sample application \e -ZipArc to observe the following process): - - first you get CZipArchive::cbAdd callback - the file is being -compressed to a temporary archive, - - then the file compression proves to be inefficient and the file -needs to be stored instead of compressed, but first the space inside archive -must be adjusted to fit the file being added in the place of file being replaced -- you get CZipArchive::cbReplace, - - then, at the end, the file is being stored - you get -CZipArchive::cbAddStore callback - \see SetAdvanced - \see CZipArchive::WillBeDuplicated - */ - int m_iReplaceIndex; - - /** - the size of the buffer used while file operations - */ - unsigned long m_nBufSize; - - /* - instead of from a physical file, the data for compression is taken from - the CZipAbstractFile object (e.g. from CZipMemFile) - "\note" - - you have to leave #m_szFilePath empty if you set #m_pFile to not NULL - - the time of the file in zip is set to the current time, and the - attributes to the default file attributes (depending on the system) - - you cannot add directories this way - */ - CZipAbstractFile* m_pFile; - - /* - Set default values for #m_iSmartLevel, #m_iReplaceIndex, #m_nBufSize and - #m_iComprLevel - */ - void Defaults(); -}; - -/** - The representation of the zip archive file. - This class provides all the operations on the zip archive. - -*/ -class ZIP_API CZipArchive -{ - - public: - /** - The purpose of this structure is to hold the data that allow communication - with the zlib library - */ - struct ZIP_API CZipInternalInfo - { - - CZipInternalInfo() { m_iBufferSize = 65536; } - virtual ~CZipInternalInfo() {} - - /** - Allocate internal buffer of m_iBufferSize size - */ - void Init() { m_pBuffer.Allocate(m_iBufferSize); } - void ReleaseBuf() { m_pBuffer.Release(); } - z_stream m_stream; ///< zlib library data stream - DWORD m_uUncomprLeft; ///< bytes left to uncompress - DWORD m_uComprLeft; ///< bytes left to decompress - DWORD m_uCrc32; ///< crc32 file control value - - /** - The size of the buffer used in decompressing data. - Set before opening the archive. - It is usually set with CZipArchive::SetAdvanced - (specify this value as the second argument). - \see CZipArchive::SetAdvanced - */ - DWORD m_iBufferSize; - - /** - This buffer caches data during compression and decompression. - */ - CZipAutoBuffer m_pBuffer; - }; - - CZipArchive(); - virtual ~CZipArchive(); - - /* - In non-UNICODE version just copy \e szSingle to \e szWide. - In UNICODE version works the same way as ZipPlatform::SingleToWide - \param szSingle - \param szWide - \return (in non-UNICODE version the number of characters copied) - \see ZipPlatform::SingleToWide -*/ - static int SingleToWide(const CZipAutoBuffer& szSingle, CZipString& szWide); - - /** - In non-UNICODE version just copy \e lpWide to \e szSingle. - In UNICODE version works the same way as ZipPlatform::WideToSingle - \param lpWide - \param szSingle - \return (in non-UNICODE version the number of characters copied) - \see ZipPlatform::WideToSingle - -*/ - static int WideToSingle(LPCTSTR lpWide, CZipAutoBuffer& szSingle); - - /** - Set the password for the file to be opened or created. - Use this method BEFORE opening or adding a file, but AFTER opening an - archive \param lpszPassword set it to NULL to clear password \return \c - false if the password contains ASCII characters with values 128 or higher or - the file inside archive is opened - -*/ - bool SetPassword(LPCTSTR lpszPassword = NULL); - - /** - \return the current archive password or an empty string if there is no - password -*/ - CZipString GetPassword() const; - - /** - Set the buffer sizes. No buffer can be set smaller than 1024. - Use this method before opening the archive. The optimal size for - the write buffer in the disk spanning archive is the size of the volume. - - \param iWriteBuffer - the write cache size used - \see CZipStorage::m_iWriteBufferSize - \param iGeneralBuffer - buffer used in extracting, compressing, deleting, getting - (#GetFromArchive) files, renaming and replacing \see - CZipInternalInfo::m_iBufferSize \param iSearchBuffer the buffer used in - searching for the central dir \see CZipCentralDir::m_iBufferSize \see - GetAdvanced -*/ - void SetAdvanced(int iWriteBuffer = 65536, - int iGeneralBuffer = 65536, - int iSearchBuffer = 32768); - - /** - retreive buffer size as set by #SetAdvanced - */ - void GetAdvanced(int* piWriteBuffer = NULL, - int* piGeneralBuffer = NULL, - int* piSearchBuffer = NULL) - { - if (piWriteBuffer) - *piWriteBuffer = m_storage.m_iWriteBufferSize; - if (piGeneralBuffer) - *piGeneralBuffer = m_info.m_iBufferSize; - if (piSearchBuffer) - *piSearchBuffer = m_centralDir.m_iBufferSize; - } - - /** - Enum values used as \e iWhich parameter in #SetCallback function. - You can assign several values to the same functor (OR them) - \see CZipActionCallback - */ - enum CallbackType - { - cbNothing = 0x0000, ///< you can use it for your own purposes - cbAdd = 0x0001, ///< called when adding a file with one of #AddNewFile - ///< functions - cbAddTmp = 0x0002, ///< called while adding a file (only on a - ///< disk-spanning archive) when the smartness level - ///< contains CZipArchive::zipsmCheckForEff or - ///< CZipArchive::zipsmCheckForEffInMem and if just - ///< compressed file is being moved from a temporary - ///< place (file or memory) to the archive - cbAddStore = 0x0004, ///< called while adding a file and if it's - ///< compressing has proven to be inefficient and - ///< it is now being stored (instead of compressed) - ///< in the archive; smartness level must contain - ///< CZipArchive::zipsmCheckForEff or - ///< CZipArchive::zipsmCheckForEffInMem; the - ///< archive can be disk-spanning or not - - cbExtract = 0x0008, ///< called when extracting a file with one of - ///< #ExtractFile functions - - cbDeleteCnt = 0x0010, ///< called before the actual deletion takes place - ///< and the map of holes and continuous areas is - ///< being created (it safe to break it by - ///< returning \c false from the callback method) - cbDelete = 0x0020, ///< called when moving data while deleting file(s) - ///< with function #DeleteFile or one of #DeleteFiles - ///< functions - - cbTest = 0x0040, ///< called when testing a file with #TestFile function - cbSave = 0x0080, ///< called when saving the central directory with - ///< CZipCentralDir::Write (usually on close or flush); - ///< it is safe to break on non-disk spanning archive - - ///< the saved part of the central directory will be - ///< removed from disk - cbGetFromArchive = - 0x0100, ///< called when using one of #GetFromArchive methods - cbRename = 0x0200, ///< called when during the renaming a file there is - ///< a need to make less or more space for the new - ///< filename - cbReplace = 0x0400, ///< called when moving data while replacing files - ///< to make less or more space for the new file - cbNextValue = 0x0800, ///< for CZipActionCallback overrides and user - ///< defined callbacks - - cbSubActions = cbAddTmp | cbAddStore | cbDeleteCnt | - cbReplace, ///< sub actions - they are part of bigger - ///< actions (#cbAddTmp | #cbAddStore | - ///< #cbDeleteCnt | #cbReplace) - cbActions = - cbAdd | cbExtract | cbDelete | cbTest | cbSave | cbGetFromArchive | - cbRename, ///< main actions (#cbAdd | #cbExtract | #cbDelete | #cbTest - ///< | #cbSave | #cbGetFromArchive | #cbRename) - cbAll = - cbActions | cbSubActions ///< assign all callbacks to the same functor - }; - - /* - Set callback functors for the following operations on the zip archive: - adding, extracting, testing or deleting files. See \ref sectCallb - information on how to use functors. \param pCallback the address of the - functional object which class is derived from CZipActionCallback (you - need to override member function CZipCallback::Callback in the derived - class) Set it to \c NULL to clear callback for the selected actions. - \param iWhich - can be one or more (use logical OR) #CallbackType values. - \see CZipActionCallback - \see GetCallback - */ - void SetCallback(CZipActionCallback* pCallback = NULL, int iWhich = cbAll); - - /** - \return the callback \e iWhich set with #SetCallback - */ - CZipActionCallback* GetCallback(CallbackType iWhich) - { - return m_callbacks.Get(iWhich); - } - - /* - Set the callback functor used during operations on a - PKZIP compatible disk spanning archive to change disks. - Set it before opening the archive. If you open the archive - in the \ref PKSpan "PKZIP compatible mode" and don't set the callback - functor, the exception CZipException::noCallback will be thrown. - - Callback functor's method CZipSpanCallback::Callback is called when - there is a need for a disk change. Calling CZipArchive methods from - inside this method may result in an unexpected behavior. \param pCallback - the address of the functional object which class is derived from - CZipSpanCallback (you need to override member function - CZipCallback::Callback in the derived class) Set it to \c NULL to clear - the callback. - \see CZipSpanCallback - */ - void SetSpanCallback(CZipSpanCallback* pCallback = NULL) - { - m_storage.m_pChangeDiskFunc = pCallback; - } - - /* - Archive open modes used in #Open(LPCTSTR , int , int ) - and #Open(CZipMemFile, int ) - */ - enum OpenMode - { - zipOpen, ///< open an existing archive - /** - Open an existing archive as a read only file. - This mode is intended to use in a self extract code or opening - archive on storage without write access (e.g. CD-ROMS), - If you try to modify the archive in this mode, - an exception will be thrown. - */ - zipOpenReadOnly, - zipCreate, ///< create a new archive - zipCreateSpan ///< create a disk spanning archive - }; - - /* - Open or create a zip archive. - - The archive creation mode depends on \e iMode and \e iVolumesSize values: - - if \e iMode == #zipCreateSpan and \e iVolumeSize <= 0 then create disk - spanning archive in \ref PKSpan "PKZIP compatible mode" (pkzipSpan) - - if \e iMode == #zipCreateSpan and \e iVolumeSize > 0 then create disk - spanning archive in \ref TDSpan "TD compatible mode" (tdSpan) - - if \e iMode == #zipOpen and the existing archive is a spanned archive - then pkzipSpan mode is assumed if the archive is on a removable device - or tdSpan otherwise;
- if you want to open tdSpan archive on a removable device, set \e - iVolumeSize to a value different from 0 - - if \e iMode == #zipCreate then \e iVolumeSize doesn't matter - - \param szPathName - the path to the archive - \param iMode - one of the #OpenMode values - \param iVolumeSize - the volume size in the disk spanning archive; - the size of the volume may be from 1 to INT_MAX , - and the bigger - the faster is creation and extraction (no file changes - between volumes) - but the size of the whole archive is the same. If you're - creating disk-spanning archive in \ref TDSpan "TD span compatible mode" and - plan later to convert it to \ref PKSpan "PKZIP compatible mode" (see \ref - sectSpan), it is good to set this this value to about the size of the - diskette (a little less just in case). - \note Throws exceptions. - \see Open(CZipMemFile&, int); - \see GetSpanMode -*/ - void Open(LPCTSTR szPathName, int iMode = zipOpen, int iVolumeSize = 0); - - /* - Open or create the archive in memory. The CZipMemFile object is not closed - after closing the archive, so that is it possible to work with it - afterwards. \param mf CZipMemFile structure to create archive in or extract - from \note This is important: you shouldn't destroy CZipMemFile object - before closing the archive, because you'll get an error; \param iMode Open - mode. The following modes are valid: #zipOpen, #zipOpenReadOnly, #zipCreate - \note Throws exceptions. - \see Open(LPCTSTR, int, int); -*/ - void Open(CZipMemFile& mf, int iMode = zipOpen); - - /* - Set #m_szRootPath to a specified value. Use it if you don't want to set - \e bFullPath argument in #AddNewFile or #ExtractFile to true and you - don't want to strip the whole path neither, but only a specific beginning. - Use it AFTER opening the archive and before using #AddNewFile or - #ExtractFile. See \ref q9 "the FAQ" for the example of use. \param szPath - Set it to the string that you want to be omitted from the beginning of - the path of the file in the archive
if \c NULL - clears the - #m_szRootPath and no path beginning will be matched against it - - \note Set the case-sensitivity with #SetCaseSensitivity - - \see AddNewFile - \see ExtractFile - \see GetRootPath - -*/ - void SetRootPath(LPCTSTR szPath = NULL); - - /* - Return the current value of #m_szRootPath - \return CZipString - */ - CZipString GetRootPath() const { return m_szRootPath; } - - /* - The levels of smartness of the adding files action (see #AddNewFile) - \note If you wish to use \e zipsmCheckForEff, you should use - \e zipsmNotCompSmall as well, because it will save you the time - ( the small file will be surely larger after compression, so that - we can add it not compressed straight away);the compression level - is always ignored for a directory and set to 0 - */ - - enum Smartness - { - zipsmLazy = - 0x0000, ///< do not bother (you know what you're doing after all) - zipsmCPassDir = 0x0001, ///< clear password for directories - zipsmCPFile0 = 0x0002, ///< clear password for files of 0 size - zipsmNotCompSmall = 0x0004, ///< do not compress files smaller than 5 - ///< bytes (they are always stored larger - ///< than uncompressed) - zipsmCheckForEff = - 0x0008, ///< check whether the compressed file is larger than - ///< uncompressed and if so, remove it and store without the - ///< compression; in the disk spanning mode, the temporary - ///< file is used for that: if the file compression is - ///< efficient, the data is not compressed again, but moved - ///< from the temporary file to the archive; you can use - ///< #SetTempPath() to set the path where the file will be - ///< created or you can let the library figure it out (the - ///< library tries first the system default temporary - ///< directory, if it is not present or there is not enough - ///< space there, it tries the current directory, if it fails, - ///< no temporary file is created and the compression goes the - ///< usual way - - zipsmMemoryFlag = 0x0010, ///< combine it with zipsmCheckForEff or use - ///< zipsmCheckForEffInMem, you can also use - ///< this when replacing files see note at - ///< CZipAddNewFileInfo::m_iReplaceIndex - - zipsmCheckForEffInMem = - zipsmMemoryFlag | - zipsmCheckForEff, ///< the same as #zipsmCheckForEff, but the - ///< temporary file is created created in memory - ///< instead (the temporary directory set with - ///< #SetTempPath() is ignored); has the meaning - ///< only with a disk-spanning archive, non-disk - ///< spanning archives don't need a temporary file - zipsmSmartPass = - zipsmCPassDir | zipsmCPFile0, ///< smart password policy (a - ///< combination of \e zipsmCPassDir and - ///< \e zipsmCPFile0) - zipsmSmartAdd = - zipsmNotCompSmall | zipsmCheckForEff, ///< smart adding (a combination - ///< of \e zipsmNotCompSmall and - ///< \e zipsmCheckForEff) - zipsmSafeSmart = - zipsmSmartPass | zipsmNotCompSmall, ///< safe smart (smartest without - ///< checking for efficiency) - zipsmSmartest = zipsmSmartPass | zipsmSmartAdd, ///< smart at its best - - zipsmInternal01 = 0xf000 ///< for internal use only - - }; - - /* - Add a new file to the archive. You can set the callback functor with - #SetCallback. \param info see CZipAddNewFileInfo \return \c if it - returns false then the file was not added, but the internal state allows - you to add other files (which is not possible after throwing an - exception) - \note - - If you abort while adding a file in a non-disk-spanning archive, the - added data will be removed from the archive - - Throws exceptions. - \see SetCallback - \see AddNewFile(LPCTSTR, LPCTSTR, int, int, unsigned long) - \see AddNewFile(LPCTSTR, int, bool, int, unsigned long) - \see AddNewFile(CZipMemFile&, LPCTSTR, int, int, unsigned - long) - */ - bool AddNewFile(CZipAddNewFileInfo& info); - - // \see AddNewFile(CZipAddNewFileInfo& ); the parameters are equivalent to - // CZipAddNewFileInfo member variablesd - - bool AddNewFile(LPCTSTR lpszFilePath, - int iComprLevel = -1, - bool bFullPath = true, - int iSmartLevel = zipsmSafeSmart, - unsigned long nBufSize = 65536); - - /* - \see AddNewFile(CZipAddNewFileInfo& ); the parameters are equivalent to - CZipAddNewFileInfo member variables - */ - bool AddNewFile(LPCTSTR lpszFilePath, - LPCTSTR lpszFileNameInZip, - int iComprLevel = -1, - int iSmartLevel = zipsmSafeSmart, - unsigned long nBufSize = 65536); - - /* - \see AddNewFile(CZipAddNewFileInfo& ); the parameters are equivalent to - CZipAddNewFileInfo member variables - */ - bool AddNewFile(CZipMemFile& mf, - LPCTSTR lpszFileNameInZip, - int iComprLevel = -1, - int iSmartLevel = zipsmSafeSmart, - unsigned long nBufSize = 65536); - - /* - Add a new file to the opened zip archive. The zip archive cannot be - an existing disk spanning archive (existing at the moment of opening - archive), because modifying such an archive is not possible (at least not - with this version ). - \param header - The structure that provides additional information about the added file. - The following fields are valid: - - \e m_uMethod - file compression method; can be 0 (storing) or - Z_DEFLATE (deflating) otherwise Z_DEFLATE is assumed - - \e m_uModDate, \e m_uModTime - Use CZipFileHeader::SetTime to set - them. If \e lpszFilePath is not NULL this fields are overwritten and updated - automatically. See CZipFileHeader::SetTime - - \e m_uExternalAttr - Attributes of the file. - If \e lpszFilePath is not NULL this field is overwritten and updated - automatically. Use #SetFileHeaderAttr to set them. See #SetFileHeaderAttr. - - \e m_szFileName - A filename (may be with path) to be stored inside - archive to represent this file. See CZipFileHeader::SetFileName - - \e m_szComment - A file comment. See CZipFileHeader::SetComment - - \e m_pExtraField - LOCAL extra field, use #SetExtraField after opening - a new file, but before closing it to set the not local extra field - in the header in the central directory. See #SetExtraField
- Other fields are ignored - they are updated automatically. - If the function returns \c true, \link #GetSystemCompatibility - system compatibility \endlink for this object is - set to the correct value (the same as #m_iArchiveSystCompatib), - additionally if \e lpszFilePath was not NULL, the attributes and - the time fields are filled with information retrieved from - the file pointed by \e lpszFilePath. - \param iLevel - The level of compression (-1, 0 - 9). - The are several preset values for the compression level: - - Z_DEFAULT_COMPRESSION : -1 (equals 6) - - Z_NO_COMPRESSION : 0 - - Z_BEST_SPEED : 1 - - Z_BEST_COMPRESSION : 9 - \param lpszFilePath - The path to the file to retrieve date stamp and attributes from. - These values are stored inside the archive. - \param uInternal - for internal use only - - \return \c false in the following cases: - - the \e lpszFilePath is not NULL and the file attributes and data was not - correctly retrieved - - a file is already opened for extraction or compression - - archive is an existing disk span archive - - maximum file count inside archive already reached (65536) - \note Throws exceptions. - -*/ - bool OpenNewFile(CZipFileHeader& header, - int iLevel = Z_DEFAULT_COMPRESSION, - LPCTSTR lpszFilePath = NULL, - DWORD uInternal = 0); - - /* - Compress the contents of the buffer and write it to a new file. - \param pBuf - the buffer containing the data to be compressed and written - \param iSize - the number of bytes to be written from the buffer - \return \c false if the new file hasn't been opened yet - \note Throws exceptions. - \see OpenNewFile -*/ - bool WriteNewFile(const void* pBuf, DWORD iSize); - - /* - Set the extra field in the central directory of the currently opened file. - Must be used after opening a new file in the archive, but before closing it - To set the local extra field, set it in the CZipFileHeader structure passed - as the argument to the #OpenNewFile - \param pBuf - the bufer with the data to be copied - \param iSize - the size of the extra field in the buffer - \see OpenNewFile -*/ - void SetExtraField(const char* pBuf, WORD iSize); - - /* - Close the new file in the archive. - \return \c false if there is no new file opened - \param bAfterException - it will close the new file without writing anything (call it also - with this parameter set to \c true after an exception other than - CZipException::abortedSafely was thrown from one of #AddNewFile functions) - \note Throws exceptions. - \see OpenNewFile -*/ - bool CloseNewFile(bool bAfterException = false); - - /* - Acquire a file with the given index from another archive. - The compressed data of the file from another archive are copied - without decompressing to the current archive. - You can set the callback functor with #SetCallback. - \param zip - an opened archive to get the file from (must not be multi-disk) - \param uIndex - a zero-based index of the file to get from the \e zip archive - \param iReplaceIndex the same as CZipAddNewFileInfo::m_iReplaceIndex - \param bKeepSystComp - if \c false, which is default, then the file from \e zip archive - system compatibility is converted to the current archive system - compatibility (if they differ) - \return \c false if the operation could not be performed (either of archives - is closed, a file inside either of archives is opened, \e zip archive is - multi-disk or the current archive is an existing multi-disk archive) \note - Throws exceptions
(when an exception is thrown, you may need to call - #CloseNewFile with \e bAfterException set to \c true, to make the archive - reusable). \note it is safe to abort the action (by returning false from the - callback call) in non-disk spanning archive and when no replacing is taking - place (the file not entirely added is removed from the archive) \see - SetCallback \see GetFromArchive(CZipArchive& , CZipWordArray &, bool) \see - GetFromArchive(CZipArchive& , CZipStringArray &, bool) \see FindMatches \see - SetAdvanced -*/ - bool GetFromArchive(CZipArchive& zip, - WORD uIndex, - int iReplaceIndex = -1, - bool bKeepSystComp = false) - { - - m_info.Init(); - bool bRet; - try { - bRet = GetFromArchive(zip, - uIndex, - iReplaceIndex, - bKeepSystComp, - GetCallback(cbGetFromArchive)); - } catch (...) { - m_info.ReleaseBuf(); - throw; - } - m_info.ReleaseBuf(); - if (bRet && m_bAutoFlush) - Flush(); - - return bRet; - } - - /* - Acquire files with the given indexes from another archive. - \param aIndexes - an array of zero-based indexes of the files inside the \e zip archive - - \see GetFromArchive(CZipArchive& , WORD, int, bool) - - \note - - To get files which filenames match a specified pattern, use #FindMatches - function - */ - bool GetFromArchive(CZipArchive& zip, - CZipWordArray& aIndexes, - bool bKeepSystComp = false); - - /* - Acquire files with the given indexes from another archive. - \param aNames - an array of filenames inside the \e zip archive; - \see GetFromArchive(CZipArchive& , WORD, int, bool) - \see EnableFindFast - - \note - - Set the case-sensitivity with #SetCaseSensitivity - - Enables FindFast if not enabled - */ - - bool GetFromArchive(CZipArchive& zip, - CZipStringArray& aNames, - bool bKeepSystComp = false) - { - CZipWordArray indexes; - zip.GetIndexes(aNames, indexes); - return GetFromArchive(zip, indexes, bKeepSystComp); - } - - /* - Get indexes of the files stored int \e aNames array and put them into \e - aIndexes \param aNames an array of filenames inside the archive; \param - aIndexes an array of indexes to be build \note - - Set the case-sensitivity with #SetCaseSensitivity - - Enables FindFast if not enabledd - */ - void GetIndexes(const CZipStringArray& aNames, CZipWordArray& aIndexes); - - /* - Extract the file from the archive. You can set the callback functor with - #SetCallback. The argument \e lpszNewName may point to the full path and is - influenced by \e bFullPath argument (if \e lpszNewName contains drive - specification then it is removed) \param uIndex the index of the file to - extract \param lpszPath \verbatim The PATH only to extract the file to. May - not be NULL. If you wish to use UNC path you need to replace \\\\ at the - beginning of UNC path with \\\\?\UNC\ . \endverbatim \param bFullPath
- - if \c true, then extract with the full path - in this case the - resulting file path is \e lpszPath plus the path stored in the archive or - plus \e lpszNewName if \e lpszNewName is not NULL.
- - if \c false, the destination file path is \e lpszPath + \e the - filename only extracted from the path stored in the archive or from \e - lpszNewName if \e lpszNewName is specified;
if #m_szRootPath is set - previously with #SetRootPath then to \e lpszPath is added the path stored in - the archive (or \e lpszNewName if \e lpszNewName is specified) that has - removed the beginning that equals #m_szRootPath (if there is no common - beginning then is behaves like #m_szRootPath was empty) \param lpszNewName - The new name of the file after extraction. - If NULL the original filename stored in the archive is used. - May point to the full path but, if \e bFullPath is \c false, only - the filename is extracted from this argument, \param nBufSize the size of - the buffer used while file operations \return \c true if successful \note - - To extract files which filenames match a specified pattern, use - #FindMatches function - - Throws exceptions. - \see SetCallback - \see ExtractFile(WORD, CZipMemFile&, DWORD) - \see FindMatches -*/ - bool ExtractFile(WORD uIndex, - LPCTSTR lpszPath, - bool bFullPath = true, - LPCTSTR lpszNewName = NULL, - DWORD nBufSize = 65536); - - /* - The same as #ExtractFile(WORD , LPCTSTR , bool , LPCTSTR , DWORD - ) but instead to a physical file, this function decompress the - data into CZipMemFile object \note - - if you pass CZipMemFile object already with data, its contents are NOT - overwirtten, but the decompressed data is appended at the end - - if you try to extract a directory, the function will return \c false - */ - bool ExtractFile(WORD uIndex, CZipMemFile& mf, DWORD nBufSize = 65536); - - /* - Open the file with the given index in the archive for extracting. - Not successful opening the file doesn't lock the whole archive, so - you can try to open another one (after catching an exception if it was - thrown). Throw exception CZipException::badPassword if the password - was not set for the encrypted file. - \param uIndex - the index of the file - \return \c true if successful - \note Throws exceptions. -*/ - bool OpenFile(WORD uIndex); - - /* - Decompress currently opened file to the buffer. - \param pBuf - buffer to receive data - \param iSize - the size of the buffer - \return the number of bytes read - \see OpenFile - \note Throws exceptions. -*/ - DWORD ReadFile(void* pBuf, DWORD iSize); - - /* - Test the file with the given index for the integrity. You can set the - callback functor with #SetCallback. The method throws exceptions but - performs all the necessary cleanup before, so that the next file can be - tested after catching the exception. \param uIndex index of the file to test - \param uBufSize - the size of the buffer used during extraction - \return \c false if the incorrect action has been taken by - the user or the programmer (it is when #OpenFile or #GetFileInfo returned \c - false or \e uBufSize is 0). If the file didn't passed the test or there was - a disk I/O error or the password supplied was incorrect, an exception is - thrown. \note Throws exceptions. \see SetCallbackd -*/ - bool TestFile(WORD uIndex, DWORD uBufSize = 65536); - - /* - Perform the necessary cleanup after an exception was thrown - while testing the archive so that next files in the archive can be tested. - Called by #TestFile. Does not remove the file headers - information from the central directory. - \see TestFile - \see CZipCentralDir::Clear -*/ - void CloseFileAfterTestFailed(); - - /* - Get the local extra filed of the currently opened - for extraction file in the archive. - \param pBuf - the buffer to receive the data - \param iSize - the size of the buffer - \return If \e pBuf is NULL or iSize is 0, returns the size of the local - extra field. Returns -1 if there is no file opened for the extraction. -*/ - int GetLocalExtraField(char* pBuf, int iSize) const; - - /* - The same as CZipArchive::CloseFile(LPCTSTR), but additionally - closes \e file. - \param file - OPENED CZipFile structure of the extracted file - \return - \note Throws exceptions. - \see CZipArchive::CloseFile(LPCTSTR) -*/ - int CloseFile(CZipFile& file); - - /* - Close the file opened for extraction in the archive and copy its date and - attributes to the file pointed by \e lpszFilePath - \param lpszFilePath - Points to the path of the file to have the date and attributes - information updated. \param bAfterException Set to \c true to close the file - inside archive after an exception has been thrown, to allow futher - operations on the archive. \warning Close the file pointed by \e - lpszFilePath before using this method, because the system may not be able to - retrieve information from it. \return
- - "1" = ok - - "-1" = some bytes left to uncompress - probably due to a bad password or - corrupted archive - - "-2" = setting extracted file date and attributes was not successful - \note Throws exceptions. -*/ - int CloseFile(LPCTSTR lpszFilePath = NULL, bool bAfterException = false); - - /* - Delete the file from the archive with the given index. - You can set the callback functor with #SetCallback. - If you plan to delete more than one file, use one of DeleteFiles - functions rather than calling DeleteFile successively, because these - functions are optimized for deleting multiple files \param uIndex a - zero-based index \note Throws exceptions. \see SetCallback \see - DeleteFiles(CZipWordArray&) \see DeleteFiles(const CZipStringArray&) \see - FindMatches -*/ - void DeleteFile(WORD uIndex); - - /* - Delete files from the archive. - You can set the callback functor with #SetCallback. - Sorts \e aIndexes array in an ascending order. - \param aIndexes - an array of zero-based indexes of the files inside the archive - \note - - To remove files which filenames match a specified pattern, use - #FindMatches function - - Throws exceptions. - \see SetCallback - \see DeleteFile - \see DeleteFiles(const CZipStringArray& ) - \see FindMatches -*/ - void DeleteFiles(CZipWordArray& aIndexes); - - /* - Delete files from the archive. - You can set the callback functor with #SetCallback. - \param aNames - an array of filenames inside the archive; - \note - - Set the case-sensitivity with #SetCaseSensitivity - - Enables FindFast if not enabled - - Throws exceptions. - \see SetCallback - \see DeleteFile - \see DeleteFiles(CZipWordArray&) - \see EnableFindFast -*/ - void DeleteFiles(const CZipStringArray& aNames); - - /** - Set the global comment in the archive. - \param lpszComment - the file comment - \return \c false if the archive is closed or if it is an existing disk - spanning archive \note Throws exceptions. -*/ - bool SetGlobalComment(LPCTSTR lpszComment); - - /** - \return the global comment or an empty string if the archive is closed -*/ - CZipString GetGlobalComment() const; - - /** - Set the comment of the file with the given index inside the archive. - \param uIndex - zero-based index of the file in the archive - \param lpszComment - a comment to add - \return \c false if the comment change is impossible - \note Throws exceptions. -*/ - bool SetFileComment(WORD uIndex, LPCTSTR lpszComment); - - /** - \return the path of the currently opened archive volume -*/ - CZipString GetArchivePath() const; - - /** - \return
- - a one-based number of the current disk - - 0 if there is no current disk (the archive is closed) - \note Useful mostly while working with the disk-spanning archive in creation - to find out how many disks were already created. To find out how many disks - are in an existing disk-spanning archive, use the function - #GetCentralDirInfo -*/ - int GetCurrentDisk() const; - - /* - Return the disk spanning mode of the current archive. - - \return
- - -2 - existing TD mode compatible disk spanning archive - - -1 - existing PKZIP compatible - - 0 - no disk spanning - - 1 - PKZIP compatible in creation - - 2 - TD compatible in creation - - \see \ref PKSpan, \ref TDSpan - -*/ - int GetSpanMode() const - { - return m_storage.m_iSpanMode * m_storage.IsSpanMode(); - } - - /** - case-sensitivity values used as argument \e iCaseSensitive in #FindFile - */ - enum FFCaseSens - { - ffDefault, ///< use the default case-sensitivity as set with - ///< #SetCaseSensitivity function; - ///< if CZipCentralDir::m_findarray was build before with a different - ///< case-sensitivity, it is rebuild again, if it hasn't been build so - ///< far, it is build now with the default case-sensitivity - ffCaseSens, ///< perform a case-sensitive search (if the \c CZipArchive - ///< is non-case-sensitive, - ///< a less effective search is perfomed); does not rebuild - ///< CZipCentralDir::m_findarray, but if the array hasn't been built - ///< yet, it is build now as \b non-case-sensitive (you can use \c - ///< SetCaseSensitivity(true) and then #ffDefault to build it as - ///< case-sensitive) - ffNoCaseSens ///< perform a non-case-sensitive search (if the \c - ///< CZipArchive is case-sensitive, a less effective search - ///< is performed); does not rebuild - ///< CZipCentralDir::m_findarray, but if the array hasn't - ///< been built yet, it is build now as \b case-sensitive - ///< (you can use \c SetCaseSensitivity(false) and then - ///< #ffDefault to build it as non-case-sensitive) - - }; - - /** - Find the file in the archive. - If the archive wasn't opened with CZipCentralDir::m_bConvertAfterOpen set to - \c true, this function automatically convert all the filenames with the - function CZipCentralDir::ConvertAll and set - CZipCentralDir::m_bConvertAfterOpen to \c true. This function requires \link - CZipCentralDir::m_bFindFastEnabled FindFast \endlink feature enabled. \param - lpszFileName the name of the file to be found in the archive; must be with - path unless you set \e bFileNameOnly to \c true. Use path separators the - same as they are for your system - (\e "\" for Windows and \e "/" for Unix/Linux) - \param iCaseSensitive can be one of #FFCaseSens values - \param bFileNameOnly - if \c true, the function tries to find a filename without a path (a less - effective search is performed); if you wish to find a directory name, do not - end it with the path separator, which is required if you set \e bFileName to - \c false \return
- - the index of the file found - - -1 if there is no such a file in the archive - \see CZipCentralDir::FindFileNameIndex - \see EnableFindFast - \see CZipCentralDir::ConvertAll - \see SetConvertAfterOpen -*/ - int FindFile(LPCTSTR lpszFileName, - int iCaseSensitive = ffDefault, - bool bFileNameOnly = false); - - /** - Get the info of the file with the given index. - \param fhInfo - the structure to receive info - \param uIndex - a zero-based index of the file inside the archive - \return \c true if successful -*/ - bool GetFileInfo(CZipFileHeader& fhInfo, WORD uIndex) const; - - /** - \param bOnlyFiles - if \c true, the directories are not inluded in a total count; - default is \c false - \return the number of files in the archive -*/ - int GetCount(bool bOnlyFiles = false) const - { - int iTotalCount = m_centralDir.m_headers.GetSize(); - if (bOnlyFiles) { - int iCount = 0; - for (int i = 0; i < iTotalCount; i++) - if (!m_centralDir.m_headers[i]->IsDirectory()) - iCount++; - return iCount; - } else - return iTotalCount; - } - - /** - values used in #Close function as parameter \e iAfterException - */ - enum CloseAfterException - { - afNoException, ///< normal close, no exception was thrown before by - ///< CZipArchive object - afAfterException, ///< an exception has been thrown, don't write any - ///< data but perform necessary cleaning to reuse - ///< CZipArchive object for another archive - afWriteDir ///< the same as above, but write the central directory end - ///< structure to the archive, so that we can save at least - ///< the files that have been added properly and maybe try to - ///< repair the archive later - }; - - /** - Close the archive. - \param iAfterException - one of #CloseAfterException enum values - \param bUpdateTimeStamp - if \c true, set the modification date of the zip file to the date of the - newest file in the archive; in disk-spanning mode only the last archive file - will have the time stamp updated; you can use this option even without - performing any additional processing on the archive, just open and close it - \note Throws exceptions if \e iAfterException is different from \c - afAfterException -*/ - void Close(int iAfterException = afNoException, - bool bUpdateTimeStamp = false); - - /** - Test if the archive is closed (a whole or the current volume only) - \param bArchive
- - \c true: test for the whole archive - - \c false: test for the volume file only - - \return \c true if closed -*/ - bool IsClosed(bool bArchive = true) const; - - /** - Write the central directory to the archive and flushes the internal - buffers to the disk, so that the archive is finalized on the disk, but - you can still modify it. Use it after opening (or creating) and modifying - the archive if you want to prevent the loss of the data you've compressed - so far in case of the program crash.
If you use it on a disk - spanning archive in creation it will not be closed, but its state will be - changed from "archive in creation" to "an existing span archive". Use it - when you finish adding files to the disk-spanning archive and want to - begin extracting or testing it. It follows that you can call it only - once in this case. However, if after finalizing the disk spanning archive - it turns out that it is one disk only, it is converted to a normal - archive and you can use it as such. If you want to know what is the state - of the archive after using this function call #GetSpanMode. \note - - Cannot be used on existing disk spanning archives (they are not - modifable anyway) - - If you have an archive with a huge central directory, it'll influence - the perfomance calling this function without a reason. - - Throws exceptions. - \see GetSpanMode - \see SetAutoFlush - \see GetAutoFlush - - */ - void Flush(); - - /** - Set the CZipArchive object to call #Flush after each operation that - modifies the archive (adding a new file, deleting file(s), modifying the - global or a file comment). It is useful when we want to prevent the loss - of data in case of the program crash - the zip file will be then - finalized on the disk. Use it after opening the archive. \note - - You can set AutoFlush only for non-disk spanning archives, however you - can call #Flush once for a disk-spanning archive in creation. - - If you have an archive with a huge central directory, setting - Auto-Flush will influence the performance. \see Flush \see GetAutoFlush - */ - void SetAutoFlush(bool bAutoFlush = true); - - /** - return the current #m_bAutoFlush value - \see Flush - \see SetAutoFlush - */ - bool GetAutoFlush() const { return m_bAutoFlush; } - - /** - Return the system compatibility of the current archive. - System compatibility value for the single file in the archive - (represented by CZipFileHeader) influences file attributes conversion - (the file attributes are defined differently across the platforms). - When opening an existing archive CZipArchive assumes the system - compatibility of the whole archive to be the same as of the first file in - the archive (if present). In other cases the current system value is assumed - which is taken from ZipPlatform::GetSystemID during creating or opening an - archive \remark If the existing archive during opening is empty, - ZipPlatform::GetSystemID is assumed to be the default system for the files - that will be added to the archive - \return - one of the enum values defined in \link ZipCompatibility::ZipPlatforms - ZipCompatibility.h \endlink - \see ZipCompatibility::ZipPlatforms - \see ZipPlatform::GetSystemID - \see CZipFileHeader::GetSystemCompatibility -*/ - int GetSystemCompatibility() const { return m_iArchiveSystCompatib; } - - /** - Set the system compatibility of the archive. By default it is set to the - current system value (the one returned by ZipPlatform::GetSystemID() - function). Use it after opening the archive, but before adding a new file or - using SetFileHeaderAttr() function \param iSystemComp can be one of - ZipCompatibility::ZipPlatforms values \return return \c false if the value - \e iSystemComp is not supported (ZipCompatibility::IsPlatformSupported - returns \c false for the value) or it is not possible to set it right now -*/ - bool SetSystemCompatibility(int iSystemComp); - - /** - Set the attributes for CZipFileHeader structure to be used - in #OpenNewFile method as an argument. - This special procedure is taken, because the system compatibility must - be set for CZipFileHeader prior to the value, which must be identical to - the return value of #GetSystemCompatibility method. - \param header - the structure to have attributes set - \param uAttr - attributes to set - \note Throws exceptions if the archive system or the current system - is not supported by the ZipArchive library. - \see GetSystemCompatibility -*/ - void SetFileHeaderAttr(CZipFileHeader& header, DWORD uAttr); - - /** - A helper for a various purposes (needed e.g. by the program that - cracks the zip archives password) - \return the pointer to the static CRC table in the zlib library -*/ - static const DWORD* GetCRCTable() { return get_crc_table(); } - - /** - Return the underlying archive storage medium. - \warning A method for a very advanced use - you normally never need it. - \return the pointer to #m_storage - \see CZipStorage -*/ - CZipStorage* GetStorage() { return &m_storage; } - - /* - Set #m_bDetectZlibMemoryLeaks value. - \param bDetect - \note Use before opening a file in the archive. - \see m_bDetectZlibMemoryLeaks -*/ - void SetDetectZlibMemoryLeaks(bool bDetect) - { - if (m_iFileOpened != nothing) { - TRACE(_T("CZipArchive::SetDetectZlibMemoryLeaks: Set it before ") - _T("opening a file in the archive")); - return; - } - m_bDetectZlibMemoryLeaks = bDetect; - } - - /** - Set CZipCentralDir::m_bConvertAfterOpen value. - The default value is \c true. - Setting this value to \c false is generally not effective and is intended - only for quick and short operations on archives with lots of files inside - e.g. open archive, make an operation on a file which index you already know - and close the archive - using #FindFile function already makes setting this - value to \c false inefficient - \param bConvertAfterOpen - \note Use before opening the archive. - \see CZipCentralDir::m_bConvertAfterOpen -*/ - void SetConvertAfterOpen(bool bConvertAfterOpen) - { - if (!IsClosed()) { - TRACE(_T("CZipArchive::SetConvertAfterOpen: Set it before opening ") - _T("the archive")); - return; - } - m_centralDir.m_bConvertAfterOpen = bConvertAfterOpen; - } - - /** - Enable fast finding by the file name of the files inside the archive. - Set CZipCentralDir::m_bFindFastEnabled to \c true, which is required by - #FindFile. #FindFileIt is called by #FindFileif necessary. It builds - CZipCentralDir::m_findarray with the default case-sensitivity (set with - #SetCaseSensitivity) \note Call it only after opening the archive. \param - bEnable \see CZipCentralDir::m_bFindFastEnabled \see FindFile -*/ - void EnableFindFast(bool bEnable = true); - - /* - After you enable FindFast feature with #EnableFindFast, you can retrieve - how the files are sorted in CZipCentralDir::m_findarray (you can use it - in your own program if you need to display the sorted list and do not - want to duplicate data) - \param iFindFastIndex - index in CZipCentralDir::m_findarray (not necessary the same as the - one you'd pass to #GetFileInfo); the number of items in this array is the - same as the number of files in the archive (you can retrieve it with - #GetCount) - \return - index of the file in central directory (now you can call - #GetFileInfo to get the information); if the value is \c -1 then you have - not called #EnableFindFast before or the archive is closed or the \e - iFindFastIndex is out of range) - */ - int GetFindFastIndex(int iFindFastIndex) const - { - if (IsClosed()) { - TRACE(_T("CZipArchive::GetFindFastIndex: ZipArchive not yet ") - _T("opened.\n")); - return -1; - } - - return m_centralDir.GetFindFastIndex(iFindFastIndex); - } - - /** - Set a temporary path used when compressing files and #zipsmCheckForEff - is specified as an argument in #AddNewFile and the disk spanning archive - is in creation. - \param lpszPath set it to NULL to clear the temporary path and let the - library figure it out (it uses the system temporary directory if - possible) \param bForce if \e lpszPath is not \c NULL and this parameter - set to \c true the directory is created if it doesn't exists (if the - given directory does not exists , the temporary file will not be created) - \see AddNewFile - \see Smartness - \see GetTempPath - */ - void SetTempPath(LPCTSTR lpszPath = NULL, bool bForce = true); - - /** - enum values used in #PredictFileNameInZip - */ - enum Predict - { - - prDir, ///< if an argument is a directory, add a separator at the end - prFile, ///< treat the argument as a common file - prAuto ///< treat the argument as a directory only if it has a path - ///< separator at the end - - }; - - /** - Given the file path in the form it would be passed to #AddNewFile - as \e lpszFilePath argument, the function returns the file name - as it would be stored in the archive.
- The function takes into account the root path set with #SetRootPath. You - can use this function to eliminate duplicates before adding a list of - files.
- \param lpszFilePath - the file path as it would be passed to #AddNewFile function - \param bFullPath - the same as \e bFullPath in #AddNewFile - \param iWhat - one of #Predict values to treat \e lpszFilePath correctly - \param bExactly - if \c true, return the filename exactly as it would look inside the - archive i.e. convert slash to backslash, and perform ANSI->OEM - conversion; otherwise return the filename with the path separators that - are used by default in the system - \return a modified file path - */ - CZipString PredictFileNameInZip(LPCTSTR lpszFilePath, - bool bFullPath, - int iWhat = prAuto, - bool bExactly = false) const; - - /* - Check if the filename will be duplicted in the archive, if added to the - archive in the given form \param bFileNameOnly if \c true, assume that - the filename is duplicated if only the filename (no path) is the same (\e - bFullPath is ignored), otherwise the whole filename with path is taken - into account - \b Default: \c false - The rest of the parameters have the same meaning as in - #PredictFileNameInZip. - \return the zero-based index of the file in the archive that the - filename would be duplicated, or -1, if the filename is unique - */ - int WillBeDuplicated(LPCTSTR lpszFilePath, - bool bFullPath, - bool bFileNameOnly = false, - int iWhat = prAuto); - - /** - Predict the full filename with path after extraction. The parameters - (except for the first) are in the form you'd pass to the - #ExtractFile(WORD , LPCTSTR , bool , LPCTSTR , DWORD ) function. - The function takes into account the root path set with #SetRootPath. - \param lpszFileNameInZip - the filename of the file inside the archive (may be \c NULL if - lpszNewName is not \c NULL) \param lpszPath \param bFullPath \param - lpszNewName \return a predicted file path - */ - CZipString PredictExtractedFileName(LPCTSTR lpszFileNameInZip, - LPCTSTR lpszPath, - bool bFullPath, - LPCTSTR lpszNewName = NULL) const; - - /* - Return the current value of #m_szTempPath - \return CZipString - */ - CZipString GetTempPath() const { return m_szTempPath; } - - /** - Function used in conjunction with #m_szRootPath to trim paths in - #AddNewFile and #ExtractFile \param zpc \see SetRootPath - -*/ - CZipString TrimRootPath(CZipPathComponent& zpc) const; - - /* - Remove \e lpszBeginning from the beginning of the \e szPath. Both - argument are considered to be paths so they matches up to the path - separator. - \param lpszBeginning - \param szPath - \param pCompareFunction (see: #m_pZipCompare) - \return \c true if the path beginning was removed - */ - static bool RemovePathBeginning(LPCTSTR lpszBeginning, - CZipString& szPath, - ZIPSTRINGCOMPARE pCompareFunction); - - /* - Set the default archive case-sensitivity. Affects the following - functions: - - #FindFile - - #FindMatches - - #EnableFindFast - - #TrimRootPath - - #DeleteFiles - \param bCaseSensitive - the default CZipArchive case-sensitivity depends on the system and is - set as follows: - - on Windows: \c false
- - on Linux: \c true - \note Set it before using one of the functions above or leave it as it - is by default; - */ - - void SetCaseSensitivity(bool bCaseSensitive) - { - m_bCaseSensitive = bCaseSensitive; - m_pZipCompare = GetCZipStrCompFunc(bCaseSensitive); - } - - /** - Return the central directory information. - \see GetCentralDirSize - */ - void GetCentralDirInfo(CZipCentralDir::Info& info) const; - - /** - Get the central directory size. - \see CZipCentralDir::GetSize - \see GetCentralDirInfo - */ - DWORD GetCentralDirSize(bool bWhole = true) const - { - return m_centralDir.GetSize(bWhole); - } - - /** - return \c true if the archive cannot be modified, because it is an - existing disk spanning archive or it was opened with #zipOpenReadOnly - */ - bool IsReadOnly() { return m_storage.IsReadOnly(); } - - /* - If you set \e bIgnore to \c true, CRC is not checked for the files being - tested or extracted. This method is useful when working with Java - TM Archives (jar). The CRC is checked by - default. You can use this function on an opened or closed archive. - */ - void SetIgnoreCRC(bool bIgnore = true) { m_bIgnoreCRC = bIgnore; } - - /** - A class used in wildcard pattern matching. - This class is based on code by J. Kercheval, created 01/05/1991 - and available as a public domain at http://www.snippets.org. - */ - class ZIP_API CWildcard - { - public: - enum Match - { - matchNone, ///< for internal use - matchValid, ///< valid match - matchEnd, ///< premature end of pattern string - matchAbort, ///< premature end of text string - matchRange, ///< match failure on [..] construct - matchLiteral, ///< match failure on literal match - matchPattern ///< bad pattern - }; - - enum Pattern - { - patternEmpty = -4, ///< [..] construct is empty - patternClose, ///< no end bracket in [..] construct - patternRange, ///< malformed range in [..] construct - patternEsc, ///< literal escape at end of pattern - patternValid, ///< valid pattern - }; - - /* - Match the pattern against the string \e lpszText - A match means the entire string \e lpszText is used up in matching. - \param lpszText - the string to match against - \param iRetCode - if not \c NULL, set to one of #Match values indicating the - return code \return \c true if \e lpszText matches the pattern. \see - SetPattern - */ - bool IsMatch(LPCTSTR lpszText, int* iRetCode = NULL); - - /* - \param lpszPattern - \return \c true if \e lpszPattern has any special wildcard - characters. - */ - static bool IsPattern(LPCTSTR lpszPattern); - - /* - Test the pattern for validity. - \param lpszPattern - the pattern to test - \param iErrorType - if not \c NULL, set to one of #Pattern values indicating the - return code \return \c true if \e lpszPattern is a well formed - regular expression according to the CWildcard class syntax (see - #SetPattern) - */ - static bool IsPatternValid(LPCTSTR lpszPattern, int* iErrorType = NULL); - - /* - Match the pattern \e lpszPattern against the string \e lpszText - A match means the entire string \e lpszText is used up in matching. - \param lpszPattern - see #SetPattern - \param lpszText - the string to match against - \return - one of #Match values - */ - static int Match(LPCTSTR lpszPattern, LPCTSTR lpszText); - - CWildcard() {} - /* - Initialize the pattern. - \see SetPattern - */ - CWildcard(LPCTSTR lpszPattern, bool bCaseSensitive) - { - SetPattern(lpszPattern, bCaseSensitive); - } - virtual ~CWildcard() {} - - /* - Set the pattern to \e lpszPattern. - \param lpszPattern - In the pattern string: - - * matches any sequence of characters(zero or more) - - ? matches any character - - [SET] matches any character in the specified set, - - [!SET] or[^SET] matches any character not in the specified set. - A set is composed of characters or ranges; a range looks like - character hyphen character(as in 0 - 9 or A - Z).[0 - 9a - zA - - Z_] is the minimal set of characters allowed in the[..] pattern - construct. Other characters are allowed(ie. 8 bit characters) if your - system will support them. - \note To suppress the special syntactic significance of any of - []*?!^-\, - and match the character exactly, precede it with a \ - */ - void SetPattern(LPCTSTR lpszPattern, bool bCaseSensitive) - { - m_szPattern = lpszPattern; - m_bCaseSensitive = bCaseSensitive; - if (!bCaseSensitive) - m_szPattern.MakeLower(); - } - operator LPCTSTR() { return (LPCTSTR)m_szPattern; } - - protected: - bool m_bCaseSensitive; - static int MatchAfterStar(LPCTSTR p, LPCTSTR t); - CZipString m_szPattern; - }; - - /** - This function finds the indexes of the files, which filenames match the - specified pattern and stores these indexes in the array. The indexes can - be used then e.g. in deleting (CZipArchive::DeleteFiles) or extracting - files (CZipArchive::ExtractFile). - \param lpszPattern - the pattern to match (see CWildcard::SetPattern on how to build the - pattern). The case-sensitivity of the pattern is set to the global - archive case-sensitivity (set with #SetCaseSensitivity) \param ar the - array which will contain the indexes of the files which filenames match - the pattern; the contents of the array are NOT clearead, but the indexes - are appended to it \param bFullPath
- - if \c true, match the filename with path (if present) of the file - (if the file is a directory, end it with the path separator or use a - pattern that will recognize it) - - otherwise match only the name of the file (if the file is a - directory, do not end it with the path separator) - */ - void FindMatches(LPCTSTR lpszPattern, - CZipWordArray& ar, - bool bFullPath = true) const; - - /** - Change the name of the file with the given index. - \param uIndex - zero-based index of the file - \param lpszNewName - new name for the file - \return - \note Throws exceptions. - \see SetAdvanced - */ - bool RenameFile(WORD uIndex, LPCTSTR lpszNewName); - - /** - If \c true, the drive letter is removed from the filename stored inside - the archive when adding a new file to the archive. It affects - #AddNewFile, #ExtractFile, #PredictFileNameInZip, - #PredictExtractedFileName, #WillBeDuplicated methods. - - \b Default: \c true - */ - bool m_bRemoveDriveLetter; - - protected: - /** - \param iReplaceIndex index of file to be replaced - \param uTotal the size of the new file to replace existing - \param lpszFileName the filename for callback initialization - */ - void MakeSpaceForReplace(int iReplaceIndex, - DWORD uTotal, - LPCTSTR lpszFileName); - /** - A structure for the internal use only. Clears the password if necessary - and restores it later (also in case of an exception). - */ - struct ZIP_API CZipSmClrPass - { - void ClearPasswordSmartly(CZipArchive* pZip) - { - m_pZip = pZip; - m_szPass = pZip->GetPassword(); - if (!m_szPass.IsEmpty()) - pZip->SetPassword(); - } - ~CZipSmClrPass() - { - if (!m_szPass.IsEmpty()) - m_pZip->SetPassword(m_szPass); - } - CZipString m_szPass; - CZipArchive* m_pZip; - }; - - /** - Holds map of holes and areas to remain when deleting files from the - archive. A structure for the internal use only. - */ - struct ZIP_API CZipDeleteInfo - { - CZipDeleteInfo() - { - m_pHeader = NULL; - m_bDelete = false; - } - CZipDeleteInfo(CZipFileHeader* pHeader, bool bDelete) - : m_pHeader(pHeader) - , m_bDelete(bDelete) - { - } - CZipFileHeader* m_pHeader; - bool m_bDelete; - }; - - /** - Storage for callback functors. A structure for the internal use only. - \see SetCallback - */ - struct ZIP_API CZipClbckStrg - : public CZipMap - { - void Set(CZipActionCallback* pCallback, CallbackType iType) - { - if (pCallback) { - SetAt(iType, pCallback); - } else - RemoveKey(iType); - } - CZipActionCallback* Get(CallbackType iType) - { - CZipActionCallback* pCallback = NULL; - if (Lookup(iType, pCallback)) { - pCallback->m_iType = iType; - return pCallback; - } else - return NULL; - } - }; - - /** - \see CZipClbckStrg - */ - CZipClbckStrg m_callbacks; - - /** - Write central directory calling a callback functor if available - */ - void WriteCentralDirectory(bool bFlush = true); - - /** - Default archive case-sensitivity - \see SetCaseSensitivity - */ - bool m_bCaseSensitive; - - /** - a pointer to the function in CZipString structure, - used to compare elements; can point to Compare, CompareNoCase, - Collate or CollateNoCase function address in CZipString structure - ZIPSTRINGCOMPARE is defined as follows:
typedef int - (CZipString::*ZIPSTRINGCOMPARE)( LPCTSTR ) const; - */ - ZIPSTRINGCOMPARE m_pZipCompare; - - /** - Internal data. - \see CZipInternalInfo - */ - CZipInternalInfo m_info; - - /** - Physical layer of the archive. - \see CZipStorage - */ - CZipStorage m_storage; - - /** - A central directory object. - \see CZipCentralDir - */ - CZipCentralDir m_centralDir; - - /** - The open mode of the current file inside archive. - */ - enum OpenFileType - { - extract = -1, ///< current file opened for extraction - nothing, ///< no file inside archive opened - compress ///< a new file opened for compression - }; - - /** - Takes one of the #OpenFileType enum values. - */ - char m_iFileOpened; - - /** - The current AutoFlush value. - \see Flush - \see SetAutoFlush - \see GetAutoFlush - */ - bool m_bAutoFlush; - - /** - The value set with #SetIgnoreCRC - */ - bool m_bIgnoreCRC; - - /** - The root path to be omitted in #AddNewFile and #ExtractFile functions - from the beginning of the full file path. Set by #SetRootPath - \see TrimRootPath - \see SetRootPath -*/ - CZipString m_szRootPath; - - /** - A temporary path set with #SetTempPath function - \see SetTempPath - \see AddNewFile - \see Smartness - */ - CZipString m_szTempPath; - - /** - Open the archive in the given mode. - Called by #Open(LPCTSTR, int, int) and #Open(CZipMemFile&, int). - \param iMode - an opening mode - \note Throws exceptions. -*/ - void OpenInternal(int iMode); - - /** - The system code of the current archive. All new files in the archive - will be created regarding this value. Can be one of the enum values - defined in \link ZipCompatibility::ZipPlatforms ZipCompatibility.h - \endlink - - \see GetSystemCompatibility - */ - int m_iArchiveSystCompatib; - - /** - Free the memory allocated by the zlib library that hasn't been freed - due to an error in the zlib library (usually never happens). -*/ - void EmptyPtrList(); - - /* - Move the range of data in the archive specified by the \e uStartOffset - and \e uEndOffset by \e uToMove -*/ - void MovePackedFiles(DWORD uStartOffset, - DWORD uEndOffset, - DWORD uMoveBy, - CZipActionCallback* pCallback, - bool bForward = false); - - /** - Remove recently added file (used by AddNewFile) if compressed is larger - than uncompressed or if callback method return \c false. \param - bRemoveAnyway if \c true, do not check for the efficiency, but remove the - file - - */ - bool RemoveLast(bool bRemoveAnyway = false); - - /** - It is used in GetFromArchive public functions and in AddNewFile and the - callback parameter is needed - */ - bool GetFromArchive(CZipArchive& zip, - WORD uIndex, - int iReplaceIndex, - bool bKeepSystComp, - CZipActionCallback* pCallback); - - /** - \return whether the code should continue or not - */ - bool UpdateReplaceIndex(int& iReplaceIndex, LPCTSTR lpszNewFileName); - - /** - \return the currently opened for compression or decompression - file inside the archive NULL if there is no file opened -*/ - CZipFileHeader* CurrentFile(); - - /** - If the parameter \e iErr signalizes a zlib library error, throw - CZipException \param iErr a zlib library error to check \note Throws - exceptions. -*/ - void CheckForError(int iErr); - - /** - Throw a CZipException error. - \param err - the error code - \see CZipException::ZipErrors - \param bZlib - if \c true, treat \e err as a zlib error code and perform the conversion - to the one of CZipException codes. \see CZipException::Throw -*/ - void ThrowError(int err, bool bZlib = false); - - typedef CZipPtrList::iterator CZipPtrListIter; - CZipPtrList m_list; ///< a list holding pointers to the memory areas - ///< allocated by the zlib library - - static void* _zliballoc( - void* opaque, - UINT items, - UINT size); ///< memory allocator called by the zlib library - static void _zlibfree( - void* opaque, - void* address); ///< memory deallocator called by the zlib library - - /* - Specify whether to control memory allocation and freeing by the zlib - library. - \b Default: \c true - \note Set it before opening a file (new or existing) in the archive. - \see SetDetectZlibMemoryLeaks - */ - bool m_bDetectZlibMemoryLeaks; - - /** - Copyright string. - */ - static const TCHAR m_gszCopyright[]; - - /** - \defgroup Cryptography Cryptography - Methods performing data encryption and decryption - and attributes used by them. -*/ - /*@{*/ - - /** - Decode \e uCount bytes from the internal buffer. - \see m_info - \see CZipInternalInfo::m_pBuffer - -*/ - void CryptDecodeBuffer(DWORD uCount); - /** - Encode the internal buffer. - \see m_info - \see CZipInternalInfo::m_pBuffer -*/ - void CryptEncodeBuffer(); - - /** - Encode the character \e c and update \link #m_keys encryption keys \endlink. - -*/ - void CryptEncode(char& c); - /** - Create an encryption header for the new file in the archive. - \param iCrc - A control value. Use the two lower bytes of CZipFileHeader::m_uModTime. - This entails the need for a data description presence at the end of - the compressed data. We cannot use the real CRC now, because we don't - know it yet. \param buf a buffer to receive the header \see CryptCheck -*/ - void CryptCryptHeader(long iCrc, CZipAutoBuffer& buf); - /** - \internal - \return -*/ - DWORD CryptCRC32(DWORD l, char c); - /** - Decode the character \e c and update \link #m_keys encryption keys \endlink. -*/ - void CryptDecode(char& c); - /** - \internal - */ - char CryptDecryptByte(); - - /** - Decrypt the encryption header and check its control value. - The control value depends on the presence of the data descriptor. - \return \c true if the control value is correct - \see CryptCryptHeader -*/ - bool CryptCheck(); - /** - Update \link #m_keys encryption keys \endlink with the given value. -*/ - void CryptUpdateKeys(char c); - /** - Initialize \link #m_keys encryption keys \endlink. -*/ - void CryptInitKeys(); - /** - The archive password. If empty, the new file will not be encrypted. - */ - CZipAutoBuffer m_pszPassword; - - /** - Encryption keys. - The key values are initialized using a supplied encryption password. - \see CryptInitKeys - */ - DWORD m_keys[3]; - - /*@}*/ -}; - -#endif // !defined(AFX_ZIPARCHIVE_H__A7F528A6_1872_4071_BE66_D56CC2DDE0E6__INCLUDED_) \ No newline at end of file diff --git a/src/smpackagee/ZipArchive/ZipArchive.rc b/src/smpackagee/ZipArchive/ZipArchive.rc deleted file mode 100644 index 6d9ca8bc5b..0000000000 --- a/src/smpackagee/ZipArchive/ZipArchive.rc +++ /dev/null @@ -1,109 +0,0 @@ -//Microsoft Developer Studio generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// Polish resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PLK) -#ifdef _WIN32 -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT -#pragma code_page(1250) -#endif //_WIN32 - -#ifndef _MAC -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,3,0,0 - PRODUCTVERSION 2,3,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "http://www.artpol-software.com\0" - VALUE "CompanyName", "Artpol Software\0" - VALUE "FileDescription", "ZipArchive - zip compression library\0" - VALUE "FileVersion", "2.3\0" - VALUE "InternalName", "ZipArchive\0" - VALUE "LegalCopyright", "Copyright © 2000 - 2003 Tadeusz Dracz\0" - VALUE "LegalTrademarks", "\0" - VALUE "OriginalFilename", "ZipArchive.dll\0" - VALUE "PrivateBuild", "\0" - VALUE "ProductName", " ZipArchive library\0" - VALUE "ProductVersion", "2, 3, 0, 0\0" - VALUE "SpecialBuild", "\0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // !_MAC - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE DISCARDABLE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE DISCARDABLE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE DISCARDABLE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - -#endif // Polish resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/smpackagee/ZipArchive/ZipAutoBuffer.cpp b/src/smpackagee/ZipArchive/ZipAutoBuffer.cpp deleted file mode 100644 index 523f61f7d8..0000000000 --- a/src/smpackagee/ZipArchive/ZipAutoBuffer.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipAutoBuffer.cpp $ -// $Archive: /ZipArchive_STL/ZipAutoBuffer.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipAutoBuffer.h" -#include "stdafx.h" -#include - -// #ifdef _DEBUG -// #undef THIS_FILE -// static char THIS_FILE[]=__FILE__; -// #define new DEBUG_NEW -// #endif - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CZipAutoBuffer::CZipAutoBuffer() -{ - m_iSize = 0; - m_pBuffer = NULL; -} - -CZipAutoBuffer::CZipAutoBuffer(DWORD iSize, bool bZeroMemory) -{ - m_iSize = 0; - m_pBuffer = NULL; - Allocate(iSize, bZeroMemory); -} - -CZipAutoBuffer::~CZipAutoBuffer() -{ - Release(); -} - -void -CZipAutoBuffer::Release() -{ - if (m_pBuffer) { - delete[] m_pBuffer; - m_iSize = 0; - m_pBuffer = NULL; - } -} - -char* -CZipAutoBuffer::Allocate(DWORD iSize, bool bZeroMemory) -{ - if (iSize != m_iSize) - Release(); - else { - if (bZeroMemory) - memset(m_pBuffer, 0, iSize); // zerowanie bufora - return m_pBuffer; - } - - if (iSize > 0) { - m_pBuffer = new char[iSize]; - if (bZeroMemory) - memset(m_pBuffer, 0, iSize); // zerowanie bufora - m_iSize = iSize; - } else - m_pBuffer = NULL; - - return m_pBuffer; -} - -CZipAutoBuffer::CZipAutoBuffer(const CZipAutoBuffer& buffer) -{ - m_pBuffer = NULL; - m_iSize = 0; - - if (buffer.m_pBuffer) { - Allocate(buffer.m_iSize); - memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize); - } -} -CZipAutoBuffer& -CZipAutoBuffer::operator=(const CZipAutoBuffer& buffer) -{ - if (this == &buffer) - return *this; - Release(); - if (buffer.m_pBuffer) { - Allocate(buffer.m_iSize); - memcpy(m_pBuffer, buffer.m_pBuffer, buffer.m_iSize); - } - return *this; -} diff --git a/src/smpackagee/ZipArchive/ZipAutoBuffer.h b/src/smpackagee/ZipArchive/ZipAutoBuffer.h deleted file mode 100644 index 47040792e1..0000000000 --- a/src/smpackagee/ZipArchive/ZipAutoBuffer.h +++ /dev/null @@ -1,67 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipAutoBuffer.h $ -// $Archive: /ZipArchive/ZipAutoBuffer.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipAutoBuffer.h - * Interface for the CZipAutoBuffer class. - * - */ - -#if !defined( \ - AFX_ZIPAUTOBUFFER_H__DEC28C20_83FE_11D3_B7C3_EDEC47A8A86C__INCLUDED_) -#define AFX_ZIPAUTOBUFFER_H__DEC28C20_83FE_11D3_B7C3_EDEC47A8A86C__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "ZipExport.h" -/** - A smart buffer freeing its contents on destruction. -*/ -class ZIP_API CZipAutoBuffer -{ - public: - operator char*() { return m_pBuffer; } -#ifndef __BORLANDC__ - operator const char*() const // Borland seems to have problems with this - { - return m_pBuffer; - } -#endif - - // may produce ambiguity on some compilers - // operator const char*() const - // { - // return m_pBuffer; - // } - const char* GetBuffer() const { return m_pBuffer; } - char* Allocate(DWORD iSize, bool bZeroMemory = false); - void Release(); - DWORD GetSize() const { return m_iSize; } - bool IsAllocated() const { return (m_pBuffer != NULL); } - CZipAutoBuffer(DWORD iSize, bool bZeroMemory = false); - CZipAutoBuffer(); - CZipAutoBuffer(const CZipAutoBuffer& buffer); - virtual ~CZipAutoBuffer(); - CZipAutoBuffer& operator=(const CZipAutoBuffer& buffer); - - protected: - char* m_pBuffer; - DWORD m_iSize; -}; - -#endif // !defined(AFX_ZIPAUTOBUFFER_H__DEC28C20_83FE_11D3_B7C3_EDEC47A8A86C__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipBaseException.h b/src/smpackagee/ZipArchive/ZipBaseException.h deleted file mode 100644 index 3119f0c9d3..0000000000 --- a/src/smpackagee/ZipArchive/ZipBaseException.h +++ /dev/null @@ -1,22 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipBaseException.h $ -// $Archive: /ZipArchive/ZipBaseException.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef __ZIPBASEEXCEPTION_H__ -#define __ZIPBASEEXCEPTION_H__ - -typedef CException CZipBaseException; - -#endif //__ZIPBASEEXCEPTION_H__4 diff --git a/src/smpackagee/ZipArchive/ZipCentralDir.cpp b/src/smpackagee/ZipArchive/ZipCentralDir.cpp deleted file mode 100644 index 3119a2f441..0000000000 --- a/src/smpackagee/ZipArchive/ZipCentralDir.cpp +++ /dev/null @@ -1,836 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipCentralDir.cpp $ -// $Archive: /ZipArchive/ZipCentralDir.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipCentralDir.h" -#include "ZipArchive.h" -#include "ZipFileMapping.h" -#include "ZipPlatform.h" -#include "stdafx.h" - -#define CENTRALDIRSIZE 22 - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -char CZipCentralDir::m_gszSignature[] = { 0x50, 0x4b, 0x05, 0x06 }; -CZipCentralDir::CZipCentralDir() -{ - m_bConvertAfterOpen = true; - m_bFindFastEnabled = false; - m_bCaseSensitive = false; - m_pCompare = GetCZipStrCompFunc(ZipPlatform::GetSystemCaseSensitivity()); - m_pStorage = NULL; - m_pOpenedFile = NULL; - m_iBufferSize = 32768; -} - -void -CZipCentralDir::Init() -{ - m_info.m_bOnDisk = false; - m_info.m_uBytesBeforeZip = m_info.m_uCentrDirPos = 0; - m_pOpenedFile = NULL; - m_pszComment.Release(); -} - -CZipCentralDir::~CZipCentralDir() -{ - Clear(); -} - -void -CZipCentralDir::Read() -{ - ASSERT(m_pStorage); - WORD uCommentSize; - m_info.m_uCentrDirPos = Locate(); - m_pStorage->m_pFile->Seek(m_info.m_uCentrDirPos, CZipAbstractFile::begin); - CZipAutoBuffer buf(CENTRALDIRSIZE); - - int uRead = m_pStorage->m_pFile->Read(buf, CENTRALDIRSIZE); - if (uRead != CENTRALDIRSIZE) - ThrowError(CZipException::badZipFile); - memcpy(&m_szSignature, buf, 4); - memcpy(&m_info.m_uThisDisk, buf + 4, 2); - memcpy(&m_info.m_uDiskWithCD, buf + 6, 2); - memcpy(&m_info.m_uDiskEntriesNo, buf + 8, 2); - memcpy(&m_info.m_uEntriesNumber, buf + 10, 2); - memcpy(&m_info.m_uSize, buf + 12, 4); - memcpy(&m_info.m_uOffset, buf + 16, 4); - memcpy(&uCommentSize, buf + 20, 2); - buf.Release(); - - m_pStorage->UpdateSpanMode(m_info.m_uThisDisk); - // if m_uThisDisk is not zero, it is enough to say that it is a multi disk - // archive - ASSERT((!m_info.m_uThisDisk && - (m_info.m_uEntriesNumber == m_info.m_uDiskEntriesNo) && - !m_info.m_uDiskWithCD) || - m_info.m_uThisDisk); - - if (!m_pStorage->IsSpanMode() && !m_info.CheckIfOK_1()) - ThrowError(CZipException::badZipFile); - - if (uCommentSize) { - m_pszComment.Allocate(uCommentSize); - uRead = m_pStorage->m_pFile->Read(m_pszComment, uCommentSize); - if (uRead != uCommentSize) - ThrowError(CZipException::badZipFile); - } - - m_info.SetBytesBeforeZip(m_pStorage->IsSpanMode() != 0); - - if (!m_info.CheckIfOK_2()) - ThrowError(CZipException::badZipFile); - - m_info.m_bOnDisk = true; - m_pStorage->ChangeDisk(m_info.m_uDiskWithCD); - - if (!m_info.m_uSize) - return; - - ReadHeaders(); -} - -DWORD -CZipCentralDir::Locate() -{ - - // maximum size of end of central dir record - long uMaxRecordSize = 0xffff + CENTRALDIRSIZE; - DWORD uFileSize = m_pStorage->m_pFile->GetLength(); - - if ((DWORD)uMaxRecordSize > uFileSize) - uMaxRecordSize = uFileSize; - - CZipAutoBuffer buf(m_iBufferSize); - - long uPosInFile = 0; - int uRead = 0; - // backward reading - while (uPosInFile < uMaxRecordSize) { - uPosInFile = uRead + m_iBufferSize; - if (uPosInFile > uMaxRecordSize) - uPosInFile = uMaxRecordSize; - - int iToRead = uPosInFile - uRead; - - m_pStorage->m_pFile->Seek(-uPosInFile, CZipAbstractFile::end); - int iActuallyRead = m_pStorage->m_pFile->Read(buf, iToRead); - if (iActuallyRead != iToRead) - ThrowError(CZipException::badZipFile); - // search from the very last bytes to prevent an error if inside archive - // there are packed other arhives - for (int i = iToRead - 4; i >= 0; i--) - if (!memcmp((char*)buf + i, m_gszSignature, 4)) - return uFileSize - (uPosInFile - i); - - uRead += iToRead - 3; - } - - ThrowError(CZipException::cdirNotFound); - return 0; -} - -void -CZipCentralDir::ThrowError(int err) const -{ - CZipException::Throw(err, m_pStorage->m_pFile->GetFilePath()); -} - -void -CZipCentralDir::ReadHeaders() -{ - m_pStorage->m_pFile->Seek(m_info.m_uOffset + m_info.m_uBytesBeforeZip, - CZipAbstractFile::begin); - RemoveHeaders(); // just in case - for (int i = 0; i < m_info.m_uEntriesNumber; i++) { - CZipFileHeader* pHeader = new CZipFileHeader; - m_headers.Add(pHeader); - - if (!pHeader->Read(m_pStorage)) - ThrowError(CZipException::badZipFile); - ConvertFileName(true, true, pHeader); - } - SortHeaders(); // this is necessary when deleting files and removing data - // descriptors - if (m_bFindFastEnabled) - BuildFindFastArray(m_bCaseSensitive); -} - -void -CZipCentralDir::SortHeaders() -{ - // we cannot use the Sort method of the CZipWordArray, - // because we store pointers (and we need to store pointers - // to make sure that the address of the CZipFileHeader structure - // remains the same while working with the library) - int iSize = m_headers.GetSize(); - if (iSize) - qsort((void*)&(m_headers[0]), - iSize, - sizeof(CZipFileHeader*), - CompareHeaders); -} - -void -CZipCentralDir::Clear(bool bEverything) -{ - m_pOpenedFile = NULL; - m_pLocalExtraField.Release(); - if (bEverything) { - RemoveHeaders(); - m_findarray.RemoveAll(); - m_pszComment.Release(); - } -} - -bool -CZipCentralDir::IsValidIndex(int uIndex) const -{ - return uIndex < m_headers.GetSize() && uIndex >= 0; -} - -void -CZipCentralDir::OpenFile(WORD uIndex) -{ - WORD uLocalExtraFieldSize; - m_pOpenedFile = (*this)[uIndex]; - m_pStorage->ChangeDisk(m_pOpenedFile->m_uDiskStart); - m_pStorage->m_pFile->Seek(m_pOpenedFile->m_uOffset + - m_info.m_uBytesBeforeZip, - CZipAbstractFile::begin); - if (!m_pOpenedFile->ReadLocal(m_pStorage, uLocalExtraFieldSize)) - ThrowError(CZipException::badZipFile); - - m_pLocalExtraField.Release(); // just in case - if (uLocalExtraFieldSize) { - int iCurrDsk = m_pStorage->GetCurrentDisk(); - m_pLocalExtraField.Allocate(uLocalExtraFieldSize); - m_pStorage->Read(m_pLocalExtraField, uLocalExtraFieldSize, true); - if (m_pStorage->GetCurrentDisk() != iCurrDsk) - ThrowError(CZipException::badZipFile); - } -} - -void -CZipCentralDir::CloseFile(bool bAfterException) -{ - if (!m_pOpenedFile) - return; - m_pLocalExtraField.Release(); - if (!bAfterException && m_pOpenedFile->IsDataDescr()) { - CZipAutoBuffer buf(12); - m_pStorage->Read(buf, 4, false); - // in span mode, files that are divided between disks have bit 3 of flag - // set which tell about the presence of the data descriptor after the - // compressed data This signature may be in the disk spanning archive - // that is one volume only (it is detected as a non disk spanning - // archive) - if (memcmp(buf, CZipStorage::m_gszExtHeaderSignat, 4) != - 0) // there is no signature - m_pStorage->m_pFile->Seek(-4, CZipAbstractFile::current); - - m_pStorage->Read(buf, 12, false); - if (!m_pOpenedFile->CheckCrcAndSizes(buf)) - ThrowError(CZipException::badZipFile); - } - m_pOpenedFile = NULL; -} - -// add new header using the argument as a template -CZipFileHeader* -CZipCentralDir::AddNewFile(const CZipFileHeader& header, int iReplaceIndex) -{ - CZipFileHeader* pHeader = new CZipFileHeader(header); - m_pOpenedFile = pHeader; - WORD uIndex; - DWORD uOffset = 0; - bool bReplace = IsValidIndex(iReplaceIndex); - if (bReplace) { - CZipFileHeader* pfh = m_headers[iReplaceIndex]; - uOffset = pfh->m_uOffset + m_info.m_uBytesBeforeZip; - RemoveFile(pfh, iReplaceIndex, false); - m_headers.InsertAt(iReplaceIndex, pHeader); - uIndex = (WORD)iReplaceIndex; - } else - uIndex = m_headers.Add(pHeader); - - if (m_bFindFastEnabled) - InsertFindFastElement( - pHeader, uIndex); // GetCount > 0, 'cos we've just added a header - RemoveFromDisk(); - if (bReplace) - m_pStorage->m_pFile->Seek(uOffset, CZipAbstractFile::begin); - else - m_pStorage->m_pFile->SeekToEnd(); - return pHeader; -} - -void -CZipCentralDir::RemoveFromDisk() -{ - if (m_info.m_bOnDisk) { - ASSERT(!m_pStorage->IsSpanMode()); // you can't add files to the - // existing disk span archive or to - // delete them from it - m_pStorage->m_pFile->SetLength(m_info.m_uBytesBeforeZip + - m_info.m_uOffset); - m_info.m_bOnDisk = false; - } else - m_pStorage->Flush(); // if remove from disk is requested, then the - // archive modification will follow, so flush the - // buffers -} - -void -CZipCentralDir::CloseNewFile() -{ - CZipAutoBuffer buf(ZIPARCHIVE_DATADESCRIPTOR_LEN + 4); - short iToWrite = 0; - bool bIsSpan = m_pStorage->IsSpanMode() != 0; - bool bEncrypted = m_pOpenedFile->IsEncrypted(); - if (m_pOpenedFile->IsDataDescr()) { - if (bIsSpan || bEncrypted) { - memcpy(buf, m_pStorage->m_gszExtHeaderSignat, 4); - iToWrite += 4; - } - } else /*if (!IsSpan)*/ - { - ASSERT(!bIsSpan && !bEncrypted); - m_pStorage->Flush(); - // the offset contains bytes before zip (set while writting the local - // header) - m_pStorage->m_pFile->Seek(m_pOpenedFile->m_uOffset + 14, - CZipAbstractFile::begin); - // we don't have to restore the pointer, because before adding a new - // file, the pointer is moved to the end - } - - m_pOpenedFile->GetCrcAndSizes(buf + iToWrite); - iToWrite += ZIPARCHIVE_DATADESCRIPTOR_LEN; - - // offset set during writing the local header - m_pOpenedFile->m_uOffset -= m_info.m_uBytesBeforeZip; - - // write the data descriptor and a disk spanning signature at once - m_pStorage->Write(buf, iToWrite, true); - if (!bIsSpan) { - if (bEncrypted) { - // write the information to the local header too - m_pStorage->Flush(); - m_pStorage->m_pFile->Seek(m_info.m_uBytesBeforeZip + - m_pOpenedFile->m_uOffset + 14, - CZipAbstractFile::begin); - m_pStorage->Write(buf + 4, ZIPARCHIVE_DATADESCRIPTOR_LEN, true); - } - m_pStorage->Flush(); - } - - m_pOpenedFile = NULL; -} - -void -CZipCentralDir::Write(CZipActionCallback* pCallback) -{ - if (m_info.m_bOnDisk) - return; - if (!m_pStorage->IsSpanMode()) { - m_pStorage->Flush(); - m_pStorage->m_pFile->SeekToEnd(); - } - - // else - // // we are at the end already - - m_info.m_uEntriesNumber = (WORD)m_headers.GetSize(); - m_info.m_uSize = 0; - bool bDontAllowDiskChange = false; - // if there is a disk spanning archive in creation and it is only - // one-volume, - // (current disk is 0 so far, no bytes has been written so we know they are - // all in the buffer) make sure that it will be after writing central dir - // and make it a non disk spanning archive - if (m_pStorage->IsSpanMode() && m_pStorage->GetCurrentDisk() == 0) { - DWORD uVolumeFree = m_pStorage->VolumeLeft(); - // calculate the size of data descriptors already in the buffer or on - // the disk (they will be removed in the non disk spanning archive): - // multi span signature at the beginnig (4 bytes) + the size of the data - // descr. for each file (multi span signature + 12 bytes data) - // the number of bytes to add: central dir size - total to remove; - DWORD uToGrow = - GetSize(true) - (4 + m_info.m_uEntriesNumber * (4 + 12)); - if (uVolumeFree >= uToGrow) - // lets make sure it will be one-disk archive - { - // can the operation be done only in the buffer? - if (!m_pStorage->m_iBytesWritten && // no bytes on the disk yet - (m_pStorage->GetFreeInBuffer() >= - uToGrow)) // is the buffer big enough? - { - RemoveDataDescr(true); - bDontAllowDiskChange = true; // if the disk change occurs - // somehow, we'll throw an error - // later - } else { - m_pStorage->Flush(); - if (RemoveDataDescr(false)) - bDontAllowDiskChange = true; // if the disk change occurs - // somehow, we'll throw an - // error later - } - } - } - - try { - WriteHeaders(pCallback, - bDontAllowDiskChange || !m_pStorage->IsSpanMode()); - - m_info.m_uThisDisk = (WORD)m_pStorage->GetCurrentDisk(); - DWORD uSize = WriteCentralEnd(); - if (bDontAllowDiskChange) { - if (m_pStorage->GetCurrentDisk() != 0) - ThrowError(CZipException::badZipFile); - } - // if after adding a central directory there is a disk change, - // update the information and write it again - if (m_info.m_uThisDisk != m_pStorage->GetCurrentDisk()) { - m_info.DiskChange(m_pStorage->GetCurrentDisk()); - - if (m_pStorage->m_uBytesInWriteBuffer >= uSize) - // if the data is still in the buffer, simply remove it - m_pStorage->m_uBytesInWriteBuffer -= uSize; - else { - m_pStorage->Flush(); - m_pStorage->m_iBytesWritten -= uSize; - m_pStorage->m_pFile->SeekToBegin(); - } - - WriteCentralEnd(); - } - } catch (...) { - if (bDontAllowDiskChange) { - m_pStorage->FinalizeSpan(); - m_info.m_uThisDisk = 0; - } - throw; - } - m_info.m_bOnDisk = true; -} - -void -CZipCentralDir::WriteHeaders(CZipActionCallback* pCallback, bool bOneDisk) -{ - m_info.m_uDiskEntriesNo = 0; - m_info.m_uDiskWithCD = (WORD)m_pStorage->GetCurrentDisk(); - m_info.m_uOffset = m_pStorage->GetPosition() - m_info.m_uBytesBeforeZip; - if (!m_info.m_uEntriesNumber) - return; - - WORD iDisk = m_info.m_uDiskWithCD; - int iStep = 0; // for the compiler - - if (pCallback) { - pCallback->Init(); - pCallback->SetTotal(m_info.m_uEntriesNumber); - iStep = CZipActionCallback::m_iStep; // we don't want to wait forever - } - - int iAborted = 0; - for (int i = 0; i < m_info.m_uEntriesNumber; i++) { - CZipFileHeader* pHeader = (*this)[i]; - - CZipString szRemember; - if (m_bConvertAfterOpen) - // if CZipArchive::Flush is called we will be still using the - // archive, so restore changed name - szRemember = pHeader->GetFileName(); - - ConvertFileName(false, true, pHeader); - m_info.m_uSize += pHeader->Write(m_pStorage); - - if (m_bConvertAfterOpen) - pHeader->SetFileName(szRemember); - - if (m_pStorage->GetCurrentDisk() != iDisk) { - m_info.m_uDiskEntriesNo = 1; - iDisk = (WORD)m_pStorage->GetCurrentDisk(); - // update the information about the offset and starting disk if the - // first header was written on the new disk - if (i == 0) { - m_info.m_uOffset = 0; - m_info.m_uDiskWithCD = iDisk; - } - } else - m_info.m_uDiskEntriesNo++; - if (pCallback && !(i % iStep)) - if (!pCallback->Callback(iStep)) { - - if (bOneDisk) { - if (!m_pStorage->IsSpanMode()) - m_pStorage->EmptyWriteBuffer(); - else - m_pStorage->Flush(); // must be flush before - flush was - // not called in span mode - - // remove saved part from the disk - m_pStorage->m_pFile->SetLength(m_info.m_uBytesBeforeZip + - m_info.m_uOffset); - // We can now abort safely - iAborted = CZipException::abortedSafely; - } else - iAborted = CZipException::abortedAction; - break; - } - } - - if (pCallback) - pCallback->CallbackEnd(); - - if (iAborted) - ThrowError(iAborted); -} - -DWORD -CZipCentralDir::WriteCentralEnd() -{ - DWORD uSize = GetSize(); - CZipAutoBuffer buf(uSize); - WORD uCommentSize = (WORD)m_pszComment.GetSize(); - memcpy(buf, m_gszSignature, 4); - memcpy(buf + 4, &m_info.m_uThisDisk, 2); - memcpy(buf + 6, &m_info.m_uDiskWithCD, 2); - memcpy(buf + 8, &m_info.m_uDiskEntriesNo, 2); - memcpy(buf + 10, &m_info.m_uEntriesNumber, 2); - memcpy(buf + 12, &m_info.m_uSize, 4); - memcpy(buf + 16, &m_info.m_uOffset, 4); - memcpy(buf + 20, &uCommentSize, 2); - memcpy(buf + 22, m_pszComment, uCommentSize); - m_pStorage->Write(buf, uSize, true); - return uSize; -} - -void -CZipCentralDir::RemoveAll() -{ - m_findarray.RemoveAll(); - RemoveHeaders(); -} - -void -CZipCentralDir::RemoveFile(CZipFileHeader* pHeader, int iIndex, bool bShift) -{ - - if (iIndex == -1) { - int iCount = m_headers.GetSize(); - for (int i = 0; i < iCount; i++) - if (pHeader == m_headers[i]) { - iIndex = i; - break; - } - } - ASSERT(iIndex != -1 || pHeader); - if (!pHeader) - pHeader = m_headers[iIndex]; - - if (m_bFindFastEnabled) { - int i = FindFileNameIndex(pHeader->GetFileName()); - ASSERT(i != -1); - int uIndex = m_findarray[i].m_uIndex; - m_findarray.RemoveAt(i); - // shift down the indexes - - if (bShift) { - int iSize = m_findarray.GetSize(); - for (int j = 0; j < iSize; j++) { - if (m_findarray[j].m_uIndex > uIndex) - m_findarray[j].m_uIndex--; - } - } - } - - if (iIndex != -1) { - delete pHeader; - m_headers.RemoveAt(iIndex); - } -} - -DWORD -CZipCentralDir::GetSize(bool bWhole) const -{ - DWORD uHeaders = 0; - int iCount = m_headers.GetSize(); - if (bWhole) { - for (int i = 0; i < iCount; i++) { - const CZipFileHeader* pHeader = m_headers[i]; - uHeaders += pHeader->GetSize(); - } - } - return CENTRALDIRSIZE + m_pszComment.GetSize() + uHeaders; -} - -bool -CZipCentralDir::RemoveDataDescr(bool bFromBuffer) -{ - ziparchv::CZipFileMapping fm; - char* pFile; - DWORD uSize; - if (bFromBuffer) { - uSize = m_pStorage->m_uBytesInWriteBuffer; - pFile = m_pStorage->m_pWriteBuffer; - } else { - uSize = m_pStorage->m_pFile->GetLength(); - // we cannot use CZipMemFile in multidisk archive - // so it MUST be CZipFile - if (!fm.CreateMapping(static_cast(m_pStorage->m_pFile))) - return false; - pFile = fm.GetMappedMemory(); - } - - DWORD uOffsetToChange = 4; - DWORD uPosInBuffer = 0; - DWORD uExtraHeaderLen; - int iCount = m_headers.GetSize(); - for (int i = 0; i < iCount; i++) { - // update the flag value in the local and central header - // int uDataDescr = (m_headers[i]->m_uFlag & 8) ? (4 + 12) : 0; - - CZipFileHeader* pHeader = m_headers[i]; - - char* pSour = pFile + pHeader->m_uOffset; - - if (!pHeader->IsEncrypted()) { - // removing data descriptor - pHeader->m_uFlag &= ~8; - // update local header: - // write modified flag in the local header - memcpy(pSour + 6, &pHeader->m_uFlag, 2); - uExtraHeaderLen = - 4 /*ext. header signature*/ + 12 /*data descriptor*/; - } else - // do not remove data descriptors from encrypted files - uExtraHeaderLen = 0; - - // update crc32 and sizes' values - pHeader->GetCrcAndSizes(pSour + 14); - - DWORD uToCopy = - (i == (iCount - 1) ? uSize : m_headers[i + 1]->m_uOffset) - - pHeader->m_uOffset - uExtraHeaderLen; - - memmove(pFile + uPosInBuffer, pSour, uToCopy); - - uPosInBuffer += uToCopy; - pHeader->m_uOffset -= uOffsetToChange; - uOffsetToChange += uExtraHeaderLen; - } - - if (bFromBuffer) - m_pStorage->m_uBytesInWriteBuffer = uPosInBuffer; - else { - m_pStorage->m_iBytesWritten = uPosInBuffer; - fm.RemoveMapping(); - m_pStorage->m_pFile->SetLength(uPosInBuffer); - } - return true; -} - -void -CZipCentralDir::RemoveHeaders() -{ - int iCount = m_headers.GetSize(); - for (int i = 0; i < iCount; i++) - delete m_headers[i]; - m_headers.RemoveAll(); -} - -void -CZipCentralDir::ConvertAll() -{ - ASSERT(!m_bConvertAfterOpen); - int iCount = m_headers.GetSize(); - for (int i = 0; i < iCount; i++) - ConvertFileName(true, false, m_headers[i]); - m_bConvertAfterOpen = true; -} - -void -CZipCentralDir::BuildFindFastArray(bool bCaseSensitive) -{ - m_findarray.RemoveAll(); - m_bCaseSensitive = bCaseSensitive; - m_pCompare = GetCZipStrCompFunc(bCaseSensitive); - int iCount = m_headers.GetSize(); - if (!m_bConvertAfterOpen) { - for (int i = 0; i < iCount; i++) { - CZipFileHeader fh = *m_headers[i]; - ConvertFileName(true, false, &fh); - InsertFindFastElement( - &fh, i); // this method requires the name to be already converted - } - } else - for (int i = 0; i < iCount; i++) - InsertFindFastElement(m_headers[i], i); -} - -void -CZipCentralDir::EnableFindFast(bool bEnable, bool bCaseSensitive) -{ - if (m_bFindFastEnabled == bEnable) - return; - m_bFindFastEnabled = bEnable; - if (bEnable) - BuildFindFastArray(bCaseSensitive); - else - m_findarray.RemoveAll(); -} - -int -CZipCentralDir::FindFile(LPCTSTR lpszFileName, - bool bCaseSensitive, - bool bSporadically, - bool bFileNameOnly) -{ - // this is required for fast finding and is done only once - if (!m_bConvertAfterOpen) { - TRACE( - _T("%s(%i) : Converting all the filenames.\n"), __FILE__, __LINE__); - ConvertAll(); - } - if (!m_bFindFastEnabled) - EnableFindFast(true, bSporadically ? !bCaseSensitive : bCaseSensitive); - int iResult = -1; - if (bFileNameOnly) { - // a non-effective search (treat an array as unsorted) - int iSize = m_findarray.GetSize(); - for (int i = 0; i < iSize; i++) { - CZipString sz = GetProperHeaderFileName(m_findarray[i].m_pHeader); - CZipPathComponent::RemoveSeparators(sz); // to find a dir - CZipPathComponent zpc(sz); - sz = zpc.GetFileName(); - if ((sz.*m_pCompare)(lpszFileName) == 0) { - iResult = i; - break; - } - } - } else if (bCaseSensitive == m_bCaseSensitive) - iResult = FindFileNameIndex(lpszFileName); - else { - if (bSporadically) { - // a non-effective search (treat an array as unsorted) - int iSize = m_findarray.GetSize(); - for (int i = 0; i < iSize; i++) - if (CompareElement(lpszFileName, (WORD)i) == 0) { - iResult = i; - break; - } - } else { - BuildFindFastArray(bCaseSensitive); - iResult = FindFileNameIndex(lpszFileName); - } - } - return iResult == -1 ? -1 : m_findarray[iResult].m_uIndex; -} - -void -CZipCentralDir::InsertFindFastElement(CZipFileHeader* pHeader, WORD uIndex) -{ - CZipString fileName = pHeader->GetFileName(); - int iSize = m_findarray.GetSize(); - - // Our initial binary search range encompasses the entire array of - // filenames: - int start = 0; - int end = iSize; - - // Keep halving our search range until we find the right place - // to insert the new element: - while (start < end) { - // Find the midpoint of the search range: - int midpoint = (start + end) / 2; - - // Compare the filename with the filename at the midpoint of the - // current search range: - int result = CompareElement(fileName, (WORD)midpoint); - - // If our filename is larger, it must fall in the first half of the - // search range: - if (result > 0) { - end = midpoint; - } - - // If it's smaller, it must fall in the last half: - else if (result < 0) { - start = midpoint + 1; - } - - // If they're equal, we can go ahead and insert here: - else { - start = midpoint; - break; - } - } - m_findarray.InsertAt( - start, - CZipFindFast( - pHeader, WORD(uIndex == WORD(-1) ? iSize : uIndex /* just in case */))); -} - -int -CZipCentralDir::FindFileNameIndex(LPCTSTR lpszFileName) const -{ - int start = 0; - int end = m_findarray.GetUpperBound(); - - // Keep halving our search range until we find the given element: - while (start <= end) { - // Find the midpoint of the search range: - int midpoint = (start + end) / 2; - - // Compare the given filename with the filename at the midpoint of the - // search range: - int result = CompareElement(lpszFileName, (WORD)midpoint); - - // If our filename is smaller, it must fall in the first half of the - // search range: - if (result > 0) { - end = midpoint - 1; - } - - // If it's larger, it must fall in the last half: - else if (result < 0) { - start = midpoint + 1; - } - - // If they're equal, return the result: - else { - return midpoint; - } - } - - // Signal failure: - return -1; -} - -void -CZipCentralDir::RenameFile(WORD uIndex, LPCTSTR lpszNewName) -{ - CZipFileHeader* pHeader = m_headers[uIndex]; - pHeader->SetFileName(lpszNewName); - if (!m_bConvertAfterOpen) - ZipCompatibility::FileNameUpdate(*pHeader, false); - if (m_bFindFastEnabled) - BuildFindFastArray(m_bCaseSensitive); -} \ No newline at end of file diff --git a/src/smpackagee/ZipArchive/ZipCentralDir.h b/src/smpackagee/ZipArchive/ZipCentralDir.h deleted file mode 100644 index 839ea80280..0000000000 --- a/src/smpackagee/ZipArchive/ZipCentralDir.h +++ /dev/null @@ -1,558 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipCentralDir.h $ -// $Archive: /ZipArchive/ZipCentralDir.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipCentralDir.h - * Interface for the CZipCentralDir class. - * - */ - -#if !defined(AFX_CENTRALDIR_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_) -#define AFX_CENTRALDIR_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#if (_MSC_VER > 1000) && (defined ZIP_HAS_DLL) -#pragma warning(disable : 4251) // needs to have dll-interface to be used by - // clients of class -#endif - -#include "ZipAutoBuffer.h" -#include "ZipCollections.h" -#include "ZipCompatibility.h" -#include "ZipException.h" -#include "ZipExport.h" -#include "ZipFileHeader.h" -#define ZIPARCHIVE_DATADESCRIPTOR_LEN 12 - -/** - A class representing the central directory record in the archive. -*/ -class ZIP_API CZipCentralDir -{ - public: - /** - Used in fast finding files by the filename. - A structure for the internal use only. - \see CZipCentralDir::m_findarray - \see CZipArchive::GetFindFastElement - \see CZipArchive::FindFile - \see CZipArchive::EnableFindFast - */ - struct ZIP_API CZipFindFast - { - CZipFindFast() - { - m_uIndex = 0; - m_pHeader = NULL; - } - CZipFindFast(CZipFileHeader* pHeader, WORD uIndex) - : m_pHeader(pHeader) - , m_uIndex(uIndex) - { - } - /** - A pointer to the structure in CZipCentralDir. We extract a name - from it. - */ - CZipFileHeader* m_pHeader; - - /** - The index in the central directory of the \e m_pHeader. - */ - WORD m_uIndex; - }; - - /** - Stores general information about the central directory record. - */ - struct ZIP_API Info - { - DWORD m_uCentrDirPos; ///< the position of the beginning of the central - ///< directory (as located by #Locate) - DWORD m_uBytesBeforeZip; ///< The number of bytes before the actual zip - ///< archive in a file. It is non-zero for - ///< self-extracting archives. - WORD m_uThisDisk; ///< number of the disk with the central directory end - ///< record (the number of disks in the disk-spanning - ///< archive) - WORD m_uDiskWithCD; ///< number of the disk with the start of the - ///< central directory - WORD m_uDiskEntriesNo; ///< total number of entries in the central dir - ///< on this disk - WORD m_uEntriesNumber; ///< total number of entries in the central dir - DWORD m_uSize; ///< size of the central directory (valid only if - ///< #m_bOnDisk is \c true; use #GetSize instead) - DWORD m_uOffset; ///< offset of start of central directory with respect - ///< to the starting disk number (as written in the - ///< central directory record); valid only if - ///< #m_bOnDisk is \c true - bool m_bOnDisk; - //\c true if the central directory is physically present in the archive - - protected: - friend CZipCentralDir; - bool CheckIfOK_1() - { - return ((DWORD)m_uCentrDirPos >= m_uOffset + m_uSize); - } - void SetBytesBeforeZip(bool bIsSpan) - { - m_uBytesBeforeZip = - bIsSpan ? 0 : m_uCentrDirPos - m_uSize - m_uOffset; - } - bool CheckIfOK_2() - { - return (m_uSize || !m_uEntriesNumber) && - (m_uEntriesNumber || !m_uSize); - } - void DiskChange(int iCurrentDisk) - { - m_uThisDisk = (WORD)iCurrentDisk; - if (m_uEntriesNumber) { - m_uDiskEntriesNo = 0; - } else { - m_uDiskWithCD = m_uThisDisk; - m_uOffset = 0; - } - } - }; - - CZipCentralDir(); - virtual ~CZipCentralDir(); - - static char m_gszSignature[]; ///< central dir signature - - char - m_szSignature[4]; ///< end of central dir signature (must be 0x06054b50) - - CZipAutoBuffer m_pszComment; ///< the archive comment - CZipAutoBuffer m_pLocalExtraField; ///< a local extra field - CZipFileHeader* m_pOpenedFile; ///< points to a currently opened file or - ///< NULL if no file is opened - - /** - Called by CZipArchive::OpenInternal. - */ - void Init(); - - /** - Read the central directory from the archive. - \note Throws exceptions. - */ - void Read(); - - /** - Open the file. - \param uIndex - zero-based index of the file to open - \note Throws exceptions. - */ - void OpenFile(WORD uIndex); - - /** - Test if the given file header index is valid. - \param uIndex - a zero-based index - \return \c true if the file with the given index exists inside the - archive; otherwise \c false; -*/ - bool IsValidIndex(int uIndex) const; - - /** - Remove the file header from the central directory. - \param pHeader - the header to remove - \param iIndex if index is not known set it to -1 - \param bShift - \note Throws exceptions. -*/ - void RemoveFile(CZipFileHeader* pHeader, - int iIndex = -1, - bool bShift = true); - - /* - Remove last file from the central directory. - */ - void RemoveLastFile(CZipFileHeader* pHeader = NULL, int iIndex = -1) - { - if (iIndex == -1) { - iIndex = m_headers.GetSize() - 1; - if (iIndex == -1) - return; - } - if (!pHeader) - pHeader = m_headers[iIndex]; - DWORD uNewSize = pHeader->m_uOffset + GetBytesBefore(); - // then remove - RemoveFile(pHeader, iIndex); - - m_pStorage->Flush(); - m_pStorage->m_pFile->SetLength(uNewSize); - m_info.m_bOnDisk = false; // it is true when AutoFlush is set to true - } - - /** - Remove all files - \note Throws exceptions. - */ - void RemoveAll(); - /** - Cleanup the structure. - \param bEverything - - \c true - clear some attributes and remove all the file headers from - memory - - \c false - do not remove the file headers. It is called in that manner - from CZipArchive::CloseFileAfterTestFailed so that the - next file can be tested for the integrity - \see CZipArchive::CloseFileAfterTestFailed -*/ - void Clear(bool bEverything = true); - - /** - Add a new file to the central directory. - \param header - copy data from it to the new file header - \param iReplaceIndex if different from -1, the index of the file to be - replaced \return the pointer to the new header \note Throws exceptions. -*/ - CZipFileHeader* AddNewFile(const CZipFileHeader& header, - int iReplaceIndex = -1); - - /** - return the header filename, converted if needed - */ - CZipString GetProperHeaderFileName(const CZipFileHeader* pHeader) const - { - if (!m_bConvertAfterOpen) { - CZipFileHeader fh = *pHeader; - ConvertFileName(true, false, &fh); - return fh.GetFileName(); - } else - return pHeader->GetFileName(); - } - - /** - Remove physically the central directory from the archive. - Called during adding or deleting files. - \note Throws exceptions. -*/ - void RemoveFromDisk(); - - /** - Get the central directory size. - \param bWhole - if \c true, include the size of the file headers - \return the size of the central directory - \see CZipArchive::GetCentralDirSize -*/ - DWORD GetSize(bool bWhole = false) const; - - /** - Close a file inside archive opened for reading. - \param bAfterException \c true if closing after exception - \note Throws exceptions. - */ - void CloseFile(bool bAfterException = false); - - /** - Close a file inside archive opened for reading. - \note Throws exceptions. - */ - void CloseNewFile(); - - /** - Write the central directory to the archive. - \note Throws exceptions. - */ - void Write(CZipActionCallback* pCallback); - - /** - \see CZipArchive::EnableFindFast - */ - void EnableFindFast(bool bEnable, bool bCaseSensitive); - - /** - \see CZipArchive::FindFile - \note \e bSporadically set to \c false rebuilds #m_findarray if - necessary - */ - int FindFile(LPCTSTR lpszFileName, - bool bCaseSensitive, - bool bSporadically, - bool bFileNameOnly); - - /** - \see CZipArchive::GetFindFastIndex - */ - int GetFindFastIndex(int iFindFastIndex) const - { - if (!IsValidIndex(iFindFastIndex) || !m_bFindFastEnabled) { - // ASSERT(FALSE); // - return -1; - } - - return m_findarray[iFindFastIndex].m_uIndex; - } - - /** - Points to CZipArchive::m_storage. - */ - CZipStorage* m_pStorage; - - /** - The size of the buffer used in searching for the central dir. - Set before opening the archive. - It is usually set with CZipArchive::SetAdvanced - (specify this value as the third argument). - \see CZipArchive::SetAdvanced - */ - int m_iBufferSize; - - /** - Holds all the files inside archive info. - \see CZipFileHeader - */ - CZipArray m_headers; - - CZipFileHeader* operator[](int iIndex) { return m_headers[iIndex]; } - const CZipFileHeader* operator[](int iIndex) const - { - return m_headers[iIndex]; - } - - /** - - If \c true, the conversion of the filenames takes - place after opening the archive (after reading the central directory - from the file), and before writing the central directory back to - the archive. - - If \c false, the conversion takes place on each call to - CZipArchive::GetFileInfo - - Change is value with CZipArchive::SetConvertAfterOpen. - - Set it to \c true when you plan to use CZipArchive::FindFile or get the - stored files information.
Set it to \c false when you plan mostly to - modify the archive. - - \b Default: \c true - \note Set it before opening the archive. - \see CZipArchive::SetConvertAfterOpen - \see ConvertFileName - */ - bool m_bConvertAfterOpen; - - /** - Convert the filename of the CZipFileHeader depending on the current system - and the system the zip file was created on (change slash to backslash or - vice versa, perform ANSI-OEM conversion if necessary). - \param bFromZip - if \c true, convert from archive format - \param bAfterOpen - if \c true, called after opening the archive or before closing - \param pHeader - the header to have filename converted; if \c NULL convert the currently - opened file - \see ZipCompatibility::FileNameUpdate - \see m_bConvertAfterOpen -*/ - void ConvertFileName(bool bFromZip, - bool bAfterOpen, - CZipFileHeader* pHeader = NULL) const - { - if (bAfterOpen != m_bConvertAfterOpen) - return; - if (!pHeader) { - pHeader = m_pOpenedFile; - ASSERT(pHeader); - } - ZipCompatibility::FileNameUpdate(*pHeader, bFromZip); - } - - /** - Convert all the filenames to the system form. - Called by CZipArchive::FindFile - \see CZipArchive::FindFile -*/ - void ConvertAll(); - - /** - \param lpszFileName - the name of the file to find, must be exactly the same (apart from case) - as it appears in the archive - \return the index in #m_findarray with the appropriate CZipFindFast - structure or \c -1 if there is no file with the given name \see - CZipArchive::FindFile -*/ - int FindFileNameIndex(LPCTSTR lpszFileName) const; - - DWORD GetBytesBefore() const { return m_info.m_uBytesBeforeZip; } - /** - Get the information about the central directory - */ - void GetInfo(Info& info) const { info = m_info; } - /** - \return the value of m_bFindFastEnabled - */ - bool IsFindFastEnabled() { return m_bFindFastEnabled; } - /** - Called by CZipArchive::RenameFile - */ - void RenameFile(WORD uIndex, LPCTSTR lpszNewName); - - protected: - /** - Sort the files inside the archive headers by the order in the archive. - */ - void SortHeaders(); - static int CompareHeaders(const void* pArg1, const void* pArg2) - { - CZipFileHeader* pw1 = *(CZipFileHeader**)pArg1; - CZipFileHeader* pw2 = *(CZipFileHeader**)pArg2; - if ((pw1->m_uOffset < pw2->m_uOffset && - pw1->m_uDiskStart == pw2->m_uDiskStart) || - (pw1->m_uDiskStart < pw2->m_uDiskStart)) - return -1; - else if ((pw1->m_uOffset > pw2->m_uOffset && - pw1->m_uDiskStart == pw2->m_uDiskStart) || - (pw1->m_uDiskStart > pw2->m_uDiskStart)) - return 1; - else { - ASSERT(FALSE); - // two files with the same offsets on the same disk??? - CZipException::Throw(CZipException::badZipFile); - return 0; // just for the compiler comfort - } - } - - /** - Build #m_findarray. -*/ - void BuildFindFastArray(bool bCaseSensitive); - - /** - Used in fast finding files by the filename. - \see CZipFindFast - \see m_bFindFastEnabled - \see CZipArchive::FindFile - */ - CZipArray m_findarray; - - /** - If \c true, the there is an additional array build, to speed up the - finding process - CZipArchive::FindFile uses this array to perform a - binary search. - \b Default: \c false - \see CZipArchive::EnableFindFast - \see CZipArchive::FindFile - \see CZipCentralDir::m_findarray - */ - bool m_bFindFastEnabled; - - /** - The \e lpszFileName and \e bCaseSensitive arguments - are the same as in the #FindFileNameIndex. The function get CZipFindFast - structure pointed by \e uIndex and compares the filename of CZipFileHeader - class stored in this structure with \e lpszFileName. - \param lpszFileName - \param uIndex - the index from #m_findarray - \return - - 0 if the filenames are the same - - < 0 if the filename stored in the array is less than \e lpszFileName - - > 0 if the filename stored in the array is greater than \e lpszFileName -*/ - int CompareElement(LPCTSTR lpszFileName, WORD uIndex) const - { - return (m_findarray[uIndex].m_pHeader->GetFileName().* - m_pCompare)(lpszFileName); - } - /** - Insert a new CZipFindFast element to the #m_findarray. - Initialize CZipFindFast object with \e pHeader and \e uIndex values. -*/ - void InsertFindFastElement(CZipFileHeader* pHeader, WORD uIndex); - - /** - A compare function (Collate or CollateNoCase) set once so as not - to check every time which one to use
- ZIPSTRINGCOMPARE is defined in CZipString.h as:
- typedef int (CZipString::*ZIPSTRINGCOMPARE)( LPCTSTR ) const; - - */ - ZIPSTRINGCOMPARE m_pCompare; - - /** - The way the m_findarray is sorted - */ - bool m_bCaseSensitive; - - /** - \see Info - */ - Info m_info; - - /** - \return the location of the beginning of the central dir end record in - the archive \note Throws exceptions. - */ - DWORD Locate(); - /** - Read the file headers from the file. - \note Throws exceptions. - */ - void ReadHeaders(); - - /** - Free the memory allocated for the CZipFileHeader structures. - */ - void RemoveHeaders(); - /** - Remove data descriptors from the write buffer in the disk spanning volume - that turned out to be one-disk only. - We do not remove them from password encrypted files. - - \param bFromBuffer - if \c true, remove from the buffer in memory otherwise from the file on - a disk \return \c false if the file mapping to memory was not successful - Can happen only when \e bFormBuffer is \c false. - \note Throws exceptions. -*/ - bool RemoveDataDescr(bool bFromBuffer); - /** - Write the file headers to the archive. - \note Throws exceptions. -*/ - void WriteHeaders(CZipActionCallback* pCallback, bool bOneDisk); - /** - Write the central directory end record. - \return the size of the record - \note Throws exceptions. -*/ - DWORD WriteCentralEnd(); - - /** - Throw an exception with the given code. - \param err - \see CZipException::Throw -*/ - void ThrowError(int err) const; -}; - -#endif // !defined(AFX_CENTRALDIR_H__859029E8_8927_4717_9D4B_E26E5DA12BAE__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipCollections.h b/src/smpackagee/ZipArchive/ZipCollections.h deleted file mode 100644 index ab38909768..0000000000 --- a/src/smpackagee/ZipArchive/ZipCollections.h +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipCollections.h $ -// $Archive: /ZipArchive/ZipCollections.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ZIPCOLLECTIONS_DOT_H -#define ZIPCOLLECTIONS_DOT_H - -#if _MSC_VER > 1000 -#pragma once -#pragma warning(push) -#pragma warning( \ - disable : 4786) // 'identifier' : identifier was truncated to 'number' - // characters in the debug information -#endif // _MSC_VER > 1000 - -#include -typedef CStringArray CZipStringArray; - -template -class CZipArray : public CArray -{ - - static int CompareAsc(const void* pArg1, const void* pArg2) - { - TYPE w1 = *(TYPE*)pArg1; - TYPE w2 = *(TYPE*)pArg2; - return w1 == w2 ? 0 : (w2 > w1 ? -1 : 1); - } - static int CompareDesc(const void* pArg1, const void* pArg2) - { - TYPE w1 = *(TYPE*)pArg1; - TYPE w2 = *(TYPE*)pArg2; - return w1 == w2 ? 0 : (w1 > w2 ? -1 : 1); - } - - public: - void Sort(bool bAscending) - { - int iSize = GetSize(); - if (!iSize) // if ommitted operator [] will fail if empty - return; - qsort((void*)&((*this)[0]), - iSize, - sizeof(TYPE), - bAscending ? CompareAsc : CompareDesc); - } -}; - -typedef CZipArray CZipWordArray; - -template -class CZipPtrList : public CTypedPtrList -{ - public: - typedef POSITION iterator; - typedef POSITION const_iterator; - - bool IteratorValid(const iterator& iter) const { return iter != NULL; } -}; - -template -class CZipMap : public CMap -{ -}; - -#ifdef _MFC_VER -#pragma warning(pop) -#endif - -#endif /* ZIPCOLLECTIONS_DOT_H */ diff --git a/src/smpackagee/ZipArchive/ZipCompatibility.cpp b/src/smpackagee/ZipArchive/ZipCompatibility.cpp deleted file mode 100644 index b07599812b..0000000000 --- a/src/smpackagee/ZipArchive/ZipCompatibility.cpp +++ /dev/null @@ -1,194 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipCompatibility.cpp $ -// $Archive: /ZipArchive/ZipCompatibility.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipCompatibility.h" -#include "ZipAutoBuffer.h" -#include "ZipException.h" -#include "ZipFileHeader.h" -#include "ZipPlatform.h" -#include "stdafx.h" -enum iInternalAttr -{ - attROnly = 0x01, - attHidd = 0x02, - attSys = 0x04, - attDir = 0x10, - attArch = 0x20 -}; -// *********************** WINDOWS ************************** -#ifndef _WIN32 -#define FILE_ATTRIBUTE_READONLY 0x00000001 -#define FILE_ATTRIBUTE_HIDDEN 0x00000002 -#define FILE_ATTRIBUTE_SYSTEM 0x00000004 -#define FILE_ATTRIBUTE_DIRECTORY 0x00000010 -#define FILE_ATTRIBUTE_ARCHIVE 0x00000020 -#endif -// *********************** UINX ************************** -#define USER_PERMISSIONS_MASK 0x01C00000 -#define EXTRACT_USER_PERMISSIONS(x) ((x & USER_PERMISSIONS_MASK) >> 22) -#define CREATE_USER_PERMISSIONS(x) ((x & 0x0007) << 22) - -#define GROUP_PERMISSIONS_MASK 0x00380000 -#define EXTRACT_GROUP_PERMISSIONS ((x & GROUP_PERMISSIONS_MASK) >> 19) -#define CREATE_GROUP_PERMISSIONS(x) ((x & 0x0007) << 19) - -#define OTHER_PERMISSIONS_MASK 0x00070000 -#define EXTRACT_OTHER_PERMISSIONS ((x & OTHER_PERMISSIONS_MASK) >> 16) -#define CREATE_OTHER_PERMISSIONS(x) ((x & 0x0007) << 16) - -#define UNIX_DIRECTORY_ATTRIBUTE 0x40000000 -#define UNIX_FILE_ATTRIBUTE 0x80000000 - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// -using namespace ZipCompatibility; - -typedef DWORD (*conv_func)(DWORD, bool); - -DWORD -AttrDos(DWORD, bool); -DWORD -AttrUnix(DWORD, bool); -DWORD -AttrMac(DWORD, bool); - -// more to come... -conv_func conv_funcs[11] = { AttrDos, NULL, NULL, AttrUnix, NULL, NULL, - AttrDos, AttrMac, NULL, NULL, AttrDos }; - -DWORD -ZipCompatibility::ConvertToSystem(DWORD uAttr, int iFromSystem, int iToSystem) -{ - - if (iToSystem != iFromSystem && iFromSystem < 11 && iToSystem < 11) { - conv_func p = conv_funcs[iFromSystem], q = conv_funcs[iToSystem]; - if (p && q) - uAttr = q(p(uAttr, true), false); - else - CZipException::Throw(CZipException::platfNotSupp); - } - return uAttr; -} - -DWORD -AttrDos(DWORD uAttr, bool) -{ - return uAttr; -} - -DWORD -AttrUnix(DWORD uAttr, bool bFrom) -{ - DWORD uNewAttr = 0; - if (bFrom) { - if (uAttr & UNIX_DIRECTORY_ATTRIBUTE) - uNewAttr = attDir; - - uAttr = EXTRACT_USER_PERMISSIONS(uAttr); - - // we may set archive attribute if the file hasn't the execute - // permissions - // - if (!(uAttr & 1)) - uNewAttr |= attArch; - - if (!(uAttr & 2)) - uNewAttr |= attROnly; - - if (!(uAttr & 4)) - uNewAttr |= attHidd; - } else { - - uNewAttr = 0; // we cannot assume that if the file hasn't the archive - // attribute set - - // then it is executable and set execute permissions - - if (!(uAttr & attHidd)) - uNewAttr |= - (CREATE_OTHER_PERMISSIONS(4) | CREATE_GROUP_PERMISSIONS(4)) | - CREATE_USER_PERMISSIONS(4); - - if (!(uAttr & attROnly)) - uNewAttr |= - (CREATE_GROUP_PERMISSIONS(2) | CREATE_USER_PERMISSIONS(2)); - if (uAttr & attDir) - uNewAttr |= UNIX_DIRECTORY_ATTRIBUTE | attDir; - else - uNewAttr |= UNIX_FILE_ATTRIBUTE; - } - - return uNewAttr; -} - -DWORD -AttrMac(DWORD uAttr, bool) -{ - DWORD uNewAttr = uAttr & (attDir | attROnly); - // if (bFrom) - // { - // - // } - // else - // { - // - // } - return uNewAttr; -} - -// ************************************************************************ -ZIPINLINE bool -ZipCompatibility::IsPlatformSupported(int iCode) -{ - return iCode == zcDosFat || iCode == zcUnix || iCode == zcMacintosh || - iCode == zcNtfs || iCode == zcOs2Hpfs; -} - -void -ZipCompatibility::FileNameUpdate(CZipFileHeader& header, bool bFromZip) -{ - int iSysHeader = header.GetSystemCompatibility(); - int iCurSystem = ZipPlatform::GetSystemID(); - if (bFromZip) { - if (iCurSystem == zcDosFat) - SlashBackslashChg(header.m_pszFileName, true); - if (iSysHeader == zcDosFat) - ZipPlatform::AnsiOem(header.m_pszFileName, false); - } else { - if (iSysHeader == zcDosFat) { - ZipPlatform::AnsiOem(header.m_pszFileName, true); - } - SlashBackslashChg(header.m_pszFileName, false); - } -} - -void -ZipCompatibility::SlashBackslashChg(CZipAutoBuffer& buffer, bool bReplaceSlash) -{ - char t1 = '\\' /*backslash*/, t2 = '/', c1, c2; - if (bReplaceSlash) { - c1 = t1; - c2 = t2; - } else { - c1 = t2; - c2 = t1; - } - for (DWORD i = 0; i < buffer.GetSize(); i++) { - if (buffer[i] == c2) - buffer[i] = c1; - } -} diff --git a/src/smpackagee/ZipArchive/ZipCompatibility.h b/src/smpackagee/ZipArchive/ZipCompatibility.h deleted file mode 100644 index 70a159aff4..0000000000 --- a/src/smpackagee/ZipArchive/ZipCompatibility.h +++ /dev/null @@ -1,107 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipCompatibility.h $ -// $Archive: /ZipArchive/ZipCompatibility.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipCompatibility.h - * ZipCompatibility namespace declaration. - * - */ - -#if !defined( \ - AFX_ZIPCOMPATIBILITY_H__8E8B9904_84C7_4B22_B364_A10ED0E7DAD6__INCLUDED_) -#define AFX_ZIPCOMPATIBILITY_H__8E8B9904_84C7_4B22_B364_A10ED0E7DAD6__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -class CZipAutoBuffer; -class CZipFileHeader; - -/** - Functions that provides the proper conversion of attributes - and filename strings between different system platforms. -*/ -namespace ZipCompatibility { -/** - The codes of the compatibility of the file attribute information. - \see CZipArchive::GetSystemCompatibility - \see CZipFileHeader::GetSystemCompatibility - \see ZipPlatform::GetSystemID - */ -enum ZipPlatforms -{ - zcDosFat, ///< MS-DOS and OS/2 (FAT / VFAT / FAT32 file systems) - zcAmiga, ///< Amiga - zcVaxVms, ///< VAX/VMS - zcUnix, ///< Unix / Linux - zcVmCms, ///< VM/CMS - zcAtari, ///< Atari ST - zcOs2Hpfs, ///< OS/2 H.P.F.S. - zcMacintosh, ///< Macintosh - zcZsystem, ///< Z-System - zcCpm, ///< CP/M - zcNtfs ///< Windows NTFS -}; - -/** - Check whether the system with the given code is supported by the ZipArchive - library. \param iCode \link #ZipPlatforms the system code \endlink \return - \c true if supported -*/ -bool -IsPlatformSupported(int iCode); - -/** - Convert the system attributes between different system platforms. - It calls one of the converting functions. - \param uAttr - attributes to convert - \param iFromSystem - system code to convert from - \param iToSystem - system code to convert to - \return the converted attributes - \note Throws exceptions. - \see ZipPlatforms -*/ -DWORD -ConvertToSystem(DWORD uAttr, int iFromSystem, int iToSystem); - -/** - Convert the filename of the file inside archive. - This conversion may not change the size of the filename, otherwise an - error may occur in #ReadLocal while comparing the filename sizes. - \param header - the file header to have the filename converted - \param bFromZip - if \c true convert the path from the from it is stored in the archive - to the current system compatible form; otherwise vice-versa. - \see CZipCentralDir::ConvertFileName -*/ void -FileNameUpdate(CZipFileHeader& header, bool bFromZip); - -/** - Change the slash to backslash or vice-versa in \e buffer. - \param buffer - \param bReplaceSlash - if \c true, change slash to backslash -*/ -void -SlashBackslashChg(CZipAutoBuffer& buffer, bool bReplaceSlash); -}; - -#endif // !defined(AFX_ZIPCOMPATIBILITY_H__8E8B9904_84C7_4B22_B364_A10ED0E7DAD6__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipException.cpp b/src/smpackagee/ZipArchive/ZipException.cpp deleted file mode 100644 index bea4374b70..0000000000 --- a/src/smpackagee/ZipArchive/ZipException.cpp +++ /dev/null @@ -1,285 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipException.cpp $ -// $Archive: /ZipArchive/ZipException.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipException.h" -#include "stdafx.h" -#include - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// -#ifdef _MFC_VER -IMPLEMENT_DYNAMIC(CZipException, CException) -#endif - -CZipException::CZipException(int iCause, LPCTSTR lpszZipName) -#ifdef _MFC_VER - : CException(TRUE) -#endif -{ - m_iCause = iCause; - - if (lpszZipName) - m_szFileName = lpszZipName; -} - -CZipException::~CZipException() {} - -// inline void CZipException::Throw(int iZipError, LPCTSTR lpszZipName) -// { -// #ifdef _MFC_VER -// throw new CZipException(iZipError, lpszZipName); -// #else -// CZipException e(iZipError, lpszZipName); -// throw e; -// #endif -// MSVC++: ignore "Unreachable code" warning here, it's due to -// optimizations -// } - -int -CZipException::ZlibErrToZip(int iZlibError) -{ - switch (iZlibError) { - case 2: // Z_NEED_DICT: - return CZipException::needDict; - case 1: // Z_STREAM_END: - return CZipException::streamEnd; - case -1: // Z_ERRNO: - return CZipException::errNo; - case -2: // Z_STREAM_ERROR: - return CZipException::streamError; - case -3: // Z_DATA_ERROR: - return CZipException::dataError; - case -4: // Z_MEM_ERROR: - return CZipException::memError; - case -5: // Z_BUF_ERROR: - return CZipException::bufError; - case -6: // Z_VERSION_ERROR: - return CZipException::versionError; - default: - return CZipException::generic; - } -} - -#ifdef ZIP_ENABLE_ERROR_DESCRIPTION - -BOOL -CZipException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError, UINT*) - -{ - if (!lpszError || !nMaxError) - return FALSE; - CZipString sz = GetErrorDescription(); - if (sz.IsEmpty()) - return FALSE; - UINT iLen = sz.GetLength(); - if (nMaxError - 1 < iLen) - iLen = nMaxError - 1; - LPTSTR lpsz = sz.GetBuffer(iLen); -#ifdef _UNICODE - wcsncpy(lpszError, lpsz, iLen); -#else - strncpy(lpszError, lpsz, iLen); -#endif - lpszError[iLen] = _T('\0'); - return TRUE; -} - -CZipString -CZipException::GetErrorDescription() -{ - return GetInternalErrorDescription(m_iCause); -} - -CZipString -CZipException::GetSystemErrorDescription() -{ -#ifdef WIN32 - DWORD x = GetLastError(); - if (x) { - LPVOID lpMsgBuf; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - x, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf, - 0, - NULL); - CZipString sz = (LPCTSTR)lpMsgBuf; - LocalFree(lpMsgBuf); - return sz; - } -#endif - return GetInternalErrorDescription(errno == 0 ? generic : errno, true); -} - -CZipString -CZipException::GetInternalErrorDescription(int iCause, bool bNoLoop) -{ - CZipString sz; - switch (iCause) { - case EROFS: - sz = _T("Read-only file system"); - break; - case ESPIPE: - sz = _T("Illegal seek"); - break; - case ENOSPC: - sz = _T("No space left on device"); - break; - case EFBIG: - sz = _T("File too large"); - break; - case EMFILE: - sz = _T("Too many open files"); - break; - case ENFILE: - sz = _T("File table overflow"); - break; - case EINVAL: - sz = _T("Invalid argument"); - break; - case EISDIR: - sz = _T("Is a directory"); - break; - case ENOTDIR: - sz = _T("Not a directory"); - break; - case ENODEV: - sz = _T("No such device"); - break; - case EXDEV: - sz = _T("Cross-device link"); - break; - case EEXIST: - sz = _T("File exists"); - break; - case EFAULT: - sz = _T("Bad address"); - break; - case EACCES: - sz = _T("Permission denied"); - break; - case ENOMEM: - sz = _T("Not enough space"); - break; - case EBADF: - sz = _T("Bad file number"); - break; - case ENXIO: - sz = _T("No such device or address"); - break; - case EIO: - sz = _T("I/O error"); - break; - case EINTR: - sz = _T("Interrupted system call"); - break; - case ENOENT: - sz = _T("No such file or directory"); - break; - case EPERM: - sz = _T("Not super-user"); - break; - case badZipFile: - sz = _T("Damaged or not a zip file"); - break; - case badCrc: - sz = _T("Crc mismatched"); - break; - case noCallback: - sz = _T("No disk-spanning callback functor set"); - break; - case aborted: - sz = _T("Disk change aborted"); - break; - case abortedAction: - sz = _T("Action aborted"); - break; - case abortedSafely: - sz = _T("Action aborted safely"); - break; - case nonRemovable: - sz = _T("The device selected for the disk spanning archive is non ") - _T("removable"); - break; - case tooManyVolumes: - sz = _T("Limit of the maximum volumes reached (999)"); - break; - case tooLongFileName: - sz = _T("The filename of the file being added to the archive is ") - _T("too long"); - break; - case badPassword: - sz = _T("Incorrect password set for the file being decrypted"); - break; - case dirWithSize: - sz = _T("During testing found the directory with the size greater ") - _T("than 0"); - break; - case internal: - sz = _T("Internal error"); - break; - case notRemoved: - sz.Format(_T("%s (%s)"), - _T("Error while removing a file"), - (LPCTSTR)GetSystemErrorDescription()); - break; - case notRenamed: - sz.Format(_T("%s (%s)"), - _T("Error while renaming a file"), - (LPCTSTR)GetSystemErrorDescription()); - break; - case platfNotSupp: - sz = _T("Cannot create the file for the specified platform"); - break; - case cdirNotFound: - sz = _T("The central directory was not found in the archive (or ") - _T("you were trying to open not the last disk of a ") - _T("multi-disk archive)"); - break; - case streamEnd: - sz = _T("Zlib Library error (end of stream)"); - break; - case errNo: - sz = GetInternalErrorDescription(errno != errNo ? errno : generic); - break; - case streamError: - sz = _T("Zlib library error (stream error)"); - break; - case dataError: - sz = _T("Zlib library error (data error)"); - break; - case memError: - sz = _T("Not enough memory"); - break; - case bufError: - sz = _T("Zlib library error (buffer error)"); - break; - case versionError: - sz = _T("Zlib library error (version error)"); - break; - default: - sz = bNoLoop ? _T("Unknown error") - : (LPCTSTR)GetSystemErrorDescription(); - } - return sz; -} - -#endif // ZIP_ENABLE_ERROR_DESCRIPTION diff --git a/src/smpackagee/ZipArchive/ZipException.h b/src/smpackagee/ZipArchive/ZipException.h deleted file mode 100644 index 1333a4157e..0000000000 --- a/src/smpackagee/ZipArchive/ZipException.h +++ /dev/null @@ -1,219 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipException.h $ -// $Archive: /ZipArchive/ZipException.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipException.h - * Interface for the CZipException class. - * - */ - -#if !defined( \ - AFX_ZIPEXCEPTION_H__E3546921_D728_11D3_B7C7_E77339672847__INCLUDED_) -#define AFX_ZIPEXCEPTION_H__E3546921_D728_11D3_B7C7_E77339672847__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#pragma warning(push) -#pragma warning(disable : 4702) // disable "Unreachable code" warning in Throw - // function in the Release mode -#endif // _MSC_VER > 1000 - -#include "ZipBaseException.h" -#include "ZipExport.h" -#include "ZipString.h" - -#define ZIP_ENABLE_ERROR_DESCRIPTION - -/** - A class representing exceptions specific to the ZipArchive library. - Library exception class derived in the MFC version from \c CException - and in non-MFC version from \c std::exception. -*/ -class ZIP_API CZipException : public CZipBaseException -{ - public: - /** - \param iCause - error cause (takes one of the #ZipErrors enumeration codes) - \param lpszZipName - the name of the file where the error occurred (if applicable) -*/ - CZipException(int iCause = generic, LPCTSTR lpszZipName = NULL); - - CZipException::CZipException(CZipException& e) - { - m_szFileName = e.m_szFileName; - m_iCause = e.m_iCause; - } - - /* - Throw an exception. - Throw CZipException* in the MFC version of the library - (the object must be deleted with Delete() method) - and CZipException in other versions. - The arguments are the same as in CZipException(). - \param iZipError - \param lpszZipName - \see CZipException() -*/ - - static void Throw(int iZipError = CZipException::generic, - LPCTSTR lpszZipName = NULL) - { -#ifdef _MFC_VER - throw new CZipException(iZipError, lpszZipName); -#else - CZipException e(iZipError, lpszZipName); - throw e; -#endif - } - - /** - Convert a zlib library error code to a \link #ZipErrors CZipException error - code \endlink \param iZlibError zlib library error code \return \link - #ZipErrors CZipException error code \endlink -*/ - - static int ZlibErrToZip(int iZlibError); - -#ifdef ZIP_ENABLE_ERROR_DESCRIPTION - - /* - Return the error description. - \note You need to have defined ZIP_ENABLE_ERROR_DESCRIPTION - (in file ZipException.h); undefine this value if you don't want to - store the messages in the library. - */ - CZipString GetErrorDescription(); - - /** - Return the description of the error based on system variables - (this function is provided only for compatibility with MFC \c - CException::GetErrorMessage) - - \param lpszError - a pointer to a buffer that will receive the error message - if \c NULL - - \param nMaxError - the maximum number of characters the buffer can hold, including the NULL - terminator - - - \return - \c TRUE if the error string is not empty - \note - - The function will not copy more than \c nMaxError � 1 characters - to the buffer, and it always adds a trailing null to end the string; - if the buffer is too small, the error message will be truncated. - - You need to have defined ZIP_ENABLE_ERROR_DESCRIPTION - (in file ZipException.h); undefine this value if you don't want to - store the messages in the library. - - */ - BOOL GetErrorMessage(LPTSTR lpszError, UINT nMaxError, UINT* = NULL); - -#endif // ZIP_ENABLE_ERROR_DESCRIPTION - - /** - The name of the zip file where the error occurred. - */ - CZipString m_szFileName; - - /** - The codes of errors thrown by the ZipArchive library - */ - enum ZipErrors - { - noError, ///< no error - // 1 - 42 reserved for errno (from STL) values - - // used only in non-MFC versions 43 - 99 reserved - generic = 100, ///< unknown error - badZipFile, ///< damaged or not a zip file - badCrc, ///< crc mismatched - noCallback, ///< no disk-spanning callback functor set - aborted, ///< callback functor's method Callback returned \c false while - ///< disk change in the disk-spanning archive - abortedAction, ///< callback functor's method Callback returned \c false - ///< in CZipArchive class members: AddNewFile, - ///< ExtractFile, TestFile, DeleteFile or DeleteFiles - abortedSafely, ///< the same as above, you may be sure that the - ///< operation was successfully completed before or it - ///< didn't cause any damage in the archive (break when - ///< counting before deleting files; see - ///< CZipArchive::cbDeleteCnt) - nonRemovable, ///< the disk selected for pkzipSpan archive is non - ///< removable - tooManyVolumes, ///< limit of the maximum volumes reached (999) - tooLongFileName, ///< the filename of the file added to the archive is - ///< too long - badPassword, ///< incorrect password set for the file being decrypted - dirWithSize, ///< during testing: found the directory with the size - ///< greater than 0 - internal, ///< internal error - notRemoved, ///< error while removing a file (under Windows call - ///< GetLastError() to find out more) - notRenamed, ///< error while renaming a file (under Windows call - ///< GetLastError() to find out more) - platfNotSupp, ///< the platform that the zip file is being created for - ///< is not supported - cdirNotFound, ///< the central directory was not found in the archive - ///< (it is thrown also when the last disk of multi-disk - ///< archive is not in the drive when opening the archive) - streamEnd = 500, ///< zlib library error - needDict, ///< zlib library error - errNo, ///< zlib library error - streamError, ///< zlib library error - dataError, ///< zlib library error - memError, ///< zlib library error thrown by CZipMemFile as well - bufError, ///< zlib library error - versionError, ///< zlib library error - }; - - /** - A cause of the error - takes one of the #ZipErrors enumeration codes. - */ - int m_iCause; - - virtual ~CZipException(); - - protected: -#ifdef ZIP_ENABLE_ERROR_DESCRIPTION - - /* - Return the error description - \param iCause : error number - \param bNoLoop: if \c true tells not to search for en error description, - it the error is generic - \return - */ - CZipString GetInternalErrorDescription(int iCause, bool bNoLoop = false); - - /* - Return the description of the error based on system variables - \return - */ - CZipString GetSystemErrorDescription(); - -#endif // ZIP_ENABLE_ERROR_DESCRIPTION - -#ifdef _MFC_VER - DECLARE_DYNAMIC(CZipException) -#pragma warning(pop) -#endif -}; - -#endif // !defined(AFX_ZIPEXCEPTION_H__E3546921_D728_11D3_B7C7_E77339672847__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipExport.h b/src/smpackagee/ZipArchive/ZipExport.h deleted file mode 100644 index 0efad48a30..0000000000 --- a/src/smpackagee/ZipArchive/ZipExport.h +++ /dev/null @@ -1,18 +0,0 @@ -#if !defined(ZIP_EXPORT_H) -#define ZIP_API_H - -#if defined(ZIP_HAS_DLL) -#if (ZIP_HAS_DLL == 1) -#if defined(ZIP_BUILD_DLL) -#define ZIP_API __declspec(dllexport) -#else -#define ZIP_API __declspec(dllimport) -#endif /* ZIP_BUILD_DLL */ -#else -#define ZIP_API -#endif /* ! ZIP_HAS_DLL == 1 */ -#else -#define ZIP_API -#endif /* ZIP_HAS_DLL */ - -#endif /* ZIP_EXPORT_H */ diff --git a/src/smpackagee/ZipArchive/ZipFile.cpp b/src/smpackagee/ZipArchive/ZipFile.cpp deleted file mode 100644 index f50e84004f..0000000000 --- a/src/smpackagee/ZipArchive/ZipFile.cpp +++ /dev/null @@ -1,53 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFile.cpp $ -// $Archive: /ZipArchive/ZipFile.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipFile.h" -#include "stdafx.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -// IMPLEMENT_DYNAMIC(CZipAbstractFile, CFile) -IMPLEMENT_DYNAMIC(CZipFile, CFile) - -CZipFile::CZipFile() {} - -CZipFile::~CZipFile() {} - -CZipFile::operator HANDLE() -{ - return (HANDLE)m_hFile; -} - -// __int64 CZipFile::Seek(__int64 dOff, UINT nFrom) -// { -// ASSERT_VALID(this); -// ASSERT(m_hFile != (UINT)hFileNull); -// ASSERT(nFrom == begin || nFrom == end || nFrom == current); -// ASSERT(begin == FILE_BEGIN && end == FILE_END && current == FILE_CURRENT); -// LARGE_INTEGER li; -// li.QuadPart = dOff; -// -// li.LowPart = ::SetFilePointer((HANDLE)m_hFile, li.LowPart, &li.HighPart, -// (DWORD)nFrom); DWORD dw = GetLastError(); if ((li.LowPart == (DWORD)-1) && -// (dw != NO_ERROR)) -// { -// CFileException::ThrowOsError((LONG)dw); -// } -// -// return li.QuadPart; -// } diff --git a/src/smpackagee/ZipArchive/ZipFile.h b/src/smpackagee/ZipArchive/ZipFile.h deleted file mode 100644 index 04a99d6126..0000000000 --- a/src/smpackagee/ZipArchive/ZipFile.h +++ /dev/null @@ -1,68 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFile.h $ -// $Archive: /ZipArchive/ZipFile.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_) -#define AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -#include "ZipAbstractFile.h" -#include "ZipExport.h" - -class ZIP_API CZipFile - : public CZipAbstractFile - , public CFile -{ - public: - DECLARE_DYNAMIC(CZipFile) - void Flush() { CFile::Flush(); } - ZIP_ULONGLONG GetPosition() const { return CFile::GetPosition(); } - CZipString GetFilePath() const { return CFile::GetFilePath(); } - void SetLength(ZIP_ULONGLONG nNewLen) { CFile::SetLength(nNewLen); } - UINT Read(void* lpBuf, UINT nCount) { return CFile::Read(lpBuf, nCount); } - void Write(const void* lpBuf, UINT nCount) { CFile::Write(lpBuf, nCount); } - ZIP_ULONGLONG Seek(ZIP_LONGLONG lOff, int nFrom) - { - return CFile::Seek(lOff, nFrom); - } - ZIP_ULONGLONG GetLength() const { return CFile::GetLength(); } - bool Open(LPCTSTR lpszFileName, UINT nOpenFlags, bool bThrowExc) - { - CFileException* e = new CFileException; - bool bRet = CFile::Open(lpszFileName, nOpenFlags, e) != 0; - if (!bRet && bThrowExc) - throw e; - e->Delete(); - return bRet; - } - CZipFile(); - bool IsClosed() const { return m_hFile == CFile::hFileNull; } - - CZipFile(LPCTSTR lpszFileName, UINT nOpenFlags) - : CFile(lpszFileName, nOpenFlags) - { - } - void Close() - { - if (!IsClosed()) - CFile::Close(); - } - operator HANDLE(); - virtual ~CZipFile(); -}; - -#endif // !defined(AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipFileHeader.cpp b/src/smpackagee/ZipArchive/ZipFileHeader.cpp deleted file mode 100644 index 594e15829e..0000000000 --- a/src/smpackagee/ZipArchive/ZipFileHeader.cpp +++ /dev/null @@ -1,358 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFileHeader.cpp $ -// $Archive: /ZipArchive_STL/ZipFileHeader.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipFileHeader.h" -#include "ZipArchive.h" -#include "ZipAutoBuffer.h" -#include "ZipCompatibility.h" -#include "ZipPlatform.h" -#include "stdafx.h" -#include - -#define FILEHEADERSIZE 46 -#define LOCALFILEHEADERSIZE 30 - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// -char CZipFileHeader::m_gszSignature[] = { 0x50, 0x4b, 0x01, 0x02 }; -char CZipFileHeader::m_gszLocalSignature[] = { 0x50, 0x4b, 0x03, 0x04 }; -CZipFileHeader::CZipFileHeader() -{ - m_uExternalAttr = 0; // ZipPlatform::GetDefaultAttributes(); - m_uModDate = m_uModTime = 0; - m_uMethod = Z_DEFLATED; - // SetSystemCompatibility(ZipPlatform::m_sSystemID); -} - -CZipFileHeader::~CZipFileHeader() {} - -// read the header from the central dir -bool -CZipFileHeader::Read(CZipStorage* pStorage) -{ - // // just in case - // m_pszComment.Release(); - // m_pszFileName.Release(); - WORD uFileNameSize, uCommentSize, uExtraFieldSize; - CZipAutoBuffer buf(FILEHEADERSIZE); - pStorage->Read(buf, FILEHEADERSIZE, true); - memcpy(&m_szSignature, buf, 4); - memcpy(&m_uVersionMadeBy, buf + 4, 2); - memcpy(&m_uVersionNeeded, buf + 6, 2); - memcpy(&m_uFlag, buf + 8, 2); - memcpy(&m_uMethod, buf + 10, 2); - memcpy(&m_uModTime, buf + 12, 2); - memcpy(&m_uModDate, buf + 14, 2); - memcpy(&m_uCrc32, buf + 16, 4); - memcpy(&m_uComprSize, buf + 20, 4); - memcpy(&m_uUncomprSize, buf + 24, 4); - memcpy(&uFileNameSize, buf + 28, 2); - memcpy(&uExtraFieldSize, buf + 30, 2); - memcpy(&uCommentSize, buf + 32, 2); - memcpy(&m_uDiskStart, buf + 34, 2); - memcpy(&m_uInternalAttr, buf + 36, 2); - memcpy(&m_uExternalAttr, buf + 38, 4); - memcpy(&m_uOffset, buf + 42, 4); - buf.Release(); - - if (memcmp(m_szSignature, m_gszSignature, 4) != 0) - return false; - - int iCurDsk = pStorage->GetCurrentDisk(); - m_pszFileName.Allocate(uFileNameSize); // don't add NULL at the end - pStorage->Read(m_pszFileName, uFileNameSize, true); - if (uExtraFieldSize) { - ASSERT(!m_pExtraField.IsAllocated()); - m_pExtraField.Allocate(uExtraFieldSize); - pStorage->Read(m_pExtraField, uExtraFieldSize, true); - } - if (uCommentSize) { - m_pszComment.Allocate(uCommentSize); - pStorage->Read(m_pszComment, uCommentSize, true); - } - - return pStorage->GetCurrentDisk() == - iCurDsk; // check that the whole header is on the one disk -} - -time_t -CZipFileHeader::GetTime() const -{ - struct tm atm; - atm.tm_sec = (m_uModTime & ~0xFFE0) << 1; - atm.tm_min = (m_uModTime & ~0xF800) >> 5; - atm.tm_hour = m_uModTime >> 11; - - atm.tm_mday = m_uModDate & ~0xFFE0; - atm.tm_mon = ((m_uModDate & ~0xFE00) >> 5) - 1; - atm.tm_year = (m_uModDate >> 9) + 80; - atm.tm_isdst = -1; - return mktime(&atm); -} - -// write the header to the central dir -DWORD -CZipFileHeader::Write(CZipStorage* pStorage) -{ - WORD uFileNameSize = GetFileNameSize(), uCommentSize = GetCommentSize(), - uExtraFieldSize = GetExtraFieldSize(); - DWORD iSize = - FILEHEADERSIZE + uFileNameSize + uCommentSize + uExtraFieldSize; - CZipAutoBuffer buf(iSize); - memcpy(buf, &m_szSignature, 4); - memcpy(buf + 4, &m_uVersionMadeBy, 2); - memcpy(buf + 6, &m_uVersionNeeded, 2); - memcpy(buf + 8, &m_uFlag, 2); - memcpy(buf + 10, &m_uMethod, 2); - memcpy(buf + 12, &m_uModTime, 2); - memcpy(buf + 14, &m_uModDate, 2); - memcpy(buf + 16, &m_uCrc32, 4); - memcpy(buf + 20, &m_uComprSize, 4); - memcpy(buf + 24, &m_uUncomprSize, 4); - memcpy(buf + 28, &uFileNameSize, 2); - memcpy(buf + 30, &uExtraFieldSize, 2); - memcpy(buf + 32, &uCommentSize, 2); - memcpy(buf + 34, &m_uDiskStart, 2); - memcpy(buf + 36, &m_uInternalAttr, 2); - memcpy(buf + 38, &m_uExternalAttr, 4); - memcpy(buf + 42, &m_uOffset, 4); - - memcpy(buf + 46, m_pszFileName, uFileNameSize); - - if (uExtraFieldSize) - memcpy(buf + 46 + uFileNameSize, m_pExtraField, uExtraFieldSize); - - if (uCommentSize) - memcpy(buf + 46 + uFileNameSize + uExtraFieldSize, - m_pszComment, - uCommentSize); - - pStorage->Write(buf, iSize, true); - return iSize; -} - -bool -CZipFileHeader::ReadLocal(CZipStorage* pStorage, WORD& iLocExtrFieldSize) -{ - char buf[LOCALFILEHEADERSIZE]; - pStorage->Read(buf, LOCALFILEHEADERSIZE, true); - if (memcmp(buf, m_gszLocalSignature, 4) != 0) - return false; - - bool bIsDataDescr = (((WORD) * (buf + 6)) & 8) != 0; - - WORD uFileNameSize = GetFileNameSize(); - WORD uTemp; - memcpy(&uTemp, buf + 6, 2); // give the priority to the local flag - if ((uTemp & 0xf) != (m_uFlag & 0xf)) - m_uFlag = uTemp; - if ((memcmp(buf + 8, &m_uMethod, 2) != 0) || - (m_uMethod && (m_uMethod != Z_DEFLATED)) || - (memcmp(buf + 26, &uFileNameSize, 2) != 0)) - return false; - - // jeszcze mo¿naby porównaæ nazwy plików - - if (!bIsDataDescr /* || !pStorage->IsSpanMode()*/) - if (!CheckCrcAndSizes(buf + 14)) - return false; - - memcpy(&iLocExtrFieldSize, buf + 28, 2); - pStorage->m_pFile->Seek(uFileNameSize, CZipAbstractFile::current); - - return true; -} - -void -CZipFileHeader::SetTime(const time_t& ttime) -{ - tm* gt = localtime(&ttime); - WORD year = (WORD)(gt->tm_year + 1900); - if (year <= 1980) - year = 0; - else - year -= 1980; - m_uModDate = (WORD)(gt->tm_mday + ((gt->tm_mon + 1) << 5) + (year << 9)); - m_uModTime = - (WORD)((gt->tm_sec >> 1) + (gt->tm_min << 5) + (gt->tm_hour << 11)); -} -// the buffer contains crc32, compressed and uncompressed sizes to be compared -// with the actual values -bool -CZipFileHeader::CheckCrcAndSizes(char* pBuf) const -{ - return (memcmp(pBuf, &m_uCrc32, 4) == 0) && - (memcmp(pBuf + 4, &m_uComprSize, 4) == 0) && - (memcmp(pBuf + 8, &m_uUncomprSize, 4) == 0); -} - -// write the local header -void -CZipFileHeader::WriteLocal(CZipStorage& storage) -{ - // extra field is local by now - WORD uFileNameSize = GetFileNameSize(), - uExtraFieldSize = GetExtraFieldSize(); - DWORD iLocalSize = LOCALFILEHEADERSIZE + uExtraFieldSize + uFileNameSize; - CZipAutoBuffer buf(iLocalSize); - memcpy(buf, m_gszLocalSignature, 4); - memcpy(buf + 4, &m_uVersionNeeded, 2); - memcpy(buf + 6, &m_uFlag, 2); - memcpy(buf + 8, &m_uMethod, 2); - memcpy(buf + 10, &m_uModTime, 2); - memcpy(buf + 12, &m_uModDate, 2); - memcpy(buf + 14, &m_uCrc32, 4); - memcpy(buf + 18, &m_uComprSize, 4); - memcpy(buf + 22, &m_uUncomprSize, 4); - memcpy(buf + 26, &uFileNameSize, 2); - memcpy(buf + 28, &uExtraFieldSize, 2); - memcpy(buf + 30, m_pszFileName, uFileNameSize); - memcpy(buf + 30 + uFileNameSize, m_pExtraField, uExtraFieldSize); - - // possible disk change before writing to the file in the disk spanning mode - // so write the local header first - storage.Write(buf, iLocalSize, true); - // it was only local information, use CZipArchive::SetExtraField to set the - // file extra field in the central directory - m_pExtraField.Release(); - - m_uDiskStart = (WORD)storage.GetCurrentDisk(); - m_uOffset = storage.GetPosition() - iLocalSize; -} - -// prepare the data before adding a new file -bool -CZipFileHeader::PrepareData(int iLevel, bool bSpan, bool bEncrypted) -{ - memcpy(m_szSignature, m_gszSignature, 4); - m_uInternalAttr = 0; - m_uVersionNeeded = IsDirectory() ? 0xa : 0x14; // 1.0 or 2.0 - SetVersion((WORD)(0x14)); - - m_uCrc32 = 0; - m_uComprSize = 0; - m_uUncomprSize = 0; - if (iLevel == 0) - m_uMethod = 0; - - if ((m_uMethod != Z_DEFLATED) && (m_uMethod != 0)) - m_uMethod = Z_DEFLATED; - - m_uFlag = 0; - if (m_uMethod == Z_DEFLATED) - switch (iLevel) { - case 1: - m_uFlag |= 6; - break; - case 2: - m_uFlag |= 4; - break; - case 8: - case 9: - m_uFlag |= 2; - break; - } - - if (bSpan || bEncrypted) - m_uFlag |= 8; // data descriptor present - - if (bEncrypted) { - m_uComprSize = ZIPARCHIVE_ENCR_HEADER_LEN; // encrypted header - m_uFlag |= 1; // encrypted file - } - - return !(m_pszComment.GetSize() > USHRT_MAX || - m_pszFileName.GetSize() > USHRT_MAX || - m_pExtraField.GetSize() > USHRT_MAX); -} - -void -CZipFileHeader::GetCrcAndSizes(char* pBuffer) const -{ - memcpy(pBuffer, &m_uCrc32, 4); - memcpy(pBuffer + 4, &m_uComprSize, 4); - memcpy(pBuffer + 8, &m_uUncomprSize, 4); -} - -DWORD -CZipFileHeader::GetSize(bool bLocal) const -{ - if (bLocal) - return LOCALFILEHEADERSIZE + GetExtraFieldSize() + GetFileNameSize(); - else - return FILEHEADERSIZE + GetExtraFieldSize() + GetFileNameSize() + - GetCommentSize(); -} - -bool -CZipFileHeader::SetComment(LPCTSTR lpszComment) -{ - return CZipArchive::WideToSingle(lpszComment, m_pszComment) != -1; -} - -CZipString -CZipFileHeader::GetComment() const -{ - CZipString temp; - CZipArchive::SingleToWide(m_pszComment, temp); - return temp; -} - -bool -CZipFileHeader::SetFileName(LPCTSTR lpszFileName) -{ - - return CZipArchive::WideToSingle(lpszFileName, m_pszFileName) != -1; -} - -CZipString -CZipFileHeader::GetFileName() const -{ - CZipString temp; - CZipArchive::SingleToWide(m_pszFileName, temp); - return temp; -} - -bool -CZipFileHeader::IsDirectory() const -{ - return ZipPlatform::IsDirectory(GetSystemAttr()); -} - -DWORD -CZipFileHeader::GetSystemAttr() const -{ - int iSystemComp = GetSystemCompatibility(); - if (ZipCompatibility::IsPlatformSupported(iSystemComp)) { - if (!m_uExternalAttr && - CZipPathComponent::HasEndingSeparator(GetFileName())) - return ZipPlatform::GetDefaultDirAttributes(); // can happen - else - return ZipCompatibility::ConvertToSystem( - m_uExternalAttr, iSystemComp, ZipPlatform::GetSystemID()); - } else - return CZipPathComponent::HasEndingSeparator(GetFileName()) - ? ZipPlatform::GetDefaultDirAttributes() - : ZipPlatform::GetDefaultAttributes(); -} - -void -CZipFileHeader::SetSystemAttr(DWORD uAttr) -{ - m_uExternalAttr = ZipCompatibility::ConvertToSystem( - uAttr, ZipPlatform::GetSystemID(), GetSystemCompatibility()); -} diff --git a/src/smpackagee/ZipArchive/ZipFileHeader.h b/src/smpackagee/ZipArchive/ZipFileHeader.h deleted file mode 100644 index c2b152fab4..0000000000 --- a/src/smpackagee/ZipArchive/ZipFileHeader.h +++ /dev/null @@ -1,344 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFileHeader.h $ -// $Archive: /ZipArchive/ZipFileHeader.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipFileHeader.h - * Interface for the CZipFileHeader class. - * - */ - -#if !defined(AFX_FILEHEADER_H__0081FC65_C9C9_4D48_AF72_DBF37DF5E0CF__INCLUDED_) -#define AFX_FILEHEADER_H__0081FC65_C9C9_4D48_AF72_DBF37DF5E0CF__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "ZipAutoBuffer.h" -#include "ZipCompatibility.h" -#include "ZipExport.h" -#include "ZipStorage.h" -#include "sys/types.h" -#define ZIPARCHIVE_ENCR_HEADER_LEN 12 - -/** - Representation of a single file stored in the zip archive. - Modify all the class attributes BEFORE adding a file to and archive - ( using CZipArchive::OpenNewFile ). - It is not possible to modify the data of the existing files in the archive - (it would mean updating all the information in the local headers - and the offsets would be changed as well when the filename would changed its - size) -*/ -class ZIP_API CZipFileHeader -{ - friend class CZipCentralDir; - friend class CZipArchive; - friend void ZipCompatibility::FileNameUpdate(CZipFileHeader&, bool); - - public: - CZipFileHeader(); - virtual ~CZipFileHeader(); - - // - /** - Change slash to backslash or vice-versa in #m_pszFileName. - \param bWindowsStyle - if \c true, change slash to backslash; otherwise vice versa; -*/ - - /** - \return the filename size in characters (without NULL) -*/ - WORD GetFileNameSize() const { return (WORD)m_pszFileName.GetSize(); } - - /** - \return the comment size in characters (without NULL) -*/ - WORD GetCommentSize() const { return (WORD)m_pszComment.GetSize(); } - - /** - \return the extra field size in characters -*/ - WORD GetExtraFieldSize() const { return (WORD)m_pExtraField.GetSize(); } - - /** - \return the filename -*/ - CZipString GetFileName() const; - - /* - Set the filename - \param lpszFileName - \return - \c true, if conversion from UNICODE to single byte was successful - (or if there was no conversion needed or possible); otherwise \c false; -*/ - bool SetFileName(LPCTSTR lpszFileName); - - /** - \return the file comment -*/ - CZipString GetComment() const; - - /* - Set the file comment. - \param lpszComment - \return - \c true, if conversion from UNICODE to single byte was successful - (or if there was no conversion needed or possible); otherwise \c false; - -*/ - bool SetComment(LPCTSTR lpszComment); - - /** - \return \c true if the data descriptor is present -*/ - bool IsDataDescr() const { return (m_uFlag & (WORD)8) != 0; } - - /** - \return - get the effective compressed size: if the file is encrypted, return - less by the size of the encryption header - */ - DWORD GetEffComprSize() - { - return m_uComprSize - (IsEncrypted() ? ZIPARCHIVE_ENCR_HEADER_LEN : 0); - } - /** - \return - \c false if the file should be stored instead of being compressed - */ - bool CompressionEfficient() - { - DWORD uBefore = m_uUncomprSize; - // ignore the length of encryption header - DWORD uAfter = GetEffComprSize(); - return uAfter <= uBefore; - } - - /** - \return the compression ratio of the file - */ - float GetCompressionRatio() - { - return m_uUncomprSize ? ((float)m_uComprSize) * 100 / m_uUncomprSize - : 0; - } - - /** - \return \c if the file is encrypted ( a password is needed to extract - this file) \see CZipArchive::SetPassword -*/ - bool IsEncrypted() const { return (m_uFlag & (WORD)1) != 0; } - - char m_szSignature[4]; ///< central file header signature - WORD m_uVersionMadeBy; ///< version made by and system compatibility - WORD m_uVersionNeeded; ///< version needed to extract - WORD m_uFlag; ///< general purpose bit flag - WORD m_uMethod; ///< compression method - WORD m_uModTime; ///< last mod file time - WORD m_uModDate; ///< last mod file date - DWORD m_uCrc32; ///< crc-32 - DWORD m_uComprSize; ///< compressed size - DWORD m_uUncomprSize; ///< uncompressed size - // filename length 2 bytes - // WORD m_uFileNameSize; - // extra field length 2 bytes - // WORD m_uExtraFieldSize; - // file comment length 2 bytes - // WORD m_uCommentSize; - WORD m_uDiskStart; ///< disk number start - WORD m_uInternalAttr; ///< internal file attributes - protected: - DWORD m_uExternalAttr; ///< external file attributes - public: - DWORD m_uOffset; ///< relative offset of local header - CZipAutoBuffer m_pExtraField; ///< extra field (variable size) - static char m_gszSignature[]; ///< central file header signature - static char m_gszLocalSignature[]; ///< local file header signature - - /** - Set #m_uModDate, #m_uModTime - (file modification time) - \param ttime - \see GetTime -*/ - void SetTime(const time_t& ttime); - - /** - \return the modification time - \see SetTime -*/ - time_t GetTime() const; - - /** - \param bLocal - if \c true return the local file header size or in the central directory - otherwise \return the total size of the structure depending on the \e - bLocal parameter -*/ - DWORD GetSize(bool bLocal = false) const; - - /** - \return the system compatibility of the current file as - the one of ZipCompatibility::ZipPlatforms values; - usually the same as CZipArchive::GetSystemComatibility. - Software can use this information e.g. to determine the line - record format for text files etc. - ZipArchive library uses it to perform a proper attributes conversion. - - \see CZipArchive::GetSystemComatibility - \see ZipPlatform::GetSystemID -*/ - int GetSystemCompatibility() const - { - return (m_uVersionMadeBy & 0xFF00) >> 8; - } - - /** - \return the attributes of the file converted to the current system - compatible value \note - - Throws exception if the archive system or the current system - is not supported by the ZipArchive library. - - (only Linux version): After obtaining the attributes, you need to - shift them right by 16 -*/ - - DWORD GetSystemAttr() const; - - /** - \return - the original attributes as stored in the archive (without performing any - conversion) - */ - DWORD GetOriginalAttributes() const { return m_uExternalAttr; } - - /** - \return \c true, if this object represents a directory; otherwise \c false; - If #m_uExternalAttr value is zero, the function check for a presence of a - path separator at the end of the file name. If it is present, it is assumed - to be a directory. -*/ - bool IsDirectory() const; - - protected: - /** - Set the system compatibility of the file. - \param iSystemID - one of ZipCompatibility::ZipPlatforms values - \see CZipArchive::GetSystemCompatibility -*/ - void SetSystemCompatibility(int iSystemID) - { - m_uVersionMadeBy &= 0x00FF; - m_uVersionMadeBy |= (WORD)(iSystemID << 8); - } - - /** - Set the system attributes - if you wish to set the attributes of this structure use - CZipArchive::SetFileHeaderAttr() \param uAttr attributes to set \note Throws - exceptions if the archive system or the current system is not supported by - the ZipArchive library. \see CZipArchive::SetFileHeaderAttr \see - GetSystemAttr \see SetSystemCompatibility -*/ - void SetSystemAttr(DWORD uAttr); - - /** - Set the version made by number. - -*/ - void SetVersion(WORD uVersion) - { - if ((m_uVersionMadeBy & 0x00FF) != (uVersion & 0x00FF)) { - m_uVersionMadeBy &= 0xFF00; - m_uVersionMadeBy |= (WORD)(uVersion & 0x00FF); - } - } - - /** - a filename - */ - CZipAutoBuffer m_pszFileName; - - /** - a file comment - */ - CZipAutoBuffer m_pszComment; - - /** - Fill the buffer with the current values of crc and compressed and - uncompressed sizes of the file. -*/ - void GetCrcAndSizes(char* pBuffer) const; - - /** - Check whether the actual values of crc and compressed and - uncompressed sizes of the file are the same as defined in - the file header. - \param pBuf - buffer with the mentioned data - \return \c true if they are the same; otherwise \c false; -*/ - bool CheckCrcAndSizes(char* pBuf) const; - - /** - Prepare the data for the class while adding a new file. - Called by CZipArchive::OpenNewFile - \param iLevel - a compression level - \param bSpan - \c true, if the data descriptor will be present because of spanning - archive \param bEncrypted \c true, if the file will be encrypted \return - \c true if the sizes of the filename, extra field and comments does not - exceed \c unsigned \c short maximum value; otherwise \c false; -*/ - bool PrepareData(int iLevel, bool bSpan, bool bEncrypted); - /** - Write the local file header to the \e storage - \param storage - \note Throws exceptions. -*/ - void WriteLocal(CZipStorage& storage); - - /** - Read the file header from the central directory record from \e pStorage. - \param *pStorage - \return \c true if the whole file header is on one disk in - a multi-disk archive; otherwise \c false; - \note Throws exceptions. -*/ - bool Read(CZipStorage* pStorage); - /** - Read the local file header from \e pStorage and check for consistency. - \param *pStorage - \param iLocExtrFieldSize - receives local extra field size - \return \c false, if something goes wrong; otherwise \c true; - \note Throws exceptions. -*/ - bool ReadLocal(CZipStorage* pStorage, WORD& iLocExtrFieldSize); - /** - Write the file header to \e pStorage. - \param *pStorage - \return the size of the file header - \note Throws exceptions. -*/ - DWORD Write(CZipStorage* pStorage); -}; - -#endif // !defined(AFX_FILEHEADER_H__0081FC65_C9C9_4D48_AF72_DBF37DF5E0CF__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipFileMapping.h b/src/smpackagee/ZipArchive/ZipFileMapping.h deleted file mode 100644 index cb261b84cd..0000000000 --- a/src/smpackagee/ZipArchive/ZipFileMapping.h +++ /dev/null @@ -1,69 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFileMapping.h $ -// $Archive: /ZipArchive/ZipFileMapping.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -// -// Check the site http://www.artpol-software.com for the updated version of the -// library. -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_) -#define AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "ZipFile.h" -namespace ziparchv { - -struct CZipFileMapping -{ - CZipFileMapping() - { - m_hFileMap = NULL; - m_pFileMap = NULL; - } - bool CreateMapping(CZipFile* pFile) - { - if (!pFile) - return false; - m_hFileMap = CreateFileMapping( - (*pFile), NULL, PAGE_READWRITE, 0, 0, _T("ZipArchive Mapping File")); - if (!m_hFileMap) - return false; - // Get pointer to memory representing file - m_pFileMap = MapViewOfFile(m_hFileMap, FILE_MAP_WRITE, 0, 0, 0); - return (m_pFileMap != NULL); - } - void RemoveMapping() - { - if (m_pFileMap) { - UnmapViewOfFile(m_pFileMap); - m_pFileMap = NULL; - } - if (m_hFileMap) { - CloseHandle(m_hFileMap); - m_hFileMap = NULL; - } - } - ~CZipFileMapping() { RemoveMapping(); } - char* GetMappedMemory() { return reinterpret_cast(m_pFileMap); } - - protected: - HANDLE m_hFileMap; - LPVOID m_pFileMap; -}; -} - -#endif // !defined(AFX_AUTOHANDLE_H__D68326EA_D7FA_4792_AB1F_68D09533E399__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipMemFile.cpp b/src/smpackagee/ZipArchive/ZipMemFile.cpp deleted file mode 100644 index 35ae95c8d7..0000000000 --- a/src/smpackagee/ZipArchive/ZipMemFile.cpp +++ /dev/null @@ -1,102 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipMemFile.cpp $ -// $Archive: /ZipArchive/ZipMemFile.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipMemFile.h" -#include "ZipException.h" -#include "stdafx.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -void -CZipMemFile::Grow(size_t nGrowTo) -{ - if (m_nBufSize < (UINT)nGrowTo) { - if (m_nGrowBy == 0) - CZipException::Throw(CZipException::memError); - size_t nNewSize = m_nBufSize; - while (nNewSize < nGrowTo) - nNewSize += m_nGrowBy; - BYTE* lpNew; - if (m_lpBuf) - lpNew = (BYTE*)realloc((void*)m_lpBuf, nNewSize); - else - lpNew = (BYTE*)malloc(nNewSize); - - if (!lpNew) - CZipException::Throw(CZipException::memError); - m_nBufSize = nNewSize; - m_lpBuf = lpNew; - } -} - -void -CZipMemFile::SetLength(ZIP_ULONGLONG nNewLen) -{ - if (m_nBufSize < (UINT)nNewLen) - Grow((size_t)nNewLen); - else - m_nPos = (size_t)nNewLen; - m_nDataSize = (size_t)nNewLen; -} - -UINT -CZipMemFile::Read(void* lpBuf, UINT nCount) -{ - if (m_nPos > m_nDataSize) - return 0; - UINT nToRead = - (m_nPos + nCount > m_nDataSize) ? m_nDataSize - m_nPos : nCount; - memcpy(lpBuf, m_lpBuf + m_nPos, nToRead); - m_nPos += nToRead; - return nToRead; -} - -void -CZipMemFile::Write(const void* lpBuf, UINT nCount) -{ - if (!nCount) - return; - - if (m_nPos + nCount > m_nBufSize) - Grow(m_nPos + nCount); - memcpy(m_lpBuf + m_nPos, lpBuf, nCount); - m_nPos += nCount; - if (m_nPos > m_nDataSize) - m_nDataSize = m_nPos; -} - -ZIP_ULONGLONG -CZipMemFile::Seek(ZIP_LONGLONG lOff, int nFrom) -{ - ZIP_ULONGLONG lNew = m_nPos; - - if (nFrom == CZipAbstractFile::begin) - lNew = lOff; - else if (nFrom == CZipAbstractFile::current) - lNew += lOff; - else if (nFrom == CZipAbstractFile::end) - lNew = m_nDataSize + lOff; - else - return lNew; - - if (lNew < 0) - CZipException::Throw(CZipException::memError); - - m_nPos = (size_t)lNew; - return lNew; -} diff --git a/src/smpackagee/ZipArchive/ZipMemFile.h b/src/smpackagee/ZipArchive/ZipMemFile.h deleted file mode 100644 index 2e1e1afa26..0000000000 --- a/src/smpackagee/ZipArchive/ZipMemFile.h +++ /dev/null @@ -1,105 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipMemFile.h $ -// $Archive: /ZipArchive/ZipMemFile.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipMemFile.h - * Interface for the CZipMemFile class. - * - */ -#if !defined(AFX_ZIPMEMFILE_H__EA73AB25_6B51_4C5E_8D78_BAC95812598F__INCLUDED_) -#define AFX_ZIPMEMFILE_H__EA73AB25_6B51_4C5E_8D78_BAC95812598F__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -#include "ZipAbstractFile.h" -#include "ZipExport.h" -#include "ZipString.h" - -/** - A memory buffer which behaves like a physical file. - Automatically grows when necessary -*/ -class ZIP_API CZipMemFile : public CZipAbstractFile -{ - protected: - size_t m_nGrowBy, m_nPos; - size_t m_nBufSize, m_nDataSize; - BYTE* m_lpBuf; - bool m_bAutoDelete; - void Free() - { - if (m_lpBuf) { - free(m_lpBuf); - m_lpBuf = NULL; - } - } - void Init() - { - m_nGrowBy = m_nPos = 0; - m_nBufSize = m_nDataSize = 0; - m_lpBuf = NULL; - } - void Grow(size_t nBytes); - - public: - bool IsClosed() const { return m_lpBuf == NULL; } - void Flush() {} - - ZIP_ULONGLONG Seek(ZIP_LONGLONG lOff, int nFrom); - ZIP_ULONGLONG GetLength() const { return m_nDataSize; } - void Write(const void* lpBuf, UINT nCount); - UINT Read(void* lpBuf, UINT nCount); - void SetLength(ZIP_ULONGLONG nNewLen); - CZipString GetFilePath() const { return _T(""); } - CZipMemFile(long nGrowBy = 1024) - { - Init(); - m_nGrowBy = nGrowBy; - m_bAutoDelete = true; - } - - CZipMemFile(BYTE* lpBuf, UINT nBufSize, long nGrowBy = 0) - { - Init(); - Attach(lpBuf, nBufSize, nGrowBy); - } - ZIP_ULONGLONG GetPosition() const { return m_nPos; } - void Attach(BYTE* lpBuf, UINT nBufSize, long nGrowBy = 0) - { - Close(); - m_lpBuf = lpBuf; - m_nGrowBy = nGrowBy; - m_nBufSize = nBufSize; - m_nDataSize = nGrowBy == 0 ? nBufSize : 0; - m_bAutoDelete = false; - } - BYTE* Detach() - { - BYTE* b = m_lpBuf; - Init(); - return b; - } - void Close() - { - if (m_bAutoDelete) - Free(); - Init(); - } - virtual ~CZipMemFile() { Close(); } -}; - -#endif // !defined(AFX_ZIPMEMFILE_H__EA73AB25_6B51_4C5E_8D78_BAC95812598F__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipPathComponent.cpp b/src/smpackagee/ZipArchive/ZipPathComponent.cpp deleted file mode 100644 index abbaaada45..0000000000 --- a/src/smpackagee/ZipArchive/ZipPathComponent.cpp +++ /dev/null @@ -1,72 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPathComponent.cpp $ -// $Archive: /ZipArchive/ZipPathComponent.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipPathComponent.h" -#include "stdafx.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CZipPathComponent::~CZipPathComponent() {} - -void -CZipPathComponent::SetFullPath(LPCTSTR lpszFullPath) -{ - - TCHAR szDrive[_MAX_DRIVE]; - TCHAR szDir[_MAX_DIR]; - TCHAR szFname[_MAX_FNAME]; - TCHAR szExt[_MAX_EXT]; - - CZipString szTempPath(lpszFullPath); - const CZipString szPrefix = _T("\\\\?\\unc\\"); - int i = -1, iLen = szPrefix.GetLength(); - if (iLen > szTempPath.GetLength()) - iLen = szTempPath.GetLength(); - CZipString szPossiblePrefix = szTempPath.Left(iLen); - szPossiblePrefix.MakeLower(); // must perform case insensitive comparison - while (++i < iLen && szPossiblePrefix[i] == szPrefix[i]) - ; - if (i == 2 || i == 4 || i == 8) // unc path, unicode path or unc path - // meeting windows file name conventions - { - m_szPrefix = szTempPath.Left(i); - szTempPath = szTempPath.Mid(i); - } else - m_szPrefix.Empty(); - - _tsplitpath(szTempPath, szDrive, szDir, szFname, szExt); - m_szDrive = szDrive; - m_szDirectory = szDir; - - m_szDirectory.TrimLeft(m_cSeparator); - m_szDirectory.TrimRight(m_cSeparator); - SetExtension(szExt); - m_szFileTitle = szFname; -} - -CZipString -CZipPathComponent::GetNoDrive() const -{ - CZipString szPath = m_szDirectory; - CZipString szFileName = GetFileName(); - if (!szFileName.IsEmpty() && !szPath.IsEmpty()) - szPath += m_cSeparator; - - szPath += szFileName; - return szPath; -} diff --git a/src/smpackagee/ZipArchive/ZipPathComponent.h b/src/smpackagee/ZipArchive/ZipPathComponent.h deleted file mode 100644 index e268cb3616..0000000000 --- a/src/smpackagee/ZipArchive/ZipPathComponent.h +++ /dev/null @@ -1,195 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPathComponent.h $ -// $Archive: /ZipArchive/ZipPathComponent.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipPathComponent.h - * Interface for the CZipPathComponent class. - * - */ -#if !defined( \ - AFX_ZIPPATHCOMPONENT_H__9B222C08_AD11_4138_96CC_1237511E3E37__INCLUDED_) -#define AFX_ZIPPATHCOMPONENT_H__9B222C08_AD11_4138_96CC_1237511E3E37__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -#include "ZipExport.h" -#include "ZipString.h" - -/** - A class splitting a file path into components. -*/ -class ZIP_API CZipPathComponent -{ - public: - CZipPathComponent() {} - virtual ~CZipPathComponent(); - - static const TCHAR m_cSeparator; ///< A system - specific default path - ///< separator. Defined in ZipPlatform.cpp. - /** - Append a path separator to \e szPath if it is not already there. - */ - static void AppendSeparator(CZipString& szPath) - { - RemoveSeparators(szPath); - szPath += m_cSeparator; - } - - /** - Remove separators from the end of \e szPath - */ - static void RemoveSeparators(CZipString& szPath) - { - // szPath.TrimRight(m_cSeparator); - szPath.TrimRight(_T("\\/")); - } - - /** - Remove separators from the beginning of \e szPath - - */ - - static void RemoveSeparatorsLeft(CZipString& szPath) - { - szPath.TrimLeft(_T("\\/")); - } - - /** - \return \c true if \e c is a slash or a backslash - */ - static bool IsSeparator(TCHAR c) { return c == _T('\\') || c == _T('/'); } - - /** - \return \c true if the path has a path separator at the and - */ - static bool HasEndingSeparator(const CZipString& szPath) - { - int iLen = szPath.GetLength(); - if (iLen) - return IsSeparator(szPath[iLen - 1]); - else - return false; - } - - /** - Construct the object and set a path. - \param lpszFullPath - the full path of the file - \see SetFullPath -*/ - CZipPathComponent(LPCTSTR lpszFullPath) { SetFullPath(lpszFullPath); } - - // full path of the file (not a directory alone) - /** - Set the path. - \param lpszFullPath - a full path to the file (including a filename - the last element in the - path is assumed to be a filename) -*/ - void SetFullPath(LPCTSTR lpszFullPath); - - /** - \return the filename (without an extension) -*/ - CZipString GetFileTitle() const { return m_szFileTitle; } - - /** - Set the file title (without an extension). - \param lpszFileTitle - \return -*/ - void SetFileTitle(LPCTSTR lpszFileTitle) { m_szFileTitle = lpszFileTitle; } - - /** - Set the extension alone. - \param lpszExt - may but not have to contain a dot at the beginning -*/ - void SetExtension(LPCTSTR lpszExt) - { - m_szFileExt = lpszExt; - m_szFileExt.TrimLeft(_T('.')); - } - - /** - \return the file extension without a dot -*/ - CZipString GetFileExt() const { return m_szFileExt; } - /** - \return the drive (no path separator at the end) -*/ - CZipString GetFileDrive() const { return m_szDrive; } - /** - \return the full path without the drive (no separator at the beginning) -*/ - CZipString GetNoDrive() const; - - /** - \return the filename including an extension -*/ - CZipString GetFileName() const - { - CZipString szFullFileName = m_szFileTitle; - if (!m_szFileExt.IsEmpty()) { - szFullFileName += _T("."); - szFullFileName += m_szFileExt; - } - return szFullFileName; - } - /** - \return the full path of the file (including the filename) -*/ - CZipString GetFullPath() const - { - CZipString szFullPath = GetFilePath(); - CZipString szFileName = GetFileName(); - if (!szFileName.IsEmpty()) { - szFullPath += m_cSeparator; - szFullPath += szFileName; - } - return szFullPath; - } - /** - \return the path of the file (without the separator at the end) -*/ - CZipString GetFilePath() const - { - CZipString szDrive = m_szDrive; - CZipString szDir = m_szDirectory; - if (!szDrive.IsEmpty() && !szDir.IsEmpty()) - szDrive += m_cSeparator; - - return m_szPrefix + szDrive + szDir; - } - - protected: - /** - \name Path components - */ - //@{ - CZipString m_szDirectory, ///< a directory(ies) (one or more) without the - ///< path separators at the end and the beginning - m_szFileTitle, ///< a filename without an extension - m_szFileExt, ///< a file extension without a dot - m_szDrive, ///< a drive (if the system path standard uses it) without a - ///< path separator at the end - m_szPrefix; ///< a prefix (e.g. for the UNC path or Unicode path under - ///< Windows) - //@} -}; - -#endif // !defined(AFX_ZIPPATHCOMPONENT_H__9B222C08_AD11_4138_96CC_1237511E3E37__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipPlatform.cpp b/src/smpackagee/ZipArchive/ZipPlatform.cpp deleted file mode 100644 index 03d1259351..0000000000 --- a/src/smpackagee/ZipArchive/ZipPlatform.cpp +++ /dev/null @@ -1,370 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPlatform.cpp $ -// $Archive: /ZipArchive/ZipPlatform.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipPlatform.h" -#include "ZipAutoBuffer.h" -#include "ZipException.h" -#include "ZipFileHeader.h" -#include "stdafx.h" -#include - -#if defined _MSC_VER && !defined __BORLANDC__ -#include -#else -#include -#endif - -#include "ZipCompatibility.h" -#include "ZipPathComponent.h" -#include -#include -#include - -const TCHAR CZipPathComponent::m_cSeparator = _T('\\'); - -#ifndef _UTIMBUF_DEFINED -#define _utimbuf utimbuf -#endif - -DWORD -ZipPlatform::GetDeviceFreeSpace(LPCTSTR lpszPath) -{ - DWORD SectorsPerCluster, BytesPerSector, NumberOfFreeClusters, - TotalNumberOfClusters; - CZipPathComponent zpc(lpszPath); - CZipString szDrive = zpc.GetFileDrive(); - if (!GetDiskFreeSpace(szDrive, - &SectorsPerCluster, - &BytesPerSector, - &NumberOfFreeClusters, - &TotalNumberOfClusters)) { - CZipPathComponent::AppendSeparator(szDrive); // in spite of what is - // written in MSDN it is - // sometimes needed (on - // fixed disks) - if (!GetDiskFreeSpace(szDrive, - &SectorsPerCluster, - &BytesPerSector, - &NumberOfFreeClusters, - &TotalNumberOfClusters)) - - return 0; - } - __int64 total = SectorsPerCluster * BytesPerSector * NumberOfFreeClusters; - return (DWORD)total; -} - -bool -ZipPlatform::GetFileSize(LPCTSTR lpszFileName, DWORD& dSize) -{ - HANDLE f = CreateFile(lpszFileName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - 0, - NULL); - if (!f) - return false; - DWORD dwSize; - dwSize = ::GetFileSize(f, NULL); - CloseHandle(f); - if (dwSize == 0xFFFFFFFF) - return false; - dSize = dwSize; - return true; -} - -CZipString -ZipPlatform::GetTmpFileName(LPCTSTR lpszPath, DWORD iSizeNeeded) -{ - TCHAR empty[] = _T(""); - CZipString tempPath; - bool bCheckTemp = true; - if (lpszPath) { - tempPath = lpszPath; - bCheckTemp = GetDeviceFreeSpace(tempPath) < iSizeNeeded; - } - if (bCheckTemp) { - DWORD size = GetTempPath(0, NULL); - if (size == 0) - return empty; - - GetTempPath(size, tempPath.GetBuffer(size)); - tempPath.ReleaseBuffer(); - if (GetDeviceFreeSpace(tempPath) < iSizeNeeded) { - if (!GetCurrentDirectory(tempPath) || - GetDeviceFreeSpace(tempPath) < iSizeNeeded) - return empty; - } - } - CZipString tempName; - if (!GetTempFileName(tempPath, _T("ZAR"), 0, tempName.GetBuffer(_MAX_PATH))) - return empty; - tempName.ReleaseBuffer(); - return tempName; -} - -bool -ZipPlatform::GetCurrentDirectory(CZipString& sz) -{ - DWORD i = ::GetCurrentDirectory(0, NULL); - if (!i) - return false; - TCHAR* pBuf = new TCHAR[i]; - bool b = true; - if (!::GetCurrentDirectory(i, pBuf)) - b = false; - else - sz = pBuf; - delete[] pBuf; - return b; -} - -bool -ZipPlatform::SetFileAttr(LPCTSTR lpFileName, DWORD uAttr) -{ - return ::SetFileAttributes(lpFileName, uAttr) != 0; -} - -bool -ZipPlatform::GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr) -{ - // not using MFC due to MFC bug (attr is one byte there) - DWORD temp = ::GetFileAttributes(lpFileName); - if (temp == -1) - return false; - uAttr = temp; - return true; -} - -bool -ZipPlatform::GetFileModTime(LPCTSTR lpFileName, time_t& ttime) -{ -#if defined _MSC_VER && !defined __BORLANDC__ - struct _stat st; - if (_tstat(lpFileName, &st) != 0) -#else - struct stat st; - if (stat(lpFileName, &st) != 0) -#endif - return false; - - ttime = st.st_mtime; - return ttime != -1; -} - -bool -ZipPlatform::SetFileModTime(LPCTSTR lpFileName, time_t ttime) -{ - struct _utimbuf ub; - ub.actime = time(NULL); - ub.modtime = ttime == -1 - ? time(NULL) - : ttime; // if wrong file time, set it to the current - return _tutime(lpFileName, &ub) == 0; -} - -bool -ZipPlatform::ChangeDirectory(LPCTSTR lpDirectory) -{ - return _tchdir(lpDirectory) == 0; // returns 0 if ok -} -int -ZipPlatform::FileExists(LPCTSTR lpszName) -{ - if (_taccess(lpszName, 0) == 0) { - if (DirectoryExists(lpszName)) - return -1; - return 1; - } else - return 0; -} - -ZIPINLINE bool -ZipPlatform::IsDriveRemovable(LPCTSTR lpszFilePath) -{ - CZipPathComponent zpc(lpszFilePath); - return ::GetDriveType(zpc.GetFileDrive()) == DRIVE_REMOVABLE; -} - -ZIPINLINE bool -ZipPlatform::SetVolLabel(LPCTSTR lpszPath, LPCTSTR lpszLabel) -{ - CZipPathComponent zpc(lpszPath); - CZipString szDrive = zpc.GetFileDrive(); - CZipPathComponent::AppendSeparator(szDrive); - return ::SetVolumeLabel(szDrive, lpszLabel) != 0; -} - -ZIPINLINE void -ZipPlatform::AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem) -{ - if (bAnsiToOem) - CharToOemBuffA(buffer, buffer, buffer.GetSize()); - else - OemToCharBuffA(buffer, buffer, buffer.GetSize()); -} - -ZIPINLINE bool -ZipPlatform::RemoveFile(LPCTSTR lpszFileName, bool bThrow) -{ - if (!::DeleteFile((LPTSTR)lpszFileName)) - if (bThrow) - CZipException::Throw(CZipException::notRemoved, lpszFileName); - else - return false; - return true; -} -ZIPINLINE bool -ZipPlatform::RenameFile(LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow) -{ - if (!::MoveFile((LPTSTR)lpszOldName, (LPTSTR)lpszNewName)) - if (bThrow) - CZipException::Throw(CZipException::notRenamed, lpszOldName); - else - return false; - return true; -} -ZIPINLINE bool -ZipPlatform::IsDirectory(DWORD uAttr) -{ - return (uAttr & FILE_ATTRIBUTE_DIRECTORY) != 0; -} -ZIPINLINE bool -ZipPlatform::CreateDirectory(LPCTSTR lpDirectory) -{ - return ::CreateDirectory(lpDirectory, NULL) != 0; -} - -ZIPINLINE DWORD -ZipPlatform::GetDefaultAttributes() -{ - return 0x81a40020; // make it readable under Unix -} - -ZIPINLINE DWORD -ZipPlatform::GetDefaultDirAttributes() -{ - return 0x41ff0010; // make it readable under Unix -} - -ZIPINLINE int -ZipPlatform::GetSystemID() -{ - return ZipCompatibility::zcDosFat; -} - -ZIPINLINE bool -ZipPlatform::GetSystemCaseSensitivity() -{ - return false; -} - -#ifdef _UNICODE -int -ZipPlatform::WideToSingle(LPCTSTR lpWide, CZipAutoBuffer& szSingle) -{ - size_t wideLen = wcslen(lpWide); - if (wideLen == 0) { - szSingle.Release(); - return 0; - } - - // iLen does not include terminating character - int iLen = - WideCharToMultiByte(CP_ACP, 0, lpWide, wideLen, szSingle, 0, NULL, NULL); - if (iLen > 0) { - szSingle.Allocate(iLen, true); - iLen = WideCharToMultiByte( - CP_ACP, 0, lpWide, wideLen, szSingle, iLen, NULL, NULL); - ASSERT(iLen != 0); - } else // here it means error - { - szSingle.Release(); - iLen--; - } - return iLen; -} -int -ZipPlatform::SingleToWide(const CZipAutoBuffer& szSingle, CZipString& szWide) -{ - int singleLen = szSingle.GetSize(); - // iLen doesn't include terminating character - int iLen = MultiByteToWideChar( - CP_ACP, MB_PRECOMPOSED, szSingle.GetBuffer(), singleLen, NULL, 0); - if (iLen > 0) { - iLen = MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED, - szSingle.GetBuffer(), - singleLen, - szWide.GetBuffer(iLen), - iLen); - szWide.ReleaseBuffer(iLen); - ASSERT(iLen != 0); - } else { - szWide.Empty(); - iLen--; // return -1 - } - return iLen; -} -#endif - -#ifndef _MFC_VER -#include -#include -bool -ZipPlatform::TruncateFile(int iDes, DWORD iSize) -{ - int ret = chsize(iDes, iSize); - return ret != -1; -} - -int -ZipPlatform::OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode) -{ - switch (iShareMode) { - case (CZipFile::shareDenyWrite & CZipFile::shareDenyRead): - iShareMode = SH_DENYRW; - break; - case (CZipFile::shareDenyRead): - iShareMode = SH_DENYRD; - break; - case (CZipFile::shareDenyWrite): - iShareMode = SH_DENYWR; - break; - default: - iShareMode = SH_DENYNO; - } - return _tsopen(lpszFileName, - iMode, - iShareMode, - S_IREAD | S_IWRITE /*required only when O_CREAT mode*/); -} - -bool -ZipPlatform::FlushFile(int iDes) -{ - return _commit(iDes) == 0; -} - -int -ZipPlatform::GetFileSystemHandle(int iDes) -{ - return _get_osfhandle(iDes); -} - -#endif //_MFC_VER diff --git a/src/smpackagee/ZipArchive/ZipPlatform.h b/src/smpackagee/ZipArchive/ZipPlatform.h deleted file mode 100644 index 31b0fa3b1c..0000000000 --- a/src/smpackagee/ZipArchive/ZipPlatform.h +++ /dev/null @@ -1,204 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPlatform.h $ -// $Archive: /ZipArchive/ZipPlatform.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipPlatform.h - * ZipPlatform namespace declaration. - * - */ -#if !defined(AFX_ZipPlatform_H__E2FE6343_9D03_4F3C_A1F7_706C9F0ED978__INCLUDED_) -#define AFX_ZipPlatform_H__E2FE6343_9D03_4F3C_A1F7_706C9F0ED978__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -class CZipFileHeader; -class CZipAutoBuffer; -#include "ZipExport.h" -#include "ZipPathComponent.h" -#include "ZipString.h" -#include - -/** - Interface to the system API. - All functions have a system - specific implementation . -*/ -namespace ZipPlatform { - -/** - return the default system case-sensitivity - */ -ZIP_API bool -GetSystemCaseSensitivity(); - -/** - \return A current system name tag. - May be one of ZipCompatibility::ZipPlatforms values. - \see CZipArchive::GetSystemCompatibility - */ -ZIP_API int -GetSystemID(); - -/** - \return the default file attributes for the current system -*/ -ZIP_API DWORD -GetDefaultAttributes(); - -/** - \return the default directory attributes for the current system -*/ -ZIP_API DWORD -GetDefaultDirAttributes(); - -/** - Get the free space on the device pointed by \e lpszPath -*/ -ZIP_API DWORD -GetDeviceFreeSpace(LPCTSTR lpszPath); - -/** - Return the temporary file name ensuring there is enough size in the - destination directory,. Checking for the size is disabled by default. -*/ -ZIP_API CZipString -GetTmpFileName(LPCTSTR lpszPath = NULL, DWORD iSizeNeeded = DWORD(-1)); -/** - \name Various operations on files and directories. - All the functions which are returning a \c bool value, - return \c true when the operation was successful. -*/ -//@{ -ZIP_API bool -GetCurrentDirectory( - CZipString& sz); ///< Get the current directory and store it in \e sz -ZIP_API bool -ChangeDirectory(LPCTSTR lpDirectory); -ZIP_API bool -SetFileAttr(LPCTSTR lpFileName, DWORD uAttr); -ZIP_API bool -GetFileAttr(LPCTSTR lpFileName, DWORD& uAttr); -ZIP_API bool -GetFileModTime(LPCTSTR lpFileName, - time_t& ttime); ///< get the file modification time -ZIP_API bool -GetFileSize(LPCTSTR lpszFileName, DWORD& dSize); -ZIP_API bool -SetFileModTime(LPCTSTR lpFileName, - time_t ttime); ///< set the file modification time -ZIP_API bool -CreateDirectory(LPCTSTR lpDirectory); -ZIP_API bool -SetVolLabel( - LPCTSTR lpszPath, - LPCTSTR lpszLabel); ///< \c lpszPath may point to a file on the device -ZIP_API bool -ForceDirectory(LPCTSTR lpDirectory); ///< create nested directories at once -ZIP_API bool -RemoveFile(LPCTSTR lpszFileName, bool bThrow = true); -ZIP_API bool -RenameFile(LPCTSTR lpszOldName, LPCTSTR lpszNewName, bool bThrow = true); - -#ifndef _MFC_VER -ZIP_API bool -TruncateFile(int iDes, DWORD iSize); -ZIP_API int -OpenFile(LPCTSTR lpszFileName, UINT iMode, int iShareMode); -ZIP_API bool -FlushFile(int iDes); ///< flush the file to the disk. -ZIP_API int -GetFileSystemHandle(int iDes); ///< return the underlying system handle -#endif -//@} - -/* - \param lpszDir - \return \c true, if \e lpszDir directory exists; otherwise \c false; -*/ -ZIP_API bool -DirectoryExists(LPCTSTR lpszDir); -/** - \param lpszFilePath - may point to a file path or a directory on the device - \return \c true if the drive is removable. - Implemented only on Windows system, in all others always returns \c true. -*/ -ZIP_API bool -IsDriveRemovable(LPCTSTR lpszFilePath); -/** - \param uAttr - attributes value to test - \return \c true if the attributes are the directory attributes -*/ -ZIP_API bool -IsDirectory(DWORD uAttr); - -/** - Perform the translation between ANSI and OEM character sets. - \remark - - The conversion is performed only for the zip archives created under - Windows platform. - - Windows archiving programs convert a filename to OEM before adding it to - the archive. - - OEM conversion only influences the ANSI values above 126, so it - affects only strings containing international characters. - - \param buffer - buffer to be translated - \param bAnsiToOem - if \c true, convert ANSI to OEM - if \c false, OEM to ANSI -*/ -ZIP_API void -AnsiOem(CZipAutoBuffer& buffer, bool bAnsiToOem); -/** - Check if the given file or directory exists. - \param lpszName - \return - - -1 if the given file is a directory - - 1 a file - - 0 if there is no such a file -*/ -ZIP_API int -FileExists(LPCTSTR lpszName); - -#ifdef _UNICODE -/** - Convert wide character string to single character string. - \param lpWide - Wide string to convert - \param szSingle - buffer to receive converted string (without the terminating NULL - character) \return the \e szSingle buffer length, or \c -1 when not succeeded - \note Only in UNICODE version. -*/ -ZIP_API int -WideToSingle(LPCTSTR lpWide, CZipAutoBuffer& szSingle); -/** - Convert single character string to wide character string. - \param szSingle - single string to convert (no terminating NULL character at the end) - \param szWide - receives the wide string after the conversion - \return \e the length of the string after the conversion (without the - NULL character), or \c -1 when not succeeded \note Only in UNICODE version. -*/ -ZIP_API int -SingleToWide(const CZipAutoBuffer& szSingle, CZipString& szWide); -#endif -}; - -#endif // !defined(AFX_ZipPlatform_H__E2FE6343_9D03_4F3C_A1F7_706C9F0ED978__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipPlatformComm.cpp b/src/smpackagee/ZipArchive/ZipPlatformComm.cpp deleted file mode 100644 index 77e53e5f61..0000000000 --- a/src/smpackagee/ZipArchive/ZipPlatformComm.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipPlatformComm.cpp $ -// $Archive: /ZipArchive/ZipPlatformComm.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipPlatform.h" -#include "stdafx.h" - -using namespace ZipPlatform; - -bool -ZipPlatform::DirectoryExists(LPCTSTR lpszDir) -{ - CZipString sz; - if (!GetCurrentDirectory(sz)) - return false; - if (!ChangeDirectory(lpszDir)) - return false; - ChangeDirectory(sz); - return true; -} - -bool -ZipPlatform::ForceDirectory(LPCTSTR lpDirectory) -{ - ASSERT(lpDirectory); - CZipString szDirectory = lpDirectory; - szDirectory.TrimRight(CZipPathComponent::m_cSeparator); - CZipPathComponent zpc(szDirectory); - if ((zpc.GetFilePath() == szDirectory) || (FileExists(szDirectory) == -1)) - return true; - if (!ForceDirectory(zpc.GetFilePath())) - return false; - if (!CreateDirectory(szDirectory)) - return false; - return true; -} diff --git a/src/smpackagee/ZipArchive/ZipStorage.cpp b/src/smpackagee/ZipArchive/ZipStorage.cpp deleted file mode 100644 index ff0bfd0460..0000000000 --- a/src/smpackagee/ZipArchive/ZipStorage.cpp +++ /dev/null @@ -1,447 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipStorage.cpp $ -// $Archive: /ZipArchive/ZipStorage.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipStorage.h" -#include "ZipArchive.h" -#include "stdafx.h" -// #include "ZipPathComponent.h" -#include "ZipPlatform.h" - -////////////////////////////////////////////////////////////////////// -// disk spanning objectives: -// - sinature at the first disk at the beginning -// - headers and central dir records not divided between disks -// - each file has a data descriptor preceded by the signature -// (bit 3 set in flag); - -int CZipActionCallback::m_iStep = 256; - -char CZipStorage::m_gszExtHeaderSignat[] = { 0x50, 0x4b, 0x07, 0x08 }; -CZipStorage::CZipStorage() -{ - m_pChangeDiskFunc = NULL; - m_iWriteBufferSize = 65536; - m_iCurrentDisk = -1; - m_pFile = NULL; -} - -CZipStorage::~CZipStorage() {} - -DWORD -CZipStorage::Read(void* pBuf, DWORD iSize, bool bAtOnce) -{ - if (iSize == 0) - return 0; - DWORD iRead = 0; - while (!iRead) { - iRead = m_pFile->Read(pBuf, iSize); - if (!iRead) - if (IsSpanMode()) - ChangeDisk(m_iCurrentDisk + 1); - else - ThrowError(CZipException::badZipFile); - } - - if (iRead == iSize) - return iRead; - else if (bAtOnce || !IsSpanMode()) - ThrowError(CZipException::badZipFile); - - while (iRead < iSize) { - ChangeDisk(m_iCurrentDisk + 1); - UINT iNewRead = m_pFile->Read((char*)pBuf + iRead, iSize - iRead); - if (!iNewRead && iRead < iSize) - ThrowError(CZipException::badZipFile); - iRead += iNewRead; - } - - return iRead; -} - -void -CZipStorage::Open(LPCTSTR szPathName, int iMode, int iVolumeSize) -{ - m_pWriteBuffer.Allocate(m_iWriteBufferSize); - m_uBytesInWriteBuffer = 0; - m_bNewSpan = false; - m_pFile = &m_internalfile; - m_bInMemory = false; - - if ((iMode == CZipArchive::zipCreate) || - (iMode == CZipArchive::zipCreateSpan)) // create new archive - { - m_bReadOnly = false; - m_iCurrentDisk = 0; - if (iMode == CZipArchive::zipCreate) { - m_iSpanMode = noSpan; - OpenFile(szPathName, - CZipFile::modeCreate | CZipFile::modeReadWrite); - } else // create disk spanning archive - { - m_bNewSpan = true; - m_iBytesWritten = 0; - if (iVolumeSize <= 0) // pkzip span - { - if (!m_pChangeDiskFunc) - ThrowError(CZipException::noCallback); - if (!ZipPlatform::IsDriveRemovable(szPathName)) - ThrowError(CZipException::nonRemovable); - m_iSpanMode = pkzipSpan; - } else { - m_iTdSpanData = iVolumeSize; - m_iSpanMode = tdSpan; - } - - NextDisk(4, szPathName); - Write(m_gszExtHeaderSignat, 4, true); - } - } else // open existing - { - m_bReadOnly = iMode == CZipArchive::zipOpenReadOnly; - OpenFile( - szPathName, - CZipFile::modeNoTruncate | - (m_bReadOnly ? CZipFile::modeRead : CZipFile::modeReadWrite)); - // m_uData, i m_iSpanMode are automatically set during reading the - // central dir - m_iSpanMode = iVolumeSize == 0 ? suggestedAuto : suggestedTd; - } -} - -void -CZipStorage::Open(CZipMemFile& mf, int iMode) -{ - m_pWriteBuffer.Allocate(m_iWriteBufferSize); - m_uBytesInWriteBuffer = 0; - m_bNewSpan = false; - m_pFile = &mf; - m_bInMemory = true; - - if (iMode == CZipArchive::zipCreate) { - m_iCurrentDisk = 0; - m_iSpanMode = noSpan; - mf.SetLength(0); - } else // open existing - { - mf.SeekToBegin(); - m_iSpanMode = suggestedAuto; - } -} - -void -CZipStorage::ChangeDisk(int iNumber) -{ - if (iNumber == m_iCurrentDisk) - return; - - ASSERT(m_iSpanMode != noSpan); - m_iCurrentDisk = iNumber; - OpenFile(m_iSpanMode == pkzipSpan ? ChangePkzipRead() : ChangeTdRead(), - CZipFile::modeNoTruncate | CZipFile::modeRead); -} - -void -CZipStorage::ThrowError(int err) -{ - CZipException::Throw(err, m_pFile->GetFilePath()); -} - -bool -CZipStorage::OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow) -{ - return m_pFile->Open(lpszName, uFlags | CZipFile::shareDenyWrite, bThrow); -} - -CZipString -CZipStorage::ChangePkzipRead() -{ - CZipString szTemp = m_pFile->GetFilePath(); - m_pFile->Close(); - CallCallback(-1, szTemp); - return szTemp; -} - -CZipString -CZipStorage::ChangeTdRead() -{ - CZipString szTemp = GetTdVolumeName(m_iCurrentDisk == m_iTdSpanData); - m_pFile->Close(); - return szTemp; -} - -CZipString -CZipStorage::RenameLastFileInTDSpan() -{ - ASSERT(m_iSpanMode == tdSpan); - // give to the last volume the zip extension - CZipString szFileName = m_pFile->GetFilePath(); - CZipString szNewFileName = GetTdVolumeName(true); - if (!m_bInMemory) { - m_pFile->Flush(); - m_pFile->Close(); - } - if (ZipPlatform::FileExists(szNewFileName)) - ZipPlatform::RemoveFile(szNewFileName); - ZipPlatform::RenameFile(szFileName, szNewFileName); - return szNewFileName; -} - -CZipString -CZipStorage::Close(bool bAfterException) -{ - bool bClose = true; - CZipString sz; - if (!bAfterException) { - Flush(); - if ((m_iSpanMode == tdSpan) && (m_bNewSpan)) { - sz = RenameLastFileInTDSpan(); - bClose = false; // already closed in RenameLastFileInTDSpan - } - } - if (sz.IsEmpty()) - sz = m_pFile->GetFilePath(); - if (bClose && !m_bInMemory) { - FlushFile(); - m_pFile->Close(); - } - - m_pWriteBuffer.Release(); - m_iCurrentDisk = -1; - m_iSpanMode = noSpan; - m_pFile = NULL; - return sz; -} - -CZipString -CZipStorage::GetTdVolumeName(bool bLast, LPCTSTR lpszZipName) const -{ - CZipString szFilePath = - lpszZipName ? lpszZipName : (LPCTSTR)m_pFile->GetFilePath(); - CZipPathComponent zpc(szFilePath); - CZipString szExt; - if (bLast) - szExt = m_szSpanExtension; - else - szExt.Format(_T("%.3d"), m_iCurrentDisk); - zpc.SetExtension(szExt); - return zpc.GetFullPath(); -} - -void -CZipStorage::NextDisk(int iNeeded, LPCTSTR lpszFileName) -{ - Flush(); - ASSERT(m_iSpanMode != noSpan); - if (m_iBytesWritten) { - m_iBytesWritten = 0; - m_iCurrentDisk++; - if (m_iCurrentDisk >= 999) - ThrowError(CZipException::tooManyVolumes); - } - CZipString szFileName; - bool bPkSpan = (m_iSpanMode == pkzipSpan); - if (bPkSpan) - szFileName = - lpszFileName ? lpszFileName : (LPCTSTR)m_pFile->GetFilePath(); - else - szFileName = GetTdVolumeName(false, lpszFileName); - - if (!m_pFile->IsClosed()) { - m_pFile->Flush(); - m_pFile->Close(); - } - - if (bPkSpan) { - int iCode = iNeeded; - while (true) { - CallCallback(iCode, szFileName); - if (ZipPlatform::FileExists(szFileName)) - iCode = -2; - else { - CZipString label; - label.Format(_T("pkback# %.3d"), m_iCurrentDisk + 1); - if (!ZipPlatform::SetVolLabel(szFileName, label)) - iCode = -3; - else if (!OpenFile(szFileName, - CZipFile::modeCreate | - CZipFile::modeReadWrite, - false)) - iCode = -4; - else - break; - } - } - m_uCurrentVolSize = GetFreeVolumeSpace(); - } else { - m_uCurrentVolSize = m_iTdSpanData; - OpenFile(szFileName, CZipFile::modeCreate | CZipFile::modeReadWrite); - } -} - -void -CZipStorage::CallCallback(int iCode, CZipString szTemp) -{ - ASSERT(m_pChangeDiskFunc); - m_pChangeDiskFunc->m_szExternalFile = szTemp; - m_pChangeDiskFunc->m_uDiskNeeded = m_iCurrentDisk + 1; - if (!m_pChangeDiskFunc->Callback(iCode)) - CZipException::Throw(CZipException::aborted, szTemp); -} - -DWORD -CZipStorage::GetFreeVolumeSpace() const -{ - ASSERT(m_iSpanMode == pkzipSpan); - CZipString szTemp = m_pFile->GetFilePath(); - if (szTemp.IsEmpty()) // called once when creating a disk spanning archive - return 0; - else { - CZipPathComponent zpc(szTemp); - return ZipPlatform::GetDeviceFreeSpace(zpc.GetFilePath()); - } -} - -void -CZipStorage::UpdateSpanMode(WORD uLastDisk) -{ - m_iCurrentDisk = uLastDisk; - if (uLastDisk) { - // disk spanning detected - CZipString szFilePath = m_pFile->GetFilePath(); - if (m_iSpanMode == suggestedAuto) - m_iSpanMode = - ZipPlatform::IsDriveRemovable(szFilePath) ? pkzipSpan : tdSpan; - else { - ASSERT(m_iSpanMode == suggestedTd); - m_iSpanMode = tdSpan; - } - - if (m_iSpanMode == pkzipSpan) { - if (!m_pChangeDiskFunc) - ThrowError(CZipException::noCallback); - } else /*if (m_iSpanMode == tdSpan)*/ - m_iTdSpanData = - uLastDisk; // disk with .zip extension ( the last one) - CZipPathComponent zpc(szFilePath); - m_szSpanExtension = zpc.GetFileExt(); - m_pWriteBuffer.Release(); // no need for this in this case - } else - m_iSpanMode = noSpan; -} - -void -CZipStorage::Write(const void* pBuf, DWORD iSize, bool bAtOnce) -{ - if (!IsSpanMode()) - WriteInternalBuffer((char*)pBuf, iSize); - else { - // if not at once, one byte is enough free space - DWORD iNeeded = bAtOnce ? iSize : 1; - DWORD uTotal = 0; - - while (uTotal < iSize) { - DWORD uFree; - while ((uFree = VolumeLeft()) < iNeeded) { - if ((m_iSpanMode == tdSpan) && !m_iBytesWritten && - !m_uBytesInWriteBuffer) - // in the tdSpan mode, if the size of the archive is less - // than the size of the packet to be written at once, - // increase once the size of the volume - m_uCurrentVolSize = iNeeded; - else - NextDisk(iNeeded); - } - - DWORD uLeftToWrite = iSize - uTotal; - DWORD uToWrite = uFree < uLeftToWrite ? uFree : uLeftToWrite; - WriteInternalBuffer((char*)pBuf + uTotal, uToWrite); - if (bAtOnce) - return; - else - uTotal += uToWrite; - } - } -} - -void -CZipStorage::WriteInternalBuffer(const char* pBuf, DWORD uSize) -{ - DWORD uWritten = 0; - while (uWritten < uSize) { - DWORD uFreeInBuffer = GetFreeInBuffer(); - if (uFreeInBuffer == 0) { - Flush(); - uFreeInBuffer = m_pWriteBuffer.GetSize(); - } - DWORD uLeftToWrite = uSize - uWritten; - DWORD uToCopy = - uLeftToWrite < uFreeInBuffer ? uLeftToWrite : uFreeInBuffer; - memcpy( - m_pWriteBuffer + m_uBytesInWriteBuffer, pBuf + uWritten, uToCopy); - uWritten += uToCopy; - m_uBytesInWriteBuffer += uToCopy; - } -} - -DWORD -CZipStorage::VolumeLeft() const -{ - // for pkzip span m_uCurrentVolSize is updated after each flush() - return m_uCurrentVolSize - m_uBytesInWriteBuffer - - ((m_iSpanMode == pkzipSpan) ? 0 : m_iBytesWritten); -} - -void -CZipStorage::Flush() -{ - if (m_iSpanMode != noSpan) - m_iBytesWritten += m_uBytesInWriteBuffer; - if (m_uBytesInWriteBuffer) { - m_pFile->Write(m_pWriteBuffer, m_uBytesInWriteBuffer); - m_uBytesInWriteBuffer = 0; - } - if (m_iSpanMode == pkzipSpan) - // after writing it is difficult to predict the free space due to - // not completly written clusters, write operation may start from - // the new cluster - m_uCurrentVolSize = GetFreeVolumeSpace(); -} - -void -CZipStorage::FinalizeSpan() -{ - ASSERT(IsSpanMode() == 1); // span in creation - ASSERT(!m_bInMemory); - - CZipString szFileName; - if ((m_iSpanMode == tdSpan) && (m_bNewSpan)) - szFileName = RenameLastFileInTDSpan(); - else { - szFileName = m_pFile->GetFilePath(); - // the file is already closed - m_pFile->Close(); - } - m_bNewSpan = false; - if (m_iCurrentDisk == 0) // one-disk span was converted to normal archive - m_iSpanMode = noSpan; - else - m_iTdSpanData = m_iCurrentDisk; - - OpenFile( - szFileName, - CZipFile::modeNoTruncate | - (m_iSpanMode == noSpan ? CZipFile::modeReadWrite : CZipFile::modeRead)); -} diff --git a/src/smpackagee/ZipArchive/ZipStorage.h b/src/smpackagee/ZipArchive/ZipStorage.h deleted file mode 100644 index 89fbdabf9e..0000000000 --- a/src/smpackagee/ZipArchive/ZipStorage.h +++ /dev/null @@ -1,579 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipStorage.h $ -// $Archive: /ZipArchive/ZipStorage.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $. -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -/** - * \file ZipStorage.h - * Interface for the CZipStorage class. - * - */ - -#if !defined(AFX_ZIPSTORAGE_H__941824FE_3320_4794_BDE3_BE334ED8984B__INCLUDED_) -#define AFX_ZIPSTORAGE_H__941824FE_3320_4794_BDE3_BE334ED8984B__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "ZipAutoBuffer.h" -#include "ZipExport.h" -#include "ZipFile.h" -#include "ZipMemFile.h" -#include "ZipString.h" - -/** - A base class for functional objects (functors) that are used as a callbacks - during various actions. You need to derive your own class and overload \c - Callback method to use it. Do not derive from CZipCallback directly but from - CZipSpanCallback (as a callback when there is a need for a disk change in a - disk-spanning archive) or from CZipActionCallback for other actions. -*/ -struct ZIP_API CZipCallback -{ - /** - Method called as a callback. - Return \c false from inside the method to abort the current operation. - If it is a span callback functor, a CZipException with - CZipException::aborted code will be thrown, otherwise the code will be - CZipException::abortedAction or CZipException::abortedSafely. The - following actions can be safely aborted (without having the archive - corrupted): - - counting bytes before deleting files - - testing - - saving central directory on non-disk-spanning archive - (saved data is removed in case of break and you can save it again); - it the archive is disk-spanning and if saving is aborted, the archive - will not be damaged, but saved part of the central directory will be not - removed and the new central directory will have to be saved after it - - \note Overrride this method in the derived class. If you define this - method inside the class declaration, it should be inlined by the compiler - making the action progress faster. - */ - virtual bool Callback(int iProgress) = 0; - - CZipString m_szExternalFile; ///< if the action (adding, extracting or - ///< disk-spanning) uses an external file, its - ///< filename is stored here -}; - -/** - Derive from this a class to be used as a callback functor for the disk - change callback. You need to override member function CZipCallback::Callback. - The meaning of \e iProgress parameter is the reason for calling: - - -1 : a disk needed for reading
- other codes occurs during writing: - - >=0 : min. number of bytes needed - - -2 : the file with the archive name already exists on the disk - - -3 : the disk is probably write - protected - - -4 : couldn't create a file - Return \c false from the callback function to abort operation: the proper - exception will be thrown. - - \see CZipCallback::Callback - \see CZipArchive::SetSpanCallback -*/ -struct ZIP_API CZipSpanCallback : public CZipCallback -{ - DWORD m_uDiskNeeded; ///< the number of a disk needed (counting from 1) -}; - -/** - Derive from this a class to be used as a callback functors when adding, - extracting, deleting, testing a file or saving central directory. You need to - override member function CZipCallback::Callback. The meaning of \e iProgress - parameter is the count of data just processed. It is a smallest number of - bytes after which the callback method is called and it depends on the value - of \e nBufSize in the CZipArchive methods that uses the callback feature. In - case of saving the central directory action it is the count of file headers - just written (see CZipArchive::cbSave) \see CZipCallback::Callback \see - CZipArchive::SetCallback -*/ -struct ZIP_API CZipActionCallback : public CZipCallback -{ - - CZipActionCallback() - { - m_uTotalToDo = 0; - m_uTotalSoFar = 0; - } - - /** - The type of the callback. It is set to one of CZipArchive::CallbackType - values when the action begins. It's useful if you have more than one - callback assigned to the same functor. - */ - int m_iType; - - /** - Used by the ZipArchive library to init the callback function with the - filenames. Resets #m_uTotalToDo and #m_uTotalSoFar variables to 0. - #m_iType variable is already set to the proper value. Called at the - beginning of the action. - */ - virtual void Init(LPCTSTR lpszFileInZip = NULL, - LPCTSTR lpszExternalFile = NULL) - { - m_szFileInZip = lpszFileInZip; - m_szExternalFile = lpszExternalFile; - m_uTotalToDo = 0; // not yet known - m_uTotalSoFar = 0; // nothing yet done - } - - /** - Called by the ZipArchive functions that use the callback feature after - calculating total data to process. \param uTotalToDo total data to - process; set #m_uTotalToDo to this value - */ - virtual void SetTotal(DWORD uTotalToDo) - { - m_uTotalToDo = uTotalToDo; - // m_uTotalSoFar = 0; // already done in - // CZipArchive::CZipClbckStrg::Get - } - - /** - Total number of data to process. The value of this variable is set after - calling by the library #SetTotal method (it is 0 before). Depending on - the action it is set then to: - - adding file: the size the external file being added (or if callback is - CZipArchive::cbAddTmp, the size of compressed data: - CZipFileHeader::m_uComprSize) - - extracting file: the size of uncompressed data - (CZipFileHeader::m_uUncomprSize) - - testing file: the same as above - - deleting file: the count of bytes to move - the size of all files to - remain above the first file to delete (calculated from offsets - CZipFileHeader::m_uOffset - - saving central directory: the number of files in the archive - - */ - DWORD m_uTotalToDo; - DWORD m_uTotalSoFar; ///< total number of bytes processed so far - CZipString m_szFileInZip; ///< file in zip archive being currently processed - - /** - \return the number of bytes left to process - */ - DWORD LeftToDo() { return m_uTotalToDo - m_uTotalSoFar; } - - /** - Called after the action finishes (it is not called in case of an - exception, but it is called before throwing CZipException::abortedAction - or CZipException::abortedSafely) - */ - virtual void CallbackEnd() { ASSERT(m_uTotalSoFar == m_uTotalToDo); }; - - /** - Used internally to call Callback and increase #m_uTotalSoFar by \e - iProgress - */ - virtual bool operator()(int iProgress) - { - m_uTotalSoFar += iProgress; - return Callback(iProgress); - } - - /** - Used only when creating map before deletion (see - CZipArchive::cbDeleteCnt) or saving the central directory record. You'll - be notified every nth step (n is \e m_iStep value) with \e iProgress set - to \e m_iStep . Do not set it to low values or you can have a long - waiting on archives with huge number of files. - - \b Default: 256. - */ - static int m_iStep; - - /** - Used internally to return #m_iStep value but not 0 (return 1 in this - case). - */ - int GetStep() { return m_iStep ? m_iStep : 1; } // do not allow 0 (crash) -}; - -/** - A low-level class - operates physically on archive (CZipArchive operates - logically) -*/ -class ZIP_API CZipStorage -{ - friend class CZipCentralDir; - - public: - /** - The type of the disk spanning archive. - \see CZipArchive::GetSpanMode - */ - enum ZipSpanMode - { - noSpan, ///< no disk spanning - pkzipSpan, ///< \ref PKSpan "disk spanning compatible with PKZIP" - tdSpan, ///< \ref TDSpan "TD mode disk spanning archive" - /** - Detect the type automatically. - If the archive is on the removable device assume PKZIP - compatible, otherwise TD mode compatible. - */ - suggestedAuto, - /** - If the disk spanning archive is on the removable device - assume it is TD mode compatible - */ - suggestedTd - }; - - CZipStorage(); - virtual ~CZipStorage(); - - /* - Open the archive in memory (new or existing). - The parameters are the same as CZipArchive::OpenMode. - \param mf - \param iMode - \note Throws exceptions - \see CZipArchive::Open(LPCTSTR, int, int) -*/ - void Open(CZipMemFile& mf, int iMode); - - /* - Open or create an archive. - The parameters are the same as CZipArchive::Open. - \param szPathName - \param iMode - \param iVolumeSize - \note Throws exceptions - \see CZipArchive::Open(CZipMemFile& , int); -*/ - void Open(LPCTSTR szPathName, int iMode, int iVolumeSize); - - /** - Close the disk-spanning archive and reopens as an existing disk-spanning - archive or set mode to #noSpan - */ - void FinalizeSpan(); - - /** - Called only by CZipCentralDir::Read() when opening an existing archive. - \param uLastDisk - the disk number the central directory is on - \note Throws exceptions. - -*/ - void UpdateSpanMode(WORD uLastDisk); - - /** - Write chunk of data to the archive. - \param pBuf - buffer with data - \param iSize - bytes to write - \param bAtOnce - if \c true, the whole data must fit in the current volume, - otherwise the disk change is performed - \note Throws exceptions. -*/ - void Write(const void* pBuf, DWORD iSize, bool bAtOnce); - - /** - Read chunk of data from the archive. - \param pBuf - buffer to receive data - \param iSize - bytes to read - \param bAtOnce - if \c true, the specified number of bytes must be read from the same - volume (no disk change allowed) - \note Throws exceptions. -*/ - DWORD Read(void* pBuf, DWORD iSize, bool bAtOnce); - - /** - Return the position in the file, taking into account the bytes in the - write buffer. \note Throws exceptions. - */ - DWORD GetPosition() const - { - return (DWORD)(m_pFile->GetPosition()) + m_uBytesInWriteBuffer; - } - - /** - Flush the data from the read buffer to the disk. - \note Throws exceptions. - */ - void Flush(); - - /** - Forces any data remaining in the file buffer to be written to the disk - */ - void FlushFile() - { - if (!m_bInMemory && !IsReadOnly()) - m_pFile->Flush(); - } - - /** - A method used to change disks during writing to the disk spanning archive. - \param iNeeded - no of bytes needed on the disk - \param lpszFileName - the archive filename - \note Throws exceptions. -*/ - void NextDisk(int iNeeded, LPCTSTR lpszFileName = NULL); - - /** - \return a zero-based number of the current disk -*/ - int GetCurrentDisk() const { return m_iCurrentDisk; } - - /** - Change the disk during extract operations. - \param iNumber - a zero-based disk number requested - \return -*/ - void ChangeDisk(int iNumber); - - /** - Detect the span mode. - \return - - -1 - existing disk spanning archive opened - - 0 - no disk spanning archive - - 1 - disk spanning archive in creation - -*/ - int IsSpanMode() const - { - return m_iSpanMode == noSpan ? 0 : (m_bNewSpan ? 1 : -1); - } - - /** - return \c true if the archive cannot be modified. - */ - bool IsReadOnly() { return m_bReadOnly || IsSpanMode() < 0; } - - /* - \param bAfterException - set to \c true after the library has throw an exception. - The simplified mode is used then. - In this case it'll be possible to reuse the object to operate on another - archive, but the current archive file will not be valid anyway. - \return the filepath of the archive (used by CZipArchive::Close) - \note Throws exceptions. -*/ - CZipString Close(bool bAfterException); - - /** - The size of the write buffer. - Set before opening the archive. - It is usually set with CZipArchive::SetAdvanced - (specify this value as the first argument). - \see CZipArchive::SetAdvanced - */ - int m_iWriteBufferSize; - - /** - The physical archive file (on a storage device). - Not used when opening archive in memory - with Open(CZipMemFile& , int). - */ - CZipFile m_internalfile; - - /* - The buffer representing the archive. - It is a physical file or a memory buffer depending on what - method was used to open the archive. In the first case it is - a pointer to #m_internalfile. - \see Open(LPCTSTR, int, int); - \see Open(CZipMemFile& mf, int) - */ - CZipAbstractFile* m_pFile; - - /** - Takes one of the values of #ZipSpanMode. - */ - int m_iSpanMode; - - /** - A callback functor which method \c Callback is called when there is a - need for a disk change while operating on a #pkzipSpan archive. \see - CZipArchive::SetSpanCallback - */ - CZipSpanCallback* m_pChangeDiskFunc; - - /** - The signature of the extended header - */ - static char m_gszExtHeaderSignat[]; - - protected: - /** - Flush without writing. Can be used only on non-disk spanning archives. - */ - void EmptyWriteBuffer() { m_uBytesInWriteBuffer = 0; } - - /** - Open a physical file. - \param lpszName - the name of the file to open - \param uFlags - file open flags - \param bThrow - if \c true then throw an exception in case of failure - \return \c true if successful -*/ - bool OpenFile(LPCTSTR lpszName, UINT uFlags, bool bThrow = true); - /** - Throw an exception with the given code. - \param err - \see CZipException::Throw -*/ - void ThrowError(int err); - - /** - Return the number of bytes left on the current volume. -*/ - DWORD VolumeLeft() const; - - /** - Rename last file in TD mode disk spanning archive when done with - creating - */ - CZipString RenameLastFileInTDSpan(); - /** - Write data to the internal buffer. - \param *pBuf - the buffer to copy data from - \param uSize - bytes to write - \note Throws exceptions. -*/ - void WriteInternalBuffer(const char* pBuf, DWORD uSize); - - /** - \return the number of free bytes on the current removable disk -*/ - DWORD GetFreeVolumeSpace() const; - - /** - Call the callback functor. - Throw an exception if the callback functor's method \c Callback returns \c - false. \param iCode a code to be passed to the callback functor \param - szTemp a string to be used as a filename (the second argument of - CZipException::Throw) when the exception must be thrown \note Throws - exceptions. \see CZipArchive::SetSpanCallback \see CZipException::Throw -*/ - void CallCallback(int iCode, CZipString szTemp); - - /** - Construct the name of the volume in #tdSpan mode. - \param bLast - must be \c true if constructing the last volume name (an extension "zip" - is given) \param lpszZipName the name of the archive \return the new - volume name -*/ - CZipString GetTdVolumeName(bool bLast, LPCTSTR lpszZipName = NULL) const; - - /** - Change the disk in #tdSpan mode - */ - CZipString ChangeTdRead(); - - /** - Change the disk in #pkzipSpan mode - */ - CZipString ChangePkzipRead(); - - /** - Used only in \ref TDSpan "TD span mode" . The value it holds depends on - the open mode. - - Opened existing disk spanning archive - store the number of the last - disk ( the one with "zip" extension). - - Disk spanning archive in creation - the size of the volume. - - \see CZipArchive::Open - \see CZipArchive::GetSpanMode - - */ - int m_iTdSpanData; - - /** - The extension of the last volume. - */ - CZipString m_szSpanExtension; - - /** - \return the count bytes left free in the write buffer - */ - DWORD GetFreeInBuffer() const - { - return m_pWriteBuffer.GetSize() - m_uBytesInWriteBuffer; - } - - /** - Number of bytes available in the write buffer. - */ - DWORD m_uBytesInWriteBuffer; - - /** - The value it holds depends on the open mode: - \par - - #tdSpan : the total size of the current volume - - #pkzipSpan: a free space on the current volume -*/ - DWORD m_uCurrentVolSize; - - /** - number of bytes left free in the write buffer - */ - DWORD m_uVolumeFreeInBuffer; - - /** - Write buffer caching data. - */ - CZipAutoBuffer m_pWriteBuffer; - - /** - Used only during disk spanning archive creation. - Tells how many bytes have been written physically to the current volume. - */ - DWORD m_iBytesWritten; - - /** - \c True, if the current archive is a new disk spanning archive. - */ - bool m_bNewSpan; - - /** - The current disk in a disk spanning archive. - Disk no 0 is the first disk. - */ - int m_iCurrentDisk; - - /** - It is set to \e true when an archive is created in memory; \e false - otherwise. - */ - bool m_bInMemory; - - /** - It is set to \e true if OpenMode::zipOpenReadOnly was specified when - opening the archive - */ - bool m_bReadOnly; -}; - -#endif // !defined(AFX_ZIPSTORAGE_H__941824FE_3320_4794_BDE3_BE334ED8984B__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/ZipString.cpp b/src/smpackagee/ZipArchive/ZipString.cpp deleted file mode 100644 index 13ea2e2fe8..0000000000 --- a/src/smpackagee/ZipArchive/ZipString.cpp +++ /dev/null @@ -1,28 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipString.cpp $ -// $Archive: /ZipArchive/ZipString.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipString.h" - -ZIPSTRINGCOMPARE -GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate) -{ - if (bCollate) - return bCaseSensitive ? &CZipString::Collate - : &CZipString::CollateNoCase; - else - return bCaseSensitive ? &CZipString::Compare - : &CZipString::CompareNoCase; -} diff --git a/src/smpackagee/ZipArchive/ZipString.h b/src/smpackagee/ZipArchive/ZipString.h deleted file mode 100644 index ea2b7fe729..0000000000 --- a/src/smpackagee/ZipArchive/ZipString.h +++ /dev/null @@ -1,37 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipString.h $ -// $Archive: /ZipArchive/ZipString.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ZIPSTRING_DOT_H -#define ZIPSTRING_DOT_H -#include "ZipExport.h" -#include "stdafx.h" - -typedef CString CZipString; - -/** - A poiter type to point to CZipString to Collate or CollateNoCase - or Compare or CompareNoCase -*/ -typedef int (CZipString::*ZIPSTRINGCOMPARE)(LPCTSTR) const; - -/** - return a pointer to the function in CZipString structure, - used to compare elements depending on the arguments -*/ -ZIP_API ZIPSTRINGCOMPARE -GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate = true); - -#endif /* ZIPSTRING_DOT_H */ diff --git a/src/smpackagee/ZipArchive/__Windows_MFC.zcfg b/src/smpackagee/ZipArchive/__Windows_MFC.zcfg deleted file mode 100644 index dc711df027..0000000000 --- a/src/smpackagee/ZipArchive/__Windows_MFC.zcfg +++ /dev/null @@ -1 +0,0 @@ -Windows MFC diff --git a/src/smpackagee/ZipArchive/_copy_from_Win-MFC.bat b/src/smpackagee/ZipArchive/_copy_from_Win-MFC.bat deleted file mode 100644 index adac7df4d9..0000000000 --- a/src/smpackagee/ZipArchive/_copy_from_Win-MFC.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -copy Windows\*.* *.* -copy mfc\*.* *.* -del __*.zcfg -echo Windows MFC > __Windows_MFC.zcfg diff --git a/src/smpackagee/ZipArchive/_copy_from_Win-STL.bat b/src/smpackagee/ZipArchive/_copy_from_Win-STL.bat deleted file mode 100644 index 88f426740b..0000000000 --- a/src/smpackagee/ZipArchive/_copy_from_Win-STL.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -copy Windows\*.* *.* -copy stl\*.* *.* -del __*.zcfg -echo Windows STL > __Windows_STL.zcfg diff --git a/src/smpackagee/ZipArchive/_version.txt b/src/smpackagee/ZipArchive/_version.txt deleted file mode 100644 index 3f684d2d90..0000000000 --- a/src/smpackagee/ZipArchive/_version.txt +++ /dev/null @@ -1 +0,0 @@ -2.3.4 diff --git a/src/smpackagee/ZipArchive/borland.zip b/src/smpackagee/ZipArchive/borland.zip deleted file mode 100644 index 98dfe5ded0c5bdfa90dda381b6cd6b8f780cb078..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7568 zcmZ{pWl$a4pS2I}?he7--3jgz+#wvC!$E>ea1HM677_^V?(Ps=gS+d?o%z>$?@Zn4 zuIjF?UC)=*Rco*PTdE3B(AWS-06d_{?tua2>_O`Y005jp001cOZ+lZ)3p4Z2c6Kc0 zj*gX+UGhC*=&&14-R(VMta|xfH6MZ;a=)gADAmdk)Xcb0tTMG^NHey#RQG9!v%Y{h zdyvUEXNnJCrOw%G3LdA{9mx2%?SLfpg3vCNWI|;*M#Sp|bYLOF4Ci7ce^)Ik3)r96 z4qkX-E`~M%PjpY#?l2?YOAiZm3ajS&L*aWpsbTD9=@5KCAI3M<6Im-1{Z|z(cWw(e z(rYHR^9$Jcpz6Gp&-kCV>_~Gy5xJO5@h*!0SkG3?7>dXKkVC!%Ek2_PEi*#LW+HV0 zYND!55}72cZT)V8kaZKA>_ez)l_J zskQ3bVoaq?d-_D>-Qo;dKoZV@NAq0+*u}lAC#$ud z**6eQ6%M)7V~%};r(o8Agr6SxA}E2%7p@OUVE*`c<29Bc#8n|*=W}{-adT7G)O3Ga zk2r;7iV$7UHFY3&2Ol>W14YOTD?^{7@JD8Uc|8;kuR{(~UDS`XmVi}Q4q{Bq z%-8|AX06nYLe?Fs!kTmkl#UqJkIuXgeDDZIcgkB!SPbl$@i;+1$$Q z6bjXF6L4>HA}X6ITXGdX`#3k> z?j>-CQmt}DSvPvE2cJZ2klz8}OeM7Do?-3G+p*VrG5Fe4RzjRJ2JGs%n>xi!M)odK zH~WnI497Rt5Nxv!zwOnlx7F`cns@A~bKc?0{MON_N2!{Yt*JXqe|@!Vx&0!?IkL%{T_*~;CEzd)*a{?eU57z zQgyXZAy|(={@6Y<=Bsj>OQ7ra;~6mG1=;YE%w-v>-OZAJA;Nq$wLtp%4b0msJag%w z`4QF>FFD(W18_P!HCOgMqui2!kjdHab*=&rOT@i?S1~CsZz!7=JV(q~S-o4DPCJhG zoHd+%s7N%Lxoz=;LBsF75|61Z*%lhf=Rj!sNkLTILRBAnUoF1EfPrDlf!mv z#^gpWRXA+OWl|^nNvoRqNO}-9xl|j;zE5?tQbl-y<0;e=i<^>nM9+$taW2R3U`+1KgxEmzJ z#{?w!{PiQZQ3q$U&Lw6lM=7ILsxYm;j!8b-$3dwFCc1BdvwwiLwRMSfn7RGvgjIoz z>0)2c9mEoZSb9EeiD_^+DS;eS zn|(1`Rx+9k?yk7PQQR z9nwK`?#K5rsxyS5p|f%|5x4g0VB*#Z$4;CFoFsdMU!?sfM<;pp&)fqJ*QBBG^fqW@74j? z2w{8uc&L~34N|9YnLw#y#h8@^#F7%}5c-;#dXi#Ih^P2QkC@;e#FjD9Oyb=Mw}11q zIENK){A9zFs~eLFAwQO9+hDbE9Jwm2W@yVwig9#;RxBy)Y}@bS^VN+v$7K(#WRqLg zuH`4u&Nd?Ii9c90rcj;KzdI}K$nSK&9<1VMR{3k&m3D6&_}dAIs_@qx&$?gZIh7?BBbyLVQtqK;8DWjq>1-9%W2SCe(fq@}=#6KCvpHBZ3n7{Mm5 zpRB}hiAfy~cCC0c4`qH|FR=!bUiiT8M`gS^qi=dy}mR!X@y3ly}lK*m7In@BuOGM z$P)*9I5Sp4!z}YhI=ZJ+8G=aup{o}7P*gi&icVRlO)W>6lv=JyE^oH;6sSY3coj{9 zYmx4yQdmu1pN}`*>ZFvRj1`}#Hy&cQ4_RdWNe7FS+(T&|`f>}4Cz3m<|6HirNOywtivUoIkqg#Nl5< z)XbDOp!5fAW9!-_)U`5?3qA9T;Jhk3IvzF@SiD_3`_nU3uqVdFVG;Q=70dx`nXD*S z>V38F>#ba$m_eS`ci8mM>HOQ-RBEl!dviW zvq@1K5+z}Qnh%|O&^&G&W(<3ohBzC-NuwfSB4(_(rn3?`xQLsa;M->D$X5WSo~^9B z7=$Jn4SjvMCJ|FpA-#^GZGt>BwyG0YD>rqXCJ~-4w;V+xZ_6x0ha-QZyq-QdGSc2@ zC`{0IPPIV+f~I!9G0`8n;`c8YOl>`=_)WfVo}XhSCG61T!yA`#9%nToDoMOvm}a`X z?>jz4^@fp)*~n0~_-;6ec@pJ&Vq;Z69NhE4%AfFA@frw!gVRK#9Gu-Qtu*xfCS3r7 zPTY^N$aAJQP*Y1FNzI}2jhE&IVrt^C9$dmDzV@v*jKc9S1-WHY!mIYe8op+|_i%xD zxmAVN<4_=jvS&qQCNojP=BCQzX zrsPPMN&=hb?>$m(f%BO6Kg3J4=$7n}-UbO(-7a;1kENj7fGhHv8B;WRxwg-nf{MF&d|13{NTyIk2*KZQsOate~L!=D0(tKihpJ zF?b|F&a($bt^(RQz8@zGjco7E@UXnNNTN?XqhGT$2PU@pMpI8$lngEXC$)F%64-PW zYy&sXe?^vZoD1F02gQVrI4my<;U;DE{6?*Wy$e2y0*SvyK=OuVv$iM(Tv*2hkM!pZ zU1-E`?@yeSLZUd<7a?vJIal==5jv}SkS0)}ZI$LW$S@vWg)Vobaq7=H5&a3=?9>ae zZSZlyyAp8Txe_*(<}GnVVd46P%D1cPy#Gmyl4` z=*kFYr%LW~^Zoua7GC!m(JnrAkT&ivVugGp4UrIp7|3+QJ&4cfq0;3xZC&HIVB6Y- z!=Ql@@~cFu1>=lf+O2B8zgp#UjuZaAA%ndrvUN#6zp*^7jRD!G8PS8yz)zT`m*jQ> zM;#tuJP-7YTI?#acx=8RbV;H%g>1}t>zhz{c)<`FJI7?(Zh@$_Kk659MKLl94{!zSVzl-@jOXl6f+h0}Dwg7zS0TBh5mlg{sDxv=zqYyu z*%PMA`#6$*4`drOz9D2&0q?^-HoB(_9IXO1swhmh#m6_vx$)k1vkQPj8ZjEOp|@Yww|WSvtf8atClo&qble7%yz!Mo(X zVQau-gA4b`MWt1VO6$lq=tuz1_yNkX&aCpvqDgG3gI{`I_L-l2BUQ*`Q~(_fveZx= zG)B4_dSB32ItBRv_%XULGj)SZCt)P?AH;p`yr>7&3%nSvJg;b|bJ7L`)fi<=ikvSlSfYa4*?tPUH)66CZBU1QyJW#ny145L%(;x}E-w5uYVrvM zTIOb|)PL%;xnwAd=66cjJum~^T&P4>!NFcGsy%etrGXwBLLYuKkeu&&U=vabBYNtS z@TXkF2wnJ9Bd>c_eEBha**=L$;#N0o$!3SB!!RXqq>%dqhDnjtxAH9t8U?>A27l}+ zeAPK~#zb z)u)KnWV#{X%LshgBN-%A&igmgNhrpto}BA*g4YW?KE>v1HaOAQ#^U5dw1qdGeLsSq zMo(~mCp!C7bLJLS(cUsd005E#0D$|;5zRpkKo+ZLJ$;SkK}=ue@=LPED*YB72uNiK zS$O?{#en+_Bn#)EJt=B^O8rO{BWrB7I?-2`yM2y$i<%#Z$)4>82g}zkF;@W&!aNzJGHp&f34>fa_aoWzx$RQ!2WtIK`Z=6R5Lm5Xc&Mru19jkgEiwaD zn>isII`eZ2dyiH#7C=TF%fW9vzSiA8g`XA@uOpA3>m56vrwCA3M?tb(+Pvt5!8E^w zgyFPIAzR|ARQnC#gQ~g$s2tyvp>w;xJwc-)M)#0wD`3<_l|gjM1rXT&8dw>W{z1Dj zm1H$`igx8`XK>w4)`_AArcLIXi#R5+m~_XW$wtwLQ>yVWN|klo6)&e?_}Kh8GZqkQ z6KI@GEye0s^l-Q|Yiw%*lMkGPKQ<#ab_pZG_J&Y<^g{U|Hj7;D8j*r>Sj+HOdx)J5 zzvQ}fzY|7m{9!?{z>&FeMjyqB$&3OCyJNodN9EwlnrvRcaue@AH>4snz;A^kF)h=3CO zi)haWbl*M~hYvQVP4nM=SvTyYVkJ_xHCa^=!OK%dEEZlfyp!+Ert9>!KNr?sdIR#GmLR8&*g3A-jy zNY#PFB`Y(o2A0ujsK;z7Iqi0))2CRETv@$5Hg;3>n&etrC!zOkL|Tnw!0I6K%SN&j z15L5R)2_9Q=glAsUe@r9l^CRJk`+`&!xGgT+HXR%fikptO@c{-1m8waPfX5Bmbe98 zB5EnWTaEV&7JMixQ0Uw8N{*Du;VvQ^aH~#6-a|)7lN2|gy?L-&0ih+;Ol49ddI$HE zpbdmt3?U<{Q7JQG1j{;d|Foox9{ESVi zS?S4~a4-Z8%9td^hpGXs5WH}8s(V)R*QwHPZc4&L<3-w+P7r;xHQblst?C(Y*6z18 zOOUy_l$yJ`JGrRhZG8@Ks7)YvNWkqFaN&el_v{?JUhT{hZBY<9e-KKh2%{y?>!b=lz(NE>S%hEnOt^$kY4Cgy~1?K;?~*+cxN3*3}uo=2rm0U&7mwOZB@1 z3~k&YQNVViFCPlJ`pV?E=IaoT>MmwdKkx#c6=*8wJ3zK5PJ2)#b+L4W%uKKBO&IQC z2NxiR(?(H}Zg$;Bxb9DmE|z#>D!+BF5|TOQ&}1{M{924^Dwp%Dt@EIJ)DwCtB)dR@C1%h8(qm7Z&T)#gXF@Jjka;VY)O=7A)jyNh^fE3vM097pC||=0Pb|68kDp}gld3iAy*gYj6PucK3^CJ^+yx!F>c>L zbEDr6ljqD{w3fY9&DW*+468)ihAF~#xzDAT+<>Xi#a%!v5yz-DlOaQu7?GF}wzhdx zYez0n?oZ+ZDm_pgAz~(_J^)l{V)~+}(5Na%z^*E|;CHDh6@YMP0tPHm2a>>cD7f~B z35L3=cb6{*c3^&|S6BXwx}&f(W;~o^bbtesvLwi#jVx~|FasO7w}+_Ohja*k^F?8s zf-xHQ#Fs4T@YVrNFVo~gS{YYHx}%fXCkPVk$e z{BB(<{+zB}^}8_Mi<9(8JZNBJy18Plum zfJ^39=1sf}5XiRubYtZWrD;0c<934Vm{QH!4aQ<+>%-D@Mp8kIBiLO+Y>aJpXBb80 zE~1V}QTQ!7UR5mo?Cw68moUNHWR`)jfX%6d$!!#&+jA>K?RX_MVxOUDJ072J?Vha3 zMvsp)b|hK3*slBoQ8Fgg^=ZN0puVBY=Pf;SSYO)swI3g?Y!F*b6_kPU;BfS5VWHT; zMo?o_0fCYhr%YpDtBpG6%wH``|+-=fhL-e?`e8clROq(m&a zS_Vl`FNfaZdo6EyK9?xty z_jF2GbE!jwz5|V(jNlM3ma*cN)c|VZ-_oP(eN7pk&(WcGv=1D?5S1rhd}?k4aq14k zF|XrYu8)=yt2F9_yj=#%q~R2(EJWuY%fPo=2r)}1CMDvllacq7L9_#BWd;Rof_@UH zxF$H}mCDJuMMSM?;>DC46k3(jLs=p2HCwMYbZ3j5(}w9O?hVO4SI2v z>Sv-EHU?euyo?HL?DA>k1r`sNY%j%vloX_&?znNBdErYHQAtkgs);KUs|CHFGxem}-g>h1S7m^$4-BY&MkTOcSLOCM&v*I;E$5JY;=^?+sqN#e)Tr1$ z+DX2geepUF*mi)-CKB4f{6becli=~SP(6KD+~k2T$bLGLDsN;V;rg&{Z~mA?l)h@a zYOg&w`0ZDoVPvY8pkV>;$`YbYQRzG|6=N|-9BSU=+IZ#mi)YX88~F|<`cJE#eIQWK zQZwlbpJeV(jy~HXng((|RTF`Oay61y7=rtn9|jP1OHDkqf5gP*5a-eCnL{8yrv}@* zHTnVBD?h-^vNnk~5XS*&xZ2FDIvn)Y`2 zBe7`>6QWphxtE3{8@in!2Xxf|xy-l{e5$zF!piAZs-d+XnbKrAE>Y#A1y(-C+ATcx zgFG*O6IE4!fW!v;-^Jj2q -Q: I experience linking problems. What to do? - - - -Q: When do I need to purchase the commercial license? - - - - -Q: When I open a multi-disk archive (Pkzip mode) and the last disk is not in - the drive, I receive the %CZipException::cdirNotFound exception. How to detect - whether the last disk is in the drive? - - - -Q: Of what size should be a single volume in a multi-disk archive created in -the TD span mode ? - - - - -Q: How can I detect the disk spanning mode of an archive? - - - -Q: How to integrate the library with the sample application? - - - -Q: Why the library doesn't want to extract archives (mostly old)? - - - -Q: In %CZipArchive::AddNewFile and %CZipArchive::ExtractFile I want to use partial -path for the filename inside the archive. - - - -Q: I want to create an archive that will be readable under Unix/Linux. - - - -Q: How can I use UNC path with %CZipArchive::ExtractFile function ? - - - -Q: How to create a zip archive in memory and then write it to disk or -read the archive from the disk and extract from memory ? - - - -Q: How can I extract or delete files that matches a specified wildcard pattern ? - - -
-***************************************************************************** -\anchor q1 - -Q: I experience linking problems. What to do? - - -A: -\par If you get mostly LNK2005 : - If you changed the project configuration (e.g. from Release to Unicode Release), rebuild the projects. - If you are still getting link errors, make sure that the library and your program are both using single-threaded or both - multithreaded (or multithreaded DLL) run-time library. The option Project->Settings-> c/c++ ->Code Generation->Use run-time library - should be set to the same value in the ZipArchive library and the program - project options. Make sure that you link appropriate configurations (Release against Release, Debug against Debug...) - and that you're using MFC library in the same way (shared, static or not using) in those configurations. -\par If you get LNK1104 (e.g. cannot open file "mfc42u.lib") - You're trying to compile the Unicode version but you haven't installed the necessary libraries. -When installing Visual C++ Professional for example, you need to check the boxes "Static Libraries for Unicode" and -"Shared Libraries for Unicode". They are in "VC++ MFC and Template libraries\\MS Foundation Class Libraries". -You don't need to reinstall the Visual Studio to add them. - - - - -\anchor q13 - -Q: When do I need to purchase the commercial license? - - -A: The ZipArchive library is distributed under GNU GPL which implies that it can only be used -with software that is licensed under conditions compliant with the GPL. It means that -you need to provide a customer with the source code of your software that uses the library. -The commercial license removes this obligation. You can find out more at \ref s1. - -\anchor q2 - -Q: When I open a multi-disk archive (Pkzip mode) and the last disk is not in - the drive, I receive the CZipException::cdirNotFound exception. How to detect - whether the last disk is in the drive? - - -A: The last disk can not be detected before opening an archive. The only way to -prevent the program from failing when an incorrect disk is inserted is to -catch the CZipException::cdirNotFound exception while opening the archive and keep prompting the user to insert the last disk into the drive. Please see the sample application on how -it can be done in details. - -\anchor q3 - -Q: Of what size should be a single volume in a multi-disk archive created in -the TD span mode ? - - -A: The size of the volume may be from 1 byte to the maximum integer value, and the bigger - the - faster is creation and extraction (no file changes meantime), but the size - of the whole archive is the same. The optimal solution is to set it to about - the size of the diskette (a little less to be comfortable when there are bad sectors found on the disk) to allow the future conversion to PKZIP span mode. - -\anchor q5 - -Q: How can I detect the disk spanning mode of an archive? - - -A: You need to open the archive and the call CZipArchive::GetSpanMode. When opening the archive in tdSpan mode on a removable device, you should set \e iVolumeSize to a non-zero value while opening the archive (with CZipArchive::Open). There is no universal way to distinguish a PKSpan archive from a TDSpan archive on a removable device, because they have identical internal structure. - - -\anchor q7 - -Q: How to integrate the library with the sample application? - - -A:The usual way is to put ZipArchive library at the same directory level what your -project is, and then use one of the \ref sectVisual "integration methods". -Make a directory structure like this:
-\htmlonly ----
-    |-ZipArc           // the application project
-    |-ZipArchive   // the ZipArchive library
-\endhtmlonly - -You can now follow the integration method 1 or 2 (the easier one). - -\anchor q8 - -Q: Why the library doesn't want to extract archives (mostly old)? - - -A: The common reason is that the data is compressed using \e imploded method (usually with old archivers). -The only methods supported by the zlib library are \e deflation which is the most commonly used by archivers and \e storing which is in fact not a compression method. You can use a compiled ZipArc application to find out what method the file was compressed with (View->File Info) - - -\anchor q9 - -Q: In CZipArchive::AddNewFile and CZipArchive::ExtractFile I want to use partial -path for the filename inside the archive. For example:
-When I compress some directory, like this: - c:\\program files\\example (full directory path: c:\\program files\\example\\text\\txt) - it comes with the whole path. I would like that the zip only get the EXAMPLE\\text\\txt path. -
- -A: You can set \e bFullPath argument to \c false in these functions and set -the beginning part of the path that you commonly want to eliminate with -CZipArchive::SetRootPath function. In the example above you'd set it to -c:\\program files\\ (the path separator at the end is added automatically). - -\anchor q10 - -Q: I want to create an archive that will be readable under Unix/Linux. - - -A: Inside the archive there is an information stored about the system it was -created under. It helps converting the file attributes that are stored inside -the archive to file attributes that are used on the system on which the file is extracted. -Some Unix archivers cannot convert Windows attributes to Unix, so that it is needed -to create the archive with the Unix attributes already (and the internal info about the -system set to a Unix value). To achieve that, simply call CZipArchive::SetSystemCompatibility -with the argument set to ZipCompatibility::zcUnix after creating the archive. - -\anchor q11 - -Q: How can I use UNC path with CZipArchive::ExtractFile function ? - - -\verbatim -A: You need to replace \\\\ at the beginning of the UNC path with \\\\?\UNC\ . -\endverbatim - -\anchor q12 - -Q: How to create a zip archive in memory and then write it to a disk or -read the archive from the disk and extract from memory ? - - -A: See \ref sectMemory - -\anchor q14 - -Q: How can I extract or delete files that matches a specified wildcard pattern ? - - -A: You need to build a CZipWordArray with CZipArchive::FindMatches and then: -- to delete: use the array as an argument to CZipArchive::DeleteFiles -- to extract: the array stores the indexes of the files to extract; you need to -enumerate the array and pass the indexes one-by-one to CZipArchive::ExtractFile function - -*/ diff --git a/src/smpackagee/ZipArchive/gpl.txt b/src/smpackagee/ZipArchive/gpl.txt deleted file mode 100644 index 832de66790..0000000000 --- a/src/smpackagee/ZipArchive/gpl.txt +++ /dev/null @@ -1,285 +0,0 @@ -/** \page pageGPL GNU GENERAL PUBLIC LICENSE - - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - -*/ \ No newline at end of file diff --git a/src/smpackagee/ZipArchive/mfc/ZipBaseException.h b/src/smpackagee/ZipArchive/mfc/ZipBaseException.h deleted file mode 100644 index 3119f0c9d3..0000000000 --- a/src/smpackagee/ZipArchive/mfc/ZipBaseException.h +++ /dev/null @@ -1,22 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipBaseException.h $ -// $Archive: /ZipArchive/ZipBaseException.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef __ZIPBASEEXCEPTION_H__ -#define __ZIPBASEEXCEPTION_H__ - -typedef CException CZipBaseException; - -#endif //__ZIPBASEEXCEPTION_H__4 diff --git a/src/smpackagee/ZipArchive/mfc/ZipCollections.h b/src/smpackagee/ZipArchive/mfc/ZipCollections.h deleted file mode 100644 index ab38909768..0000000000 --- a/src/smpackagee/ZipArchive/mfc/ZipCollections.h +++ /dev/null @@ -1,82 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipCollections.h $ -// $Archive: /ZipArchive/ZipCollections.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ZIPCOLLECTIONS_DOT_H -#define ZIPCOLLECTIONS_DOT_H - -#if _MSC_VER > 1000 -#pragma once -#pragma warning(push) -#pragma warning( \ - disable : 4786) // 'identifier' : identifier was truncated to 'number' - // characters in the debug information -#endif // _MSC_VER > 1000 - -#include -typedef CStringArray CZipStringArray; - -template -class CZipArray : public CArray -{ - - static int CompareAsc(const void* pArg1, const void* pArg2) - { - TYPE w1 = *(TYPE*)pArg1; - TYPE w2 = *(TYPE*)pArg2; - return w1 == w2 ? 0 : (w2 > w1 ? -1 : 1); - } - static int CompareDesc(const void* pArg1, const void* pArg2) - { - TYPE w1 = *(TYPE*)pArg1; - TYPE w2 = *(TYPE*)pArg2; - return w1 == w2 ? 0 : (w1 > w2 ? -1 : 1); - } - - public: - void Sort(bool bAscending) - { - int iSize = GetSize(); - if (!iSize) // if ommitted operator [] will fail if empty - return; - qsort((void*)&((*this)[0]), - iSize, - sizeof(TYPE), - bAscending ? CompareAsc : CompareDesc); - } -}; - -typedef CZipArray CZipWordArray; - -template -class CZipPtrList : public CTypedPtrList -{ - public: - typedef POSITION iterator; - typedef POSITION const_iterator; - - bool IteratorValid(const iterator& iter) const { return iter != NULL; } -}; - -template -class CZipMap : public CMap -{ -}; - -#ifdef _MFC_VER -#pragma warning(pop) -#endif - -#endif /* ZIPCOLLECTIONS_DOT_H */ diff --git a/src/smpackagee/ZipArchive/mfc/ZipFile.cpp b/src/smpackagee/ZipArchive/mfc/ZipFile.cpp deleted file mode 100644 index f50e84004f..0000000000 --- a/src/smpackagee/ZipArchive/mfc/ZipFile.cpp +++ /dev/null @@ -1,53 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFile.cpp $ -// $Archive: /ZipArchive/ZipFile.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipFile.h" -#include "stdafx.h" - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -// IMPLEMENT_DYNAMIC(CZipAbstractFile, CFile) -IMPLEMENT_DYNAMIC(CZipFile, CFile) - -CZipFile::CZipFile() {} - -CZipFile::~CZipFile() {} - -CZipFile::operator HANDLE() -{ - return (HANDLE)m_hFile; -} - -// __int64 CZipFile::Seek(__int64 dOff, UINT nFrom) -// { -// ASSERT_VALID(this); -// ASSERT(m_hFile != (UINT)hFileNull); -// ASSERT(nFrom == begin || nFrom == end || nFrom == current); -// ASSERT(begin == FILE_BEGIN && end == FILE_END && current == FILE_CURRENT); -// LARGE_INTEGER li; -// li.QuadPart = dOff; -// -// li.LowPart = ::SetFilePointer((HANDLE)m_hFile, li.LowPart, &li.HighPart, -// (DWORD)nFrom); DWORD dw = GetLastError(); if ((li.LowPart == (DWORD)-1) && -// (dw != NO_ERROR)) -// { -// CFileException::ThrowOsError((LONG)dw); -// } -// -// return li.QuadPart; -// } diff --git a/src/smpackagee/ZipArchive/mfc/ZipFile.h b/src/smpackagee/ZipArchive/mfc/ZipFile.h deleted file mode 100644 index 04a99d6126..0000000000 --- a/src/smpackagee/ZipArchive/mfc/ZipFile.h +++ /dev/null @@ -1,68 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFile.h $ -// $Archive: /ZipArchive/ZipFile.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_) -#define AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -#include "ZipAbstractFile.h" -#include "ZipExport.h" - -class ZIP_API CZipFile - : public CZipAbstractFile - , public CFile -{ - public: - DECLARE_DYNAMIC(CZipFile) - void Flush() { CFile::Flush(); } - ZIP_ULONGLONG GetPosition() const { return CFile::GetPosition(); } - CZipString GetFilePath() const { return CFile::GetFilePath(); } - void SetLength(ZIP_ULONGLONG nNewLen) { CFile::SetLength(nNewLen); } - UINT Read(void* lpBuf, UINT nCount) { return CFile::Read(lpBuf, nCount); } - void Write(const void* lpBuf, UINT nCount) { CFile::Write(lpBuf, nCount); } - ZIP_ULONGLONG Seek(ZIP_LONGLONG lOff, int nFrom) - { - return CFile::Seek(lOff, nFrom); - } - ZIP_ULONGLONG GetLength() const { return CFile::GetLength(); } - bool Open(LPCTSTR lpszFileName, UINT nOpenFlags, bool bThrowExc) - { - CFileException* e = new CFileException; - bool bRet = CFile::Open(lpszFileName, nOpenFlags, e) != 0; - if (!bRet && bThrowExc) - throw e; - e->Delete(); - return bRet; - } - CZipFile(); - bool IsClosed() const { return m_hFile == CFile::hFileNull; } - - CZipFile(LPCTSTR lpszFileName, UINT nOpenFlags) - : CFile(lpszFileName, nOpenFlags) - { - } - void Close() - { - if (!IsClosed()) - CFile::Close(); - } - operator HANDLE(); - virtual ~CZipFile(); -}; - -#endif // !defined(AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/mfc/ZipString.h b/src/smpackagee/ZipArchive/mfc/ZipString.h deleted file mode 100644 index ea2b7fe729..0000000000 --- a/src/smpackagee/ZipArchive/mfc/ZipString.h +++ /dev/null @@ -1,37 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipString.h $ -// $Archive: /ZipArchive/ZipString.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ZIPSTRING_DOT_H -#define ZIPSTRING_DOT_H -#include "ZipExport.h" -#include "stdafx.h" - -typedef CString CZipString; - -/** - A poiter type to point to CZipString to Collate or CollateNoCase - or Compare or CompareNoCase -*/ -typedef int (CZipString::*ZIPSTRINGCOMPARE)(LPCTSTR) const; - -/** - return a pointer to the function in CZipString structure, - used to compare elements depending on the arguments -*/ -ZIP_API ZIPSTRINGCOMPARE -GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate = true); - -#endif /* ZIPSTRING_DOT_H */ diff --git a/src/smpackagee/ZipArchive/mfc/stdafx.h b/src/smpackagee/ZipArchive/mfc/stdafx.h deleted file mode 100644 index 3048192819..0000000000 --- a/src/smpackagee/ZipArchive/mfc/stdafx.h +++ /dev/null @@ -1,48 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////// -// $Workfile: stdafx.h $ -// $Archive: /ZipArchive/stdafx.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) -#define AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#if _MSC_VER < 1300 && !defined __BORLANDC__ -#define ZIPINLINE inline -#else -#define ZIPINLINE -#endif - -#if _MSC_VER >= 1300 -#define ZIP_ULONGLONG ULONGLONG -#define ZIP_LONGLONG LONGLONG -#else -#define ZIP_ULONGLONG DWORD -#define ZIP_LONGLONG LONG -#endif - -#define ZIP_ARCHIVE_MFC - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#include -#include - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/resource.h b/src/smpackagee/ZipArchive/resource.h deleted file mode 100644 index c7ea44ab06..0000000000 --- a/src/smpackagee/ZipArchive/resource.h +++ /dev/null @@ -1,15 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by version.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/src/smpackagee/ZipArchive/stl/ZipBaseException.h b/src/smpackagee/ZipArchive/stl/ZipBaseException.h deleted file mode 100644 index 13df362e62..0000000000 --- a/src/smpackagee/ZipArchive/stl/ZipBaseException.h +++ /dev/null @@ -1,22 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipBaseException.h $ -// $Archive: /ZipArchive_STL/ZipBaseException.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef __ZIPBASEEXCEPTION_H__ -#define __ZIPBASEEXCEPTION_H__ - -typedef std::exception CZipBaseException; - -#endif //__ZIPBASEEXCEPTION_H__ diff --git a/src/smpackagee/ZipArchive/stl/ZipCollections.h b/src/smpackagee/ZipArchive/stl/ZipCollections.h deleted file mode 100644 index 8992421fa4..0000000000 --- a/src/smpackagee/ZipArchive/stl/ZipCollections.h +++ /dev/null @@ -1,163 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipCollections.h $ -// $Archive: /ZipArchive_STL/ZipCollections.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef ZIPCOLLECTIONS_DOT_H -#define ZIPCOLLECTIONS_DOT_H - -#if _MSC_VER > 1000 -#pragma warning(push, 3) // STL "requirements" -#pragma warning(disable : 4284) // return type for 'identifier::operator >' is - // not a UDT or reference to a UDT. Will produce - // errors if applied using infix notation -#pragma warning(disable : 4018) //'expression' : signed/unsigned mismatch -#endif - -#include -#include -#include -#include -#include - -#include "ZipExport.h" -#include "ZipString.h" - -template -class CZipArray : private std::vector -{ - public: - typedef std::vector::iterator iterator; - typedef std::vector inherited; - - protected: - iterator GetIterFromIndex(int uIndex) - { - iterator iter = begin(); - iter += uIndex; - // int t = 0; while (t != uIndex) {iter++;t++;} - return iter; - } - - public: - void Sort(bool bAscending) - { - if (bAscending) - std::sort(begin(), end(), std::less()); - else - std::sort(begin(), end(), std::greater()); - } - int GetSize() const { return (int)size(); } - int GetUpperBound() const { return size() - 1; } - int Add(const TYPE& x) - { - push_back(x); - return GetUpperBound(); - } - void RemoveAll() { clear(); } - void RemoveAt(int uIndex) { erase(GetIterFromIndex(uIndex)); } - void InsertAt(int uIndex, const TYPE& x) - { - insert(GetIterFromIndex(uIndex), x); - } -#ifndef _MSC_VER - TYPE& operator[](int iIndex) { return inherited::operator[](iIndex); } - TYPE operator[](int iIndex) const { return inherited::operator[](iIndex); } -#else - using inherited::operator[]; -#endif -}; - -typedef CZipArray CZipStringArray; -typedef CZipArray CZipWordArray; - -template -class ZIP_API CZipPtrList : private std::list -{ - - public: - typedef std::list::iterator iterator; - typedef std::list::const_iterator const_iterator; - int GetCount() const { return size(); } - void AddTail(const TYPE& x) { push_back(x); } - void AddHead(const TYPE& x) { push_front(x); } - void RemoveHead() { pop_front(); } - void RemoveTail() { pop_back(); } - void RemoveAll() { clear(); } - TYPE& GetHead() { return front(); } - TYPE GetHead() const { return front(); } - TYPE& GetTail() { return back(); } - TYPE GetTail() const { return back(); } - iterator GetHeadPosition() { return begin(); } - const_iterator GetHeadPosition() const { return begin(); } - iterator GetTailPosition() { return back(); } - TYPE& GetNext(iterator& pos) { return *pos++; } - const TYPE GetNext(const_iterator& pos) const { return *pos++; } - TYPE& GetPrev(iterator& pos) { return *pos--; } - TYPE GetPrev(iterator& pos) const { return *pos--; } - iterator Find(TYPE& x) { return std::find(begin(), end(), x); } - void RemoveAt(iterator& pos) { erase(pos); } - bool IteratorValid(const_iterator& iter) const { return iter != end(); } - bool IteratorValid(iterator& iter) { return iter != end(); } - iterator FindIndex(int iIndex) - { - iterator iter = begin(); - int t = 0; - while (t != iIndex) { - iter++; - t++; - } - return iter; - } - const_iterator FindIndex(int iIndex) const - { - const_iterator iter = begin(); - int t = 0; - while (t != iIndex) { - iter++; - t++; - } - return iter; - } - TYPE& GetAt(const iterator& pos) { return *pos; } - TYPE GetAt(const_iterator& pos) const { return *pos; } -}; - -// simplified and partial only -template -class ZIP_API CZipMap : private std::map -{ - public: - void SetAt(KEY key, VALUE newValue) - { - insert(std::map::value_type(key, newValue)); - } - BOOL RemoveKey(KEY key) { return erase(key) != 0; } - BOOL Lookup(KEY key, VALUE& rValue) const - { - const_iterator iter = find(key); - if (iter == end()) - return FALSE; - else { - rValue = iter->second; - return TRUE; - } - } -}; - -#if defined(_MSC_VER) && (_MSC_VER > 1100) -#pragma warning(pop) -#endif - -#endif /* ZIPCOLLECTIONS_DOT_H */ diff --git a/src/smpackagee/ZipArchive/stl/ZipFile.cpp b/src/smpackagee/ZipArchive/stl/ZipFile.cpp deleted file mode 100644 index 9b4c8dc0de..0000000000 --- a/src/smpackagee/ZipArchive/stl/ZipFile.cpp +++ /dev/null @@ -1,109 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFile.cpp $ -// $Archive: /ZipArchive_STL/ZipFile.cpp $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#include "ZipFile.h" -#include "ZipException.h" -#include "ZipPlatform.h" -#include "stdafx.h" - -#include - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -CZipFile::CZipFile() -{ - m_hFile = -1; -} - -void -CZipFile::ThrowError() const -{ - CZipException::Throw(errno, m_szFileName); -} - -ZIP_ULONGLONG -CZipFile::GetLength() const -{ - // cannot use Seek here, Seek is not const - long lLen, lCur; - lCur = lseek(m_hFile, 0, current); - if (lCur == -1) - ThrowError(); - lLen = lseek(m_hFile, 0, end); - // first get back - lseek(m_hFile, lCur, begin); - if (lLen == -1) - ThrowError(); - return lLen; -} - -bool -CZipFile::Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow) -{ - if (!IsClosed()) - Close(); -#ifndef __GNUC__ - UINT iNewFlags = O_BINARY; -#else - UINT iNewFlags = 0; -#endif - bool bReadOnly = false; - if (openFlags & CZipFile::modeCreate) - iNewFlags |= O_CREAT; - if ((openFlags & CZipFile::modeReadWrite) == CZipFile::modeReadWrite) - iNewFlags |= O_RDWR; - else if (openFlags & CZipFile::modeRead) { - // O_RDONLY is defined as 0 - bReadOnly = true; - iNewFlags |= O_RDONLY; - } else if (openFlags & CZipFile::modeWrite) - iNewFlags |= O_WRONLY; - - if (!(openFlags & CZipFile::modeNoTruncate) && !bReadOnly) - iNewFlags |= O_TRUNC; - - m_hFile = ZipPlatform::OpenFile(lpszFileName, iNewFlags, openFlags & 0x1C); - if (m_hFile == -1) - if (bThrow) - ThrowError(); - else - return false; - m_szFileName = lpszFileName; - return true; -} - -void -CZipFile::SetLength(ZIP_ULONGLONG nNewLen) -{ - ZipPlatform::TruncateFile(m_hFile, (DWORD)nNewLen); -} - -void -CZipFile::Flush() -{ - if (!ZipPlatform::FlushFile(m_hFile)) - ThrowError(); -} - -CZipFile::operator HANDLE() -{ - int fh = ZipPlatform::GetFileSystemHandle(m_hFile); - if (fh == -1) - ThrowError(); - return (HANDLE)fh; -} diff --git a/src/smpackagee/ZipArchive/stl/ZipFile.h b/src/smpackagee/ZipArchive/stl/ZipFile.h deleted file mode 100644 index 2c03923154..0000000000 --- a/src/smpackagee/ZipArchive/stl/ZipFile.h +++ /dev/null @@ -1,115 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipFile.h $ -// $Archive: /ZipArchive_STL/ZipFile.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_) -#define AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "ZipAbstractFile.h" -#include "ZipExport.h" -#include "ZipString.h" - -#ifndef __GNUC__ -#include -#else -#include -#include -#endif - -class ZIP_API CZipFile : public CZipAbstractFile -{ - void ThrowError() const; - - public: - int m_hFile; - operator HANDLE(); - enum OpenModes - { - modeRead = 0x0001, - modeWrite = 0x0002, - modeReadWrite = modeRead | modeWrite, - shareDenyWrite = 0x0004, - shareDenyRead = 0x0008, - shareDenyNone = 0x0010, - modeCreate = 0x0020, - modeNoTruncate = 0x0040, - }; - - CZipFile(LPCTSTR lpszFileName, UINT openFlags) - { - m_hFile = -1; - Open(lpszFileName, openFlags, true); - } - void Flush(); - ZIP_ULONGLONG GetLength() const; - CZipString GetFilePath() const { return m_szFileName; } - bool IsClosed() const { return m_hFile == -1; } - bool Open(LPCTSTR lpszFileName, UINT openFlags, bool bThrow); - void Close() - { - if (IsClosed()) - return; - - if (close(m_hFile) != 0) - ThrowError(); - else { - m_szFileName.empty(); - m_hFile = -1; - } - } - void Write(const void* lpBuf, UINT nCount) - { - if (write(m_hFile, lpBuf, nCount) != (int)nCount) - ThrowError(); - } - ZIP_ULONGLONG GetPosition() const - { -#ifndef __GNUC__ - long ret = tell(m_hFile); -#else - long ret = lseek(m_hFile, 0, SEEK_CUR); -#endif - if (ret == -1L) - ThrowError(); - return ret; - } - void SetLength(ZIP_ULONGLONG nNewLen); - UINT Read(void* lpBuf, UINT nCount) - { - errno = 0; - int ret = read(m_hFile, lpBuf, nCount); - if (ret < (int)nCount && errno != 0) - ThrowError(); - return ret; - } - ZIP_ULONGLONG Seek(ZIP_LONGLONG dOff, int nFrom) - { - long ret = lseek(m_hFile, (long)dOff, nFrom); - if (ret == -1) - ThrowError(); - return ret; - } - CZipFile(); - virtual ~CZipFile() { Close(); }; - - protected: - CZipString m_szFileName; -}; - -#endif // !defined(AFX_ZIPFILE_H__80609DE0_2C6D_4C94_A90C_0BE34A50C769__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/stl/ZipString.h b/src/smpackagee/ZipArchive/stl/ZipString.h deleted file mode 100644 index 02e6a410a2..0000000000 --- a/src/smpackagee/ZipArchive/stl/ZipString.h +++ /dev/null @@ -1,276 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: ZipString.h $ -// $Archive: /ZipArchive_STL/ZipString.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifndef __ZIPSTRING_H__ -#define __ZIPSTRING_H__ -#include "stdafx.h" - -#if defined(_MSC_VER) && (_MSC_VER > 1100) -#pragma warning(push, 3) // STL requrements -#endif - -/** - If you wish the class to respect your locale (if it is different from - English), you need to set it in your program with function - std::locale::global(std::locale("")) (to set it to be the same as your - system locale) or e.g. std::locale::global(std::locale("French")) - ( to set it to a specified value); setlocale() function is not sufficient - here. -*/ - -#include "ZipExport.h" -#include -#include -#include -#include - -#ifndef __GNUC__ -#ifndef _vsntprintf -#ifdef _UNICODE -#define _vsntprintf _vsnwprintf -#else -#define _vsntprintf _vsnprintf -#endif -#endif -#include -#else -#define _vsntprintf vsnprintf -#endif - -typedef std::basic_string stdbs; -/** - This is not a full MFC - CString replacement. - For now it contains mostly the methods required by ZipArchive library. -*/ -class ZIP_API CZipString : public stdbs -{ - void TrimInternalL(size_type iPos) - { - if (iPos == npos) - erase(); - if (iPos) - erase(0, iPos); - } - void TrimInternalR(size_type iPos) - { - if (iPos == npos) - erase(); - erase(++iPos); - } -#ifndef __GNUC__ - static int zslen(const TCHAR* lpsz) - { - return lpsz ? (int)std::char_traits::length(lpsz) : 0; - } - static TCHAR tl(TCHAR c) { return std::tolower(c, std::locale()); } - static TCHAR tu(TCHAR c) { return std::toupper(c, std::locale()); } -#else - static int zslen(const TCHAR* lpsz) - { - return lpsz ? std::string_char_traits::length(lpsz) : 0; - } -#endif - - public: - CZipString() {} - explicit CZipString(TCHAR ch, int nRepeat = 1) - : stdbs(nRepeat, ch) - { - } - CZipString(const CZipString& stringSrc) { assign(stringSrc); } - CZipString(const stdbs& stringSrc) { assign(stringSrc); } - CZipString(LPCTSTR lpsz) - { - if (!lpsz) - Empty(); - else - assign(lpsz); - } - operator LPCTSTR() const { return c_str(); } - - int GetLength() const { return (int)size(); } - bool IsEmpty() const { return empty(); } - void Empty() { erase(begin(), end()); } - TCHAR GetAt(int iIndex) const { return at(iIndex); } - TCHAR operator[](int iIndex) const { return at(iIndex); } - void SetAt(int nIndex, TCHAR ch) { at(nIndex) = ch; } - LPTSTR GetBuffer(int nMinBufLength) - { - if ((int)size() < nMinBufLength) - resize(nMinBufLength); - return empty() ? const_cast(data()) : &(at(0)); - } - void ReleaseBuffer(int nNewLength = -1) - { - resize(nNewLength > -1 ? nNewLength : zslen(c_str())); - } - void TrimLeft(TCHAR chTarget) - { - TrimInternalL(find_first_not_of(chTarget)); - } - void TrimLeft(LPCTSTR lpszTargets) - { - TrimInternalL(find_first_not_of(lpszTargets)); - } - void TrimRight(TCHAR chTarget) - { - TrimInternalR(find_last_not_of(chTarget)); - } - void TrimRight(LPCTSTR lpszTargets) - { - TrimInternalR(find_last_not_of(lpszTargets)); - } - void Format(LPCTSTR lpszFormat, ...) - { - va_list arguments; - va_start(arguments, lpszFormat); - TCHAR* pBuf = NULL; - int iCounter = 1, uTotal = 0; - do { - int nLen = sizeof(TCHAR) * iCounter * 1024; - pBuf = (TCHAR*)realloc((void*)pBuf, nLen); - if (!pBuf) - return; - uTotal = _vsntprintf(pBuf, nLen - 1, lpszFormat, arguments); - if (uTotal == -1 || - (uTotal == nLen - 1)) // for some implementations - { - pBuf[nLen - 1] = _T('\0'); - if (iCounter == 7) - break; - } else { - pBuf[uTotal] = _T('\0'); - break; - } - - } while (true); - - va_end(arguments); - *this = pBuf; - free(pBuf); - } - void Insert(int nIndex, LPCTSTR pstr) { insert(nIndex, pstr, zslen(pstr)); } - void Insert(int nIndex, TCHAR ch) { insert(nIndex, 1, ch); } - int Delete(int nIndex, int nCount = 1) - { - int iSize = (int)size(); - int iToDelete = iSize < nIndex + nCount ? iSize - nIndex : nCount; - if (iToDelete > 0) { - erase(nIndex, iToDelete); - iSize -= iToDelete; - } - return iSize; - } - void MakeLower() - { -#ifndef __GNUC__ - // use_facet doesn't work here well (doesn't convert all the local - // characters properly) - std::transform(begin(), end(), begin(), tl); -#else - - std::transform(begin(), end(), begin(), tolower); -#endif - } - void MakeUpper() - { -#ifndef __GNUC__ - // use_facet doesn't work here well (doesn't convert all the local - // characters properly) - std::transform(begin(), end(), begin(), tu); -#else - std::transform(begin(), end(), begin(), toupper); -#endif - } - void MakeReverse() { std::reverse(begin(), end()); } - CZipString Left(int nCount) const { return substr(0, nCount); } - CZipString Right(int nCount) const - { - nCount = (int)size() < nCount ? (int)size() : nCount; - return substr(size() - nCount); - } - CZipString Mid(int nFirst) const { return substr(nFirst); } - CZipString Mid(int nFirst, int nCount) const - { - return substr(nFirst, nCount); - } - int Collate(LPCTSTR lpsz) const - { -#ifndef __GNUC__ -#ifdef _UNICODE - return wcscoll(c_str(), lpsz); -#else - return strcoll(c_str(), lpsz); -#endif -#else - // return compare(lpsz); - return strcoll(c_str(), lpsz); -#endif - } - int CollateNoCase(LPCTSTR lpsz) const - { - CZipString s1(c_str()), s2(lpsz); - s1.MakeLower(); - s2.MakeLower(); - return s1.Collate(s2); - } - int Compare(LPCTSTR lpsz) const { return compare(lpsz); } - int CompareNoCase(LPCTSTR lpsz) const - { - CZipString s1(c_str()), s2(lpsz); - s1.MakeLower(); - s2.MakeLower(); - return s1.Compare(s2); - } - bool operator!=(LPCTSTR lpsz) { return Compare(lpsz) != 0; } - bool operator==(LPCTSTR lpsz) { return Compare(lpsz) == 0; } - int Find(TCHAR ch, int nStart = 0) const { return (int)find(ch, nStart); } - - int Find(LPCTSTR pstr, int nStart = 0) const - { - return (int)find(pstr, nStart); - } - - int Replace(TCHAR chOld, TCHAR chNew) - { - int iCount = 0; - for (iterator it = begin(); it != end(); ++it) - if (*it == chOld) { - *it = chNew; - iCount++; - } - return iCount; - } -}; - -/** - A poiter type to point to CZipString to Collate or CollateNoCase - or Compare or CompareNoCase -*/ -typedef int (CZipString::*ZIPSTRINGCOMPARE)(LPCTSTR) const; - -/** - return a pointer to the function in CZipString structure, - used to compare elements depending on the arguments -*/ -ZIP_API ZIPSTRINGCOMPARE -GetCZipStrCompFunc(bool bCaseSensitive, bool bCollate = true); - -#if defined(_MSC_VER) && (_MSC_VER > 1100) -#pragma warning(pop) -#endif - -#endif //__ZIPSTRING_H__ diff --git a/src/smpackagee/ZipArchive/stl/stdafx.h b/src/smpackagee/ZipArchive/stl/stdafx.h deleted file mode 100644 index cd7eeeff08..0000000000 --- a/src/smpackagee/ZipArchive/stl/stdafx.h +++ /dev/null @@ -1,125 +0,0 @@ -//////////////////////////////////////////////////////////////////////////////// -// $Workfile: stdafx.h $ -// $Archive: /ZipArchive_STL/stdafx.h $ -// $Date: 2003-07-21 21:10:30 -0500 (Mon, 21 Jul 2003) $ $Author: gmaynard $ -//////////////////////////////////////////////////////////////////////////////// -// This source file is part of the ZipArchive library source distribution and -// is Copyright 2000-2003 by Tadeusz Dracz (http://www.artpol-software.com/) -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) -#define AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_ - -#if (_MSC_VER < 1300) && !defined(__BORLANDC__) && !defined(__GNUC__) -#define ZIPINLINE inline -#else -#define ZIPINLINE -#endif - -#define ZIP_ARCHIVE_STL - -#if _MSC_VER > 1000 -#pragma once -// because of STL -#pragma warning(disable : 4710) // 'function' : function not inlined -#pragma warning( \ - disable : 4514) // unreferenced inline/local function has been removed -#pragma warning( \ - disable : 4786) // 'identifier' : identifier was truncated to 'number' - // characters in the debug information -#endif // _MSC_VER > 1000 - -// some Windows typical definitions - -#if defined(_UNICODE) && !defined(UNICODE) -#define UNICODE -#endif -#if defined(UNICODE) && !defined(_UNICODE) -#define _UNICODE -#endif - -#ifndef _WIN32 -#ifndef NULL -#define NULL 0 -#endif - -#include -typedef int HFILE; -typedef void* HANDLE; -typedef unsigned long DWORD; -typedef long LONG; -typedef int BOOL; -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned int UINT; - -#ifndef FALSE -#define FALSE (int)0 -#endif - -#ifndef TRUE -#define TRUE (int)1 -#endif - -typedef unsigned short WCHAR; // wc, 16-bit UNICODE character -typedef const WCHAR* LPCWSTR; -typedef const char* LPCSTR; -typedef WCHAR* LPWSTR; -typedef char* LPSTR; - -#ifdef _UNICODE -typedef wchar_t TCHAR; -typedef LPCWSTR LPCTSTR; -typedef LPWSTR LPTSTR; -#define _T(x) L##x -#else /* _UNICODE */ // r_winnt -typedef char TCHAR; -typedef LPCSTR LPCTSTR; -typedef LPSTR LPTSTR; -#define _T(x) x -#endif /* _UNICODE */ // r_winnt - -#else -#include -#include -#ifndef STRICT -#define STRICT -#endif -#endif // #ifndef _WIN32 - -#ifndef ASSERT -#include -#define ASSERT(f) assert((f)) -#endif -#ifndef VERIFY -#ifdef _DEBUG -#define VERIFY(x) ASSERT((x)) -#else -#define VERIFY(x) x -#endif -#endif - -#ifndef TRACE -#define TRACE -#endif - -#if _MSC_VER >= 1300 -#define ZIP_ULONGLONG ULONGLONG -#define ZIP_LONGLONG LONGLONG -#else -#define ZIP_ULONGLONG DWORD -#define ZIP_LONGLONG LONG -#endif - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_STDAFX_H__926F70F4_1B34_49AA_9532_498E8D2F3495__INCLUDED_) diff --git a/src/smpackagee/ZipArchive/stl/zippie/CmdLine.cpp b/src/smpackagee/ZipArchive/stl/zippie/CmdLine.cpp deleted file mode 100644 index 05c59ca2ce..0000000000 --- a/src/smpackagee/ZipArchive/stl/zippie/CmdLine.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/*------------------------------------------------------ - CCmdLine - - A utility for parsing command lines. - - Copyright (C) 1999 Chris Losinger, Smaller Animals Software. - http://www.smalleranimals.com - - This software is provided 'as-is', without any express - or implied warranty. In no event will the authors be - held liable for any damages arising from the use of this software. - - Permission is granted to anyone to use this software - for any purpose, including commercial applications, and - to alter it and redistribute it freely, subject to the - following restrictions: - - 1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment - in the product documentation would be appreciated but is not required - 2. Altered source versions must be plainly marked as such, - and must not be misrepresented as being the original software - 3. This notice may not be removed or altered from any source - distribution - See SACmds.h for more info. -------------------------------------------------------*/ - -// if you're using MFC, you'll need to un-comment this line - -#include "CmdLine.h" -//#include "crtdbg.h" - -/*------------------------------------------------------ - int CCmdLine::SplitLine(int argc, char **argv) - - parse the command line into switches and arguments - - returns number of switches found -------------------------------------------------------*/ -int -CCmdLine::SplitLine(int argc, char** argv) -{ - clear(); - - StringType curParam; // current argv[x] - - // skip the exe name (start with i = 1) - for (int i = 1; i < argc; i++) { - // if it's a switch, start a new CCmdLine - if (IsSwitch(argv[i])) { - curParam = argv[i]; - - StringType arg; - - // look at next input string to see if it's a switch or an argument - if (i + 1 < argc) { - if (!IsSwitch(argv[i + 1])) { - // it's an argument, not a switch - arg = argv[i + 1]; - - // skip to next - i++; - } else { - arg = ""; - } - } - - // add it - CCmdParam cmd; - cmd.m_strings.push_back(arg); - - // add the CCmdParam to 'this' - pair res = - insert(CCmdLine::value_type(curParam, cmd)); - } else { - // it's not a new switch, so it must be more stuff for the last - // switch - - // ...let's add it - CCmdLine::iterator theIterator; - - // get an iterator for the current param - theIterator = find(curParam); - if (theIterator != end()) { - (*theIterator).second.m_strings.push_back(argv[i]); - } else { - // ?? - } - } - } - - return size(); -} - -/*------------------------------------------------------ - - protected member function - test a parameter to see if it's a switch : - - switches are of the form : -x - where 'x' is one or more characters. - the first character of a switch must be non-numeric! - -------------------------------------------------------*/ - -bool -CCmdLine::IsSwitch(const char* pParam) -{ - if (pParam == NULL) - return false; - - // switches must non-empty - // must have at least one character after the '-' - int len = strlen(pParam); - if (len <= 1) { - return false; - } - - // switches always start with '-' - if (pParam[0] == '-') { - // allow negative numbers as arguments. - // ie., don't count them as switches - return (!isdigit(pParam[1])); - } else { - return false; - } -} - -/*------------------------------------------------------ - bool CCmdLine::HasSwitch(const char *pSwitch) - - was the switch found on the command line ? - - ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 - - call return - ---- ------ - cmdLine.HasSwitch("-a") true - cmdLine.HasSwitch("-z") false -------------------------------------------------------*/ - -bool -CCmdLine::HasSwitch(const char* pSwitch) -{ - CCmdLine::iterator theIterator; - theIterator = find(pSwitch); - return (theIterator != end()); -} - -/* - - StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const -char *pDefault) - - fetch an argument associated with a switch . if the parameter at - index iIdx is not found, this will return the default that you - provide - example: - command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 - call return - ---- ------ - cmdLine.GetSafeArgument("-a", 0, "zz") p1 - cmdLine.GetSafeArgument("-a", 1, "zz") p2 - cmdLine.GetSafeArgument("-b", 0, "zz") p4 - cmdLine.GetSafeArgument("-b", 1, "zz") zz - -*/ - -StringType -CCmdLine::GetSafeArgument(const char* pSwitch, int iIdx, const char* pDefault) -{ - StringType sRet; - - if (pDefault != NULL) - sRet = pDefault; - - try { - sRet = GetArgument(pSwitch, iIdx); - } catch (...) { - } - - return sRet; -} - -/* - - StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx) - - fetch a argument associated with a switch. throws an exception - of (int)0, if the parameter at index iIdx is not found. - - example: - command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 - - call return - ---- ------ - cmdLine.GetArgument("-a", 0) p1 - cmdLine.GetArgument("-b", 1) throws (int)0, returns an empty string - -*/ - -StringType -CCmdLine::GetArgument(const char* pSwitch, int iIdx) -{ - if (HasSwitch(pSwitch)) { - CCmdLine::iterator theIterator; - - theIterator = find(pSwitch); - if (theIterator != end()) { - if ((*theIterator).second.m_strings.size() > iIdx) { - return (*theIterator).second.m_strings[iIdx]; - } - } - } - - throw(int) 0; - - return ""; -} - -/*------------------------------------------------------ - int CCmdLine::GetArgumentCount(const char *pSwitch) - - returns the number of arguments found for a given switch. - - returns -1 if the switch was not found - -------------------------------------------------------*/ - -int -CCmdLine::GetArgumentCount(const char* pSwitch) -{ - int iArgumentCount = -1; - - if (HasSwitch(pSwitch)) { - CCmdLine::iterator theIterator; - - theIterator = find(pSwitch); - if (theIterator != end()) { - iArgumentCount = (*theIterator).second.m_strings.size(); - } - } - - return iArgumentCount; -} diff --git a/src/smpackagee/ZipArchive/stl/zippie/CmdLine.h b/src/smpackagee/ZipArchive/stl/zippie/CmdLine.h deleted file mode 100644 index b1ad6ec0b0..0000000000 --- a/src/smpackagee/ZipArchive/stl/zippie/CmdLine.h +++ /dev/null @@ -1,234 +0,0 @@ -/*------------------------------------------------------ - CCmdLine - - A utility for parsing command lines. - - Copyright (C) 1999 Chris Losinger, Smaller Animals Software. - http://www.smalleranimals.com - - This software is provided 'as-is', without any express - or implied warranty. In no event will the authors be - held liable for any damages arising from the use of this software. - - Permission is granted to anyone to use this software - for any purpose, including commercial applications, and - to alter it and redistribute it freely, subject to the - following restrictions: - - 1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment - in the product documentation would be appreciated but is not required - 2. Altered source versions must be plainly marked as such, - and must not be misrepresented as being the original software - 3. This notice may not be removed or altered from any source - distribution - ------------------------- - Example: - Our example application uses a command line that has two - required switches and two optional switches. The app should abort - if the required switches are not present and continue with default - values if the optional switches are not present - Sample command line: - MyApp.exe -p1 text1 text2 -p2 "this is a big argument" -opt1 -55 -opt2 - Switches -p1 and -p2 are required - p1 has two arguments and p2 has one - Switches -opt1 and -opt2 are optional - opt1 requires a numeric argument - opt2 has no arguments - Also, assume that the app displays a 'help' screen if the '-h' switch - is present on the command line - #include "CmdLine.h" - - void main(int argc, char **argv) - { - // our cmd line parser object - CCmdLine cmdLine; - - // parse argc,argv - if (cmdLine.SplitLine(argc, argv) < 1) - { - // no switches were given on the command line, abort - ASSERT(0); - exit(-1); - } - - // test for the 'help' case - if (cmdLine.HasSwitch("-h")) - { - show_help(); - exit(0); - } - - // get the required arguments - StringType p1_1, p1_2, p2_1; - try - { - // if any of these fail, we'll end up in the catch() block - p1_1 = cmdLine.GetArgument("-p1", 0); - p1_2 = cmdLine.GetArgument("-p1", 1); - p2_1 = cmdLine.GetArgument("-p2", 0); - - } - catch (...) - { - // one of the required arguments was missing, abort - ASSERT(0); - exit(-1); - } - - // get the optional parameters - - // convert to an int, default to '100' - int iOpt1Val = atoi(cmdLine.GetSafeArgument("-opt1", 0, 100)); - - // since opt2 has no arguments, just test for the presence of - // the '-opt2' switch - bool bOptVal2 = cmdLine.HasSwitch("-opt2"); - - .... and so on.... - - } - - If this class is used in an MFC application, StringType is CString, else - it uses the STL 'string' type. - - If this is an MFC app, you can use the __argc and __argv macros from - you CYourWinApp::InitInstance() function in place of the standard argc - and argv variables. - -------------------------------------------------------*/ -#ifndef SACMDSH -#define SACMDSH - -#if _MSC_VER > 1000 -#pragma once -#pragma warning(disable : 4786) -#pragma warning(disable : 4018) -#endif // _MSC_VER > 1000 - -// #ifdef __AFX_H__ -// // if we're using MFC, use CStrings -// #define StringType CString -// #else -// // if we're not using MFC, use STL strings -// #define StringType string -// #endif -#ifdef __GNUC__ -#include "ZipString.h" -#else -#include "../../ZipString.h" -#endif - -#define StringType CZipString - -//#include // you may need this -#include -#include -#include -using namespace std; - -// handy little container for our argument vector -struct CCmdParam -{ - vector m_strings; -}; - -// this class is actually a map of strings to vectors -typedef map _CCmdLine; - -// the command line parser class -class CCmdLine : public _CCmdLine -{ - - public: - /*------------------------------------------------------ - int CCmdLine::SplitLine(int argc, char **argv) - - parse the command line into switches and arguments. - - returns number of switches found - ------------------------------------------------------*/ - int SplitLine(int argc, char** argv); - - /*------------------------------------------------------ - bool CCmdLine::HasSwitch(const char *pSwitch) - - was the switch found on the command line ? - - ex. if the command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 - - call return - ---- ------ - cmdLine.HasSwitch("-a") true - cmdLine.HasSwitch("-z") false - ------------------------------------------------------*/ - bool HasSwitch(const char* pSwitch); - - /* - - StringType CCmdLine::GetSafeArgument(const char *pSwitch, int iIdx, const - char *pDefault) - - fetch an argument associated with a switch . if the parameter at - index iIdx is not found, this will return the default that you - provide. - - example: - command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 - call return - ---- ------ - cmdLine.GetSafeArgument("-a", 0, "zz") p1 - cmdLine.GetSafeArgument("-a", 1, "zz") p2 - cmdLine.GetSafeArgument("-b", 0, "zz") p4 - cmdLine.GetSafeArgument("-b", 1, "zz") zz - - */ - - StringType GetSafeArgument(const char* pSwitch, - int iIdx, - const char* pDefault); - - /*------------------------------------------------------ - - StringType CCmdLine::GetArgument(const char *pSwitch, int iIdx) - - fetch a argument associated with a switch. throws an exception - of (int)0, if the parameter at index iIdx is not found. - - example: - command line is : app.exe -a p1 p2 p3 -b p4 -c -d p5 - - call return - ---- ------ - cmdLine.GetArgument("-a", 0) p1 - cmdLine.GetArgument("-b", 1) throws (int)0, returns an empty string - - ------------------------------------------------------*/ - StringType GetArgument(const char* pSwitch, int iIdx); - - /*------------------------------------------------------ - int CCmdLine::GetArgumentCount(const char *pSwitch) - - returns the number of arguments found for a given switch. - - returns -1 if the switch was not found - - ------------------------------------------------------*/ - int GetArgumentCount(const char* pSwitch); - - protected: - /*------------------------------------------------------ - - protected member function - test a parameter to see if it's a switch : - - switches are of the form : -x - where 'x' is one or more characters. - the first character of a switch must be non-numeric! - - ------------------------------------------------------*/ - bool IsSwitch(const char* pParam); -}; - -#endif diff --git a/src/smpackagee/ZipArchive/stl/zippie/zippie.cpp b/src/smpackagee/ZipArchive/stl/zippie/zippie.cpp deleted file mode 100644 index 8ff858ebf4..0000000000 --- a/src/smpackagee/ZipArchive/stl/zippie/zippie.cpp +++ /dev/null @@ -1,911 +0,0 @@ -/* - * $Archive: /zippie/zippie.cpp $ - * $Author: gmaynard $ - * - * $History: zippie.cpp $ - * - * ***************** Version 4 ***************** - * User: Tadeusz Dracz Date: 02-04-01 Time: 2:05 - * Updated in $/zippie - * - * ***************** Version 3 ***************** - * User: Tadeusz Dracz Date: 02-01-19 Time: 18:01 - * Updated in $/zippie - * - * ***************** Version 2 ***************** - * User: Tadeusz Dracz Date: 01-11-08 Time: 19:54 - * Updated in $/zippie - * added support for wildcards when extracting or deleting - * - */ -///////////////////////////////////////////////////////////////////////////////// -// zippie.cpp : Defines the entry point for the console application. -// An STL program that uses the ZipArchive library -// -// Copyright (C) 2000 - 2003 Tadeusz Dracz. -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// For the licensing details see the file License.txt -//////////////////////////////////////////////////////////////////////////////// - -#ifdef __GNUC__ -#include "ZipArchive.h" -#include "ZipPlatform.h" -#include -#include -#include -#include -#include -#else -#include "../../ZipArchive.h" -#include "../../ZipPlatform.h" -#endif -#include "CmdLine.h" -#include -#include -#include -#include - -ZIPSTRINGCOMPARE pZipComp; - -struct CZipAddFileInfo -{ - CZipAddFileInfo(const CZipString& szFilePath, - const CZipString& szFileNameInZip) - : m_szFilePath(szFilePath) - , m_szFileNameInZip(szFileNameInZip) - { - int is = szFileNameInZip.GetLength(); - m_iSeparators = 0; - for (int i = 0; i < is; i++) - if (CZipPathComponent::IsSeparator(szFileNameInZip[i])) - m_iSeparators++; - } - CZipString m_szFilePath, m_szFileNameInZip; - - bool CheckOrder(const CZipString& sz1, - const CZipString& sz2, - int iSep1, - int iSep2, - bool bCheckTheBeginning = false) const - { - if (iSep1) { - if (iSep2) { - if (iSep1 == iSep2) - return (sz1.*pZipComp)(sz2) < 0; - - if (bCheckTheBeginning) { - - int is = sz1.GetLength() > sz2.GetLength() - ? sz2.GetLength() - : sz1.GetLength(); - int iSeparators = 0; - // find the common path beginning - int iLastSepPos = -1; - for (int i = 0; i < is; i++) { - CZipString sz = sz2.Mid(i, 1); - if ((sz1.Mid(i, 1).*pZipComp)(sz) != - 0) // must be Mid 'cos of case sens. here - break; - else if (CZipPathComponent::IsSeparator(sz[0])) { - iLastSepPos = i; - iSeparators++; - } - } - - // if necessary remove the common path beginning and check - // again - if (iLastSepPos != -1) - return CheckOrder(sz1.Mid(iLastSepPos), - sz2.Mid(iLastSepPos), - iSep1 - iSeparators, - iSep2 - iSeparators); - } - return (sz1.*pZipComp)(sz2) < 0; - } else - return false; - } else if (iSep2) - return true; - else - return (sz1.*pZipComp)(sz2) < 0; - } - bool operator>(const CZipAddFileInfo& wz) const - { - bool b = CheckOrder(m_szFileNameInZip, - wz.m_szFileNameInZip, - m_iSeparators, - wz.m_iSeparators, - true); - return b; - } - - protected: - int m_iSeparators; // for a sorting puroposes -}; - -typedef list FILELIST; -typedef list::iterator FILELISTIT; -typedef list FILELISTADD; -typedef list::iterator FILELISTADDIT; - -struct AddDirectoryInfo -{ - AddDirectoryInfo(FILELIST& l) - : m_l(l) - { - } - FILELIST& m_l; - CZipString m_lpszFile; - bool m_bRecursive; - bool m_bAddEmpty; -}; - -void -DisplayUsage() -{ - printf("\ -\n\ -Zippie v2.2\n\ -Copyright (C) 2000 - 2003 Tadeusz Dracz\n\ -E-Mail: tdracz@artpol-software.com\n\ -Web : http://www.artpol-software.com\n\ -\n\ -This program is free software; you can redistribute it and/or\n\ -modify it under the terms of the GNU General Public License\n\ -as published by the Free Software Foundation; either version 2\n\ -of the License, or (at your option) any later version.\n\ -\n\ -This is a zipping and unzipping program.\n\ -It was created using ZipArchive library in the STL version.\n\ -\n\ -\n\ -USAGE: zippie \n\ -\n\ -Notes:\n\ - - the order of commands and switches doesn't matter\n\ - - if some files have spaces inside, put them inside quotation marks\n\ -\n\ -************ Default switches ************\n\ -\n\ --f [.zip]\n\ - file to create or open (can be with or without extension)\n\ - the extension .zip is added automatically if not present\n\ --st\n\ - use this switch if you're opening an existing disk spanning archive\n\ - in tdSpan mode on a removable device (or under Linux)\n\ - (doesn't matter for commands that modify the archive \n\ - e.g. add or delete commands)\n\ -\n\ -************ Add files to archive commands ************\n\ -\n\ --a \n\ - add to the ; separate them with spaces;\n\ - you can use wildcards (*?)\n\ --af \n\ - add files listed in (one file per line);\n\ - no wildcards allowed in the files\n\ --ax \n\ - prevent from being added to the ;\n\ - separate them with spaces; you can use wildcards (*?)\n\ --afx \n\ - prevent files listed in (one file per line) to be added \n\ - to the ; no wildcards allowed in the files\n\ -\n\ - you can use switches -a, -af, -ax, -afx simultaneously\n"); - printf("\ -\n\ --r\n\ - recurse subdirectories; don't include in the directories\n\ - from which no file is added; under linux put file masks into \n\ - quotation marks otherwise they will be automatically expaned by \n\ - the shell and the recursion will be one level only\n\ --re\n\ - recurse subdirectories and add all subdirectories even empty to the\n\ - ; see a note above about using file masks under Linux\n\ --u\n\ - this switch tells the program to not delete the if it\n\ - already exists (and if it is not a disk spanning archive), but add\n\ - the to it;\n\ - if this switch is not specified, there is a new archive created\n\ - even if one with the same name already exists (it is overwritten)\n\ --as []\n\ - (add smartly) if this switch is specified, in the disk spanning mode\n\ - the file is first compressed to a temporary directory to see whether \n\ - it is smaller after compression; if it is not it stored then without \n\ - a compression; (you can specify a where the temporary files \n\ - will be created, if you do not specify it, they will be created in \n\ - the directory specified by the TMP system variable or if this variable\n\ - is not defined the file will be created in the current directory;\n\ - in normal archive if there is a such a situation the file is removed\n\ - from the archive and then stored again but with no compression \n\ - (the argument is ignored)\n\ --c \n\ - set the compression level (from 0 to 9);\n\ - if not specified, 5 is assumed\n\ - 0 means no compression - only storing\n\ --v \n\ - create a disk spanning archive\n\ - if is 0 create archive in pkSpan mode,\n\ - if is greater than 0 create archive in tdSpan mode\n\ -\n"); - printf("\ -************ Extract commands ************\n\ -\n\ --xp \n\ - it specifies the path the files will be extracted to; if not present,\n\ - the current path is assumed\n\ --x \n\ - extract to the destination ;\n\ - separate them with spaces; wildcards are allowed\n\ --xr \n\ - extract files with the given to the destination \n\ - separate number with spaces; to specify a range of numbers \n\ - put between them a hyphen without spaces e.g. 3-6; \n\ - put before an exclamation mark to exclude the numbers from the set\n\ - (e.g. 2-20 !6-8 !10);\n\ - (use -lr command to list the files with numbers)\n\ --xf \n\ - extract files listed in (one file per line)\n\ - to the destination ; wildcards are allowed\n\ --xa \n\ - extract all files from the archive to the \n\ -\n\ - you can use switches -x , -xr and -xf (and even -xa) simultaneously\n\ -\n\ -************ Delete commands ************\n\ -\n\ --d \n\ - delete separate them with spaces; wildcards are allowed\n"); - printf("\ --dr \n\ - delete files with the given \n\ - separate number with spaces; to specify a range of numbers \n\ - put between them a hyphen without spaces e.g. 3-6 \n\ - put before an exclamation mark to exclude the numbers from the set\n\ - (e.g. 2-20 !6-8 !10);\n\ - (use -lr command to list the files with numbers)\n\ --df \n\ - delete files listed in (one file per line)\n\ - wildcards are allowed\n\ --da \n\ - delete all the files from the archive\n\ -\n\ - you can use switches -d , -dr and -df (and even -da) simultaneously\n\ -\n\ -************ Other commands ************\n\ -\n\ --t\n\ - test the \n\ --p \n\ - set the when adding files to \n\ - or extracting them; the is set for all the files\n\ - - you cannot set it separately for each file in one session\n\ --l\n\ - list the files inside \n\ --lr\n\ - list the files inside with the numbers\n\ --ll\n\ - list the files inside (only filenames)\n\ - when redirected to a file, it can be used then with command -xf\n\ -\n"); - printf("\ -************ Special switches ************\n\ -\n\ --cs \n\ - enable case sensitivity when:\n\ - - searching for files inside while using the command\n\ - -x or -xf (if not specified a search is non-case-sensitive)\n\ - - adding files to and trying to avoid the same\n\ - filenames in the archive\n\ --g \n\ - Set the global of the \n\ - (cannot be used on an existing disk spanning archive)\n\ - if the contains spaces, put the whole \n\ - inside quotation marks\n\ --rp \n\ - set root (see CZipArchive::SetRootPath() function description)\n\ --nfp\n\ - the same as bFullPath set to false in functions\n\ - CZipArchive::AddNewFile() and CZipArchive::ExtractFile()\n\ - (if not present, bFullPath is assumed to be true; if -rp specified\n\ - bFullPath is always false);\n\ --w\n\ - Wait for a key after finishing the work to let the user read the output\n\ - in some environments\n\ --dse\n\ - Display only errors when adding or extracting files\n\ -\n\ -************ Sample commands ************\n\ -\n\ -zippie -f a:\\archive -a * -v 0 -as -c 9 \n\ - (create a disk spanning archive adding all the files from the current \n\ - directory, smart add is used, compression level set to maximum)\n\ -\n\ -zippie -f a:\\archive -xp d:\\a -x zippie.cpp -xr 2-12 !5-7 !9\n\ - (extract file zippie.cpp from the archive and the files with numbers \n\ - from 2 to 12 and the file number 15 apart from 5 to 7 and 9)\n\ -\n\ -zippie -f example -xa\n\ - extract all files from example.zip file to the current directory\n\ -\n\ -"); -} - -char -ReadKey() -{ - fflush(stdin); - char c = (char)tolower(getchar()); - return c; -} - -struct SpanCallback : public CZipSpanCallback -{ - bool Callback(int iProgress) - { - printf("Insert disk number %d and hit ENTER to contuniue \n or press " - "'n' key followed by ENTER to abort (code = %d)\n", - m_uDiskNeeded, - iProgress); - return ReadKey() != 'n'; - } -}; - -void -FillFromFile(FILELIST& l, LPCTSTR lpszFile, bool bCheck) -{ - FILE* f = fopen(lpszFile, "rt"); - if (!f) { - printf("File %s could not be opened\n", lpszFile); - return; - } - fseek(f, 0, SEEK_END); - int iSize = ftell(f); - fseek(f, 0, SEEK_SET); - CZipAutoBuffer buf(iSize + 1); - iSize = fread(buf, 1, iSize, f); - fclose(f); - char* sEnd = buf + iSize; - char* sBeg = buf; - for (char* pos = buf;; pos++) { - bool bEnd = pos == sEnd; // there may be no newline at the end - if (strncmp(pos, "\n", 1) == 0 || bEnd) { - *pos = '\0'; - CZipString s = sBeg; - s.TrimLeft(" "); - s.TrimRight(" "); - if (!s.IsEmpty() && (!bCheck || ZipPlatform::FileExists(s) != 0)) - l.push_back(s); - if (bEnd) - break; - sBeg = pos + 1; - } - } -} - -bool -IsDots(LPCTSTR lpsz) -{ - return strcmp(lpsz, ".") == 0 || strcmp(lpsz, "..") == 0; -} - -void -AddDirectory(CZipString szPath, struct AddDirectoryInfo& info, bool bDoNotAdd) -{ - if (!szPath.IsEmpty()) - CZipPathComponent::AppendSeparator(szPath); - - bool bPathAdded = info.m_bAddEmpty || bDoNotAdd; - if (info.m_bAddEmpty && !szPath.IsEmpty() && !bDoNotAdd) - info.m_l.push_back(szPath); - -#ifdef __GNUC__ - DIR* dp = opendir(szPath.IsEmpty() ? "." : szPath); - if (!dp) - return; - struct dirent* entry; - while (entry = readdir(dp)) { - struct stat sStats; - CZipString szFullFileName = szPath + entry->d_name; - if (stat(szFullFileName, &sStats) == -1) - continue; - if (S_ISDIR(sStats.st_mode)) { - if (info.m_bRecursive) { - if (IsDots(entry->d_name)) - continue; - - AddDirectory(szFullFileName, info, false); - } - } else if (fnmatch(info.m_lpszFile, - entry->d_name, - FNM_NOESCAPE | FNM_PATHNAME) == 0) { - if (!bPathAdded) { - if (!szPath.IsEmpty()) - info.m_l.push_back(szPath); - bPathAdded = true; - } - info.m_l.push_back(szPath + entry->d_name); - } - } - closedir(dp); - -#else - CZipString szFullFileName = szPath + info.m_lpszFile; - struct _finddata_t c_file; - long hFile; - if ((hFile = _findfirst(szFullFileName, &c_file)) != -1L) { - do { - if (!(c_file.attrib & FILE_ATTRIBUTE_DIRECTORY)) { - // add it when the first file comes - if (!bPathAdded) { - if (!szPath.IsEmpty()) - info.m_l.push_back(szPath); - bPathAdded = true; - } - info.m_l.push_back(szPath + c_file.name); - } - } while (_findnext(hFile, &c_file) == 0L); - } - _findclose(hFile); - - if (info.m_bRecursive) { - szFullFileName = szPath + "*"; - if ((hFile = _findfirst(szFullFileName, &c_file)) != -1L) { - do { - if (c_file.attrib & FILE_ATTRIBUTE_DIRECTORY) { - if (IsDots(c_file.name)) - continue; - szFullFileName = szPath + c_file.name; - AddDirectory(szFullFileName, info, false); - } - } while (_findnext(hFile, &c_file) == 0L); - } - _findclose(hFile); - } -#endif -} - -void -ExpandFile(FILELIST& l, - LPCTSTR lpszPath, - bool bRecursive, - bool bAddEmpty, - bool bFullPath) -{ - // check if we need to expand it - // size_t pos = strcspn(lpszFile, "*?"); - // if (pos == strlen(lpszFile)) - // { - // l.push_back(lpszFile); - // return; - // } - - CZipPathComponent zpc(lpszPath); - CZipString szDir = zpc.GetFilePath(); - // if (szDir.IsEmpty()) - // if (!ZipPlatform::GetCurrentDirectory(szDir)) - // return; - struct AddDirectoryInfo adi(l); - adi.m_bAddEmpty = bAddEmpty; - adi.m_bRecursive = bRecursive; - adi.m_lpszFile = zpc.GetFileName(); - AddDirectory(szDir, adi, !bFullPath); // when not full path is specified for - // a single file with a path, do not - // add a directory then -} - -void -FindInZip(CZipArchive& zip, FILELIST& l, CZipWordArray& n) -{ - - for (FILELISTIT it = l.begin(); it != l.end(); ++it) - zip.FindMatches(*it, n); -} - -void -ProcessData(CZipArchive& zip, - CCmdLine& cmd, - CZipWordArray& vRevised, - bool bExtract) -{ - - if (cmd.HasSwitch(bExtract ? "-xa" : "-da")) { - int iMax = zip.GetCount(); - for (int i = 0; i < iMax; i++) - vRevised.Add(i); - } else { - CZipWordArray numbers; - CZipString temp = bExtract ? "-x" : "-d"; - int iCount = cmd.GetArgumentCount(temp); - if (iCount > 0) { - FILELIST lFiles; - for (int i = 0; i < iCount; i++) - lFiles.push_back(cmd.GetArgument(temp, i)); - FindInZip(zip, lFiles, numbers); - } - temp = bExtract ? "-xf" : "-df"; - if (cmd.GetArgumentCount(temp) > 0) { - FILELIST lFiles; - FillFromFile(lFiles, cmd.GetArgument(temp, 0), false); - FindInZip(zip, lFiles, numbers); - } - - temp = bExtract ? "-xr" : "-dr"; - iCount = cmd.GetArgumentCount(temp); - CZipWordArray notNumbers; - if (iCount > 0) { - for (int i = 0; i < iCount; i++) { - CZipString sz = cmd.GetArgument(temp, i); - bool bNot = !sz.IsEmpty() && sz[0] == '!'; - CZipWordArray& vN = bNot ? notNumbers : numbers; - if (bNot) - sz.TrimLeft('!'); - size_t pos = strcspn(sz, "-"); - if (pos == sz.GetLength()) - vN.Add(atoi(sz) - 1); - else { - int b = atoi(sz.Left(pos)); - int e = atoi(sz.Mid(pos + 1)); - for (int i = b; i <= e; i++) - vN.Add(i - 1); - } - } - } - int iSize = notNumbers.GetSize(); - if (iSize) { - for (int j = 0; j < iSize; ++j) - for (int i = numbers.GetSize(); i >= 0; i--) - if (numbers[i] == notNumbers[j]) - numbers.RemoveAt(i); - } - - int iMax = zip.GetCount() - 1; - for (int i = 0; i < numbers.GetSize(); ++i) { - int x = numbers[i]; - if (x < 0 || x > iMax) - continue; - bool bNew = true; - for (int j = 0; j < vRevised.GetSize(); ++j) - if (vRevised[j] == numbers[i]) { - bNew = false; - break; - } - if (bNew) - vRevised.Add(x); - } - } -} - -int -main(int argc, char* argv[]) -{ -#ifndef __GNUC__ - // set the locale the same as the system locale - // to handle local characters (non-English) properly by CZipString - std::locale::global(std::locale("")); -#endif - int iRet = 0; - - CCmdLine cmd; - CZipArchive zip; - CZipString szArchive; - try { - - if (cmd.SplitLine(argc, argv) < 1) - throw 0; - if (cmd.GetArgumentCount("-f") <= 0) - throw 0; - int iVolumeSize = 0; - int iMode = CZipArchive::zipOpen; - bool bIsAdding = - cmd.GetArgumentCount("-a") > 0 || cmd.GetArgumentCount("-af") > 0; - bool bIsExtracting = - cmd.GetArgumentCount("-x") > 0 || cmd.GetArgumentCount("-xr") > 0 || - cmd.GetArgumentCount("-xf") > 0 || cmd.HasSwitch("-xa"); - bool bIsDeleting = - cmd.GetArgumentCount("-d") > 0 || cmd.GetArgumentCount("-dr") > 0 || - cmd.GetArgumentCount("-df") > 0 || cmd.HasSwitch("-da"); - - szArchive = cmd.GetArgument("-f", 0); - CZipPathComponent zpc(szArchive); - if (zpc.GetFileExt().IsEmpty()) - szArchive += ".zip"; - bool bUpdateMode = cmd.HasSwitch("-u"); - bool bSetComment = cmd.GetArgumentCount("-g") > 0; - bool bIsListing = - cmd.HasSwitch("-l") || cmd.HasSwitch("-ll") || cmd.HasSwitch("-lr"); - bool bOnlyErrors = cmd.HasSwitch("-dse"); - if (bIsAdding) { - if (cmd.GetArgumentCount("-v") > 0) { - iMode = CZipArchive::zipCreateSpan; - iVolumeSize = atoi(cmd.GetArgument("-v", 0)); - } else { - if (!bUpdateMode || !ZipPlatform::FileExists(szArchive)) - iMode = CZipArchive::zipCreate; - } - } else if (bIsExtracting || cmd.HasSwitch("-t") || bIsListing) { - if (cmd.HasSwitch("-st")) - iVolumeSize = 1; - } else if (!bSetComment && !bIsDeleting) - throw 0; - - SpanCallback span; - zip.SetSpanCallback(&span); - - bool bAddEmpty = cmd.HasSwitch("-re"); - bool bRecursive = cmd.HasSwitch("-r") || bAddEmpty; - - bool bCaseSensitiveInZip = cmd.HasSwitch("-cs"); - pZipComp = GetCZipStrCompFunc(bCaseSensitiveInZip); - - zip.SetCaseSensitivity(bCaseSensitiveInZip); - try { - zip.Open(szArchive, iMode, iVolumeSize); - if (cmd.GetArgumentCount("-p") > 0) - zip.SetPassword(cmd.GetArgument("-p", 0)); - } catch (...) { - bool bContinue = false; - if (iMode == CZipArchive::zipOpen && !bIsDeleting && !bSetComment) { - try { - // try to open in read only mode (required if there is no - // write access to the storage) - zip.Open( - szArchive, CZipArchive::zipOpenReadOnly, iVolumeSize); - bContinue = true; - } catch (...) { - throw; - } - } - if (!bContinue) - throw; - } - - if (cmd.GetArgumentCount("-rp") > 0) - zip.SetRootPath(cmd.GetArgument("-rp", 0)); - - bool bFullPath = !cmd.HasSwitch("-nfp") && zip.GetRootPath().IsEmpty(); - - bool bIsSpan = zip.GetSpanMode() != 0; - if (bSetComment && !bIsSpan) { - CZipString sz = cmd.GetArgument("-g", 0); - sz.TrimLeft("\""); - sz.TrimRight("\""); - zip.SetGlobalComment(sz); - } - - if (bIsAdding) { - if (bUpdateMode && bIsSpan) { - printf("Cannot update an existing disk spanning archive\n"); - zip.Close(); - return 1; - } - int iLevel = atoi(cmd.GetSafeArgument("-c", 0, "5")); - int iSmartLevel; - if (cmd.HasSwitch("-as")) { - iSmartLevel = CZipArchive::zipsmSmartest; - zip.SetTempPath(cmd.GetSafeArgument("-as", 0, "")); - } else - iSmartLevel = CZipArchive::zipsmSafeSmart; - - FILELIST lFiles; - int iCount = cmd.GetArgumentCount("-a"); - if (iCount > 0) { - - for (int i = 0; i < iCount; i++) - - ExpandFile(lFiles, - cmd.GetArgument("-a", i), - bRecursive, - bAddEmpty, - bFullPath); - } - - iCount = cmd.GetArgumentCount("-af"); - if (iCount > 0) - FillFromFile(lFiles, cmd.GetArgument("-af", 0), true); - - FILELIST excl; - - iCount = cmd.GetArgumentCount("-ax"); - if (iCount > 0) { - for (int i = 0; i < iCount; i++) - - ExpandFile(excl, - cmd.GetArgument("-ax", i), - bRecursive, - bAddEmpty, - bFullPath); - } - - iCount = cmd.GetArgumentCount("-afx"); - if (iCount > 0) - FillFromFile(excl, cmd.GetArgument("-afx", 0), true); - - FILELISTADD rev; - for (FILELISTIT it = lFiles.begin(); it != lFiles.end(); ++it) { - // that is how the filename will look in the archive - CZipString sz = zip.PredictFileNameInZip(*it, bFullPath); - if (!sz.IsEmpty()) { - bool bAdd = true; - for (FILELISTIT itt = excl.begin(); itt != excl.end(); - ++itt) { - if (!((*itt).*pZipComp)(*it)) { - bAdd = false; - break; - } - } - if (bAdd) - rev.push_back(CZipAddFileInfo(*it, sz)); - } - } - lFiles.clear(); - excl.clear(); - - // remove duplicates - FILELISTADDIT it1; - for (it1 = rev.begin(); it1 != rev.end();) { - bool bErase = false; - FILELISTADDIT it2 = it1; - for (++it2; it2 != rev.end(); ++it2) { - int x = ((*it1).m_szFileNameInZip.* - pZipComp)((*it2).m_szFileNameInZip); - if (x == 0) { - bErase = true; - break; - } - } - if (bErase) - rev.erase(it1++); - else - ++it1; - } - - // sort - rev.sort(std::greater()); - printf("\n"); - for (it1 = rev.begin(); it1 != rev.end(); ++it1) { - if (zip.AddNewFile( - (*it1).m_szFilePath, iLevel, bFullPath, iSmartLevel)) { - if (!bOnlyErrors) - printf("%s added\n", (LPCTSTR)(*it1).m_szFileNameInZip); - } else - printf("%s not added\n", (LPCTSTR)(*it1).m_szFilePath); - } - } else if (bIsExtracting) { - CZipString szPath = cmd.GetSafeArgument("-xp", 0, "."); - - CZipWordArray vRevised; - ProcessData(zip, cmd, vRevised, true); - printf("\n"); - for (int k = 0; k < vRevised.GetSize(); ++k) { - int iFile = vRevised[k]; - try { - zip.ExtractFile(iFile, szPath, bFullPath); - CZipFileHeader fh; - if (zip.GetFileInfo(fh, iFile)) { - if (!bOnlyErrors) - printf("%s extracted\n", (LPCTSTR)fh.GetFileName()); - } - } catch (...) { - CZipFileHeader fh; - if (zip.GetFileInfo(fh, iFile)) - printf("Error extracting file %s\n", - (LPCTSTR)fh.GetFileName()); - else - printf("There are troubles with getting info from file " - "number %d\n", - iFile); - } - } - printf("\n"); - } else if (bIsDeleting) { - if (bIsSpan) { - printf( - "Cannot delete from an existing disk spanning archive\n"); - zip.Close(); - return 1; - } - CZipWordArray vRevised; - ProcessData(zip, cmd, vRevised, false); - try { - zip.DeleteFiles(vRevised); - } catch (...) { - printf("Error occured while deleting files\n"); - } - } else if (cmd.HasSwitch("-t")) { - FILELIST lFiles; - int iCount = zip.GetCount(); - for (int i = 0; i < iCount; i++) { - bool bOK = false; - try { - bOK = zip.TestFile(i); - printf("Tested: %d of %d \r", i, iCount); - } catch (...) { - } - if (!bOK) { - CZipFileHeader fh; - if (zip.GetFileInfo(fh, i)) - lFiles.push_back(fh.GetFileName()); - else { - char buf[50]; - sprintf(buf, - "There are troubles with getting info from " - "file number %d", - i); - lFiles.push_back(buf); - } - } - } - printf("\n"); - if (lFiles.size()) { - printf("There were errors found in the following files:\n"); - for (FILELISTIT it = lFiles.begin(); it != lFiles.end(); ++it) - printf("%s\n", (LPCTSTR)(*it)); - } else - printf("There were no errors found in the archive\n"); - } else if (bIsListing) { - bool bNumbers = cmd.HasSwitch("-lr"); - bool bDescription = !cmd.HasSwitch("-ll"); - int iCount = zip.GetCount(); - if (bDescription) - printf("\n File name\tSize\t\tRatio\tTime Stamp\n\n"); - for (int i = 0; i < iCount; i++) { - CZipFileHeader fh; - if (zip.GetFileInfo(fh, i)) { - if (bNumbers) - printf("%d. ", i + 1); - - printf("%s\n", (LPCTSTR)fh.GetFileName()); - if (bDescription) { - printf("\t\t"); - if (fh.IsDirectory()) - printf("\t\t"); - else { - printf("%u Bytes\t", fh.m_uUncomprSize); - printf("%.2f%%", fh.GetCompressionRatio()); - } - time_t t = fh.GetTime(); - printf("\t%s", ctime(&t)); - } - } else - printf("There are troubles with getting info from file " - "number %d\n", - i); - } - printf("\n"); - CZipString sz = zip.GetGlobalComment(); - if (!sz.IsEmpty()) - printf("Global archive comment:\n%s\n", (LPCTSTR)sz); - } - - zip.Close(); - } catch (int) { - DisplayUsage(); - iRet = 1; - } catch (CZipException e) { - printf("Error while processing archive %s\n%s\n", - (LPCTSTR)szArchive, - (LPCTSTR)e.GetErrorDescription()); - if (e.m_szFileName.IsEmpty()) - printf("\n"); - else - printf("Filename in error object: %s\n\n", (LPCTSTR)e.m_szFileName); - zip.Close(true); - iRet = 1; - } catch (...) { - printf("Unknown error while processing archive %s\n\n", - (LPCTSTR)szArchive); - zip.Close(true); - iRet = 1; - } - - if (cmd.HasSwitch("-w")) { - printf("\nPress to exit.\n"); - ReadKey(); - printf("\n"); - } - return iRet; -} diff --git a/src/smpackagee/ZipArchive/stl/zippie/zippie.dsp b/src/smpackagee/ZipArchive/stl/zippie/zippie.dsp deleted file mode 100644 index 288dc3bfb6..0000000000 --- a/src/smpackagee/ZipArchive/stl/zippie/zippie.dsp +++ /dev/null @@ -1,111 +0,0 @@ -# Microsoft Developer Studio Project File - Name="zippie" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=zippie - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "zippie.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "zippie.mak" CFG="zippie - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "zippie - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "zippie - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName ""$/zippie", BGAAAAAA" -# PROP Scc_LocalPath "." -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "zippie - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "NDEBUG" -# ADD RSC /l 0x415 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "zippie - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "_DEBUG" -# ADD RSC /l 0x415 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "zippie - Win32 Release" -# Name "zippie - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\CmdLine.cpp -# End Source File -# Begin Source File - -SOURCE=.\zippie.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\CmdLine.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/src/smpackagee/ZipArchive/stl/zippie/zippie.dsw b/src/smpackagee/ZipArchive/stl/zippie/zippie.dsw deleted file mode 100644 index 032bc18743..0000000000 --- a/src/smpackagee/ZipArchive/stl/zippie/zippie.dsw +++ /dev/null @@ -1,44 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "ZipArchive"="..\..\ZipArchive_STL.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "zippie"=".\zippie.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name ZipArchive - End Project Dependency -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsp b/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsp deleted file mode 100644 index 6af7af75a5..0000000000 --- a/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsp +++ /dev/null @@ -1,112 +0,0 @@ -# Microsoft Developer Studio Project File - Name="zippie" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Console Application" 0x0103 - -CFG=zippie - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "zippie_DLL.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "zippie_DLL.mak" CFG="zippie - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "zippie - Win32 Release" (based on "Win32 (x86) Console Application") -!MESSAGE "zippie - Win32 Debug" (based on "Win32 (x86) Console Application") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName ""$/zippie", BGAAAAAA" -# PROP Scc_LocalPath "." -CPP=cl.exe -RSC=rc.exe - -!IF "$(CFG)" == "zippie - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ZIP_HAS_DLL" /FD /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "NDEBUG" -# ADD RSC /l 0x415 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 - -!ELSEIF "$(CFG)" == "zippie - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c -# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ZIP_HAS_DLL" /FR /FD /GZ /c -# SUBTRACT CPP /YX /Yc /Yu -# ADD BASE RSC /l 0x415 /d "_DEBUG" -# ADD RSC /l 0x415 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "zippie - Win32 Release" -# Name "zippie - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\CmdLine.cpp -# End Source File -# Begin Source File - -SOURCE=.\zippie.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\CmdLine.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsw b/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsw deleted file mode 100644 index c78c2339c5..0000000000 --- a/src/smpackagee/ZipArchive/stl/zippie/zippie_DLL.dsw +++ /dev/null @@ -1,59 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "ZipArchive"="..\..\ZipArchive_STL_DLL.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name zlib - End Project Dependency -}}} - -############################################################################### - -Project: "zippie"=".\zippie_DLL.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name ZipArchive - End Project Dependency -}}} - -############################################################################### - -Project: "zlib"="..\..\zlib\zlib.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/src/smpackagee/res/smpackage.ico b/src/smpackagee/res/smpackage.ico deleted file mode 100644 index 7eef0bcbe6580a6f464d688906172c2d9de44262..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 zcmc&zF>b>!3}jLb9s)T}@Kod(893@u8ajANzT`op9^o+)S?=nU(FD@%0s)Sg^oyC8{H z9myetc;MEP)59v(LMa~xK8Yu^jIR*H22uCFiq5%C{s7(PJi>o15i^bmX4(vPxWAio z9ryY#AU_jfnd047-@`)XzL?%iS$gQyFP{44kS9X)fN{{QoL~hO-&=q&20Zr*cxFAt PkaNE{wR~2C$NfnjhSXWT diff --git a/src/smpackagee/res/smpackage.rc2 b/src/smpackagee/res/smpackage.rc2 deleted file mode 100644 index 50a7391dbf..0000000000 --- a/src/smpackagee/res/smpackage.rc2 +++ /dev/null @@ -1,13 +0,0 @@ -// -// SMPACKAGE.RC2 - resources Microsoft Visual C++ does not edit directly -// - -#ifdef APSTUDIO_INVOKED - #error this file is not editable by Microsoft Visual C++ -#endif //APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// Add manually edited resources here... - -///////////////////////////////////////////////////////////////////////////// diff --git a/src/smpackagee/resource.h b/src/smpackagee/resource.h deleted file mode 100644 index 4de5cc6a64..0000000000 --- a/src/smpackagee/resource.h +++ /dev/null @@ -1,105 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by smpackage.rc -// -#define IDD_SMPACKAGE_DIALOG 102 -#define IDD_MANAGER 102 -#define IDR_MAINFRAME 128 -#define IDD_INSTALL 129 -#define IDD_EXPORTER 130 -#define IDD_DIALOG_NAME 137 -#define IDD_EDIT_INSTALLATIONS 138 -#define IDD_MENU 139 -#define IDD_ENTER_COMMENT 146 -#define IDD_SHOW_COMMENT 147 -#define IDD_UNINSTALL_OLD_PACKAGES 148 -#define IDD_CHANGE_GAME_SETTINGS 149 -#define IDD_LANGUAGES 150 -#define IDD_CREATE_LANGUAGE 151 -#define IDB_BITMAP1 153 -#define IDC_LIST_SONGS 1000 -#define IDC_LIST 1000 -#define IDC_BUTTON_PLAY 1001 -#define IDC_BUTTON_EXPORT 1002 -#define IDC_BUTTON_EXPORT_AS_ONE 1002 -#define IDC_BUTTON_BACK 1003 -#define IDC_BUTTON_EXPORT_AS_INDIVIDUAL 1003 -#define IDC_BUTTON_OPEN 1004 -#define IDC_EDIT_MESSAGE1 1005 -#define IDC_EDIT_MESSAGE3 1006 -#define IDC_EDIT_MESSAGE2 1007 -#define IDC_TREE 1011 -#define IDC_EDIT 1012 -#define IDC_COMBO_DIR 1013 -#define IDC_BUTTON_EDIT 1014 -#define IDC_BUTTON_ADD 1018 -#define IDC_BUTTON_REMOVE 1019 -#define IDC_BUTTON_MAKE_DEFAULT 1020 -#define IDC_EXPORT_PACKAGES 1022 -#define IDC_LIST_THEMES 1023 -#define IDC_EDIT_INSTALLATIONS 1024 -#define IDC_BUTTON_CONVERT 1024 -#define IDC_BUTTON_ANALYZE 1025 -#define IDC_CHANGE_API 1025 -#define IDC_CHANGE_PREFERENCES 1025 -#define IDC_BUTTON_EDIT_METRICS 1026 -#define IDC_CREATE_SONG 1026 -#define IDC_BUTTON_ANALYZE_METRICS 1027 -#define IDC_OPEN_STEPMANIA_INI 1027 -#define IDC_OPEN_PREFERENCES 1027 -#define IDC_EDIT_VALUE 1028 -#define IDC_CLEAR_PREFERENCES 1028 -#define IDC_EDIT_DEFAULT 1029 -#define IDC_CLEAR_KEYMAPS 1029 -#define IDC_VIEW_STATISTICS 1030 -#define IDC_CLEAR_KEYMAPS2 1031 -#define IDC_CLEAR_CACHE 1031 -#define IDC_LANGUAGES 1032 -#define IDC_BUTTON_REFRESH 1035 -#define IDC_BUTTON_SAVE 1036 -#define IDC_BUTTON_OVERRIDE 1037 -#define IDC_BUTTON_HELP 1038 -#define IDC_BUTTON_CLOSE 1039 -#define IDC_DONTASK 1041 -#define IDC_DONTSHOW 1042 -#define IDC_PACKAGES 1044 -#define IDC_BUTTON1 1045 -#define IDC_BUTTON_DELETE 1046 -#define IDC_PROGRESS1 1047 -#define IDC_RADIO_DEFAULT 1048 -#define IDC_BUTTON_IMPORT 1048 -#define IDC_RADIO_OPENGL 1049 -#define IDC_RADIO_DIRECT3D 1050 -#define IDC_RADIO_SOUND_DEFAULT 1051 -#define IDC_RADIO_SOUND_NULL 1052 -#define IDC_CHECK_LOG_TO_DISK 1053 -#define IDC_CHECK_SHOW_LOG_WINDOW 1054 -#define IDC_EDIT_INSTALLATION 1054 -#define IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE 1055 -#define IDC_BUTTON_LAUNCH_GAME 1055 -#define IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE 1056 -#define IDC_RADIO_SOUND_WAVEOUT 1057 -#define IDC_BUTTON_CREATE 1057 -#define IDC_LIST_LANGUAGES 1058 -#define IDC_CHECK_FORCE_60HZ 1058 -#define IDC_STATIC_TOTAL_STRINGS 1060 -#define IDC_STATIC_NEED_TRANSLATION 1061 -#define IDC_COMBO_LANGUAGES 1065 -#define IDC_CHECK_EXPORT_ALREADY_TRANSLATED 1066 -#define IDC_STATIC_HEADER_TEXT 1067 -#define IDC_STATIC_MESSAGE2 1068 -#define IDC_STATIC_MESSAGE1 1069 -#define IDC_STATIC_ICON 1070 -#define IDC_SHOW_A_COMMENT 1071 -#define IDC_CHECK_LANGUAGE 1072 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 155 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1073 -#define _APS_NEXT_SYMED_VALUE 104 -#endif -#endif diff --git a/src/smpackagee/smpackage.ICO b/src/smpackagee/smpackage.ICO deleted file mode 100644 index de59ebc5d78d488ca7406aa4539306138b5af908..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6006 zcmeI0&rh328pj`(RfwxDwA+P1LSkaD{n{G>xK8>rp+~}rOTu-<6>U_B%NDA|YuS+; zG@v4po1+}6sxl`o5xH48fK)X(`4lA*GE%DcP&wE}ysG8d?=$nheqYHC={shvOwjZf23kr(r!u8Mp4qzzNFbbNuj(X;%ncDjtD9 z0KWr%6Z|sx1+ceq-2#6D{51Fw_+jv{ySod11N;*BS@0pS)W8Lvz!P`^PxEvH{s8MQRd=dOU_&xA>@OkiC;8(yef}aB)2QR@(@DjWP zFTqRj4g9^t-xK^jz~3_d<`rKCUjknQzYl&7JX_C$-U7V>dJ*&-=s4^jfjvvUv;H zyn$>^Bby;)a~OOXdfedWq?J zg6VpI=~~8g&Ce5+!I!`n!S93L1D^-qW%b!~9q^mrk!iVrfq5sWD9hkW;EUk*!S8`ba=Ij_D6yV#ZQxqMHH#~R zt6PGOkB{l~>(}(+#S41={5d^+`jj3&eoXm%o*q7YNLyQ5bno6hT3K14yLa!>;^HFR zxpRl+=H}?;&6^aD$0-~R)A{q~sjsh(%704w;n5?!$4R^|@XN0f{40Swha&mrS%k13 z3#+KM^VsgzQus5Lf{>|{Kb_0|i`ydQZ`x^55He$#MF@&tUF8SzExezLP<$qrUC#<` zy@l5fT>RVYr>*$4eZ-$#MdV%WQ!^1zNcsJ_TviRV`M71YEe#!(7ijl5QYi}g%d1x& zX%wsL>)Bi;o%W~wek9$W(_=tho_X*hi=4Um6nLe8j;xN}9jAJl&1PU99$=pxq|;7p zZ6k1ZSarV&ES<^Zke=-7y2lvY9Ux)hDZ5K#nkI+?H(JjOfl;fO8~o-UNDZUt8$R<$|+ ze0Xqh@LXhg@aomU@kon8=Xk4^Spi0a<`C{uD}0$imSD1Dyrdj3c`kB}`Dx_<{54G5 zamV~t|IX%v!Qhz5_h2Yof)bAyd4KzO)o{%(9K3V1L<4_ADpiTa-1)R-wPU
OZF zlX6T4qpWw1*Kx}00Rtbyda&0_<+$s5R@NCe9o!nP*OII7dY)q3Y+83*d(`m0aO`-6 z?O+%ZUDvaEAKP&~za8&7Tf+N(b*SCC^TIRYE;Yo1(i#k}4}9=4`UB&}@pi?4$68`f zSv-D#I)9_7HgRRbZ9*vAvhTsWS+3*vwwrxtSWeBtJ?)G8{29q^-@{jhze)IH@JB;B z+HENn_wPf+=J^xDI&F|UV6m#~!@TuP;_ZMNXs^3m+tqdiZ7J)LOqQqrp>LE_6x!|b zJ3df>Z_u|a^=3*IsQ%1RdcPqpl=GcOB0 z(kEH^8fx2i2vcjUM{7xzr!>R%3q%3tAp4kuJi{Dh4|9iB94syFjK%d?T!1<7${y^l zDZgd-gFWRR{TvT-vd}BpuPpR8bew^@9>SE?zw@)+{vi;O zpJ2bwM+t#S8zA&aM#}Uy`URT6-9@#9NS)nAH!N9wwnruLjHOFW;E0vo-p*z4HB(1I zVI2%LBi7V6GM7tpKU>ztwqUolWGtQX{_?Yi;8S0F|7bM&kES^(zi;cW8j*S#b5K>J=j#EQKSVSc~8f@+KE_Wv=q)PVqY z)P{lG`X{`%Z}HDfE>U9~`)6y%>hiC9t1)yBMYOitzwWL?jWIc9*n38of8CGyk&}_A z^36|N<5$3CBRt;J*2@!ftabTbi5Z5Y&F5i0+q!`2gmaq3cJlj_dO<7$t?N_xd409? z^YYJb=lH)8=`@ya`})%FhwjhizIFNa^k6+yLN>~OmGy7V$~yKSsMl!(8;=iW%0&IR zu$L(GHUfve_5N~yz4tUw@2LkGzWR)$(;1?FV@EO)NPpsmx SuOIr#4%=kgr!ZZoe)&I3EM-0b diff --git a/src/smpackagee/smpackage.clw b/src/smpackagee/smpackage.clw deleted file mode 100644 index ef17bb3487..0000000000 --- a/src/smpackagee/smpackage.clw +++ /dev/null @@ -1,321 +0,0 @@ -; CLW file contains information for the MFC ClassWizard - -[General Info] -Version=1 -LastClass=MainMenuDlg -LastTemplate=CDialog -NewFileInclude1=#include "stdafx.h" -NewFileInclude2=#include "smpackage.h" - -ClassCount=12 -Class1=CSmpackageApp -Class2=CSmpackageDlg - -ResourceCount=13 -Resource1=IDR_MAINFRAME -Resource2=IDD_ENTER_STRING -Class3=CSMPackageInstallDlg -Class4=CSmpackageExportDlg -Resource3=IDD_EXPORTER -Class5=EnterName -Resource4=IDD_EDIT_METRICS -Class6=EditInsallations -Resource5=IDD_CONVERT_THEME -Class7=MainMenuDlg -Resource6=IDD_MENU -Class8=ConvertThemeDlg -Resource7=IDD_SHOW_COMMENT -Class9=EditMetricsDlg -Resource8=IDD_ENTER_COMMENT -Resource9=IDD_DIALOG_NAME -Class10=EnterComment -Resource10=IDD_INSTALL -Class11=ShowComment -Resource11=IDD_UNINSTALL_OLD_PACKAGES -Resource12=IDD_EDIT_INSTALLATIONS -Class12=ChangeGameSettings -Resource13=IDD_CHANGE_GAME_SETTINGS - -[CLS:CSmpackageApp] -Type=0 -HeaderFile=smpackage.h -ImplementationFile=smpackage.cpp -Filter=N -LastObject=CSmpackageApp -BaseClass=CWinApp -VirtualFilter=AC - -[CLS:CSmpackageDlg] -Type=0 -HeaderFile=smpackageDlg.h -ImplementationFile=smpackageDlg.cpp -Filter=D -LastObject=CSmpackageDlg -BaseClass=CDialog -VirtualFilter=dWC - - - -[DLG:IDD_INSTALL] -Type=1 -Class=CSMPackageInstallDlg -ControlCount=10 -Control1=IDC_EDIT_MESSAGE1,edit,1342179460 -Control2=IDOK,button,1342242817 -Control3=IDCANCEL,button,1342242816 -Control4=IDC_BUTTON_BACK,button,1476460544 -Control5=IDC_STATIC,static,1342177294 -Control6=IDC_EDIT_MESSAGE3,edit,1342179460 -Control7=IDC_EDIT_MESSAGE2,edit,1352665220 -Control8=IDC_COMBO_DIR,combobox,1344339971 -Control9=IDC_BUTTON_EDIT,button,1342242816 -Control10=IDC_PROGRESS1,msctls_progress32,1082130432 - -[CLS:CSMPackageInstallDlg] -Type=0 -HeaderFile=SMPackageInstallDlg.h -ImplementationFile=SMPackageInstallDlg.cpp -BaseClass=CDialog -Filter=D -LastObject=CSMPackageInstallDlg -VirtualFilter=dWC - -[DLG:IDD_EXPORTER] -Type=1 -Class=CSmpackageExportDlg -ControlCount=10 -Control1=IDOK,button,1342242817 -Control2=IDC_BUTTON_PLAY,button,1342242816 -Control3=IDC_BUTTON_EXPORT_AS_ONE,button,1342242816 -Control4=IDC_STATIC,static,1342177294 -Control5=IDC_BUTTON_EXPORT_AS_INDIVIDUAL,button,1342242816 -Control6=IDC_TREE,SysTreeView32,1350631687 -Control7=IDC_COMBO_DIR,combobox,1344339971 -Control8=IDC_BUTTON_EDIT,button,1342242816 -Control9=IDC_STATIC,static,1342308352 -Control10=IDC_BUTTON_OPEN,button,1342242816 - -[CLS:CSmpackageExportDlg] -Type=0 -HeaderFile=SmpackageExportDlg.h -ImplementationFile=SmpackageExportDlg.cpp -BaseClass=CDialog -Filter=D -LastObject=CSmpackageExportDlg -VirtualFilter=dWC - -[CLS:EnterName] -Type=0 -HeaderFile=EnterName.h -ImplementationFile=EnterName.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=IDC_EDIT - -[DLG:IDD_EDIT_INSTALLATIONS] -Type=1 -Class=EditInsallations -ControlCount=10 -Control1=IDOK,button,1342242817 -Control2=IDCANCEL,button,1342242816 -Control3=IDC_LIST,listbox,1352728833 -Control4=IDC_EDIT,edit,1350631552 -Control5=IDC_BUTTON_ADD,button,1342242816 -Control6=IDC_BUTTON_REMOVE,button,1342242816 -Control7=IDC_BUTTON_MAKE_DEFAULT,button,1342242816 -Control8=IDC_STATIC,button,1342177287 -Control9=IDC_STATIC,button,1342177287 -Control10=IDC_STATIC,static,1342308352 - -[CLS:EditInsallations] -Type=0 -HeaderFile=EditInsallations.h -ImplementationFile=EditInsallations.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=EditInsallations - -[DLG:IDD_MENU] -Type=1 -Class=MainMenuDlg -ControlCount=20 -Control1=IDOK,button,1342242817 -Control2=IDC_STATIC,static,1342177294 -Control3=IDC_STATIC,static,1342308354 -Control4=IDC_EDIT_INSTALLATION,edit,1350633600 -Control5=IDC_STATIC,button,1342177287 -Control6=IDC_EDIT_INSTALLATIONS,button,1342242816 -Control7=IDC_STATIC,static,1342308352 -Control8=IDC_STATIC,button,1342177287 -Control9=IDC_EXPORT_PACKAGES,button,1342242816 -Control10=IDC_STATIC,static,1342308352 -Control11=IDC_STATIC,button,1342177287 -Control12=IDC_ANALYZE_ELEMENTS,button,1342242816 -Control13=IDC_STATIC,static,1342308352 -Control14=IDC_STATIC,button,1342177287 -Control15=IDC_CHANGE_API,button,1342242816 -Control16=IDC_OPEN_STEPMANIA_INI,button,1342242816 -Control17=IDC_STATIC,static,1342308352 -Control18=IDC_STATIC,button,1342177287 -Control19=IDC_CREATE_SONG,button,1342242816 -Control20=IDC_STATIC,static,1342308352 - -[CLS:MainMenuDlg] -Type=0 -HeaderFile=MainMenuDlg.h -ImplementationFile=MainMenuDlg.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=MainMenuDlg - -[DLG:IDD_CONVERT_THEME] -Type=1 -Class=ConvertThemeDlg -ControlCount=13 -Control1=IDOK,button,1342242817 -Control2=IDC_STATIC,static,1342177294 -Control3=IDC_LIST_THEMES,listbox,1352728835 -Control4=IDC_BUTTON_CONVERT,button,1476460544 -Control5=IDC_STATIC,static,1342308352 -Control6=IDC_STATIC,button,1342177287 -Control7=IDC_STATIC,static,1342308352 -Control8=IDC_BUTTON_ANALYZE,button,1476460544 -Control9=IDC_STATIC,button,1342177287 -Control10=IDC_STATIC,static,1342308352 -Control11=IDC_BUTTON_EDIT_METRICS,button,1476460544 -Control12=IDC_STATIC,static,1342308352 -Control13=IDC_BUTTON_ANALYZE_METRICS,button,1476460544 - -[CLS:ConvertThemeDlg] -Type=0 -HeaderFile=onvertThemeDlg.h -ImplementationFile=onvertThemeDlg.cpp -BaseClass=CDialog -Filter=D -LastObject=IDC_LIST_THEMES -VirtualFilter=dWC - -[DLG:IDD_EDIT_METRICS] -Type=1 -Class=EditMetricsDlg -ControlCount=11 -Control1=IDC_BUTTON_CLOSE,button,1342242816 -Control2=IDC_STATIC,static,1342177294 -Control3=IDC_EDIT_VALUE,edit,1484849220 -Control4=IDC_STATIC,static,1342308352 -Control5=IDC_EDIT_DEFAULT,edit,1350633540 -Control6=IDC_STATIC,static,1342308352 -Control7=IDC_BUTTON_OVERRIDE,button,1476460544 -Control8=IDC_BUTTON_REMOVE,button,1476460544 -Control9=IDC_TREE,SysTreeView32,1350631461 -Control10=IDC_BUTTON_SAVE,button,1342242816 -Control11=IDC_BUTTON_HELP,button,1342242816 - -[CLS:EditMetricsDlg] -Type=0 -HeaderFile=EditMetricsDlg.h -ImplementationFile=EditMetricsDlg.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=EditMetricsDlg - -[DLG:IDD_ENTER_STRING] -Type=1 -Class=EnterName -ControlCount=4 -Control1=IDC_STATIC,static,1342308352 -Control2=IDC_EDIT,edit,1350631552 -Control3=IDOK,button,1342242817 -Control4=IDCANCEL,button,1342242816 - -[DLG:IDD_ENTER_COMMENT] -Type=1 -Class=EnterComment -ControlCount=5 -Control1=65535,static,1342308352 -Control2=IDC_EDIT,edit,1350631556 -Control3=IDOK,button,1342242817 -Control4=IDCANCEL,button,1342242816 -Control5=IDC_DONTASK,button,1342242819 - -[DLG:IDD_DIALOG_NAME] -Type=1 -Class=? -ControlCount=5 -Control1=IDC_STATIC,static,1342308352 -Control2=IDC_EDIT,edit,1350631552 -Control3=IDOK,button,1342242817 -Control4=IDCANCEL,button,1342242816 -Control5=IDC_STATIC,static,1342308352 - -[CLS:EnterComment] -Type=0 -HeaderFile=EnterComment.h -ImplementationFile=EnterComment.cpp -BaseClass=CDialog -Filter=D -LastObject=IDC_EDIT -VirtualFilter=dWC - -[DLG:IDD_SHOW_COMMENT] -Type=1 -Class=ShowComment -ControlCount=4 -Control1=IDC_EDIT,edit,1350633604 -Control2=IDOK,button,1342242817 -Control3=IDCANCEL,button,1342242816 -Control4=IDC_DONTSHOW,button,1342242819 - -[CLS:ShowComment] -Type=0 -HeaderFile=ShowComment.h -ImplementationFile=ShowComment.cpp -BaseClass=CDialog -Filter=D -VirtualFilter=dWC -LastObject=IDC_DONTSHOW - -[DLG:IDD_UNINSTALL_OLD_PACKAGES] -Type=1 -Class=? -ControlCount=6 -Control1=IDOK,button,1342242817 -Control2=IDCANCEL,button,1342242816 -Control3=IDC_STATIC,static,1342308352 -Control4=IDC_PACKAGES,edit,1352730756 -Control5=IDC_BUTTON1,button,1342242816 -Control6=IDC_STATIC,static,1342308353 - -[DLG:IDD_CHANGE_GAME_SETTINGS] -Type=1 -Class=ChangeGameSettings -ControlCount=15 -Control1=IDOK,button,1342242817 -Control2=IDCANCEL,button,1342242816 -Control3=IDC_STATIC,button,1342177287 -Control4=IDC_RADIO_DEFAULT,button,1342308361 -Control5=IDC_RADIO_OPENGL,button,1342177289 -Control6=IDC_RADIO_DIRECT3D,button,1342177289 -Control7=IDC_STATIC,button,1342177287 -Control8=IDC_RADIO_SOUND_DEFAULT,button,1342308361 -Control9=IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE,button,1342177289 -Control10=IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE,button,1342177289 -Control11=IDC_RADIO_SOUND_NULL,button,1342177289 -Control12=IDC_STATIC,button,1342177287 -Control13=IDC_CHECK_LOG_TO_DISK,button,1342242819 -Control14=IDC_CHECK_SHOW_LOG_WINDOW,button,1342242819 -Control15=IDC_STATIC,static,1342308352 - -[CLS:ChangeGameSettings] -Type=0 -HeaderFile=ChangeGameSettings.h -ImplementationFile=ChangeGameSettings.cpp -BaseClass=CDialog -Filter=D -LastObject=IDCANCEL -VirtualFilter=dWC - diff --git a/src/smpackagee/smpackage.cpp b/src/smpackagee/smpackage.cpp deleted file mode 100644 index 45c09f3b24..0000000000 --- a/src/smpackagee/smpackage.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#define CO_EXIST_WITH_MFC -#include "global.h" -#include "stdafx.h" -#include "smpackage.h" -#include "smpackageExportDlg.h" -#include "smpackageInstallDlg.h" -#include "RageUtil.h" -#include "smpackageUtil.h" -#include "MainMenuDlg.h" -#include "RageFileManager.h" -#include "LuaManager.h" -#include "ThemeManager.h" -#include "SpecialFiles.h" -#include "IniFile.h" -#include "LocalizedString.h" -#include "arch/Dialog/Dialog.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -BEGIN_MESSAGE_MAP(CSmpackageApp, CWinApp) -//{{AFX_MSG_MAP(CSmpackageApp) -//}}AFX_MSG_MAP -ON_COMMAND(ID_HELP, CWinApp::OnHelp) -END_MESSAGE_MAP() - -CSmpackageApp::CSmpackageApp() -{ - // Place all significant initialization in InitInstance -} - -CSmpackageApp theApp; -extern const char* const version_date = ""; -extern const char* const version_time = ""; - -#include "RageLog.h" -#include "RageFileManager.h" -#include "archutils/Win32/SpecialDirs.h" -#include "ProductInfo.h" -#include "archutils/Win32/CommandLine.h" -extern RString -GetLastErrorString(); - -static LocalizedString STATS_XML_NOT_YET_CREATED("CSmpackageApp", - "The file Stats.xml has not " - "yet been created. It will " - "be created once the game is " - "run."); -static LocalizedString FAILED_TO_OPEN("CSmpackageApp", - "Failed to open '%s': %s"); -static LocalizedString THE_FILE_DOES_NOT_EXIST( - "CSmpackageApp", - "The file '%s' does not exist. Aborting installation."); -BOOL -CSmpackageApp::InitInstance() -{ - char** argv; - int argc = GetWin32CmdLine(argv); - - /* Almost everything uses this to read and write files. Load this early. */ - FILEMAN = new RageFileManager(argv[0]); - FILEMAN->MountInitialFilesystems(); - - /* Set this up next. Do this early, since it's needed for - * RageException::Throw. */ - LOG = new RageLog; - - TCHAR szCurrentDirectory[MAX_PATH]; - GetCurrentDirectory(ARRAYLEN(szCurrentDirectory), szCurrentDirectory); - if (CAN_INSTALL_PACKAGES && - SMPackageUtil::IsValidInstallDir(szCurrentDirectory)) { - SMPackageUtil::AddGameInstallDir( - szCurrentDirectory); // add this if it doesn't already exist - SMPackageUtil::SetDefaultInstallDir(szCurrentDirectory); - } - - FILEMAN->Remount("/", szCurrentDirectory); - - LUA = new LuaManager; - THEME = new ThemeManager; - - // TODO: Use PrefsManager to get the current language instead? PrefsManager - // would need to be split up to reduce dependencies - RString sTheme = SpecialFiles::BASE_THEME_NAME; - - { - RString sType = "Preferences"; - GetFileContents(SpecialFiles::TYPE_TXT_FILE, sType, true); - IniFile ini; - if (ini.ReadFile(SpecialFiles::STATIC_INI_PATH)) { - while (1) { - if (ini.GetValue(sType, "Theme", sTheme)) - break; - if (ini.GetValue(sType, "Fallback", sType)) - continue; - break; - } - } - } - - RString sLanguage; - bool bPseudoLocalize = false; - bool bShowLogOutput = false; - bool bLogToDisk = false; - { - IniFile ini; - if (ini.ReadFile(SpecialFiles::PREFERENCES_INI_PATH)) { - ini.GetValue("Options", "Theme", sTheme); - ini.GetValue("Options", "Language", sLanguage); - ini.GetValue("Options", "PseudoLocalize", bPseudoLocalize); - ini.GetValue("Options", "ShowLogOutput", bShowLogOutput); - ini.GetValue("Options", "LogToDisk", bLogToDisk); - } - } - THEME->SwitchThemeAndLanguage(sTheme, sLanguage, bPseudoLocalize); - LOG->SetShowLogOutput(bShowLogOutput); - LOG->SetLogToDisk(bLogToDisk); - LOG->SetInfoToDisk(true); - - // check for --machine-profile-stats and launch Stats.xml - for (int i = 0; i < argc; i++) { - CString sArg = argv[i]; - if (sArg == "--machine-profile-stats") { - RString sOSFile = SpecialDirs::GetAppDataDir() + PRODUCT_ID + - "/Save/MachineProfile/Stats.xml"; - HINSTANCE hinst = - ::ShellExecute(NULL, "open", sOSFile, "", "", SW_SHOWNORMAL); - // See MSDN for an explanation of this return value - if ((int)hinst == SE_ERR_FNF) - Dialog::OK(STATS_XML_NOT_YET_CREATED); - else if ((int)hinst <= 32) - Dialog::OK(ssprintf(FAILED_TO_OPEN.GetValue(), - sOSFile.c_str(), - GetLastErrorString().c_str())); - exit(1); // better way to quit? - } - } - - // check if there's a .smzip command line argument and install it - for (int i = 0; i < argc; i++) { - RString sPath = argv[i]; - TrimLeft(sPath); - TrimRight(sPath); - RString sPathLower = sPath; - sPathLower.MakeLower(); - - // test to see if this is a smzip file - if (sPathLower.Right(3).CompareNoCase("zip") == 0) { - // We found a zip package. Prompt the user to install it! - CSMPackageInstallDlg dlg(sPath); - int nResponse = dlg.DoModal(); - if (nResponse == IDCANCEL) - exit(1); // better way to exit? - } - } - - { - MainMenuDlg dlg; - int nResponse = dlg.DoModal(); - } - - SAFE_DELETE(THEME); - SAFE_DELETE(LUA); - SAFE_DELETE(FILEMAN); - - // Since the dialog has been closed, return FALSE so that we exit the - // application, rather than start the application's message pump. - return FALSE; -} - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/smpackage.h b/src/smpackagee/smpackage.h deleted file mode 100644 index 0cb24de49b..0000000000 --- a/src/smpackagee/smpackage.h +++ /dev/null @@ -1,70 +0,0 @@ -// smpackage.h : main header file for the SMPACKAGE application - -#if !defined(AFX_SMPACKAGE_H__FBCA9E6C_86A9_4271_8304_83CC34A31687__INCLUDED_) -#define AFX_SMPACKAGE_H__FBCA9E6C_86A9_4271_8304_83CC34A31687__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ -#error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -///////////////////////////////////////////////////////////////////////////// -// CSmpackageApp: -// See smpackage.cpp for the implementation of this class - -class CSmpackageApp : public CWinApp -{ - public: - CSmpackageApp(); - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CSmpackageApp) - public: - virtual BOOL InitInstance(); - //}}AFX_VIRTUAL - - // Implementation - - //{{AFX_MSG(CSmpackageApp) - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before -// the previous line. - -#endif // !defined(AFX_SMPACKAGE_H__FBCA9E6C_86A9_4271_8304_83CC34A31687__INCLUDED_) - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ diff --git a/src/smpackagee/smpackage.rc b/src/smpackagee/smpackage.rc deleted file mode 100644 index eb7dfc6c03..0000000000 --- a/src/smpackagee/smpackage.rc +++ /dev/null @@ -1,499 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "#define _AFX_NO_SPLITTER_RESOURCES\r\n" - "#define _AFX_NO_OLE_RESOURCES\r\n" - "#define _AFX_NO_TRACKER_RESOURCES\r\n" - "#define _AFX_NO_PROPERTY_RESOURCES\r\n" - "\r\n" - "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" - "#ifdef _WIN32\r\n" - "LANGUAGE 9, 1\r\n" - "#pragma code_page(1252)\r\n" - "#endif //_WIN32\r\n" - "#include ""res\\smpackage.rc2"" // non-Microsoft Visual C++ edited resources\r\n" - "#include ""afxres.rc"" // Standard components\r\n" - "#endif\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDR_MAINFRAME ICON "smpackage.ICO" - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_INSTALL DIALOGEX 0, 0, 332, 234 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION -CAPTION "Install a package" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - EDITTEXT IDC_EDIT_MESSAGE1,7,57,320,14,ES_MULTILINE | - ES_AUTOHSCROLL | ES_READONLY | NOT WS_BORDER | NOT - WS_TABSTOP - DEFPUSHBUTTON "Finish >",IDOK,200,215,55,15 - PUSHBUTTON "Cancel",IDCANCEL,275,215,50,15 - PUSHBUTTON "< Back",IDC_BUTTON_BACK,145,215,55,15,WS_DISABLED - EDITTEXT IDC_EDIT_MESSAGE2,5,90,320,87,ES_MULTILINE | - ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL | NOT - WS_TABSTOP - COMBOBOX IDC_COMBO_DIR,22,195,204,105,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Edit Installations",IDC_BUTTON_EDIT,233,194,85,14 - CONTROL "",IDC_PROGRESS1,"msctls_progress32",NOT WS_VISIBLE | - WS_BORDER,7,72,318,14 - LTEXT "You have chosen to install the package:", - IDC_STATIC_MESSAGE1,7,41,318,10 - LTEXT "This package contains the following files:", - IDC_STATIC_MESSAGE2,7,76,318,10 - LTEXT "The package will be installed in the following program folder:", - IDC_STATIC,7,181,318,10 - CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,331,33 - LTEXT "Install a package",IDC_STATIC_HEADER_TEXT,6,4,273,20 - CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,33,331,1 - ICON IDR_MAINFRAME,IDC_STATIC_ICON,295,6,21,20,0, - WS_EX_TRANSPARENT -END - -IDD_EXPORTER DIALOGEX 0, 0, 349, 222 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | - WS_VISIBLE | WS_CAPTION | WS_SYSMENU -EXSTYLE WS_EX_APPWINDOW -CAPTION "Export Packages" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - DEFPUSHBUTTON "Close",IDOK,284,201,57,14 - PUSHBUTTON "Launch Game",IDC_BUTTON_PLAY,7,200,70,15 - PUSHBUTTON "Export As One",IDC_BUTTON_EXPORT_AS_ONE,255,87,86,15 - PUSHBUTTON "Export As Individual",IDC_BUTTON_EXPORT_AS_INDIVIDUAL, - 255,120,86,15 - CONTROL "Tree2",IDC_TREE,"SysTreeView32",TVS_HASBUTTONS | - TVS_HASLINES | TVS_LINESATROOT | TVS_CHECKBOXES | - WS_BORDER | WS_TABSTOP,7,43,239,151 - COMBOBOX IDC_COMBO_DIR,16,17,229,105,CBS_DROPDOWNLIST | - WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Edit Installations",IDC_BUTTON_EDIT,250,16,85,14 - PUSHBUTTON "Open Program Folder",IDC_BUTTON_OPEN,88,200,93,15 - GROUPBOX "Installation",IDC_STATIC,7,7,334,29 -END - -IDD_DIALOG_NAME DIALOGEX 0, 0, 261, 58 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Name Your Package" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - LTEXT "Enter a name for your new package:",IDC_STATIC,7,7,188, - 12 - EDITTEXT IDC_EDIT,17,20,178,13,ES_AUTOHSCROLL - DEFPUSHBUTTON "OK",IDOK,200,7,54,14 - PUSHBUTTON "Cancel",IDCANCEL,200,24,54,14 - LTEXT "Note: leave off the "".smzip"" extension",IDC_STATIC,18, - 38,179,12 -END - -IDD_EDIT_INSTALLATIONS DIALOGEX 0, 0, 243, 221 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Edit Installations" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,125,199,50,14 - PUSHBUTTON "Cancel",IDCANCEL,185,199,50,14 - LISTBOX IDC_LIST,17,30,136,80,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | - WS_TABSTOP - EDITTEXT IDC_EDIT,19,167,136,13,ES_AUTOHSCROLL - PUSHBUTTON "Add",IDC_BUTTON_ADD,165,167,50,14 - PUSHBUTTON "Remove",IDC_BUTTON_REMOVE,160,54,68,15,WS_DISABLED - PUSHBUTTON "Make Default",IDC_BUTTON_MAKE_DEFAULT,160,34,68,15, - WS_DISABLED - GROUPBOX "Add New Installation",IDC_STATIC,7,130,228,59 - GROUPBOX "Current Installations",IDC_STATIC,7,7,228,114 - LTEXT "Enter the complete path to a StepMania or DWI installation\r\ne.g. ""C:\\Program Files\\StepMania""", - IDC_STATIC,18,144,196,17 - LTEXT "The top installation is the default.",IDC_STATIC,19,17, - 196,12 -END - -IDD_MENU DIALOGEX 0, 0, 332, 284 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "StepMania Tools Main Menu" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - CONTROL "",IDC_STATIC,"Static",SS_WHITERECT,0,0,331,33 - LTEXT "StepMania Tools Main Menu",IDC_STATIC_HEADER_TEXT,6,4, - 273,20 - DEFPUSHBUTTON "Exit",IDOK,275,263,50,14 - GROUPBOX "Installation",IDC_STATIC,7,41,318,28 - PUSHBUTTON "Edit Installations",IDC_EDIT_INSTALLATIONS,233,49,83,15 - GROUPBOX "Create and Share",IDC_STATIC,7,176,318,78 - PUSHBUTTON "Export Packages",IDC_EXPORT_PACKAGES,14,190,91,15 - LTEXT "Create .smzip package files to share with other users.", - IDC_STATIC,109,190,213,18 - PUSHBUTTON "Create Song",IDC_CREATE_SONG,14,211,91,15 - LTEXT "Create a new song in from your favorite mp3 or ogg music file.", - IDC_STATIC,109,211,213,20 - GROUPBOX "Troubleshooting",IDC_STATIC,7,73,318,99 - PUSHBUTTON "Change Preferences",IDC_CHANGE_PREFERENCES,14,85,91,15 - PUSHBUTTON "Open Preferences",IDC_OPEN_PREFERENCES,14,127,91,15 - LTEXT "Change the graphics API, sound API, and other settings that the game will use.", - IDC_STATIC,110,85,213,18 - PUSHBUTTON "Clear Preferences",IDC_CLEAR_PREFERENCES,14,106,91,15 - PUSHBUTTON "Clear Mappings",IDC_CLEAR_KEYMAPS,14,148,91,15 - EDITTEXT IDC_EDIT_INSTALLATION,16,51,210,12,ES_AUTOHSCROLL | - ES_READONLY - LTEXT "Erase all of your keyboard and joystick mappings if you've made a mistake.", - IDC_STATIC,109,148,213,18 - PUSHBUTTON "Launch Game",IDC_BUTTON_LAUNCH_GAME,183,263,76,14 - PUSHBUTTON "Languages",IDC_LANGUAGES,14,232,91,15 - LTEXT "Create a new or manage existing language translations.", - IDC_STATIC,109,232,213,20 - LTEXT "Open the preferences file to make changes by hand.", - IDC_STATIC,109,127,213,18 - LTEXT "Clear all preferences if you've made changes and the game won't start.", - IDC_STATIC,109,106,213,18 - CONTROL "",IDC_STATIC,"Static",SS_ETCHEDFRAME,0,33,331,1 - ICON IDR_MAINFRAME,IDC_STATIC_ICON,295,6,21,20,0, - WS_EX_TRANSPARENT -END - -IDD_ENTER_COMMENT DIALOGEX 0, 0, 324, 203 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Add A Comment" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - LTEXT "You can add a message to display before a user installs your package.", - IDC_STATIC,7,7,252,18 - CONTROL "Show a comment",IDC_SHOW_A_COMMENT,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,19,39,185,12 - EDITTEXT IDC_EDIT,17,53,232,123,ES_MULTILINE | ES_AUTOHSCROLL - CONTROL "Don't display this dialog in the future",IDC_DONTASK, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,185,145,11 - DEFPUSHBUTTON "OK",IDOK,267,7,50,14 - PUSHBUTTON "Cancel",IDCANCEL,267,24,50,14 - GROUPBOX "Package Comment",IDC_STATIC,7,29,252,152 -END - -IDD_SHOW_COMMENT DIALOGEX 0, 0, 246, 186 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Package Comment" -FONT 8, "MS Sans Serif", 0, 0, 0x1 -BEGIN - EDITTEXT IDC_EDIT,7,7,232,137,ES_MULTILINE | ES_AUTOHSCROLL | - ES_READONLY - DEFPUSHBUTTON "OK",IDOK,72,165,50,14 - PUSHBUTTON "Cancel",IDCANCEL,128,165,50,14 - CONTROL "Don't display this dialog in the future",IDC_DONTSHOW, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,149,145,11 -END - -IDD_UNINSTALL_OLD_PACKAGES DIALOGEX 0, 0, 228, 152 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "Uninstall Old Packages" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "&Yes",IDOK,31,131,50,14 - PUSHBUTTON "Cancel",IDCANCEL,147,131,50,14 - LTEXT "The following packages are already installed. It is strongly recommended that they be deleted before installing this package.", - IDC_STATIC,7,7,214,27 - EDITTEXT IDC_PACKAGES,31,36,165,77,ES_MULTILINE | ES_AUTOHSCROLL | - ES_READONLY | WS_VSCROLL - PUSHBUTTON "&No",IDC_BUTTON1,87,131,49,14 - CTEXT "Delete old packages?",IDC_STATIC,31,117,166,12 -END - -IDD_CHANGE_GAME_SETTINGS DIALOGEX 0, 0, 162, 298 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU -CAPTION "Change Game Settings" -FONT 8, "MS Sans Serif", 0, 0, 0x0 -BEGIN - DEFPUSHBUTTON "OK",IDOK,49,276,50,14 - PUSHBUTTON "Cancel",IDCANCEL,104,276,50,14 - GROUPBOX "Graphics API",IDC_STATIC,7,7,147,66 - CONTROL "Default (recommended)",IDC_RADIO_DEFAULT,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,21,22,129,12 - CONTROL "OpenGL",IDC_RADIO_OPENGL,"Button",BS_AUTORADIOBUTTON,21, - 38,129,12 - CONTROL "Direct3D",IDC_RADIO_DIRECT3D,"Button", - BS_AUTORADIOBUTTON,21,54,129,12 - GROUPBOX "Sound API",IDC_STATIC,7,77,147,100 - CONTROL "Default (recommended)",IDC_RADIO_SOUND_DEFAULT,"Button", - BS_AUTORADIOBUTTON | WS_GROUP,21,92,129,12 - CONTROL "DirectSound Hardware", - IDC_RADIO_SOUND_DIRECTSOUND_HARDWARE,"Button", - BS_AUTORADIOBUTTON,21,108,129,12 - CONTROL "DirectSound Software", - IDC_RADIO_SOUND_DIRECTSOUND_SOFTWARE,"Button", - BS_AUTORADIOBUTTON,21,124,129,12 - CONTROL "WaveOut",IDC_RADIO_SOUND_WAVEOUT,"Button", - BS_AUTORADIOBUTTON,21,140,129,12 - CONTROL "Null (no sound)",IDC_RADIO_SOUND_NULL,"Button", - BS_AUTORADIOBUTTON,21,156,129,12 - GROUPBOX "Other",IDC_STATIC,7,181,147,62 - CONTROL "Log to Disk",IDC_CHECK_LOG_TO_DISK,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,21,210,129,10 - CONTROL "Show Log Window",IDC_CHECK_SHOW_LOG_WINDOW,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,21,225,129,10 - LTEXT "Tip: Change these only if you experience problems when using the default settings.", - IDC_STATIC,7,247,147,26 - CONTROL "Force 60Hz Refresh",IDC_CHECK_FORCE_60HZ,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,21,195,129,10 -END - -IDD_LANGUAGES DIALOGEX 0, 0, 337, 189 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "Language Translations" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "Close",IDOK,280,168,50,14 - LTEXT "Themes",IDC_STATIC,7,7,101,10 - LTEXT "Languages",IDC_STATIC,118,7,98,10 - PUSHBUTTON "Create Language",IDC_BUTTON_CREATE,230,41,91,15 - PUSHBUTTON "Delete Language",IDC_BUTTON_DELETE,230,62,91,15 - PUSHBUTTON "Export CSV",IDC_BUTTON_EXPORT,230,83,91,15 - PUSHBUTTON "Import CSV",IDC_BUTTON_IMPORT,230,123,91,15 - LTEXT "1) Create a new language\n2) Export the theme strings to a CSV\n3) Edit the CSV using Excel or a text editor\n4) Import the CSV file back into the same language", - IDC_STATIC,7,145,258,37 - LTEXT "Selection details",IDC_STATIC,230,7,100,9 - LTEXT "Total Strings:",IDC_STATIC,221,17,89,10 - LTEXT "Need translation:",IDC_STATIC,221,28,89,10 - LTEXT "",IDC_STATIC_TOTAL_STRINGS,307,18,26,10 - LTEXT "",IDC_STATIC_NEED_TRANSLATION,307,27,26,10 - LISTBOX IDC_LIST_THEMES,7,18,102,121,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - LISTBOX IDC_LIST_LANGUAGES,116,17,100,121,LBS_SORT | - LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP - CONTROL "Export already translated strings", - IDC_CHECK_EXPORT_ALREADY_TRANSLATED,"Button", - BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,221,100,109, - 16 - PUSHBUTTON "Check Language",IDC_CHECK_LANGUAGE,230,143,91,13 -END - -IDD_CREATE_LANGUAGE DIALOGEX 0, 0, 191, 47 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "Create Language" -FONT 8, "MS Shell Dlg", 400, 0, 0x1 -BEGIN - DEFPUSHBUTTON "OK",IDOK,128,7,56,14 - PUSHBUTTON "Cancel",IDCANCEL,128,27,56,14 - LTEXT "Choose a language",IDC_STATIC,7,7,110,11 - COMBOBOX IDC_COMBO_LANGUAGES,17,24,100,110,CBS_DROPDOWNLIST | - CBS_SORT | WS_VSCROLL | WS_TABSTOP -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "FileDescription", "StepMania Tools" - VALUE "FileVersion", "1, 0, 0, 1" - VALUE "InternalName", "smpackage" - VALUE "LegalCopyright", "Copyright (C) StepMania team" - VALUE "OriginalFilename", "tools.exe" - VALUE "ProductName", "StepMania Tools" - VALUE "ProductVersion", "1, 0, 0, 1" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_INSTALL, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 325 - TOPMARGIN, 7 - BOTTOMMARGIN, 227 - END - - IDD_EXPORTER, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 341 - TOPMARGIN, 7 - BOTTOMMARGIN, 215 - END - - IDD_DIALOG_NAME, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 254 - TOPMARGIN, 7 - BOTTOMMARGIN, 51 - END - - IDD_EDIT_INSTALLATIONS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 235 - TOPMARGIN, 7 - BOTTOMMARGIN, 213 - END - - IDD_MENU, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 325 - TOPMARGIN, 7 - BOTTOMMARGIN, 277 - END - - IDD_ENTER_COMMENT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 317 - TOPMARGIN, 7 - BOTTOMMARGIN, 196 - END - - IDD_SHOW_COMMENT, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 239 - TOPMARGIN, 7 - BOTTOMMARGIN, 179 - END - - IDD_UNINSTALL_OLD_PACKAGES, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 221 - TOPMARGIN, 7 - BOTTOMMARGIN, 145 - END - - IDD_CHANGE_GAME_SETTINGS, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 154 - TOPMARGIN, 7 - BOTTOMMARGIN, 290 - END - - IDD_LANGUAGES, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 330 - TOPMARGIN, 7 - BOTTOMMARGIN, 182 - END - - IDD_CREATE_LANGUAGE, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 184 - TOPMARGIN, 7 - BOTTOMMARGIN, 40 - END -END -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// -#define _AFX_NO_SPLITTER_RESOURCES -#define _AFX_NO_OLE_RESOURCES -#define _AFX_NO_TRACKER_RESOURCES -#define _AFX_NO_PROPERTY_RESOURCES - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE 9, 1 -#pragma code_page(1252) -#endif //_WIN32 -#include "res\smpackage.rc2" // non-Microsoft Visual C++ edited resources -#include "afxres.rc" // Standard components -#endif - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/src/smpackagee/smpackageUtil.h b/src/smpackagee/smpackageUtil.h deleted file mode 100644 index 6beba92b82..0000000000 --- a/src/smpackagee/smpackageUtil.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef SMPackageUtil_H -#define SMPackageUtil_H - -struct LanguageInfo; - -namespace SMPackageUtil { -void -WriteGameInstallDirs(const vector& asInstallDirsToWrite); -void -GetGameInstallDirs(vector& asInstallDirsOut); -void -AddGameInstallDir(const RString& sNewInstallDir); -void -SetDefaultInstallDir(int iInstallDirIndex); -void -SetDefaultInstallDir(const RString& sInstallDir); -bool -IsValidInstallDir(const RString& sInstallDir); - -bool -GetPref(const RString& name, bool& val); -bool -SetPref(const RString& name, bool val); - -RString -GetPackageDirectory(const RString& path); -bool -IsValidPackageDirectory(const RString& path); - -bool -LaunchGame(); - -RString -GetLanguageDisplayString(const RString& sIsoCode); -RString -GetLanguageCodeFromDisplayString(const RString& sDisplayString); - -void -StripIgnoredSmzipFiles(vector& vsFilesInOut); - -bool -GetFileContentsOsAbsolute(const RString& sAbsoluteOsFile, RString& sOut); - -bool -DoesOsAbsoluteFileExist(const RString& sOsAbsoluteFile); -} - -#include "RageFile.h" - -class RageFileOsAbsolute : public RageFile -{ - public: - bool Open(const RString& path, int mode = READ); - ~RageFileOsAbsolute(); - - private: - RString m_sOsDir; -}; - -#endif - -/* - * (c) 2002-2005 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ From df22493b4390907c7eab80b31016c80c06af71e6 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 25 Nov 2018 23:32:14 -0500 Subject: [PATCH 058/320] add recursive actor utility functions for mouseovers and visibility --- src/Actor.cpp | 81 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/Actor.h | 7 +++++ 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 4083f49139..d949826db1 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -299,6 +299,65 @@ Actor::PartiallyOpaque() m_pTempState->glow.a > 0; } +bool +Actor::IsOver(float mx, float my) +{ + if (!IsVisible()) + return false; + + auto x = GetTrueX(); + auto y = GetTrueY(); + auto hal = GetHorizAlign(); + auto val = GetVertAlign(); + auto wi = GetZoomedWidth() * GetParent()->GetTrueZoom(); + auto hi = GetZoomedHeight() * GetParent()->GetTrueZoom(); + auto lr = x - (hal * wi); + auto rr = x + wi - (hal * wi); + auto ur = y - (val * hi); + auto br = ((y + hi) - (val * hi)); + bool withinX = mx >= lr && mx <= rr; + bool withinY = my >= ur && my <= br; + return withinX && withinY; +} +float +Actor::GetTrueX() +{ + if (!this) + return 0.f; + if (!m_pParent) + return GetX(); + return GetX() * GetParent()->GetTrueZoom() + + GetParent()->GetTrueX(); +} + +float +Actor::GetTrueY() +{ + if (!this) + return 0.f; + if (!m_pParent) + return GetY(); + return GetY() * GetParent()->GetTrueZoom() + + GetParent()->GetTrueY(); +} +float +Actor::GetTrueZoom() +{ + if (!this) + return 1.f; + if (!m_pParent) + return GetZoom(); + return GetZoom() * GetParent()->GetTrueZoom(); +} +bool +Actor::IsVisible() +{ + if (!this) + return false; + if (!m_pParent) + return GetVisible(); + return GetVisible() && GetParent()->IsVisible(); +} void Actor::Draw() { @@ -2599,11 +2658,19 @@ class LunaActor : public Luna static int LoadXY(T* p, lua_State* L) { auto doot = FILTERMAN->loadpos(p->GetName()); - p->SetX(doot.first); - p->SetY(doot.second); + p->SetX(static_cast(doot.first)); + p->SetY(static_cast(doot.second)); COMMON_RETURN_SELF; } - + static int IsOver(T* p, lua_State* L) + { + lua_pushboolean(L, p->IsOver(FArg(1), FArg(2))); + return 1; + } + DEFINE_METHOD(GetTrueX, GetTrueX()); + DEFINE_METHOD(GetTrueY, GetTrueY()); + DEFINE_METHOD(GetTrueZoom, GetTrueZoom()); + DEFINE_METHOD(IsVisible, IsVisible()); LunaActor() { ADD_METHOD(name); @@ -2777,9 +2844,15 @@ class LunaActor : public Luna ADD_METHOD(GetWrapperState); ADD_METHOD(Draw); - + ADD_METHOD(SaveXY); ADD_METHOD(LoadXY); + + ADD_METHOD(GetTrueX); + ADD_METHOD(GetTrueY); + ADD_METHOD(GetTrueZoom); + ADD_METHOD(IsVisible); + ADD_METHOD(IsOver); } }; diff --git a/src/Actor.h b/src/Actor.h index 47db4165bc..5e046147a4 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -258,6 +258,13 @@ class Actor : public MessageSubscriber // PartiallyOpaque broken out of Draw for reuse and clarity. bool PartiallyOpaque(); + bool IsOver(float mx, float my); + + float GetTrueX(); // recursive with parent (for mouseovers) -mina + float GetTrueY(); // same + float GetTrueZoom(); // same + bool IsVisible(); // same but for gating updates on things that may not explicitly set visible = false -mina + /** * @brief Calls multiple functions for drawing the Actors. * From 60324ecc04beffe6ef92c4b845759aff8c4ff381 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 00:42:30 -0500 Subject: [PATCH 059/320] make old lua mouseover functions aliases for internals --- Themes/_fallback/Scripts/00 Utility.lua | 60 ++----------------------- 1 file changed, 3 insertions(+), 57 deletions(-) diff --git a/Themes/_fallback/Scripts/00 Utility.lua b/Themes/_fallback/Scripts/00 Utility.lua index d6b2f5c29a..8b7a0160e2 100644 --- a/Themes/_fallback/Scripts/00 Utility.lua +++ b/Themes/_fallback/Scripts/00 Utility.lua @@ -38,14 +38,7 @@ end -- @tparam actor element the actor -- @treturn number function getTrueX(element) - if element == nil then - return 0 - end - if element:GetParent() == nil then - return element:GetX() or 0 - else - return element:GetX() + getTrueX(element:GetParent()) - end + element:GetTrueX() end --- Get the actor's real Y (Not relative to the parent like self:GetY()) by recursively grabbing the parents' position @@ -53,62 +46,15 @@ end -- @tparam actor element the actor -- @treturn number function getTrueY(element) - if element == nil then - return 0 - end - if element:GetParent() == nil then - return element:GetY() or 0 - else - return element:GetY() + getTrueY(element:GetParent()) - end + element:GetTrueY() end --- Checks whether the mouse is over an actor -- @tparam actor element the actor -- @treturn bool true if the mouse is over the actor function isOver(element) - --[[ - if element:GetVisible() == false then - return false - end; - --]] - local x = getTrueX(element) - local y = getTrueY(element) - local hAlign = element:GetHAlign() - local vAlign = element:GetVAlign() - local w = element:GetZoomedWidth() - local h = element:GetZoomedHeight() - local mouse = getMousePosition() - - local withinX = (mouse.x >= (x - (hAlign * w))) and (mouse.x <= ((x + w) - (hAlign * w))) - local withinY = (mouse.y >= (y - (vAlign * h))) and (mouse.y <= ((y + h) - (vAlign * h))) - - return (withinX and withinY) -end - ---- For when its just wrong and you need to control the scale yourself --- @tparam actor element the actor --- @number scale Multiplier --- @treturn bool true if the mouse is over the actor -function isOverScaled(element, scale) - if not scale then - scale = 1 - end - local x = getTrueX(element) - local y = getTrueY(element) - local hAlign = element:GetHAlign() - local vAlign = element:GetVAlign() - local w = element:GetZoomedWidth() * scale - local h = element:GetZoomedHeight() * scale - - local mouseX = INPUTFILTER:GetMouseX() - local mouseY = INPUTFILTER:GetMouseY() - - local withinX = (mouseX >= (x - (hAlign * w))) and (mouseX <= ((x + w) - (hAlign * w))) - local withinY = (mouseY >= (y - (vAlign * h))) and (mouseY <= ((y + h) - (vAlign * h))) - - return (withinX and withinY) + return element:IsOver(mouse.x, mouse.y) end --- returns true if the table contains the key. From 5437e7150b4f70f3c9a84ffd11443ca2d32b6030 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:10:40 -0500 Subject: [PATCH 060/320] not sure why these don't work with the new aliases also these are still sort of busted --- Themes/Til Death/Graphics/Player combo/default.lua | 2 +- Themes/Til Death/Graphics/Player judgment/default.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/Graphics/Player combo/default.lua b/Themes/Til Death/Graphics/Player combo/default.lua index f8cba7c593..5ddf653277 100644 --- a/Themes/Til Death/Graphics/Player combo/default.lua +++ b/Themes/Til Death/Graphics/Player combo/default.lua @@ -61,7 +61,7 @@ local t = c.Number:visible(true) c.Label:visible(true) c.Number:settext(1000) - Movable.DeviceButton_3.propertyOffsets = {getTrueX(self) -6, getTrueY(self) + c.Number:GetHeight()*1.5} -- centered to screen/valigned + Movable.DeviceButton_3.propertyOffsets = {self:GetTrueX() -6, self:GetTrueY() + c.Number:GetHeight()*1.5} -- centered to screen/valigned setBorderAlignment(c.Border, 0.5, 1) end arbitraryComboZoom(MovableValues.ComboZoom) diff --git a/Themes/Til Death/Graphics/Player judgment/default.lua b/Themes/Til Death/Graphics/Player judgment/default.lua index 0b88dcb2ae..908e388504 100644 --- a/Themes/Til Death/Graphics/Player judgment/default.lua +++ b/Themes/Til Death/Graphics/Player judgment/default.lua @@ -51,7 +51,7 @@ local t = Movable.DeviceButton_2.condition = enabledJudgment Movable.DeviceButton_2.DeviceButton_up.arbitraryFunction = judgmentZoom Movable.DeviceButton_2.DeviceButton_down.arbitraryFunction = judgmentZoom - Movable.DeviceButton_1.propertyOffsets = {getTrueX(self) , getTrueY(self) - c.Judgment:GetHeight()} -- centered to screen/valigned + Movable.DeviceButton_1.propertyOffsets = {self:GetTrueX() , self:GetTrueY() - c.Judgment:GetHeight()} -- centered to screen/valigned end end, JudgmentMessageCommand = function(self, param) From bf869c5025ef9b0377292819aa8f4704f44c94a0 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:12:19 -0500 Subject: [PATCH 061/320] remove some local isovers (their behavior is the same as the new one) --- .../playlists.lua | 30 +------------------ .../ScreenSelectMusic decorations/score.lua | 26 ---------------- .../BGAnimations/superscoreboard.lua | 26 ---------------- 3 files changed, 1 insertion(+), 81 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua index 052a44da93..897d795948 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua @@ -110,7 +110,7 @@ local function BroadcastIfActive(msg) end local function ButtonActive(self, scale) - return isOverScaled(self, scale) and update + return isOver(self) and update end local r = @@ -409,19 +409,6 @@ local b2 = end } ---Add chart button --- b2[#b2+1] = LoadFont("Common Large") .. {InitCommand=cmd(zoom,0.3;x,245;settext,"Add Chart")} --- b2[#b2+1] = Def.Quad{ --- InitCommand=function(self) --- self:x(245):diffusealpha(buttondiffuse):zoomto(80,20) --- end, --- MouseLeftClickMessageCommand=function(self) --- if ButtonActive(self) and singleplaylistactive then --- pl:AddChart(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey()) --- end --- end --- } --- Play As Course button b2[#b2 + 1] = LoadFont("Common Large") .. { @@ -722,21 +709,6 @@ local b = end } --- zzzz button positioning is lame... use shortcut key for now whynot --- New Playlist --- b[#b+1] = LoadFont("Common Large") .. {InitCommand=cmd(zoom,0.3;settext,"New Playlist")} --- b[#b+1] = Def.Quad{ --- InitCommand=function(self) --- self:diffusealpha(buttondiffuse):zoomto(110,20) --- end, --- MouseLeftClickMessageCommand=function(self) --- if ButtonActive(self,0.3) and allplaylistsactive then --- SONGMAN:NewPlaylist() --- MESSAGEMAN:Broadcast("DisplayAll") --- end --- end --- } - playlists[#playlists + 1] = b for i = 1, chartsperplaylist do diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 614eab9344..d22b70e409 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -45,32 +45,6 @@ else defaultRateText = "All" end -local function isOver(element) - if element:GetParent():GetParent():GetVisible() == false then - return false - end - if element:GetParent():GetVisible() == false then - return false - end - if element:GetVisible() == false then - return false - end - local x = getTrueX(element) - local y = getTrueY(element) - local hAlign = element:GetHAlign() - local vAlign = element:GetVAlign() - local w = element:GetZoomedWidth() - local h = element:GetZoomedHeight() - - local mouseX = INPUTFILTER:GetMouseX() - local mouseY = INPUTFILTER:GetMouseY() - - local withinX = (mouseX >= (x - (hAlign * w))) and (mouseX <= ((x + w) - (hAlign * w))) - local withinY = (mouseY >= (y - (vAlign * h))) and (mouseY <= ((y + h) - (vAlign * h))) - - return (withinX and withinY) -end - -- should maybe make some of these generic local function highlight(self) if self:GetVisible() then diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index af438eb684..895a8f2f4a 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -43,32 +43,6 @@ local function input(event) return false end -local function isOver(element) - if element:GetParent():GetParent():GetVisible() == false then - return false - end - if element:GetParent():GetVisible() == false then - return false - end - if element:GetVisible() == false then - return false - end - local x = getTrueX(element) - local y = getTrueY(element) - local hAlign = element:GetHAlign() - local vAlign = element:GetVAlign() - local w = element:GetZoomedWidth() - local h = element:GetZoomedHeight() - - local mouseX = INPUTFILTER:GetMouseX() - local mouseY = INPUTFILTER:GetMouseY() - - local withinX = (mouseX >= (x - (hAlign * w))) and (mouseX <= ((x + w) - (hAlign * w))) - local withinY = (mouseY >= (y - (vAlign * h))) and (mouseY <= ((y + h) - (vAlign * h))) - - return (withinX and withinY) -end - local function highlight(self) if self:GetVisible() then self:queuecommand("Highlight") From 67d15fc08f46be16981997a065f06318c156d681 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:15:16 -0500 Subject: [PATCH 062/320] fix theme error --- .../BGAnimations/ScreenNetSelectMusic decorations/default.lua | 2 +- .../BGAnimations/ScreenSelectMusic decorations/default.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua index a4136b6b65..5386ad53cb 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua @@ -132,7 +132,7 @@ g[#g + 1] = PlayingSampleMusicMessageCommand = function(self) local leaderboardEnabled = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() - if leaderboardEnabled then + if leaderboardEnabled and GAMESTATE:GetCurrentSteps(PLAYER_1) then local chartkey = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() DLMAN:RequestChartLeaderBoardFromOnline( chartkey, diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua index 1c677736c0..4485e07a18 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua @@ -46,7 +46,7 @@ t[#t + 1] = PlayingSampleMusicMessageCommand = function(self) local leaderboardEnabled = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() - if leaderboardEnabled then + if leaderboardEnabled and GAMESTATE:GetCurrentSteps(PLAYER_1) then local chartkey = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() DLMAN:RequestChartLeaderBoardFromOnline( chartkey, From 5249e8f8e3f0017586aad9719da7dfdd6a81b016 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:37:05 -0500 Subject: [PATCH 063/320] add a wrapper for getting fake/real parents and use them for recursives --- src/Actor.cpp | 39 ++++++++++++++++++++++++++------------- src/Actor.h | 1 + 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index d949826db1..dc004ba529 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -309,8 +309,8 @@ Actor::IsOver(float mx, float my) auto y = GetTrueY(); auto hal = GetHorizAlign(); auto val = GetVertAlign(); - auto wi = GetZoomedWidth() * GetParent()->GetTrueZoom(); - auto hi = GetZoomedHeight() * GetParent()->GetTrueZoom(); + auto wi = GetZoomedWidth() * GetFakeParentOrParent()->GetTrueZoom(); + auto hi = GetZoomedHeight() * GetFakeParentOrParent()->GetTrueZoom(); auto lr = x - (hal * wi); auto rr = x + wi - (hal * wi); auto ur = y - (val * hi); @@ -319,15 +319,26 @@ Actor::IsOver(float mx, float my) bool withinY = my >= ur && my <= br; return withinX && withinY; } +Actor* +Actor::GetFakeParentOrParent() +{ + if (!this) + return nullptr; + if (m_FakeParent) + return m_FakeParent; + if (m_pParent) + return m_pParent; + return nullptr; +} float Actor::GetTrueX() { if (!this) return 0.f; - if (!m_pParent) + auto* mfp = GetFakeParentOrParent(); + if (!mfp) return GetX(); - return GetX() * GetParent()->GetTrueZoom() + - GetParent()->GetTrueX(); + return GetX() * mfp->GetTrueZoom() + mfp->GetTrueX(); } float @@ -335,28 +346,30 @@ Actor::GetTrueY() { if (!this) return 0.f; - if (!m_pParent) + auto* mfp = GetFakeParentOrParent(); + if (!mfp) return GetY(); - return GetY() * GetParent()->GetTrueZoom() + - GetParent()->GetTrueY(); + return GetY() * mfp->GetTrueZoom() + mfp->GetTrueY(); } float Actor::GetTrueZoom() { if (!this) return 1.f; - if (!m_pParent) + auto* mfp = GetFakeParentOrParent(); + if (!mfp) return GetZoom(); - return GetZoom() * GetParent()->GetTrueZoom(); + return GetZoom() * mfp->GetTrueZoom(); } bool Actor::IsVisible() { if (!this) return false; - if (!m_pParent) + auto* mfp = GetFakeParentOrParent(); + if (!mfp) return GetVisible(); - return GetVisible() && GetParent()->IsVisible(); + return GetVisible() && mfp->IsVisible(); } void Actor::Draw() @@ -2844,7 +2857,7 @@ class LunaActor : public Luna ADD_METHOD(GetWrapperState); ADD_METHOD(Draw); - + ADD_METHOD(SaveXY); ADD_METHOD(LoadXY); diff --git a/src/Actor.h b/src/Actor.h index 5e046147a4..73e8e0a8b5 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -260,6 +260,7 @@ class Actor : public MessageSubscriber bool PartiallyOpaque(); bool IsOver(float mx, float my); + Actor* GetFakeParentOrParent(); // fake parent > parent -mina float GetTrueX(); // recursive with parent (for mouseovers) -mina float GetTrueY(); // same float GetTrueZoom(); // same From 6b157fe7d35675e5b2be386c463e1ae2da786375 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:37:28 -0500 Subject: [PATCH 064/320] use more standard setfake parent to handle lifebar customizability --- .../ScreenGameplay overlay/WifeJudgmentSpotting.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua index f5ac00013c..253296c53b 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/WifeJudgmentSpotting.lua @@ -180,8 +180,7 @@ local t = Movable.DeviceButton_t.element = noteColumns Movable.DeviceButton_r.condition = true Movable.DeviceButton_t.condition = true - lifebar:AddChild(self:GetChild("Border")) - -- self:RemoveChild("Border") ayy lmao + self:GetChild("LifeP1"):GetChild("Border"):SetFakeParent(lifebar) Movable.DeviceButton_j.element = lifebar Movable.DeviceButton_j.condition = true Movable.DeviceButton_k.element = lifebar @@ -209,9 +208,11 @@ local t = end } --- lifebar border, this is really ghetto i dont like it -t[#t + 1] = MovableBorder(200, 5, 1, -35, 0) - +-- lifebard +t[#t + 1] = Def.ActorFrame{ + Name = "LifeP1", + MovableBorder(200, 5, 1, -35, 0) +} --[[~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **LaneCover** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 58ad984c75a364c43c8c5b16ca3a1c926a6ec064 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 03:37:57 -0300 Subject: [PATCH 065/320] First attempt at chart requests --- src/NetworkSyncManager.cpp | 28 ++++++++++++++++++++++++++++ src/NetworkSyncManager.h | 17 +++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index df2769b0d6..746c9db4c9 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -65,6 +65,7 @@ std::map ettServerMessageMap = { { "newroom", ettps_newroom }, { "updateroom", ettps_updateroom }, { "userlist", ettps_roomuserlist }, + { "chartrequest", ettps_chartrequest } }; #if defined(WITHOUT_NETWORKING) @@ -915,6 +916,9 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) SCREENMAN->SetNewScreen(SMOnlineSelectScreen); } } break; + case ettps_chartrequest: { + n->requests.emplace_back(ChartRequest(*payload)); + } break; case ettps_enterroomresponse: { bool entered = (*payload)["entered"]; inRoom = false; @@ -2482,6 +2486,18 @@ NetworkSyncManager::GetCurrentSMBuild(LoadingWindow* ld) } #endif +void +ChartRequest::PushSelf(lua_State* L) +{ + lua_createtable(L, 0, 3); + lua_pushstring(L, chartkey.c_str()); + lua_setfield(L, -2, "chartkey"); + lua_pushstring(L, user.c_str()); + lua_setfield(L, -2, "user"); + lua_pushnumber(L, rate / 1000); // should this be in [0,1] or [0, 1000] ???? + lua_setfield(L, -2, "rate"); +} + static bool ConnectToServer(const RString& t) { @@ -2527,6 +2543,18 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) lua_pushboolean(L, p->IsETTP()); return 1; } + static int GetChartRequests(T* p, lua_State* L) + { + auto& reqs = p->requests; + lua_newtable(L); + int i = 1; + for (auto& req : reqs) { + req.PushSelf(L); + lua_rawseti(L, -2, 0); + i++; + } + return 1; + } static int GetChatMsg(T* p, lua_State* L) { unsigned int l = IArg(1); diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index 8e6297c1a6..843c0a9fee 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -96,6 +96,7 @@ enum ETTServerMessageTypes ettps_newroom, ettps_updateroom, ettps_roomuserlist, + ettps_chartrequest, ettps_end }; enum ETTClientMessageTypes @@ -132,6 +133,21 @@ struct NetServerInfo RString Address; }; +class ChartRequest +{ + public: + ChartRequest(json& j) + : chartkey(j["chartkey"].get()) + , user(j["requester"].get()) + , rate(j["rate"]) + { + } + const string chartkey; + const string user; // User that requested this chart + const int rate; // rate * 1000 + void PushSelf(lua_State* L); +}; + class EzSockets; class StepManiaLanServer; @@ -457,6 +473,7 @@ class NetworkSyncManager void Login(RString user, RString pass); void Logout(); vector m_Rooms; + vector requests; #if !defined(WITHOUT_NETWORKING) SMOStepType TranslateStepType(int score); From 333eefb837fa0d1585204a844eb29099967bc35c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:41:26 -0500 Subject: [PATCH 066/320] dont expose addchild to lua anymore (single use case eliminated) --- src/ActorFrame.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/ActorFrame.cpp b/src/ActorFrame.cpp index 11aadeb3d3..be34f9fbcf 100644 --- a/src/ActorFrame.cpp +++ b/src/ActorFrame.cpp @@ -792,19 +792,6 @@ class LunaActorFrame : public Luna p->SetLightDirection(vTmp); COMMON_RETURN_SELF; } - - static int AddChild(T* p, lua_State* L) - { - if (lua_isnoneornil(L, 1)) { - lua_pushboolean(L, 0); - return 1; - } - Actor* pActor = Luna::check(L, 1); - p->AddChild(pActor); - lua_pushboolean(L, 1); - return 1; - } - static int AddChildFromPath(T* p, lua_State* L) { // this one is tricky, we need to get an Actor from Lua. @@ -858,7 +845,6 @@ class LunaActorFrame : public Luna ADD_METHOD(SetDiffuseLightColor); ADD_METHOD(SetSpecularLightColor); ADD_METHOD(SetLightDirection); - ADD_METHOD(AddChild); ADD_METHOD(AddChildFromPath); ADD_METHOD(RemoveChild); ADD_METHOD(RemoveAllChildren); From 9e8cd8cd3b086c12bdb664609c16c20406237da0 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:59:25 -0500 Subject: [PATCH 067/320] use recursive isvisible instead of getvisible throughout music select --- .../ScreenSelectMusic decorations/goaltracker.lua | 11 +++++------ .../ScreenSelectMusic decorations/score.lua | 6 +++--- .../ScreenSelectMusic decorations/wifeTwirl.lua | 8 ++++---- .../ScreenSystemLayer overlay/default.lua | 2 +- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 4 ++-- Themes/Til Death/BGAnimations/goaldisplay.lua | 4 ++-- Themes/Til Death/BGAnimations/packlistDisplay.lua | 2 +- Themes/Til Death/BGAnimations/superscoreboard.lua | 4 ++-- .../Til Death/Graphics/StepsDisplayListRow frame.lua | 2 +- 9 files changed, 21 insertions(+), 22 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/goaltracker.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/goaltracker.lua index 17edd41758..f34aece870 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/goaltracker.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/goaltracker.lua @@ -1,8 +1,8 @@ local t = Def.ActorFrame { BeginCommand = function(self) - self:queuecommand("Set"):visible(false) - self:GetChild("GoalDisplay"):xy(10, 60):visible(false) + self:queuecommand("Set") + self:GetChild("GoalDisplay"):xy(10, 60) end, OffCommand = function(self) self:bouncebegin(0.2):xy(-500, 0):diffusealpha(0) @@ -14,11 +14,10 @@ local t = self:finishtweening(1) if getTabIndex() == 6 then self:queuecommand("On") - self:visible(true) -- input filter has a get:visible check so it doesn't eat inputs if the element isn't displayed - self:GetChild("GoalDisplay"):visible(true) -- however it isn't recursive, so we set the child explicitly, leaving this here to remind myself - else -- to look into changing the getvisible logic or adding a new recursive function maybe -mina + self:visible(true) + else self:queuecommand("Off") - self:GetChild("GoalDisplay"):xy(10, 60):visible(false) + self:visible(false) end end, TabChangedMessageCommand = function(self) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index d22b70e409..9a942c268f 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -47,7 +47,7 @@ end -- should maybe make some of these generic local function highlight(self) - if self:GetVisible() then + if self:IsVisible() then self:queuecommand("Highlight") end end @@ -197,7 +197,7 @@ local ret = local cheese -- eats only inputs that would scroll to a new score local function input(event) - if cheese:GetVisible() and isOver(cheese:GetChild("FrameDisplay")) then + if isOver(cheese:GetChild("FrameDisplay")) then if event.DeviceInput.button == "DeviceButton_mousewheel up" and event.type == "InputEventType_FirstPress" then moving = true if nestedTab == 1 and rtTable and rtTable[rates[rateIndex]] ~= nil then @@ -228,7 +228,7 @@ local t = SCREENMAN:GetTopScreen():AddInputCallback(input) end, OnCommand = function(self) - if nestedTab == 1 and self:GetVisible() then + if nestedTab == 1 and self:IsVisible() then if GAMESTATE:GetCurrentSong() ~= nil then rtTable = getRateTable() if rtTable ~= nil then diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 25af56e8fb..7fb82c7432 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -37,7 +37,7 @@ local t = if song ~= bong then song = bong self:queuecommand("MortyFarts") - if noteField and mcbootlarder:GetChild("NoteField"):GetVisible() and song then + if noteField and mcbootlarder:GetChild("NoteField"):IsVisible() and song then song:Borp() end end @@ -54,7 +54,7 @@ local t = self:queuecommand("On") update = true else - if GAMESTATE:GetCurrentSong() and noteField and mcbootlarder:GetVisible() then + if GAMESTATE:GetCurrentSong() and noteField and mcbootlarder:IsVisible() then mcbootlarder:visible(false) mcbootlarder:GetChild("NoteField"):visible(false) MESSAGEMAN:Broadcast("ChartPreviewOff") @@ -65,7 +65,7 @@ local t = end end, MilkyTartsCommand=function(self) -- when entering pack screenselectmusic explicitly turns visibilty on notefield off -mina - if noteField and mcbootlarder:GetVisible() then + if noteField and mcbootlarder:IsVisible() then mcbootlarder:visible(false) MESSAGEMAN:Broadcast("ChartPreviewOff") heyiwasusingthat = true @@ -127,7 +127,7 @@ local function toggleNoteField() return end if song then - if mcbootlarder:GetVisible() then + if mcbootlarder:IsVisible() then mcbootlarder:visible(false) mcbootlarder:GetChild("NoteField"):visible(false) MESSAGEMAN:Broadcast("ChartPreviewOff") diff --git a/Themes/Til Death/BGAnimations/ScreenSystemLayer overlay/default.lua b/Themes/Til Death/BGAnimations/ScreenSystemLayer overlay/default.lua index 64ad2112cb..38cc2534ff 100644 --- a/Themes/Til Death/BGAnimations/ScreenSystemLayer overlay/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSystemLayer overlay/default.lua @@ -49,7 +49,7 @@ local hhh = SCREEN_HEIGHT * 0.8 local rtzoom = 0.6 local function dooting(self) - if self:GetVisible() then + if self:IsVisible() then self:GetChild("BGQframe"):queuecommand("dooting") end end diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index 87dfb16a36..6ecbc91463 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -95,7 +95,7 @@ local t = Def.ActorFrame { self:queuecommand("GraphUpdate") end, CurrentRateChangedMessageCommand = function(self) - if self:GetParent():GetVisible() then + if self:IsVisible() then self:queuecommand("GraphUpdate") end end, @@ -111,7 +111,7 @@ t[#t+1] = Def.ActorMultiVertex { Name = "CDGraphDrawer", GraphUpdateCommand = function(self) - if self:GetParent():GetVisible() then + if self:IsVisible() then updateGraphMultiVertex(cdg, self) self:GetParent():linear(0.3) self:GetParent():diffusealpha(1) diff --git a/Themes/Til Death/BGAnimations/goaldisplay.lua b/Themes/Til Death/BGAnimations/goaldisplay.lua index 4c79d145f2..5db4894796 100644 --- a/Themes/Til Death/BGAnimations/goaldisplay.lua +++ b/Themes/Til Death/BGAnimations/goaldisplay.lua @@ -24,7 +24,7 @@ local cheese -- will eat any mousewheel inputs to scroll pages while mouse is over the background frame local function input(event) - if cheese:GetVisible() and isOver(cheese:GetChild("FrameDisplay")) then + if isOver(cheese:GetChild("FrameDisplay")) then if event.DeviceInput.button == "DeviceButton_mousewheel up" and event.type == "InputEventType_FirstPress" then moving = true cheese:queuecommand("PrevPage") @@ -40,7 +40,7 @@ local function input(event) end local function highlight(self) - if cheese:GetVisible() then + if cheese:IsVisible() then self:queuecommand("Highlight") end end diff --git a/Themes/Til Death/BGAnimations/packlistDisplay.lua b/Themes/Til Death/BGAnimations/packlistDisplay.lua index c44792a494..feabc80327 100644 --- a/Themes/Til Death/BGAnimations/packlistDisplay.lua +++ b/Themes/Til Death/BGAnimations/packlistDisplay.lua @@ -196,7 +196,7 @@ local function makePackDisplay(i) highlightIfOver(self) end, MouseLeftClickMessageCommand = function(self) - if isOver(self) and self:GetParent():GetParent():GetVisible() then -- probably should have the isOver function do a recursive parent check? + if isOver(self) then -- now contains recursive visibility checks -mina local urlstringyo = "https://etternaonline.com/pack/" .. packinfo:GetID() -- not correct value for site id GAMESTATE:ApplyGameCommand("urlnoexit," .. urlstringyo) end diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index 895a8f2f4a..7f8839e60c 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -28,7 +28,7 @@ local isGlobalRanking = true -- will eat any mousewheel inputs to scroll pages while mouse is over the background frame local function input(event) - if cheese:GetVisible() and isOver(cheese:GetChild("FrameDisplay")) then + if isOver(cheese:GetChild("FrameDisplay")) then -- visibility checks are built into isover now -mina if event.DeviceInput.button == "DeviceButton_mousewheel up" and event.type == "InputEventType_FirstPress" then moving = true cheese:queuecommand("PrevPage") @@ -44,7 +44,7 @@ local function input(event) end local function highlight(self) - if self:GetVisible() then + if self:IsVisible() then self:queuecommand("Highlight") self:queuecommand("WHAZZZAAAA") end diff --git a/Themes/Til Death/Graphics/StepsDisplayListRow frame.lua b/Themes/Til Death/Graphics/StepsDisplayListRow frame.lua index 571d2b348f..1dbee0e319 100644 --- a/Themes/Til Death/Graphics/StepsDisplayListRow frame.lua +++ b/Themes/Til Death/Graphics/StepsDisplayListRow frame.lua @@ -1,5 +1,5 @@ local function highlight(self) - if self:GetParent():GetVisible() then + if self:IsVisible() then self:queuecommand("Highlight") end end From f6e20a8ef57c66aac240400e8b91f2e964a359a6 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 01:59:40 -0500 Subject: [PATCH 068/320] fix scoreboard theme errors --- Themes/Til Death/BGAnimations/superscoreboard.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index 7f8839e60c..15b6d87c72 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -92,6 +92,9 @@ local o = self:playcommand("Update") end, UpdateCommand = function(self) + if not scoretable then + scoretable = {} + end if ind == #scoretable then ind = ind - numscores elseif ind > #scoretable - (#scoretable % numscores) then From e2f071379c26be323b1d8852cff4f9a9d5c84d1f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 02:57:58 -0500 Subject: [PATCH 069/320] add lua accessible play preview music function --- src/Song.cpp | 28 +++++++++++++++++++++++++++- src/Song.h | 3 +++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/Song.cpp b/src/Song.cpp index d9f2753279..b508fe1101 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -2075,6 +2075,27 @@ Song::Borp() SOUND->PlayMusic(PlayParams, FallbackMusic); } +void +Song::Norf() +{ + GameSoundManager::PlayMusicParams PlayParams; + PlayParams.sFile = GetMusicPath(); + PlayParams.pTiming = nullptr; + PlayParams.bForceLoop = true; + PlayParams.fStartSecond = m_fMusicSampleStartSeconds; + PlayParams.fLengthSeconds = m_fMusicSampleLengthSeconds; + PlayParams.fFadeOutLengthSeconds = 1.f; + PlayParams.bAlignBeat = true; + PlayParams.bApplyMusicRate = true; + + GameSoundManager::PlayMusicParams FallbackMusic; + FallbackMusic.sFile = GetMusicPath(); + FallbackMusic.fFadeInLengthSeconds = 1.f; + FallbackMusic.bAlignBeat = true; + + SOUND->PlayMusic(PlayParams, FallbackMusic); +} + // lua start #include "LuaBinding.h" @@ -2506,7 +2527,11 @@ class LunaSong : public Luna p->Borp(); return 0; } - + static int Norf(T* p, lua_State* L) + { + p->Norf(); + return 0; + } LunaSong() { ADD_METHOD(GetDisplayFullTitle); @@ -2576,6 +2601,7 @@ class LunaSong : public Luna ADD_METHOD(GetPreviewMusicPath); ADD_METHOD(ReloadFromSongDir); ADD_METHOD(Borp); + ADD_METHOD(Norf); } }; diff --git a/src/Song.h b/src/Song.h index f7205ece4c..d9ede3b4c0 100644 --- a/src/Song.h +++ b/src/Song.h @@ -441,6 +441,9 @@ class Song // plays music for chart preview and is available to lua -mina void Borp(); + // plays just normal preview, for those annoying places in lua where it doesnt play properly -mina + void Norf(); + bool SongCompleteForStyle(const Style* st) const; bool HasStepsType(StepsType st) const; bool HasStepsTypeAndDifficulty(StepsType st, Difficulty dc) const; From 264fb63a27b7667592adc6075f1affd0deb3c79b Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 04:00:48 -0500 Subject: [PATCH 070/320] dont bother using fallback params for preview music playing this is apparently what kept causing music not to play when using 'selectsong' --- src/ScreenSelectMusic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 02b9940791..6c78dcfc15 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -355,7 +355,7 @@ ScreenSelectMusic::CheckBackgroundRequests(bool bForce) FallbackMusic.fFadeInLengthSeconds = SAMPLE_MUSIC_FALLBACK_FADE_IN_SECONDS; FallbackMusic.bAlignBeat = ALIGN_MUSIC_BEATS; - SOUND->PlayMusic(PlayParams, FallbackMusic); + SOUND->PlayMusic(PlayParams); MESSAGEMAN->Broadcast("PlayingSampleMusic"); } } From 869469ad2437e08a5722a89ffab0278cceac98c3 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 05:27:20 -0500 Subject: [PATCH 071/320] force cd graph to update when toggling previews on --- Themes/Til Death/BGAnimations/_chorddensitygraph.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua index 6ecbc91463..00590527a1 100644 --- a/Themes/Til Death/BGAnimations/_chorddensitygraph.lua +++ b/Themes/Til Death/BGAnimations/_chorddensitygraph.lua @@ -99,6 +99,9 @@ local t = Def.ActorFrame { self:queuecommand("GraphUpdate") end end, + ChartPreviewOnMessageCommand = function(self) + self:queuecommand("GraphUpdate") + end, Def.Quad { Name = "cdbg", InitCommand = function(self) From 6dece164ce6104ed6512dfb9c4cd3bb97c54c640 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 10:27:58 -0300 Subject: [PATCH 072/320] Add Actor::SetInterval, Actor::SetTimeout and ActorFrame::SetUpdateFunctionInterval --- src/Actor.cpp | 94 ++ src/Actor.cpp-1f841de5 | 2992 ++++++++++++++++++++++++++++++++++++++++ src/Actor.h | 15 +- src/ActorFrame.cpp | 39 +- src/ActorFrame.h | 8 + src/LuaManager.cpp | 14 +- src/LuaManager.h | 47 +- src/LuaReference.h | 2 + 8 files changed, 3174 insertions(+), 37 deletions(-) create mode 100644 src/Actor.cpp-1f841de5 diff --git a/src/Actor.cpp b/src/Actor.cpp index dc004ba529..137f078e82 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -14,7 +14,10 @@ #include "ThemeManager.h" #include "XmlFile.h" #include +#include +#include #include "FilterManager.h" +#include "LuaReference.h" static Preference g_bShowMasks("ShowMasks", false); static const float default_effect_period = 1.0f; @@ -946,6 +949,29 @@ Actor::UpdateInternal(float delta_time) delta_time = m_fEffectDelta; } this->UpdateTweening(delta_time); + + for (auto it = delayedFunctions.begin(); it != delayedFunctions.end(); + ++it) { + auto& delayedF = *it; + delayedF.second -= delta_time; + if (delayedF.second <= 0) { + delayedF.first(); + } + } + // Doing this in place did weird things + std::remove_if(delayedFunctions.begin(), + delayedFunctions.end(), + [](auto& x) { return x.second <= 0; }); + for (auto it = this->delayedPeriodicFunctions.begin(); + it != this->delayedPeriodicFunctions.end(); + ++it) { + auto& delayedF = *it; + std::get<1>(delayedF) -= delta_time; + if (std::get<1>(delayedF) <= 0) { + std::get<0>(delayedF)(); + std::get<1>(delayedF) = std::get<2>(delayedF); + } + } } RString @@ -1662,6 +1688,20 @@ Actor::TweenInfo::operator=(const TweenInfo& rhs) return *this; } +void +Actor::SetTimeout(function f, float ms) +{ + delayedFunctions.emplace_back(make_pair(f, ms)); + return; +} + +void +Actor::SetInterval(function f, float ms, int id) +{ + delayedPeriodicFunctions.emplace_back(make_tuple(f, ms, ms, id)); + return; +} + // lua start #include "LuaBinding.h" @@ -1674,6 +1714,57 @@ class LunaActor : public Luna p->SetName(SArg(1)); COMMON_RETURN_SELF; } + static int setTimeout(T* p, lua_State* L) + { + auto f = GetFuncArg(1, L); + std::function execF = [f]() { + Lua* L = LUA->Get(); + f.PushSelf(L); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::RunScriptOnStack( + L, Error, 0, 0, true); // 1 args, 0 results + } + LUA->Release(L); + }; + p->SetTimeout(execF, FArg(2)); + COMMON_RETURN_SELF; + } + static int setInterval(T* p, lua_State* L) + { + lua_pushvalue(L, 1); + auto f = luaL_ref(L, LUA_REGISTRYINDEX); + std::function execF = [f]() { + Lua* L = LUA->Get(); + lua_rawgeti(L, LUA_REGISTRYINDEX, f); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::RunScriptOnStack( + L, Error, 0, 0, true); // 1 args, 0 results + } + LUA->Release(L); + }; + p->SetInterval(execF, FArg(2), f); + lua_pushnumber(L, f); + return 1; + } + static int clearInterval(T* p, lua_State* L) + { + int r = IArg(1); + auto& l = p->delayedPeriodicFunctions; + auto it = find_if( + l.begin(), l.end(), [r](auto& x) { return std::get<3>() == r; }); + if (it != l.end()) { + luaL_unref(L, LUA_REGISTRYINDEX, r); + l.erase(it); + } else { + LuaHelpers::ReportScriptError( + "Interval function not found (When triying to clearInterval() )"); + } + return 0; + } static int sleep(T* p, lua_State* L) { float fTime = FArg(1); @@ -2686,6 +2777,9 @@ class LunaActor : public Luna DEFINE_METHOD(IsVisible, IsVisible()); LunaActor() { + ADD_METHOD(name); + ADD_METHOD(setInterval); + ADD_METHOD(setTimeout); ADD_METHOD(name); ADD_METHOD(sleep); ADD_METHOD(linear); diff --git a/src/Actor.cpp-1f841de5 b/src/Actor.cpp-1f841de5 new file mode 100644 index 0000000000..7efa07415f --- /dev/null +++ b/src/Actor.cpp-1f841de5 @@ -0,0 +1,2992 @@ +#include "global.h" +#include "Actor.h" +#include "ActorFrame.h" +#include "ActorUtil.h" +#include "GamePreferences.h" +#include "LuaBinding.h" +#include "LuaReference.h" +#include "MessageManager.h" +#include "Preference.h" +#include "RageDisplay.h" +#include "RageMath.h" +#include "RageTimer.h" +#include "RageUtil.h" +#include "ThemeManager.h" +#include "XmlFile.h" +#include +#include +#include +#include "FilterManager.h" +#include "LuaReference.h" + +static Preference g_bShowMasks("ShowMasks", false); +static const float default_effect_period = 1.0f; + +/** + * @brief Set up a hidden Actor that won't be drawn. + * + * It's useful to be able to construct a basic Actor in XML, in + * order to simply delay a Transition, or receive and send broadcasts. + * Since these actors will never draw, set them hidden by default. */ +class HiddenActor : public Actor +{ + public: + HiddenActor() { SetVisible(false); } + HiddenActor* Copy() const override; +}; +REGISTER_ACTOR_CLASS_WITH_NAME(HiddenActor, Actor); + +float Actor::g_fCurrentBGMTime = 0, Actor::g_fCurrentBGMBeat; +float Actor::g_fCurrentBGMTimeNoOffset = 0, + Actor::g_fCurrentBGMBeatNoOffset = 0; +vector Actor::g_vfCurrentBGMBeatPlayer(NUM_PlayerNumber, 0); +vector Actor::g_vfCurrentBGMBeatPlayerNoOffset(NUM_PlayerNumber, 0); + +Actor* +Actor::Copy() const +{ + return new Actor(*this); +} + +static const char* HorizAlignNames[] = { "Left", "Center", "Right" }; +XToString(HorizAlign); +LuaXType(HorizAlign); + +static const char* VertAlignNames[] = { "Top", "Middle", "Bottom" }; +XToString(VertAlign); +LuaXType(VertAlign); + +void +Actor::SetBGMTime(float fTime, + float fBeat, + float fTimeNoOffset, + float fBeatNoOffset) +{ + g_fCurrentBGMTime = fTime; + g_fCurrentBGMBeat = fBeat; + + /* This timer is generally only used for effects tied to the background + * music when GameSoundManager is aligning music beats. Alignment doesn't + * handle g_fVisualDelaySeconds. */ + g_fCurrentBGMTimeNoOffset = fTimeNoOffset; + g_fCurrentBGMBeatNoOffset = fBeatNoOffset; +} + +void +Actor::SetPlayerBGMBeat(PlayerNumber pn, float fBeat, float fBeatNoOffset) +{ + g_vfCurrentBGMBeatPlayer[pn] = fBeat; + g_vfCurrentBGMBeatPlayerNoOffset[pn] = fBeatNoOffset; +} + +void +Actor::InitState() +{ + this->StopTweening(); + + m_pTempState = nullptr; + + m_baseRotation = RageVector3(0, 0, 0); + m_baseScale = RageVector3(1, 1, 1); + m_fBaseAlpha = 1; + m_internalDiffuse = RageColor(1, 1, 1, 1); + m_internalGlow = RageColor(0, 0, 0, 0); + + m_start.Init(); + m_current.Init(); + + m_fHorizAlign = 0.5f; + m_fVertAlign = 0.5f; +#if defined(SSC_FUTURES) + for (unsigned i = 0; i < m_Effects.size(); ++i) + m_Effects[i] = no_effect; +#else + m_Effect = no_effect; +#endif + m_fSecsIntoEffect = 0; + m_fEffectDelta = 0; + SetEffectPeriod(default_effect_period); + m_fEffectOffset = 0; + m_EffectClock = CLOCK_TIMER; + m_vEffectMagnitude = RageVector3(0, 0, 10); + m_effectColor1 = RageColor(1, 1, 1, 1); + m_effectColor2 = RageColor(1, 1, 1, 1); + + m_bVisible = true; + m_fShadowLengthX = 0; + m_fShadowLengthY = 0; + m_ShadowColor = RageColor(0, 0, 0, 0.5f); + m_bIsAnimating = true; + m_fHibernateSecondsLeft = 0; + m_iDrawOrder = 0; + + m_bTextureWrapping = false; + m_bTextureFiltering = true; + m_texTranslate = RageVector2(0, 0); + + m_BlendMode = BLEND_NORMAL; + m_fZBias = 0; + m_bClearZBuffer = false; + m_ZTestMode = ZTEST_OFF; + m_bZWrite = false; + m_CullMode = CULL_NONE; +} + +static bool +GetMessageNameFromCommandName(const RString& sCommandName, + RString& sMessageNameOut) +{ + if (sCommandName.Right(7) == "Message") { + sMessageNameOut = sCommandName.Left(sCommandName.size() - 7); + return true; + } + + return false; +} + +Actor::Actor() +{ + m_pLuaInstance = new LuaClass; + Lua* L = LUA->Get(); + m_pLuaInstance->PushSelf(L); + lua_newtable(L); + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "ctx"); + lua_pop(L, 1); + LUA->Release(L); + + m_size = RageVector2(1, 1); + InitState(); + m_pParent = nullptr; + m_FakeParent = nullptr; + m_bFirstUpdate = true; + m_tween_uses_effect_delta = false; +} + +Actor::~Actor() +{ + StopTweening(); + UnsubscribeAll(); + for (size_t i = 0; i < m_WrapperStates.size(); ++i) { + SAFE_DELETE(m_WrapperStates[i]); + } + m_WrapperStates.clear(); +} + +Actor::Actor(const Actor& cpy) + : MessageSubscriber(cpy) +{ + /* Don't copy an Actor in the middle of rendering. */ + ASSERT(cpy.m_pTempState == nullptr); + m_pTempState = nullptr; + +#define CPY(x) x = cpy.x + CPY(m_sName); + CPY(m_pParent); + CPY(m_FakeParent); + CPY(m_pLuaInstance); + + m_WrapperStates.resize(cpy.m_WrapperStates.size()); + for (size_t i = 0; i < m_WrapperStates.size(); ++i) { + m_WrapperStates[i] = + new ActorFrame(*dynamic_cast(cpy.m_WrapperStates[i])); + } + + CPY(m_baseRotation); + CPY(m_baseScale); + CPY(m_fBaseAlpha); + CPY(m_internalDiffuse); + CPY(m_internalGlow); + + CPY(m_size); + CPY(m_current); + CPY(m_start); + for (unsigned i = 0; i < cpy.m_Tweens.size(); ++i) + m_Tweens.push_back(new TweenStateAndInfo(*cpy.m_Tweens[i])); + + CPY(m_bFirstUpdate); + + CPY(m_fHorizAlign); + CPY(m_fVertAlign); +#if defined(SSC_FUTURES) + // I'm a bit worried about this -aj + for (unsigned i = 0; i < cpy.m_Effects.size(); ++i) + m_Effects.push_back((*cpy.m_Effects[i])); +#else + CPY(m_Effect); +#endif + CPY(m_fSecsIntoEffect); + CPY(m_fEffectDelta); + CPY(m_effect_ramp_to_half); + CPY(m_effect_hold_at_half); + CPY(m_effect_ramp_to_full); + CPY(m_effect_hold_at_full); + CPY(m_effect_hold_at_zero); + CPY(m_effect_period); + CPY(m_fEffectOffset); + CPY(m_EffectClock); + + CPY(m_effectColor1); + CPY(m_effectColor2); + CPY(m_vEffectMagnitude); + + CPY(m_bVisible); + CPY(m_fHibernateSecondsLeft); + CPY(m_fShadowLengthX); + CPY(m_fShadowLengthY); + CPY(m_ShadowColor); + CPY(m_bIsAnimating); + CPY(m_iDrawOrder); + + CPY(m_bTextureWrapping); + CPY(m_bTextureFiltering); + CPY(m_BlendMode); + CPY(m_bClearZBuffer); + CPY(m_ZTestMode); + CPY(m_bZWrite); + CPY(m_fZBias); + CPY(m_CullMode); + + CPY(m_mapNameToCommands); +#undef CPY +} + +/* XXX: This calls InitCommand, which must happen after all other + * initialization (eg. ActorFrame loading children). However, it + * also loads input variables, which should happen first. The + * former is more important. */ +void +Actor::LoadFromNode(const XNode* pNode) +{ + Lua* L = LUA->Get(); + FOREACH_CONST_Attr(pNode, pAttr) + { + // Load Name, if any. + const RString& sKeyName = pAttr->first; + const XNodeValue* pValue = pAttr->second; + if (EndsWith(sKeyName, "Command")) { + LuaReference* pRef = new LuaReference; + pValue->PushValue(L); + pRef->SetFromStack(L); + RString sCmdName = sKeyName.Left(sKeyName.size() - 7); + AddCommand(sCmdName, apActorCommands(pRef)); + } else if (sKeyName == "Name") + SetName(pValue->GetValue()); + else if (sKeyName == "BaseRotationX") + SetBaseRotationX(pValue->GetValue()); + else if (sKeyName == "BaseRotationY") + SetBaseRotationY(pValue->GetValue()); + else if (sKeyName == "BaseRotationZ") + SetBaseRotationZ(pValue->GetValue()); + else if (sKeyName == "BaseZoomX") + SetBaseZoomX(pValue->GetValue()); + else if (sKeyName == "BaseZoomY") + SetBaseZoomY(pValue->GetValue()); + else if (sKeyName == "BaseZoomZ") + SetBaseZoomZ(pValue->GetValue()); + } + + LUA->Release(L); + + // Don't recurse Init. It gets called once for every Actor when the + // Actor is loaded, and we don't want to call it again. + PlayCommandNoRecurse(Message("Init")); +} + +bool +Actor::PartiallyOpaque() +{ + return m_pTempState->diffuse[0].a > 0 || m_pTempState->diffuse[1].a > 0 || + m_pTempState->diffuse[2].a > 0 || m_pTempState->diffuse[3].a > 0 || + m_pTempState->glow.a > 0; +} + +bool +Actor::IsOver(float mx, float my) +{ + if (!IsVisible()) + return false; + + auto x = GetTrueX(); + auto y = GetTrueY(); + auto hal = GetHorizAlign(); + auto val = GetVertAlign(); + auto wi = GetZoomedWidth() * GetFakeParentOrParent()->GetTrueZoom(); + auto hi = GetZoomedHeight() * GetFakeParentOrParent()->GetTrueZoom(); + auto lr = x - (hal * wi); + auto rr = x + wi - (hal * wi); + auto ur = y - (val * hi); + auto br = ((y + hi) - (val * hi)); + bool withinX = mx >= lr && mx <= rr; + bool withinY = my >= ur && my <= br; + return withinX && withinY; +} +Actor* +Actor::GetFakeParentOrParent() +{ + if (!this) + return nullptr; + if (m_FakeParent) + return m_FakeParent; + if (m_pParent) + return m_pParent; + return nullptr; +} +float +Actor::GetTrueX() +{ + if (!this) + return 0.f; + auto* mfp = GetFakeParentOrParent(); + if (!mfp) + return GetX(); + return GetX() * mfp->GetTrueZoom() + mfp->GetTrueX(); +} + +float +Actor::GetTrueY() +{ + if (!this) + return 0.f; + auto* mfp = GetFakeParentOrParent(); + if (!mfp) + return GetY(); + return GetY() * mfp->GetTrueZoom() + mfp->GetTrueY(); +} +float +Actor::GetTrueZoom() +{ + if (!this) + return 1.f; + auto* mfp = GetFakeParentOrParent(); + if (!mfp) + return GetZoom(); + return GetZoom() * mfp->GetTrueZoom(); +} +bool +Actor::IsVisible() +{ + if (!this) + return false; + auto* mfp = GetFakeParentOrParent(); + if (!mfp) + return GetVisible(); + return GetVisible() && mfp->IsVisible(); +} +void +Actor::Draw() +{ + if (!m_bVisible || m_fHibernateSecondsLeft > 0 || this->EarlyAbortDraw()) { + return; // early abort + } + + if (m_FakeParent != nullptr) { + if (!m_FakeParent->m_bVisible || + m_FakeParent->m_fHibernateSecondsLeft > 0 || + m_FakeParent->EarlyAbortDraw()) { + return; + } + m_FakeParent->PreDraw(); + if (!m_FakeParent->PartiallyOpaque()) { + m_FakeParent->PostDraw(); + return; + } + } + + if (m_FakeParent != nullptr) { + m_FakeParent->BeginDraw(); + } + size_t wrapper_states_used = 0; + RageColor last_diffuse; + RageColor last_glow; + bool use_last_diffuse = false; + // dont_abort_draw exists because if one of the layers is invisible, + // there's no point in continuing. -Kyz + bool dont_abort_draw = true; + // abort_with_end_draw exists because PreDraw happens before the + // opaqueness test, so if we abort at the opaqueness test, there isn't + // a BeginDraw to match the EndDraw. -Kyz + bool abort_with_end_draw = true; + // It's more intuitive to apply the highest index wrappers first. + // On the lua side, it looks like this: + // wrapper[3] is the outermost frame. wrapper[2] is inside wrapper[3]. + // wrapper[1] is inside wrapper[2]. The actor is inside wrapper[1]. + // -Kyz + for (size_t i = m_WrapperStates.size(); i > 0 && dont_abort_draw; --i) { + Actor* state = m_WrapperStates[i - 1]; + if (!state->m_bVisible || state->m_fHibernateSecondsLeft > 0 || + state->EarlyAbortDraw()) { + dont_abort_draw = false; + } else { + state->PreDraw(); + if (state->PartiallyOpaque()) { + state->BeginDraw(); + last_diffuse = state->m_pTempState->diffuse[0]; + last_glow = state->m_pTempState->glow; + use_last_diffuse = true; + if (i > 1) { + m_WrapperStates[i - 2]->SetInternalDiffuse(last_diffuse); + m_WrapperStates[i - 2]->SetInternalGlow(last_glow); + } + } else { + dont_abort_draw = false; + abort_with_end_draw = false; + } + ++wrapper_states_used; + } + } + // call the most-derived versions + if (dont_abort_draw) { + if (use_last_diffuse) { + this->SetInternalDiffuse(last_diffuse); + this->SetInternalGlow(last_glow); + } + this->PreDraw(); + ASSERT(m_pTempState != nullptr); + if (PartiallyOpaque()) { + this->BeginDraw(); + this->DrawPrimitives(); + this->EndDraw(); + } + this->PostDraw(); + } + for (size_t i = 0; i < wrapper_states_used; ++i) { + Actor* state = m_WrapperStates[i]; + if (abort_with_end_draw) { + state->EndDraw(); + } + abort_with_end_draw = true; + state->PostDraw(); + state->m_pTempState = nullptr; + } + + if (m_FakeParent != nullptr) { + m_FakeParent->EndDraw(); + m_FakeParent->PostDraw(); + m_FakeParent->m_pTempState = nullptr; + } + m_pTempState = nullptr; +} + +void +Actor::PostDraw() // reset internal diffuse and glow +{ + m_internalDiffuse = RageColor(1, 1, 1, 1); + m_internalGlow.a = 0; +} + +void +Actor::PreDraw() // calculate actor properties +{ + // Somthing below may set m_pTempState to tempState + m_pTempState = &m_current; + + // set temporary drawing properties based on Effects + static TweenState tempState; + + // todo: account for SSC_FUTURES -aj + if (m_Effect == no_effect) { + } else { + m_pTempState = &tempState; + tempState = m_current; + + const float fTotalPeriod = GetEffectPeriod(); + ASSERT(fTotalPeriod > 0); + const float fTimeIntoEffect = + fmodfp(m_fSecsIntoEffect + m_fEffectOffset, fTotalPeriod); + + float fPercentThroughEffect; + const float rup_plus_ath = + m_effect_ramp_to_half + m_effect_hold_at_half; + const float rupath_plus_rdown = rup_plus_ath + m_effect_ramp_to_full; + const float rupathrdown_plus_atf = + rupath_plus_rdown + m_effect_hold_at_full; + if (fTimeIntoEffect < m_effect_ramp_to_half) { + fPercentThroughEffect = + SCALE(fTimeIntoEffect, 0, m_effect_ramp_to_half, 0.0f, 0.5f); + } else if (fTimeIntoEffect < rup_plus_ath) { + fPercentThroughEffect = 0.5f; + } else if (fTimeIntoEffect < rupath_plus_rdown) { + fPercentThroughEffect = SCALE( + fTimeIntoEffect, rup_plus_ath, rupath_plus_rdown, 0.5f, 1.0f); + } else if (fTimeIntoEffect < rupathrdown_plus_atf) { + fPercentThroughEffect = 1.0f; + } else { + fPercentThroughEffect = 0; + } + ASSERT_M(fPercentThroughEffect >= 0 && fPercentThroughEffect <= 1, + ssprintf("PercentThroughEffect: %f", fPercentThroughEffect)); + + bool bBlinkOn = fPercentThroughEffect > 0.5f; + float fPercentBetweenColors = + RageFastSin((fPercentThroughEffect + 0.25f) * 2 * PI) / 2 + 0.5f; + ASSERT_M(fPercentBetweenColors >= 0 && fPercentBetweenColors <= 1, + ssprintf("PercentBetweenColors: %f, PercentThroughEffect: %f", + fPercentBetweenColors, + fPercentThroughEffect)); + float fOriginalAlpha = tempState.diffuse[0].a; + + // todo: account for SSC_FUTURES -aj + switch (m_Effect) { + case diffuse_blink: + /* XXX: Should diffuse_blink and diffuse_shift multiply the + * tempState color? (That would have the same effect with + * 1,1,1,1, and allow tweening the diffuse while blinking and + * shifting.) */ + for (auto& i : tempState.diffuse) { + i = bBlinkOn ? m_effectColor1 : m_effectColor2; + i.a *= fOriginalAlpha; // multiply the alphas so we can fade + // even while an effect is playing + } + break; + case diffuse_shift: + for (auto& i : tempState.diffuse) { + i = m_effectColor1 * fPercentBetweenColors + + m_effectColor2 * (1.0f - fPercentBetweenColors); + i.a *= fOriginalAlpha; // multiply the alphas so we can fade + // even while an effect is playing + } + break; + case diffuse_ramp: + for (auto& i : tempState.diffuse) { + i = m_effectColor1 * fPercentThroughEffect + + m_effectColor2 * (1.0f - fPercentThroughEffect); + i.a *= fOriginalAlpha; // multiply the alphas so we can fade + // even while an effect is playing + } + break; + case glow_blink: + tempState.glow = bBlinkOn ? m_effectColor1 : m_effectColor2; + tempState.glow.a *= + fOriginalAlpha; // don't glow if the Actor is transparent! + break; + case glow_shift: + tempState.glow = + m_effectColor1 * fPercentBetweenColors + + m_effectColor2 * (1.0f - fPercentBetweenColors); + tempState.glow.a *= + fOriginalAlpha; // don't glow if the Actor is transparent! + break; + case glow_ramp: + tempState.glow = + m_effectColor1 * fPercentThroughEffect + + m_effectColor2 * (1.0f - fPercentThroughEffect); + tempState.glow.a *= + fOriginalAlpha; // don't glow if the Actor is transparent! + break; + case rainbow: + tempState.diffuse[0] = RageColor( + RageFastCos(fPercentBetweenColors * 2 * PI) * 0.5f + 0.5f, + RageFastCos(fPercentBetweenColors * 2 * PI + + PI * 2.0f / 3.0f) * + 0.5f + + 0.5f, + RageFastCos(fPercentBetweenColors * 2 * PI + + PI * 4.0f / 3.0f) * + 0.5f + + 0.5f, + fOriginalAlpha); + for (int i = 1; i < NUM_DIFFUSE_COLORS; i++) + tempState.diffuse[i] = tempState.diffuse[0]; + break; + case wag: + tempState.rotation += + m_vEffectMagnitude * + RageFastSin(fPercentThroughEffect * 2.0f * PI); + break; + case spin: + // nothing needs to be here + break; + case vibrate: + tempState.pos.x += + m_vEffectMagnitude.x * randomf(-1.0f, 1.0f) * GetZoom(); + tempState.pos.y += + m_vEffectMagnitude.y * randomf(-1.0f, 1.0f) * GetZoom(); + tempState.pos.z += + m_vEffectMagnitude.z * randomf(-1.0f, 1.0f) * GetZoom(); + break; + case bounce: { + float fPercentOffset = RageFastSin(fPercentThroughEffect * PI); + tempState.pos += m_vEffectMagnitude * fPercentOffset; + } break; + case bob: { + float fPercentOffset = + RageFastSin(fPercentThroughEffect * PI * 2); + tempState.pos += m_vEffectMagnitude * fPercentOffset; + } break; + case pulse: { + float fMinZoom = m_vEffectMagnitude[0]; + float fMaxZoom = m_vEffectMagnitude[1]; + float fPercentOffset = RageFastSin(fPercentThroughEffect * PI); + float fZoom = + SCALE(fPercentOffset, 0.f, 1.f, fMinZoom, fMaxZoom); + tempState.scale *= fZoom; + + // Use the color as a Vector3 to scale the effect for added + // control + RageColor c = SCALE( + fPercentOffset, 0.f, 1.f, m_effectColor1, m_effectColor2); + tempState.scale.x *= c.r; + tempState.scale.y *= c.g; + tempState.scale.z *= c.b; + } break; + default: + FAIL_M(ssprintf("Invalid effect: %i", m_Effect)); + } + } + + if (m_fBaseAlpha != 1) + m_internalDiffuse.a *= m_fBaseAlpha; + + if (m_internalDiffuse != RageColor(1, 1, 1, 1)) { + if (m_pTempState != &tempState) { + m_pTempState = &tempState; + tempState = m_current; + } + + for (auto& i : tempState.diffuse) { + i *= m_internalDiffuse; + } + } + + if (m_internalGlow.a > 0) { + if (m_pTempState != &tempState) { + m_pTempState = &tempState; + tempState = m_current; + } + + // Blend using Screen mode + tempState.glow = + tempState.glow + m_internalGlow - m_internalGlow * tempState.glow; + } +} + +void +Actor::BeginDraw() // set the world matrix +{ + DISPLAY->PushMatrix(); + + if (m_pTempState->pos.x != 0 || m_pTempState->pos.y != 0 || + m_pTempState->pos.z != 0) { + RageMatrix m; + RageMatrixTranslate( + &m, m_pTempState->pos.x, m_pTempState->pos.y, m_pTempState->pos.z); + DISPLAY->PreMultMatrix(m); + } + + { + /* The only time rotation and quat should normally be used + * simultaneously is for m_baseRotation. Most objects aren't rotated at + * all, so optimize that case. */ + const float fRotateX = m_pTempState->rotation.x + m_baseRotation.x; + const float fRotateY = m_pTempState->rotation.y + m_baseRotation.y; + const float fRotateZ = m_pTempState->rotation.z + m_baseRotation.z; + + if (fRotateX != 0 || fRotateY != 0 || fRotateZ != 0) { + RageMatrix m; + RageMatrixRotationXYZ(&m, fRotateX, fRotateY, fRotateZ); + DISPLAY->PreMultMatrix(m); + } + } + + // handle scaling + { + const float fScaleX = m_pTempState->scale.x * m_baseScale.x; + const float fScaleY = m_pTempState->scale.y * m_baseScale.y; + const float fScaleZ = m_pTempState->scale.z * m_baseScale.z; + + if (fScaleX != 1 || fScaleY != 1 || fScaleZ != 1) { + RageMatrix m; + RageMatrixScale(&m, fScaleX, fScaleY, fScaleZ); + DISPLAY->PreMultMatrix(m); + } + } + + // handle alignment; most actors have default alignment. + if (unlikely(m_fHorizAlign != 0.5f || m_fVertAlign != 0.5f)) { + float fX = + SCALE(m_fHorizAlign, 0.0f, 1.0f, +m_size.x / 2.0f, -m_size.x / 2.0f); + float fY = + SCALE(m_fVertAlign, 0.0f, 1.0f, +m_size.y / 2.0f, -m_size.y / 2.0f); + RageMatrix m; + RageMatrixTranslate(&m, fX, fY, 0); + DISPLAY->PreMultMatrix(m); + } + + if (m_pTempState->quat.x != 0 || m_pTempState->quat.y != 0 || + m_pTempState->quat.z != 0 || m_pTempState->quat.w != 1) { + RageMatrix mat; + RageMatrixFromQuat(&mat, m_pTempState->quat); + + DISPLAY->MultMatrix(mat); + } + + // handle skews + if (m_pTempState->fSkewX != 0) { + DISPLAY->SkewX(m_pTempState->fSkewX); + } + + if (m_pTempState->fSkewY != 0) { + DISPLAY->SkewY(m_pTempState->fSkewY); + } + + if (m_texTranslate.x != 0 || m_texTranslate.y != 0) { + DISPLAY->TexturePushMatrix(); + DISPLAY->TextureTranslate(m_texTranslate.x, m_texTranslate.y); + } +} + +void +Actor::SetGlobalRenderStates() +{ + // set Actor-defined render states + if (!g_bShowMasks.Get() || m_BlendMode != BLEND_NO_EFFECT) + DISPLAY->SetBlendMode(m_BlendMode); + DISPLAY->SetZWrite(m_bZWrite); + DISPLAY->SetZTestMode(m_ZTestMode); + + // BLEND_NO_EFFECT is used to draw masks to the Z-buffer, which always wants + // Z-bias enabled. + if (m_fZBias == 0 && m_BlendMode == BLEND_NO_EFFECT) + DISPLAY->SetZBias(1.0f); + else + DISPLAY->SetZBias(m_fZBias); + + if (m_bClearZBuffer) + DISPLAY->ClearZBuffer(); + DISPLAY->SetCullMode(m_CullMode); +} + +void +Actor::SetTextureRenderStates() +{ + DISPLAY->SetTextureWrapping(TextureUnit_1, m_bTextureWrapping); + DISPLAY->SetTextureFiltering(TextureUnit_1, m_bTextureFiltering); +} + +void +Actor::EndDraw() +{ + DISPLAY->PopMatrix(); + + if (m_texTranslate.x != 0 || m_texTranslate.y != 0) + DISPLAY->TexturePopMatrix(); +} + +void +Actor::CalcPercentThroughTween() +{ + TweenState& TS = m_Tweens[0]->state; + TweenInfo& TI = m_Tweens[0]->info; + const float percent_through = 1 - (TI.m_fTimeLeftInTween / TI.m_fTweenTime); + // distort the percentage if appropriate + float percent_along = TI.m_pTween->Tween(percent_through); + TweenState::MakeWeightedAverage(m_current, m_start, TS, percent_along); + UpdatePercentThroughTween(percent_along); +} + +void +Actor::UpdateTweening(float fDeltaTime) +{ + if (fDeltaTime < 0.0 && !m_Tweens.empty()) { + m_Tweens[0]->info.m_fTimeLeftInTween -= fDeltaTime; + CalcPercentThroughTween(); + return; + } + while (!m_Tweens.empty() // something to do + && fDeltaTime > 0) // something will change + { + // update current tween state + // earliest tween + TweenState& TS = m_Tweens[0]->state; + TweenInfo& TI = m_Tweens[0]->info; + + bool bBeginning = TI.m_fTimeLeftInTween == TI.m_fTweenTime; + + float fSecsToSubtract = min(TI.m_fTimeLeftInTween, fDeltaTime); + TI.m_fTimeLeftInTween -= fSecsToSubtract; + fDeltaTime -= fSecsToSubtract; + + RString sCommand = TI.m_sCommandName; + if (bBeginning) // we are just beginning this tween + { + m_start = m_current; // set the start position + SetCurrentTweenStart(); + } + + if (TI.m_fTimeLeftInTween == 0) // Current tween is over. Stop. + { + m_current = TS; + + // delete the head tween + delete m_Tweens.front(); + m_Tweens.erase(m_Tweens.begin()); + EraseHeadTween(); + } else // in the middle of tweening. Recalcute the current position. + { + CalcPercentThroughTween(); + } + + if (bBeginning) { + // Execute the command in this tween (if any). Do this last, and + // don't access TI or TS after, since this may modify the tweening + // queue. + if (!sCommand.empty()) { + if (sCommand.Left(1) == "!") + MESSAGEMAN->Broadcast(sCommand.substr(1)); + else + this->PlayCommand(sCommand); + } + } + } +} + +bool +Actor::IsFirstUpdate() const +{ + return m_bFirstUpdate; +} + +void +Actor::Update(float fDeltaTime) +{ + // LOG->Trace( "Actor::Update( %f )", fDeltaTime ); + ASSERT_M(fDeltaTime >= 0, ssprintf("DeltaTime: %f", fDeltaTime)); + + if (m_fHibernateSecondsLeft > 0) { + m_fHibernateSecondsLeft -= fDeltaTime; + if (m_fHibernateSecondsLeft > 0) { + return; + } + + // Grab the leftover time. + fDeltaTime = -m_fHibernateSecondsLeft; + m_fHibernateSecondsLeft = 0; + } + for (size_t i = 0; i < m_WrapperStates.size(); ++i) { + m_WrapperStates[i]->Update(fDeltaTime); + } + + this->UpdateInternal(fDeltaTime); +} + +static void +generic_global_timer_update(float new_time, + float& effect_delta_time, + float& time_into_effect) +{ + effect_delta_time = new_time - time_into_effect; + time_into_effect = new_time; +} + +void +Actor::UpdateInternal(float delta_time) +{ + if (m_bFirstUpdate) + m_bFirstUpdate = false; + + switch (m_EffectClock) { + case CLOCK_TIMER: + m_fSecsIntoEffect += delta_time; + m_fEffectDelta = delta_time; + // Wrap the counter, so it doesn't increase indefinitely (causing + // loss of precision if a screen is left to sit for a day). + if (m_fSecsIntoEffect > GetEffectPeriod()) { + m_fSecsIntoEffect -= GetEffectPeriod(); + } + break; + case CLOCK_TIMER_GLOBAL: + generic_global_timer_update( + static_cast(RageTimer::GetUsecsSinceStart()), + m_fEffectDelta, + m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT: + generic_global_timer_update( + g_fCurrentBGMBeat, m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT_PLAYER1: + generic_global_timer_update(g_vfCurrentBGMBeatPlayer[PLAYER_1], + m_fEffectDelta, + m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT_PLAYER2: + generic_global_timer_update(g_vfCurrentBGMBeatPlayer[PLAYER_2], + m_fEffectDelta, + m_fSecsIntoEffect); + break; + case CLOCK_BGM_TIME: + generic_global_timer_update( + g_fCurrentBGMTime, m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_BEAT_NO_OFFSET: + generic_global_timer_update( + g_fCurrentBGMBeatNoOffset, m_fEffectDelta, m_fSecsIntoEffect); + break; + case CLOCK_BGM_TIME_NO_OFFSET: + generic_global_timer_update( + g_fCurrentBGMTimeNoOffset, m_fEffectDelta, m_fSecsIntoEffect); + break; + default: + break; + } + + // update effect + // todo: account for SSC_FUTURES -aj + switch (m_Effect) { + case spin: + m_current.rotation += m_fEffectDelta * m_vEffectMagnitude; + wrap(m_current.rotation.x, 360); + wrap(m_current.rotation.y, 360); + wrap(m_current.rotation.z, 360); + break; + default: + break; + } + + if (m_tween_uses_effect_delta) { + delta_time = m_fEffectDelta; + } + this->UpdateTweening(delta_time); + + for (auto it = delayedFunctions.begin(); it != delayedFunctions.end(); + ++it) { + auto& delayedF = *it; + delayedF.second -= delta_time; + if (delayedF.second <= 0) { + delayedF.first(); + } + } + // Doing this in place did weird things + std::remove_if(delayedFunctions.begin(), + delayedFunctions.end(), + [](auto& x) { return x.second <= 0; }); + for (auto it = this->delayedPeriodicFunctions.begin(); + it != this->delayedPeriodicFunctions.end(); + ++it) { + auto& delayedF = *it; + std::get<1>(delayedF) -= delta_time; + if (std::get<1>(delayedF) <= 0) { + std::get<0>(delayedF)(); + std::get<1>(delayedF) = std::get<2>(delayedF); + } + } +} + +RString +Actor::GetLineage() const +{ + RString sPath; + + if (m_pParent) + sPath = m_pParent->GetLineage() + '/'; + sPath += ssprintf(" %s", typeid(*this).name(), m_sName.c_str()); + return sPath; +} + +void +Actor::AddWrapperState() +{ + auto* wrapper = new ActorFrame; + wrapper->InitState(); + m_WrapperStates.push_back(wrapper); +} + +void +Actor::RemoveWrapperState(size_t i) +{ + ASSERT(i < m_WrapperStates.size()); + SAFE_DELETE(m_WrapperStates[i]); + m_WrapperStates.erase(m_WrapperStates.begin() + i); +} + +Actor* +Actor::GetWrapperState(size_t i) +{ + ASSERT(i < m_WrapperStates.size()); + return m_WrapperStates[i]; +} + +void +Actor::BeginTweening(float time, ITween* pTween) +{ + ASSERT(time >= 0); + + // If the number of tweens to ever gets this large, there's probably an + // infinitely recursing ActorCommand. + if (m_Tweens.size() > 50 && !(GamePreferences::m_AutoPlay == PC_REPLAY)) { + LuaHelpers::ReportScriptErrorFmt( + "Tween overflow: \"%s\"; infinitely recursing ActorCommand?", + GetLineage().c_str()); + this->FinishTweening(); + } + + // add a new TweenState to the tail, and initialize it + m_Tweens.push_back(new TweenStateAndInfo); + + // latest + TweenState& TS = m_Tweens.back()->state; + TweenInfo& TI = m_Tweens.back()->info; + + if (m_Tweens.size() >= 2) // if there was already a TS on the stack + { + // initialize the new TS from the last TS in the list + TS = m_Tweens[m_Tweens.size() - 2]->state; + } else { + // This new TS is the only TS. + // Set our tween starting and ending values to the current position. + TS = m_current; + } + + TI.m_pTween = pTween; + TI.m_fTweenTime = time; + TI.m_fTimeLeftInTween = time; +} + +void +Actor::BeginTweening(float time, TweenType tt) +{ + ASSERT(time >= 0); + + ITween* pTween = ITween::CreateFromType(tt); + this->BeginTweening(time, pTween); +} + +void +Actor::StopTweening() +{ + for (unsigned i = 0; i < m_Tweens.size(); ++i) + delete m_Tweens[i]; + m_Tweens.clear(); +} + +void +Actor::FinishTweening() +{ + if (!m_Tweens.empty()) + m_current = DestTweenState(); + this->StopTweening(); +} + +void +Actor::HurryTweening(float factor) +{ + for (unsigned i = 0; i < m_Tweens.size(); ++i) { + m_Tweens[i]->info.m_fTimeLeftInTween *= factor; + m_Tweens[i]->info.m_fTweenTime *= factor; + } +} + +void +Actor::ScaleTo(const RectF& rect, StretchType st) +{ + // width and height of rectangle + float rect_width = rect.GetWidth(); + float rect_height = rect.GetHeight(); + + if (rect_width < 0) + SetRotationY(180); + if (rect_height < 0) + SetRotationX(180); + + // zoom fActor needed to scale the Actor to fill the rectangle + float fNewZoomX = fabsf(rect_width / m_size.x); + float fNewZoomY = fabsf(rect_height / m_size.y); + + float fNewZoom = 0.f; + switch (st) { + case cover: + fNewZoom = + fNewZoomX > fNewZoomY ? fNewZoomX : fNewZoomY; // use larger zoom + break; + case fit_inside: + fNewZoom = + fNewZoomX > fNewZoomY ? fNewZoomY : fNewZoomX; // use smaller zoom + break; + } + + SetX(rect.left + rect_width * m_fHorizAlign); + SetY(rect.top + rect_height * m_fVertAlign); + + SetZoom(fNewZoom); +} + +void +Actor::SetEffectClockString(const RString& s) +{ + if (s.EqualsNoCase("timer")) + this->SetEffectClock(CLOCK_TIMER); + else if (s.EqualsNoCase("timerglobal")) + this->SetEffectClock(CLOCK_TIMER_GLOBAL); + else if (s.EqualsNoCase("beat")) + this->SetEffectClock(CLOCK_BGM_BEAT); + else if (s.EqualsNoCase("music")) + this->SetEffectClock(CLOCK_BGM_TIME); + else if (s.EqualsNoCase("bgm")) + this->SetEffectClock(CLOCK_BGM_BEAT); // compat, deprecated + else if (s.EqualsNoCase("musicnooffset")) + this->SetEffectClock(CLOCK_BGM_TIME_NO_OFFSET); + else if (s.EqualsNoCase("beatnooffset")) + this->SetEffectClock(CLOCK_BGM_BEAT_NO_OFFSET); +} + +void +Actor::StretchTo(const RectF& r) +{ + // width and height of rectangle + float width = r.GetWidth(); + float height = r.GetHeight(); + + // center of the rectangle + float cx = r.left + width / 2.0f; + float cy = r.top + height / 2.0f; + + // zoom fActor needed to scale the Actor to fill the rectangle + float fNewZoomX = width / m_size.x; + float fNewZoomY = height / m_size.y; + + SetXY(cx, cy); + SetZoomX(fNewZoomX); + SetZoomY(fNewZoomY); +} + +void +Actor::RecalcEffectPeriod() +{ + m_effect_period = m_effect_ramp_to_half + m_effect_hold_at_half + + m_effect_ramp_to_full + m_effect_hold_at_full + + m_effect_hold_at_zero; +} + +void +Actor::SetEffectPeriod(float time) +{ + ASSERT(time > 0); + m_effect_ramp_to_half = time / 2; + m_effect_hold_at_half = 0; + m_effect_ramp_to_full = time / 2; + m_effect_hold_at_full = 0; + m_effect_hold_at_zero = 0; + RecalcEffectPeriod(); +} + +bool +Actor::SetEffectTiming(float ramp_toh, + float at_half, + float ramp_tof, + float at_full, + float at_zero, + RString& err) +{ + // No negative timings + if (ramp_toh < 0 || at_half < 0 || ramp_tof < 0 || at_full < 0 || + at_zero < 0) { + err = ssprintf("Effect timings (%f,%f,%f,%f,%f) must not be negative;", + ramp_toh, + at_half, + ramp_tof, + at_zero, + at_full); + return false; + } + // and at least one positive timing. + if (ramp_toh <= 0 && at_half <= 0 && ramp_tof <= 0 && at_full <= 0 && + at_zero <= 0) { + err = ssprintf("Effect timings (0,0,0,0,0) must not all be zero;"); + return false; + } + m_effect_ramp_to_half = ramp_toh; + m_effect_hold_at_half = at_half; + m_effect_ramp_to_full = ramp_tof; + m_effect_hold_at_full = at_full; + m_effect_hold_at_zero = at_zero; + RecalcEffectPeriod(); + return true; +} + +bool +Actor::SetEffectHoldAtFull(float haf, RString& err) +{ + return SetEffectTiming(m_effect_ramp_to_half, + m_effect_hold_at_half, + m_effect_ramp_to_full, + haf, + m_effect_hold_at_zero, + err); +} + +// effect "macros" + +void +Actor::ResetEffectTimeIfDifferent(Effect new_effect) +{ + if (m_Effect != new_effect) { + m_Effect = new_effect; + m_fSecsIntoEffect = 0; + } +} + +void +Actor::SetEffectDiffuseBlink(float fEffectPeriodSeconds, + const RageColor& c1, + const RageColor& c2) +{ + ASSERT(fEffectPeriodSeconds > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(diffuse_blink); + SetEffectPeriod(fEffectPeriodSeconds); + m_effectColor1 = c1; + m_effectColor2 = c2; +} + +void +Actor::SetEffectDiffuseShift(float fEffectPeriodSeconds, + const RageColor& c1, + const RageColor& c2) +{ + ASSERT(fEffectPeriodSeconds > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(diffuse_shift); + SetEffectPeriod(fEffectPeriodSeconds); + m_effectColor1 = c1; + m_effectColor2 = c2; +} + +void +Actor::SetEffectDiffuseRamp(float fEffectPeriodSeconds, + const RageColor& c1, + const RageColor& c2) +{ + ASSERT(fEffectPeriodSeconds > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(diffuse_ramp); + SetEffectPeriod(fEffectPeriodSeconds); + m_effectColor1 = c1; + m_effectColor2 = c2; +} + +void +Actor::SetEffectGlowBlink(float fEffectPeriodSeconds, + const RageColor& c1, + const RageColor& c2) +{ + ASSERT(fEffectPeriodSeconds > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(glow_blink); + SetEffectPeriod(fEffectPeriodSeconds); + m_effectColor1 = c1; + m_effectColor2 = c2; +} + +void +Actor::SetEffectGlowShift(float fEffectPeriodSeconds, + const RageColor& c1, + const RageColor& c2) +{ + ASSERT(fEffectPeriodSeconds > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(glow_shift); + SetEffectPeriod(fEffectPeriodSeconds); + m_effectColor1 = c1; + m_effectColor2 = c2; +} + +void +Actor::SetEffectGlowRamp(float fEffectPeriodSeconds, + const RageColor& c1, + const RageColor& c2) +{ + ASSERT(fEffectPeriodSeconds > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(glow_ramp); + SetEffectPeriod(fEffectPeriodSeconds); + m_effectColor1 = c1; + m_effectColor2 = c2; +} + +void +Actor::SetEffectRainbow(float fEffectPeriodSeconds) +{ + ASSERT(fEffectPeriodSeconds > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(rainbow); + SetEffectPeriod(fEffectPeriodSeconds); +} + +void +Actor::SetEffectWag(float fPeriod, const RageVector3& vect) +{ + ASSERT(fPeriod > 0); + // todo: account for SSC_FUTURES -aj + ResetEffectTimeIfDifferent(wag); + SetEffectPeriod(fPeriod); + m_vEffectMagnitude = vect; +} + +void +Actor::SetEffectBounce(float fPeriod, const RageVector3& vect) +{ + ASSERT(fPeriod > 0); + // todo: account for SSC_FUTURES -aj + m_Effect = bounce; + SetEffectPeriod(fPeriod); + m_vEffectMagnitude = vect; + m_fSecsIntoEffect = 0; +} + +void +Actor::SetEffectBob(float fPeriod, const RageVector3& vect) +{ + ASSERT(fPeriod > 0); + // todo: account for SSC_FUTURES -aj + if (m_Effect != bob || GetEffectPeriod() != fPeriod) { + m_Effect = bob; + SetEffectPeriod(fPeriod); + m_fSecsIntoEffect = 0; + } + m_vEffectMagnitude = vect; +} + +void +Actor::SetEffectSpin(const RageVector3& vect) +{ + // todo: account for SSC_FUTURES -aj + m_Effect = spin; + m_vEffectMagnitude = vect; +} + +void +Actor::SetEffectVibrate(const RageVector3& vect) +{ + // todo: account for SSC_FUTURES -aj + m_Effect = vibrate; + m_vEffectMagnitude = vect; +} + +void +Actor::SetEffectPulse(float fPeriod, float fMinZoom, float fMaxZoom) +{ + ASSERT(fPeriod > 0); + // todo: account for SSC_FUTURES -aj + m_Effect = pulse; + SetEffectPeriod(fPeriod); + m_vEffectMagnitude[0] = fMinZoom; + m_vEffectMagnitude[1] = fMaxZoom; +} + +void +Actor::AddRotationH(float rot) +{ + RageQuatMultiply( + &DestTweenState().quat, DestTweenState().quat, RageQuatFromH(rot)); +} + +void +Actor::AddRotationP(float rot) +{ + RageQuatMultiply( + &DestTweenState().quat, DestTweenState().quat, RageQuatFromP(rot)); +} + +void +Actor::AddRotationR(float rot) +{ + RageQuatMultiply( + &DestTweenState().quat, DestTweenState().quat, RageQuatFromR(rot)); +} + +void +Actor::RunCommands(const LuaReference& cmds, const LuaReference* pParamTable) +{ + if (!cmds.IsSet() || cmds.IsNil()) { + LuaHelpers::ReportScriptErrorFmt( + "RunCommands: commands for %s are unset or nil", + GetLineage().c_str()); + return; + } + + Lua* L = LUA->Get(); + + // function + cmds.PushSelf(L); + if (lua_isnil(L, -1)) { + LuaHelpers::ReportScriptErrorFmt( + "RunCommands: Error compiling commands for %s", GetLineage().c_str()); + LUA->Release(L); + return; + } + + // 1st parameter + this->PushSelf(L); + + // 2nd parameter + if (pParamTable == nullptr) + lua_pushnil(L); + else + pParamTable->PushSelf(L); + + // call function with 2 arguments and 0 results + RString Error = "Error playing command:"; + LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); + + LUA->Release(L); +} + +float +Actor::GetTweenTimeLeft() const +{ + float tot = 0; + + tot += m_fHibernateSecondsLeft; + + for (unsigned i = 0; i < m_Tweens.size(); ++i) + tot += m_Tweens[i]->info.m_fTimeLeftInTween; + + return tot; +} + +/* This is a hack to change all tween states while leaving existing tweens + * alone. + * + * Hmm. Most commands actually act on a TweenStateAndInfo, not the Actor itself. + * Conceptually, it wouldn't be hard to give TweenState a presence in Lua, so + * we can simply say eg. "for x in states(Actor) do x.SetDiffuseColor(c) end". + * However, we'd then have to give every TweenState a userdata in Lua while it's + * being manipulated, which would add overhead ... */ +void +Actor::SetGlobalDiffuseColor(const RageColor& c) +{ + for (int i = 0; i < NUM_DIFFUSE_COLORS; i++) // color, not alpha + { + for (unsigned ts = 0; ts < m_Tweens.size(); ++ts) { + m_Tweens[ts]->state.diffuse[i].r = c.r; + m_Tweens[ts]->state.diffuse[i].g = c.g; + m_Tweens[ts]->state.diffuse[i].b = c.b; + } + m_current.diffuse[i].r = c.r; + m_current.diffuse[i].g = c.g; + m_current.diffuse[i].b = c.b; + m_start.diffuse[i].r = c.r; + m_start.diffuse[i].g = c.g; + m_start.diffuse[i].b = c.b; + } +} + +void +Actor::SetDiffuseColor(const RageColor& c) +{ + for (auto& i : DestTweenState().diffuse) { + i.r = c.r; + i.g = c.g; + i.b = c.b; + } +} + +void +Actor::TweenState::Init() +{ + pos = RageVector3(0, 0, 0); + rotation = RageVector3(0, 0, 0); + quat = RageVector4(0, 0, 0, 1); + scale = RageVector3(1, 1, 1); + fSkewX = 0; + fSkewY = 0; + crop = RectF(0, 0, 0, 0); + fade = RectF(0, 0, 0, 0); + for (auto& i : diffuse) + i = RageColor(1, 1, 1, 1); + glow = RageColor(1, 1, 1, 0); + aux = 0; +} + +bool +Actor::TweenState::operator==(const TweenState& other) const +{ +#define COMPARE(x) \ + if ((x) != other.x) \ + return false; + COMPARE(pos); + COMPARE(rotation); + COMPARE(quat); + COMPARE(scale); + COMPARE(fSkewX); + COMPARE(fSkewY); + COMPARE(crop); + COMPARE(fade); + for (unsigned i = 0; i < ARRAYLEN(diffuse); i++) + COMPARE(diffuse[i]); + COMPARE(glow); + COMPARE(aux); +#undef COMPARE + return true; +} + +void +Actor::TweenState::MakeWeightedAverage(TweenState& average_out, + const TweenState& ts1, + const TweenState& ts2, + float fPercentBetween) +{ + average_out.pos = lerp(fPercentBetween, ts1.pos, ts2.pos); + average_out.scale = lerp(fPercentBetween, ts1.scale, ts2.scale); + average_out.rotation = lerp(fPercentBetween, ts1.rotation, ts2.rotation); + RageQuatSlerp(&average_out.quat, ts1.quat, ts2.quat, fPercentBetween); + average_out.fSkewX = lerp(fPercentBetween, ts1.fSkewX, ts2.fSkewX); + average_out.fSkewY = lerp(fPercentBetween, ts1.fSkewY, ts2.fSkewY); + + average_out.crop.left = lerp(fPercentBetween, ts1.crop.left, ts2.crop.left); + average_out.crop.top = lerp(fPercentBetween, ts1.crop.top, ts2.crop.top); + average_out.crop.right = + lerp(fPercentBetween, ts1.crop.right, ts2.crop.right); + average_out.crop.bottom = + lerp(fPercentBetween, ts1.crop.bottom, ts2.crop.bottom); + + average_out.fade.left = lerp(fPercentBetween, ts1.fade.left, ts2.fade.left); + average_out.fade.top = lerp(fPercentBetween, ts1.fade.top, ts2.fade.top); + average_out.fade.right = + lerp(fPercentBetween, ts1.fade.right, ts2.fade.right); + average_out.fade.bottom = + lerp(fPercentBetween, ts1.fade.bottom, ts2.fade.bottom); + + for (int i = 0; i < NUM_DIFFUSE_COLORS; ++i) + average_out.diffuse[i] = + lerp(fPercentBetween, ts1.diffuse[i], ts2.diffuse[i]); + + average_out.glow = lerp(fPercentBetween, ts1.glow, ts2.glow); + average_out.aux = lerp(fPercentBetween, ts1.aux, ts2.aux); +} + +void +Actor::Sleep(float time) +{ + ASSERT(time >= 0); + + BeginTweening(time, TWEEN_LINEAR); + BeginTweening(0, TWEEN_LINEAR); +} + +void +Actor::QueueCommand(const RString& sCommandName) +{ + BeginTweening(0, TWEEN_LINEAR); + TweenInfo& TI = m_Tweens.back()->info; + TI.m_sCommandName = sCommandName; +} + +void +Actor::QueueMessage(const RString& sMessageName) +{ + // Hack: use "!" as a marker to broadcast a command, instead of playing a + // command, so we don't have to add yet another element to every tween + // state for this rarely-used command. + BeginTweening(0, TWEEN_LINEAR); + TweenInfo& TI = m_Tweens.back()->info; + TI.m_sCommandName = "!" + sMessageName; +} + +void +Actor::AddCommand(const RString& sCmdName, apActorCommands apac, bool warn) +{ + if (HasCommand(sCmdName) && warn) { + RString sWarning = + GetLineage() + "'s command '" + sCmdName + "' defined twice"; + LuaHelpers::ReportScriptError(sWarning, "COMMAND_DEFINED_TWICE"); + } + + RString sMessage; + if (GetMessageNameFromCommandName(sCmdName, sMessage)) { + SubscribeToMessage(sMessage); + m_mapNameToCommands[sMessage] = + apac; // sCmdName w/o "Message" at the end + } else { + m_mapNameToCommands[sCmdName] = apac; + } +} + +bool +Actor::HasCommand(const RString& sCmdName) const +{ + return GetCommand(sCmdName) != nullptr; +} + +const apActorCommands* +Actor::GetCommand(const RString& sCommandName) const +{ + map::const_iterator it = + m_mapNameToCommands.find(sCommandName); + if (it == m_mapNameToCommands.end()) + return nullptr; + return &it->second; +} + +void +Actor::HandleMessage(const Message& msg) +{ + PlayCommandNoRecurse(msg); +} + +void +Actor::PlayCommandNoRecurse(const Message& msg) +{ + const apActorCommands* pCmd = GetCommand(msg.GetName()); + if (pCmd != NULL && (*pCmd)->IsSet() && !(*pCmd)->IsNil()) { + RunCommands(*pCmd, &msg.GetParamTable()); + } +} + +void +Actor::PushContext(lua_State* L) +{ + // self.ctx should already exist + m_pLuaInstance->PushSelf(L); + lua_getfield(L, -1, "ctx"); + lua_remove(L, -2); +} + +void +Actor::SetParent(Actor* pParent) +{ + m_pParent = pParent; + + Lua* L = LUA->Get(); + int iTop = lua_gettop(L); + + this->PushContext(L); + lua_pushstring(L, "__index"); + pParent->PushContext(L); + lua_settable(L, -3); + + lua_settop(L, iTop); + LUA->Release(L); +} + +Actor::TweenInfo::TweenInfo() +{ + m_pTween = nullptr; +} + +Actor::TweenInfo::~TweenInfo() +{ + delete m_pTween; +} + +Actor::TweenInfo::TweenInfo(const TweenInfo& cpy) +{ + m_pTween = nullptr; + *this = cpy; +} + +Actor::TweenInfo& +Actor::TweenInfo::operator=(const TweenInfo& rhs) +{ + delete m_pTween; + m_pTween = (rhs.m_pTween != nullptr ? rhs.m_pTween->Copy() : nullptr); + m_fTimeLeftInTween = rhs.m_fTimeLeftInTween; + m_fTweenTime = rhs.m_fTweenTime; + m_sCommandName = rhs.m_sCommandName; + return *this; +} + +void +Actor::SetTimeout(function f, float ms) +{ + delayedFunctions.emplace_back(make_pair(f, ms)); + return; +} + +void +Actor::SetInterval(function f, float ms, function fRemove) +{ + delayedPeriodicFunctions.emplace_back(make_tuple(f, ms, ms, fRemove)); + return; +} + +// lua start +#include "LuaBinding.h" + +/** @brief Allow Lua to have access to the Actor. */ +class LunaActor : public Luna +{ + public: + static int name(T* p, lua_State* L) + { + p->SetName(SArg(1)); + COMMON_RETURN_SELF; + } + static int setTimeout(T* p, lua_State* L) + { + auto f = GetFuncArg(1, L); + std::function execF = [f]() { + Lua* L = LUA->Get(); + f.PushSelf(L); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::RunScriptOnStack( + L, Error, 0, 0, true); // 1 args, 0 results + } + LUA->Release(L); + }; + p->SetTimeout(execF, FArg(2)); + COMMON_RETURN_SELF; + } + static int setInterval(T* p, lua_State* L) + { + lua_pushvalue(L, 1); + auto f = luaL_ref(L, LUA_REGISTRYINDEX); + std::function execF = [f]() { + Lua* L = LUA->Get(); + lua_rawgeti(L, LUA_REGISTRYINDEX, f); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::RunScriptOnStack( + L, Error, 0, 0, true); // 1 args, 0 results + } + LUA->Release(L); + }; + p->SetInterval(execF, FArg(2), f); + lua_pushnumber(L, f); + return 1; + } + static int clearInterval(T* p, lua_State* L) + { + int r = IArg(1); + auto& l = p->delayedPeriodicFunctions; + auto it = find_if( + l.begin(), l.end(), [r](auto& x) { return std::get<3>() == r; }); + if (it != l.end()) { + luaL_unref(L, LUA_REGISTRYINDEX, r); + l.erase(it); + } else { + LuaHelpers::ReportScriptError( + "Interval function not found (When triying to clearInterval() )"); + } + return 0; + } + static int sleep(T* p, lua_State* L) + { + float fTime = FArg(1); + if (fTime < 0) { + LuaHelpers::ReportScriptErrorFmt( + "Lua: sleep(%f): time must not be negative", fTime); + COMMON_RETURN_SELF; + } + p->Sleep(fTime); + COMMON_RETURN_SELF; + } + static int linear(T* p, lua_State* L) + { + float fTime = FArg(1); + if (fTime < 0) { + LuaHelpers::ReportScriptErrorFmt( + "Lua: linear(%f): tween time must not be negative", fTime); + COMMON_RETURN_SELF; + } + p->BeginTweening(fTime, TWEEN_LINEAR); + COMMON_RETURN_SELF; + } + static int accelerate(T* p, lua_State* L) + { + float fTime = FArg(1); + if (fTime < 0) { + LuaHelpers::ReportScriptErrorFmt( + "Lua: accelerate(%f): tween time must not be negative", fTime); + COMMON_RETURN_SELF; + } + p->BeginTweening(fTime, TWEEN_ACCELERATE); + COMMON_RETURN_SELF; + } + static int decelerate(T* p, lua_State* L) + { + float fTime = FArg(1); + if (fTime < 0) { + LuaHelpers::ReportScriptErrorFmt( + "Lua: decelerate(%f): tween time must not be negative", fTime); + COMMON_RETURN_SELF; + } + p->BeginTweening(fTime, TWEEN_DECELERATE); + COMMON_RETURN_SELF; + } + static int spring(T* p, lua_State* L) + { + float fTime = FArg(1); + if (fTime < 0) { + LuaHelpers::ReportScriptErrorFmt( + "Lua: spring(%f): tween time must not be negative", fTime); + COMMON_RETURN_SELF; + } + p->BeginTweening(fTime, TWEEN_SPRING); + COMMON_RETURN_SELF; + } + static int tween(T* p, lua_State* L) + { + float fTime = FArg(1); + if (fTime < 0) { + LuaHelpers::ReportScriptErrorFmt( + "Lua: tween(%f): tween time must not be negative", fTime); + COMMON_RETURN_SELF; + } + ITween* pTween = ITween::CreateFromStack(L, 2); + if (pTween != nullptr) { + p->BeginTweening(fTime, pTween); + } + COMMON_RETURN_SELF; + } + static int stoptweening(T* p, lua_State* L) + { + p->StopTweening(); + COMMON_RETURN_SELF; + } + static int finishtweening(T* p, lua_State* L) + { + p->FinishTweening(); + COMMON_RETURN_SELF; + } + static int hurrytweening(T* p, lua_State* L) + { + float time = FArg(1); + if (time < 0.0f) { + luaL_error(L, "Tweening hurry factor cannot be negative. %f", time); + } + p->HurryTweening(time); + COMMON_RETURN_SELF; + } + static int GetTweenTimeLeft(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetTweenTimeLeft()); + return 1; + } + static int x(T* p, lua_State* L) + { + p->SetX(FArg(1)); + COMMON_RETURN_SELF; + } + static int y(T* p, lua_State* L) + { + p->SetY(FArg(1)); + COMMON_RETURN_SELF; + } + static int z(T* p, lua_State* L) + { + p->SetZ(FArg(1)); + COMMON_RETURN_SELF; + } + static int xy(T* p, lua_State* L) + { + p->SetXY(FArg(1), FArg(2)); + COMMON_RETURN_SELF; + } + static int addx(T* p, lua_State* L) + { + p->AddX(FArg(1)); + COMMON_RETURN_SELF; + } + static int addy(T* p, lua_State* L) + { + p->AddY(FArg(1)); + COMMON_RETURN_SELF; + } + static int addz(T* p, lua_State* L) + { + p->AddZ(FArg(1)); + COMMON_RETURN_SELF; + } + static int zoom(T* p, lua_State* L) + { + p->SetZoom(FArg(1)); + COMMON_RETURN_SELF; + } + static int zoomx(T* p, lua_State* L) + { + p->SetZoomX(FArg(1)); + COMMON_RETURN_SELF; + } + static int zoomy(T* p, lua_State* L) + { + p->SetZoomY(FArg(1)); + COMMON_RETURN_SELF; + } + static int zoomz(T* p, lua_State* L) + { + p->SetZoomZ(FArg(1)); + COMMON_RETURN_SELF; + } + static int zoomto(T* p, lua_State* L) + { + p->ZoomTo(FArg(1), FArg(2)); + COMMON_RETURN_SELF; + } + static int zoomtowidth(T* p, lua_State* L) + { + p->ZoomToWidth(FArg(1)); + COMMON_RETURN_SELF; + } + static int zoomtoheight(T* p, lua_State* L) + { + p->ZoomToHeight(FArg(1)); + COMMON_RETURN_SELF; + } + static int setsize(T* p, lua_State* L) + { + p->SetWidth(FArg(1)); + p->SetHeight(FArg(2)); + COMMON_RETURN_SELF; + } + static int SetWidth(T* p, lua_State* L) + { + p->SetWidth(FArg(1)); + COMMON_RETURN_SELF; + } + static int SetHeight(T* p, lua_State* L) + { + p->SetHeight(FArg(1)); + COMMON_RETURN_SELF; + } + static int basealpha(T* p, lua_State* L) + { + p->SetBaseAlpha(FArg(1)); + COMMON_RETURN_SELF; + } + static int basezoom(T* p, lua_State* L) + { + p->SetBaseZoom(FArg(1)); + COMMON_RETURN_SELF; + } + static int basezoomx(T* p, lua_State* L) + { + p->SetBaseZoomX(FArg(1)); + COMMON_RETURN_SELF; + } + static int basezoomy(T* p, lua_State* L) + { + p->SetBaseZoomY(FArg(1)); + COMMON_RETURN_SELF; + } + static int basezoomz(T* p, lua_State* L) + { + p->SetBaseZoomZ(FArg(1)); + COMMON_RETURN_SELF; + } + static int stretchto(T* p, lua_State* L) + { + p->StretchTo(RectF(FArg(1), FArg(2), FArg(3), FArg(4))); + COMMON_RETURN_SELF; + } + static int cropleft(T* p, lua_State* L) + { + p->SetCropLeft(FArg(1)); + COMMON_RETURN_SELF; + } + static int croptop(T* p, lua_State* L) + { + p->SetCropTop(FArg(1)); + COMMON_RETURN_SELF; + } + static int cropright(T* p, lua_State* L) + { + p->SetCropRight(FArg(1)); + COMMON_RETURN_SELF; + } + static int cropbottom(T* p, lua_State* L) + { + p->SetCropBottom(FArg(1)); + COMMON_RETURN_SELF; + } + static int fadeleft(T* p, lua_State* L) + { + p->SetFadeLeft(FArg(1)); + COMMON_RETURN_SELF; + } + static int fadetop(T* p, lua_State* L) + { + p->SetFadeTop(FArg(1)); + COMMON_RETURN_SELF; + } + static int faderight(T* p, lua_State* L) + { + p->SetFadeRight(FArg(1)); + COMMON_RETURN_SELF; + } + static int fadebottom(T* p, lua_State* L) + { + p->SetFadeBottom(FArg(1)); + COMMON_RETURN_SELF; + } + static int diffuse(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuse(c); + COMMON_RETURN_SELF; + } + static int diffuseupperleft(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseUpperLeft(c); + COMMON_RETURN_SELF; + } + static int diffuseupperright(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseUpperRight(c); + COMMON_RETURN_SELF; + } + static int diffuselowerleft(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseLowerLeft(c); + COMMON_RETURN_SELF; + } + static int diffuselowerright(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseLowerRight(c); + COMMON_RETURN_SELF; + } + static int diffuseleftedge(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseLeftEdge(c); + COMMON_RETURN_SELF; + } + static int diffuserightedge(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseRightEdge(c); + COMMON_RETURN_SELF; + } + static int diffusetopedge(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseTopEdge(c); + COMMON_RETURN_SELF; + } + static int diffusebottomedge(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseBottomEdge(c); + COMMON_RETURN_SELF; + } + static int diffusealpha(T* p, lua_State* L) + { + p->SetDiffuseAlpha(FArg(1)); + COMMON_RETURN_SELF; + } + static int diffusecolor(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetDiffuseColor(c); + COMMON_RETURN_SELF; + } + static int glow(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetGlow(c); + COMMON_RETURN_SELF; + } + static int aux(T* p, lua_State* L) + { + p->SetAux(FArg(1)); + COMMON_RETURN_SELF; + } + static int getaux(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetAux()); + return 1; + } + static int rotationx(T* p, lua_State* L) + { + p->SetRotationX(FArg(1)); + COMMON_RETURN_SELF; + } + static int rotationy(T* p, lua_State* L) + { + p->SetRotationY(FArg(1)); + COMMON_RETURN_SELF; + } + static int rotationz(T* p, lua_State* L) + { + p->SetRotationZ(FArg(1)); + COMMON_RETURN_SELF; + } + static int addrotationx(T* p, lua_State* L) + { + p->AddRotationX(FArg(1)); + COMMON_RETURN_SELF; + } + static int addrotationy(T* p, lua_State* L) + { + p->AddRotationY(FArg(1)); + COMMON_RETURN_SELF; + } + static int addrotationz(T* p, lua_State* L) + { + p->AddRotationZ(FArg(1)); + COMMON_RETURN_SELF; + } + static int getrotation(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetRotationX()); + lua_pushnumber(L, p->GetRotationY()); + lua_pushnumber(L, p->GetRotationZ()); + return 3; + } + static int baserotationx(T* p, lua_State* L) + { + p->SetBaseRotationX(FArg(1)); + COMMON_RETURN_SELF; + } + static int baserotationy(T* p, lua_State* L) + { + p->SetBaseRotationY(FArg(1)); + COMMON_RETURN_SELF; + } + static int baserotationz(T* p, lua_State* L) + { + p->SetBaseRotationZ(FArg(1)); + COMMON_RETURN_SELF; + } + static int skewx(T* p, lua_State* L) + { + p->SetSkewX(FArg(1)); + COMMON_RETURN_SELF; + } + static int skewy(T* p, lua_State* L) + { + p->SetSkewY(FArg(1)); + COMMON_RETURN_SELF; + } + static int heading(T* p, lua_State* L) + { + p->AddRotationH(FArg(1)); + COMMON_RETURN_SELF; + } + static int pitch(T* p, lua_State* L) + { + p->AddRotationP(FArg(1)); + COMMON_RETURN_SELF; + } + static int roll(T* p, lua_State* L) + { + p->AddRotationR(FArg(1)); + COMMON_RETURN_SELF; + } + static int shadowlength(T* p, lua_State* L) + { + p->SetShadowLength(FArg(1)); + COMMON_RETURN_SELF; + } + static int shadowlengthx(T* p, lua_State* L) + { + p->SetShadowLengthX(FArg(1)); + COMMON_RETURN_SELF; + } + static int shadowlengthy(T* p, lua_State* L) + { + p->SetShadowLengthY(FArg(1)); + COMMON_RETURN_SELF; + } + static int shadowcolor(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetShadowColor(c); + COMMON_RETURN_SELF; + } + static int horizalign(T* p, lua_State* L) + { + p->SetHorizAlign(Enum::Check(L, 1)); + COMMON_RETURN_SELF; + } + static int vertalign(T* p, lua_State* L) + { + p->SetVertAlign(Enum::Check(L, 1)); + COMMON_RETURN_SELF; + } + static int halign(T* p, lua_State* L) + { + p->SetHorizAlign(FArg(1)); + COMMON_RETURN_SELF; + } + static int valign(T* p, lua_State* L) + { + p->SetVertAlign(FArg(1)); + COMMON_RETURN_SELF; + } + static int diffuseblink(T* p, lua_State* L) + { + p->SetEffectDiffuseBlink( + 1.0f, RageColor(0.5f, 0.5f, 0.5f, 0.5f), RageColor(1, 1, 1, 1)); + COMMON_RETURN_SELF; + } + static int diffuseshift(T* p, lua_State* L) + { + p->SetEffectDiffuseShift( + 1.0f, RageColor(0, 0, 0, 1), RageColor(1, 1, 1, 1)); + COMMON_RETURN_SELF; + } + static int diffuseramp(T* p, lua_State* L) + { + p->SetEffectDiffuseRamp( + 1.0f, RageColor(0, 0, 0, 1), RageColor(1, 1, 1, 1)); + COMMON_RETURN_SELF; + } + static int glowblink(T* p, lua_State* L) + { + p->SetEffectGlowBlink( + 1.0f, RageColor(1, 1, 1, 0.2f), RageColor(1, 1, 1, 0.8f)); + COMMON_RETURN_SELF; + } + static int glowshift(T* p, lua_State* L) + { + p->SetEffectGlowShift( + 1.0f, RageColor(1, 1, 1, 0.2f), RageColor(1, 1, 1, 0.8f)); + COMMON_RETURN_SELF; + } + static int glowramp(T* p, lua_State* L) + { + p->SetEffectGlowRamp( + 1.0f, RageColor(1, 1, 1, 0.2f), RageColor(1, 1, 1, 0.8f)); + COMMON_RETURN_SELF; + } + static int rainbow(T* p, lua_State* L) + { + p->SetEffectRainbow(2.0f); + COMMON_RETURN_SELF; + } + static int wag(T* p, lua_State* L) + { + p->SetEffectWag(2.0f, RageVector3(0, 0, 20)); + COMMON_RETURN_SELF; + } + static int bounce(T* p, lua_State* L) + { + p->SetEffectBounce(2.0f, RageVector3(0, 20, 0)); + COMMON_RETURN_SELF; + } + static int bob(T* p, lua_State* L) + { + p->SetEffectBob(2.0f, RageVector3(0, 20, 0)); + COMMON_RETURN_SELF; + } + static int pulse(T* p, lua_State* L) + { + p->SetEffectPulse(2.0f, 0.5f, 1.0f); + COMMON_RETURN_SELF; + } + static int spin(T* p, lua_State* L) + { + p->SetEffectSpin(RageVector3(0, 0, 180)); + COMMON_RETURN_SELF; + } + static int vibrate(T* p, lua_State* L) + { + p->SetEffectVibrate(RageVector3(10, 10, 10)); + COMMON_RETURN_SELF; + } + static int stopeffect(T* p, lua_State* L) + { + p->StopEffect(); + COMMON_RETURN_SELF; + } + static int effectcolor1(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetEffectColor1(c); + COMMON_RETURN_SELF; + } + static int effectcolor2(T* p, lua_State* L) + { + RageColor c; + c.FromStackCompat(L, 1); + p->SetEffectColor2(c); + COMMON_RETURN_SELF; + } + static int effectperiod(T* p, lua_State* L) + { + float fPeriod = FArg(1); + if (fPeriod <= 0) { + LuaHelpers::ReportScriptErrorFmt( + "Effect period (%f) must be positive; ignoring", fPeriod); + COMMON_RETURN_SELF; + } + p->SetEffectPeriod(FArg(1)); + COMMON_RETURN_SELF; + } + static int effecttiming(T* p, lua_State* L) + { + float rth = FArg(1); + float hah = FArg(2); + float rtf = FArg(3); + float haz = FArg(4); + // Compatibility: hold_at_full is optional. + float haf = 0; + if (lua_isnumber(L, 5) != 0) { + haf = FArg(5); + } + RString err; + if (!p->SetEffectTiming(rth, hah, rtf, haf, haz, err)) { + luaL_error(L, err.c_str()); + } + COMMON_RETURN_SELF; + } + static int effect_hold_at_full(T* p, lua_State* L) + { + RString err; + if (!p->SetEffectHoldAtFull(FArg(1), err)) { + luaL_error(L, err.c_str()); + } + COMMON_RETURN_SELF; + } + static int effectoffset(T* p, lua_State* L) + { + p->SetEffectOffset(FArg(1)); + COMMON_RETURN_SELF; + } + static int effectclock(T* p, lua_State* L) + { + p->SetEffectClockString(SArg(1)); + COMMON_RETURN_SELF; + } + static int effectmagnitude(T* p, lua_State* L) + { + p->SetEffectMagnitude(RageVector3(FArg(1), FArg(2), FArg(3))); + COMMON_RETURN_SELF; + } + static int geteffectmagnitude(T* p, lua_State* L) + { + RageVector3 v = p->GetEffectMagnitude(); + lua_pushnumber(L, v[0]); + lua_pushnumber(L, v[1]); + lua_pushnumber(L, v[2]); + return 3; + } + GETTER_SETTER_BOOL_METHOD(tween_uses_effect_delta); + static int scaletocover(T* p, lua_State* L) + { + p->ScaleToCover(RectF(FArg(1), FArg(2), FArg(3), FArg(4))); + COMMON_RETURN_SELF; + } + static int scaletofit(T* p, lua_State* L) + { + p->ScaleToFitInside(RectF(FArg(1), FArg(2), FArg(3), FArg(4))); + COMMON_RETURN_SELF; + } + static int animate(T* p, lua_State* L) + { + p->EnableAnimation(BIArg(1)); + COMMON_RETURN_SELF; + } + static int play(T* p, lua_State* L) + { + p->EnableAnimation(true); + COMMON_RETURN_SELF; + } + static int pause(T* p, lua_State* L) + { + p->EnableAnimation(false); + COMMON_RETURN_SELF; + } + static int setstate(T* p, lua_State* L) + { + p->SetState(IArg(1)); + COMMON_RETURN_SELF; + } + static int GetNumStates(T* p, lua_State* L) + { + LuaHelpers::Push(L, p->GetNumStates()); + return 1; + } + static int texturetranslate(T* p, lua_State* L) + { + p->SetTextureTranslate(FArg(1), FArg(2)); + COMMON_RETURN_SELF; + } + static int texturewrapping(T* p, lua_State* L) + { + p->SetTextureWrapping(BIArg(1)); + COMMON_RETURN_SELF; + } + static int SetTextureFiltering(T* p, lua_State* L) + { + p->SetTextureFiltering(BArg(1)); + COMMON_RETURN_SELF; + } + static int blend(T* p, lua_State* L) + { + p->SetBlendMode(Enum::Check(L, 1)); + COMMON_RETURN_SELF; + } + static int zbuffer(T* p, lua_State* L) + { + p->SetUseZBuffer(BIArg(1)); + COMMON_RETURN_SELF; + } + static int ztest(T* p, lua_State* L) + { + p->SetZTestMode((BIArg(1)) ? ZTEST_WRITE_ON_PASS : ZTEST_OFF); + COMMON_RETURN_SELF; + } + static int ztestmode(T* p, lua_State* L) + { + p->SetZTestMode(Enum::Check(L, 1)); + COMMON_RETURN_SELF; + } + static int zwrite(T* p, lua_State* L) + { + p->SetZWrite(BIArg(1)); + COMMON_RETURN_SELF; + } + static int zbias(T* p, lua_State* L) + { + p->SetZBias(FArg(1)); + COMMON_RETURN_SELF; + } + static int clearzbuffer(T* p, lua_State* L) + { + p->SetClearZBuffer(BIArg(1)); + COMMON_RETURN_SELF; + } + static int backfacecull(T* p, lua_State* L) + { + p->SetCullMode((BIArg(1)) ? CULL_BACK : CULL_NONE); + COMMON_RETURN_SELF; + } + static int cullmode(T* p, lua_State* L) + { + p->SetCullMode(Enum::Check(L, 1)); + COMMON_RETURN_SELF; + } + static int visible(T* p, lua_State* L) + { + p->SetVisible(BIArg(1)); + COMMON_RETURN_SELF; + } + static int hibernate(T* p, lua_State* L) + { + p->SetHibernate(FArg(1)); + COMMON_RETURN_SELF; + } + static int draworder(T* p, lua_State* L) + { + p->SetDrawOrder(IArg(1)); + COMMON_RETURN_SELF; + } + static int playcommand(T* p, lua_State* L) + { + if (!lua_istable(L, 2) && !lua_isnoneornil(L, 2)) + luaL_typerror(L, 2, "table or nil"); + + LuaReference ParamTable; + lua_pushvalue(L, 2); + ParamTable.SetFromStack(L); + + Message msg(SArg(1), ParamTable); + p->HandleMessage(msg); + + COMMON_RETURN_SELF; + } + static int queuecommand(T* p, lua_State* L) + { + p->QueueCommand(SArg(1)); + COMMON_RETURN_SELF; + } + static int queuemessage(T* p, lua_State* L) + { + p->QueueMessage(SArg(1)); + COMMON_RETURN_SELF; + } + static int addcommand(T* p, lua_State* L) + { + auto* pRef = new LuaReference; + pRef->SetFromStack(L); + p->AddCommand(SArg(1), apActorCommands(pRef)); + COMMON_RETURN_SELF; + } + static int GetCommand(T* p, lua_State* L) + { + const apActorCommands* pCommand = p->GetCommand(SArg(1)); + if (pCommand == nullptr) + lua_pushnil(L); + else + (*pCommand)->PushSelf(L); + + return 1; + } + static int RunCommandsRecursively(T* p, lua_State* L) + { + luaL_checktype(L, 1, LUA_TFUNCTION); + if (!lua_istable(L, 2) && !lua_isnoneornil(L, 2)) + luaL_typerror(L, 2, "table or nil"); + + LuaReference ref; + lua_pushvalue(L, 1); + ref.SetFromStack(L); + + LuaReference ParamTable; + lua_pushvalue(L, 2); + ParamTable.SetFromStack(L); + + p->RunCommandsRecursively(ref, &ParamTable); + COMMON_RETURN_SELF; + } + + static int GetX(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetX()); + return 1; + } + static int GetY(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetY()); + return 1; + } + static int GetZ(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetZ()); + return 1; + } + static int GetDestX(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetDestX()); + return 1; + } + static int GetDestY(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetDestY()); + return 1; + } + static int GetDestZ(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetDestZ()); + return 1; + } + static int GetWidth(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetUnzoomedWidth()); + return 1; + } + static int GetHeight(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetUnzoomedHeight()); + return 1; + } + static int GetZoomedWidth(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetZoomedWidth()); + return 1; + } + static int GetZoomedHeight(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetZoomedHeight()); + return 1; + } + static int GetZoom(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetZoom()); + return 1; + } + static int GetZoomX(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetZoomX()); + return 1; + } + static int GetZoomY(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetZoomY()); + return 1; + } + static int GetZoomZ(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetZoomZ()); + return 1; + } + static int GetBaseZoomX(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetBaseZoomX()); + return 1; + } + static int GetBaseZoomY(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetBaseZoomY()); + return 1; + } + static int GetBaseZoomZ(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetBaseZoomZ()); + return 1; + } + static int GetRotationX(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetRotationX()); + return 1; + } + static int GetRotationY(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetRotationY()); + return 1; + } + static int GetRotationZ(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetRotationZ()); + return 1; + } + static int GetSecsIntoEffect(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetSecsIntoEffect()); + return 1; + } + static int GetEffectDelta(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetEffectDelta()); + return 1; + } + DEFINE_METHOD(GetDiffuse, GetDiffuse()) + DEFINE_METHOD(GetGlow, GetGlow()) + static int GetDiffuseAlpha(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetDiffuseAlpha()); + return 1; + } + static int GetVisible(T* p, lua_State* L) + { + lua_pushboolean(L, p->GetVisible()); + return 1; + } + static int GetHAlign(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetHorizAlign()); + return 1; + } + static int GetVAlign(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetVertAlign()); + return 1; + } + + static int GetName(T* p, lua_State* L) + { + lua_pushstring(L, p->GetName()); + return 1; + } + static int GetParent(T* p, lua_State* L) + { + Actor* pParent = p->GetParent(); + if (pParent == nullptr) + lua_pushnil(L); + else + pParent->PushSelf(L); + return 1; + } + static int GetFakeParent(T* p, lua_State* L) + { + Actor* fake = p->GetFakeParent(); + if (fake == nullptr) { + lua_pushnil(L); + } else { + fake->PushSelf(L); + } + return 1; + } + static int SetFakeParent(T* p, lua_State* L) + { + if (lua_isnoneornil(L, 1)) { + p->SetFakeParent(NULL); + } else { + Actor* fake = Luna::check(L, 1); + p->SetFakeParent(fake); + } + COMMON_RETURN_SELF; + } + static int AddWrapperState(T* p, lua_State* L) + { + p->AddWrapperState(); + p->GetWrapperState(p->GetNumWrapperStates() - 1)->PushSelf(L); + return 1; + } + static size_t get_state_index(T* p, lua_State* L, int stack_index) + { + // Lua is one indexed. + int i = IArg(stack_index) - 1; + const auto si = static_cast(i); + if (i < 0 || si >= p->GetNumWrapperStates()) { + luaL_error(L, "%d is not a valid wrapper state index.", i + 1); + } + return si; + } + static int RemoveWrapperState(T* p, lua_State* L) + { + size_t si = get_state_index(p, L, 1); + p->RemoveWrapperState(si); + COMMON_RETURN_SELF; + } + static int GetNumWrapperStates(T* p, lua_State* L) + { + lua_pushnumber(L, p->GetNumWrapperStates()); + return 1; + } + static int GetWrapperState(T* p, lua_State* L) + { + size_t si = get_state_index(p, L, 1); + p->GetWrapperState(si)->PushSelf(L); + return 1; + } + static int Draw(T* p, lua_State* L) + { + LUA->YieldLua(); + p->Draw(); + LUA->UnyieldLua(); + COMMON_RETURN_SELF; + } + + static int SaveXY(T* p, lua_State* L) + { // in the future arguments should be optional and default to getx, gety if + // no explicit coords are provided - mina + FILTERMAN->savepos(p->GetName(), IArg(1), IArg(2)); + COMMON_RETURN_SELF; + } + + static int LoadXY(T* p, lua_State* L) + { + auto doot = FILTERMAN->loadpos(p->GetName()); + p->SetX(static_cast(doot.first)); + p->SetY(static_cast(doot.second)); + COMMON_RETURN_SELF; + } + static int IsOver(T* p, lua_State* L) + { + lua_pushboolean(L, p->IsOver(FArg(1), FArg(2))); + return 1; + } + DEFINE_METHOD(GetTrueX, GetTrueX()); + DEFINE_METHOD(GetTrueY, GetTrueY()); + DEFINE_METHOD(GetTrueZoom, GetTrueZoom()); + DEFINE_METHOD(IsVisible, IsVisible()); + LunaActor() + { + ADD_METHOD(name); + ADD_METHOD(setInterval); + ADD_METHOD(setTimeout); + ADD_METHOD(name); + ADD_METHOD(sleep); + ADD_METHOD(linear); + ADD_METHOD(accelerate); + ADD_METHOD(decelerate); + ADD_METHOD(spring); + ADD_METHOD(tween); + ADD_METHOD(stoptweening); + ADD_METHOD(finishtweening); + ADD_METHOD(hurrytweening); + ADD_METHOD(GetTweenTimeLeft); + ADD_METHOD(x); + ADD_METHOD(y); + ADD_METHOD(z); + ADD_METHOD(xy); + ADD_METHOD(addx); + ADD_METHOD(addy); + ADD_METHOD(addz); + ADD_METHOD(zoom); + ADD_METHOD(zoomx); + ADD_METHOD(zoomy); + ADD_METHOD(zoomz); + ADD_METHOD(zoomto); + ADD_METHOD(zoomtowidth); + ADD_METHOD(zoomtoheight); + ADD_METHOD(setsize); + ADD_METHOD(SetWidth); + ADD_METHOD(SetHeight); + ADD_METHOD(basealpha); + ADD_METHOD(basezoom); + ADD_METHOD(basezoomx); + ADD_METHOD(basezoomy); + ADD_METHOD(basezoomz); + ADD_METHOD(stretchto); + ADD_METHOD(cropleft); + ADD_METHOD(croptop); + ADD_METHOD(cropright); + ADD_METHOD(cropbottom); + ADD_METHOD(fadeleft); + ADD_METHOD(fadetop); + ADD_METHOD(faderight); + ADD_METHOD(fadebottom); + ADD_METHOD(diffuse); + ADD_METHOD(diffuseupperleft); + ADD_METHOD(diffuseupperright); + ADD_METHOD(diffuselowerleft); + ADD_METHOD(diffuselowerright); + ADD_METHOD(diffuseleftedge); + ADD_METHOD(diffuserightedge); + ADD_METHOD(diffusetopedge); + ADD_METHOD(diffusebottomedge); + ADD_METHOD(diffusealpha); + ADD_METHOD(diffusecolor); + ADD_METHOD(glow); + ADD_METHOD(aux); + ADD_METHOD(getaux); + ADD_METHOD(rotationx); + ADD_METHOD(rotationy); + ADD_METHOD(rotationz); + ADD_METHOD(addrotationx); + ADD_METHOD(addrotationy); + ADD_METHOD(addrotationz); + ADD_METHOD(getrotation); + ADD_METHOD(baserotationx); + ADD_METHOD(baserotationy); + ADD_METHOD(baserotationz); + ADD_METHOD(skewx); + ADD_METHOD(skewy); + ADD_METHOD(heading); + ADD_METHOD(pitch); + ADD_METHOD(roll); + ADD_METHOD(shadowlength); + ADD_METHOD(shadowlengthx); + ADD_METHOD(shadowlengthy); + ADD_METHOD(shadowcolor); + ADD_METHOD(horizalign); + ADD_METHOD(vertalign); + ADD_METHOD(halign); + ADD_METHOD(valign); + ADD_METHOD(diffuseblink); + ADD_METHOD(diffuseshift); + ADD_METHOD(diffuseramp); + ADD_METHOD(glowblink); + ADD_METHOD(glowshift); + ADD_METHOD(glowramp); + ADD_METHOD(rainbow); + ADD_METHOD(wag); + ADD_METHOD(bounce); + ADD_METHOD(bob); + ADD_METHOD(pulse); + ADD_METHOD(spin); + ADD_METHOD(vibrate); + ADD_METHOD(stopeffect); + ADD_METHOD(effectcolor1); + ADD_METHOD(effectcolor2); + ADD_METHOD(effectperiod); + ADD_METHOD(effecttiming); + ADD_METHOD(effect_hold_at_full); + ADD_METHOD(effectoffset); + ADD_METHOD(effectclock); + ADD_METHOD(effectmagnitude); + ADD_METHOD(geteffectmagnitude); + ADD_GET_SET_METHODS(tween_uses_effect_delta); + ADD_METHOD(scaletocover); + ADD_METHOD(scaletofit); + ADD_METHOD(animate); + ADD_METHOD(play); + ADD_METHOD(pause); + ADD_METHOD(setstate); + ADD_METHOD(GetNumStates); + ADD_METHOD(texturetranslate); + ADD_METHOD(texturewrapping); + ADD_METHOD(SetTextureFiltering); + ADD_METHOD(blend); + ADD_METHOD(zbuffer); + ADD_METHOD(ztest); + ADD_METHOD(ztestmode); + ADD_METHOD(zwrite); + ADD_METHOD(zbias); + ADD_METHOD(clearzbuffer); + ADD_METHOD(backfacecull); + ADD_METHOD(cullmode); + ADD_METHOD(visible); + ADD_METHOD(hibernate); + ADD_METHOD(draworder); + ADD_METHOD(playcommand); + ADD_METHOD(queuecommand); + ADD_METHOD(queuemessage); + ADD_METHOD(addcommand); + ADD_METHOD(GetCommand); + ADD_METHOD(RunCommandsRecursively); + + ADD_METHOD(GetX); + ADD_METHOD(GetY); + ADD_METHOD(GetZ); + ADD_METHOD(GetDestX); + ADD_METHOD(GetDestY); + ADD_METHOD(GetDestZ); + ADD_METHOD(GetWidth); + ADD_METHOD(GetHeight); + ADD_METHOD(GetZoomedWidth); + ADD_METHOD(GetZoomedHeight); + ADD_METHOD(GetZoom); + ADD_METHOD(GetZoomX); + ADD_METHOD(GetZoomY); + ADD_METHOD(GetZoomZ); + ADD_METHOD(GetRotationX); + ADD_METHOD(GetRotationY); + ADD_METHOD(GetRotationZ); + ADD_METHOD(GetBaseZoomX); + ADD_METHOD(GetBaseZoomY); + ADD_METHOD(GetBaseZoomZ); + ADD_METHOD(GetSecsIntoEffect); + ADD_METHOD(GetEffectDelta); + ADD_METHOD(GetDiffuse); + ADD_METHOD(GetDiffuseAlpha); + ADD_METHOD(GetGlow); + ADD_METHOD(GetVisible); + ADD_METHOD(GetHAlign); + ADD_METHOD(GetVAlign); + + ADD_METHOD(GetName); + ADD_METHOD(GetParent); + ADD_METHOD(GetFakeParent); + ADD_METHOD(SetFakeParent); + ADD_METHOD(AddWrapperState); + ADD_METHOD(RemoveWrapperState); + ADD_METHOD(GetNumWrapperStates); + ADD_METHOD(GetWrapperState); + + ADD_METHOD(Draw); + + ADD_METHOD(SaveXY); + ADD_METHOD(LoadXY); + + ADD_METHOD(GetTrueX); + ADD_METHOD(GetTrueY); + ADD_METHOD(GetTrueZoom); + ADD_METHOD(IsVisible); + ADD_METHOD(IsOver); + } +}; + +LUA_REGISTER_INSTANCED_BASE_CLASS(Actor) +// lua end + +/* + * (c) 2001-2004 Chris Danford + * All rights reserved. + * + * 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, and/or sell copies of the Software, and to permit persons to + * whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * 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 OF + * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS + * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT + * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/src/Actor.h b/src/Actor.h index 73e8e0a8b5..596658537c 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -7,6 +7,8 @@ #include "RageTypes.h" #include "RageUtil_AutoPtr.h" #include +#include +#include class XNode; struct lua_State; class LuaClass; @@ -263,8 +265,9 @@ class Actor : public MessageSubscriber Actor* GetFakeParentOrParent(); // fake parent > parent -mina float GetTrueX(); // recursive with parent (for mouseovers) -mina float GetTrueY(); // same - float GetTrueZoom(); // same - bool IsVisible(); // same but for gating updates on things that may not explicitly set visible = false -mina + float GetTrueZoom(); // same + bool IsVisible(); // same but for gating updates on things that may not + // explicitly set visible = false -mina /** * @brief Calls multiple functions for drawing the Actors. @@ -634,7 +637,7 @@ class Actor : public MessageSubscriber virtual float GetHorizAlign() { return m_fHorizAlign; } virtual float GetVertAlign() { return m_fVertAlign; } - // effects + // effects #if defined(SSC_FUTURES) void StopEffects(); Effect GetEffect(int i) const { return m_Effects[i]; } @@ -746,6 +749,12 @@ class Actor : public MessageSubscriber virtual void PushSelf(lua_State* L); virtual void PushContext(lua_State* L); + vector, float>> delayedFunctions; + void SetTimeout(function f, float ms); + std::list, float, float, int>> + delayedPeriodicFunctions; // This is a list to allow safe iterators + void SetInterval(function f, float ms, int fRemove); + // Named commands void AddCommand(const RString& sCmdName, apActorCommands apac, diff --git a/src/ActorFrame.cpp b/src/ActorFrame.cpp index be34f9fbcf..8b9780be8a 100644 --- a/src/ActorFrame.cpp +++ b/src/ActorFrame.cpp @@ -503,18 +503,24 @@ ActorFrame::UpdateInternal(float fDeltaTime) a->Update(fDeltaTime); if (unlikely(!m_UpdateFunction.IsNil())) { - Lua* L = LUA->Get(); - m_UpdateFunction.PushSelf(L); - if (lua_isnil(L, -1)) { + secsSinceLuaUpdateFWasRun += fDeltaTime; + if (secsSinceLuaUpdateFWasRun >= m_fUpdateFInterval) { + secsSinceLuaUpdateFWasRun = 0; + Lua* L = LUA->Get(); + m_UpdateFunction.PushSelf(L); + if (lua_isnil(L, -1)) { + LUA->Release(L); + LuaHelpers::ReportScriptErrorFmt( + "Error compiling UpdateFunction"); + return; + } + this->PushSelf(L); + lua_pushnumber(L, fDeltaTime); + RString Error = "Error running UpdateFunction: "; + LuaHelpers::RunScriptOnStack( + L, Error, 2, 0, true); // 1 args, 0 results LUA->Release(L); - LuaHelpers::ReportScriptErrorFmt("Error compiling UpdateFunction"); - return; } - this->PushSelf(L); - lua_pushnumber(L, fDeltaTime); - RString Error = "Error running UpdateFunction: "; - LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); // 1 args, 0 results - LUA->Release(L); } } @@ -665,6 +671,18 @@ class LunaActorFrame : public Luna p->SetFOV(FArg(1)); COMMON_RETURN_SELF; } + static int SetUpdateFunctionInterval(T* p, lua_State* L) + { + float seconds = FArg(1); + if (seconds <= 0) { + luaL_error(L, + "ActorFrame:SetUpdateRate(%f) Update interval must be " + "greater than 0.", + seconds); + } + p->SetUpdateFunctionInterval(seconds); + COMMON_RETURN_SELF; + } static int SetUpdateRate(T* p, lua_State* L) { float rate = FArg(1); @@ -839,6 +857,7 @@ class LunaActorFrame : public Luna ADD_METHOD(SetDrawFunction); ADD_METHOD(GetDrawFunction); ADD_METHOD(SetUpdateFunction); + ADD_METHOD(SetUpdateFunctionInterval); ADD_METHOD(SortByDrawOrder); // ADD_METHOD( CustomLighting ); ADD_METHOD(SetAmbientLightColor); diff --git a/src/ActorFrame.h b/src/ActorFrame.h index 74a0c05d78..b7c0010abf 100644 --- a/src/ActorFrame.h +++ b/src/ActorFrame.h @@ -99,6 +99,12 @@ class ActorFrame : public Actor void FinishTweening() override; void HurryTweening(float factor) override; + void SetUpdateFunctionInterval(float ms) + { + if (ms > 0.0f) { + m_fUpdateFInterval = ms; + } + } void SetUpdateRate(float rate) override { if (rate > 0.0f) { @@ -148,6 +154,8 @@ class ActorFrame : public Actor LuaReference m_UpdateFunction; LuaReference m_DrawFunction; + int m_fUpdateFInterval{ 0 }; + float secsSinceLuaUpdateFWasRun{ 0.016f }; // state effects float m_fUpdateRate; float m_fFOV; // -1 = no change diff --git a/src/LuaManager.cpp b/src/LuaManager.cpp index cf46df869f..424a225e9a 100644 --- a/src/LuaManager.cpp +++ b/src/LuaManager.cpp @@ -1236,7 +1236,8 @@ LuaHelpers::ReportScriptError(std::string const& Error, LOG->Warn("%s", Error.c_str()); if (UseAbort) { std::string with_correct = - Error + "\nCorrect this and click Retry, click Abort to crash, or click Ignore to attempt to continue."; + Error + "\nCorrect this and click Retry, click Abort to crash, or " + "click Ignore to attempt to continue."; return Dialog::AbortRetryIgnore(with_correct, ErrorType); } // Dialog::OK(Error, ErrorType); @@ -1487,6 +1488,17 @@ LuaHelpers::PushValueFunc(lua_State* L, int iArgs) lua_pushcclosure(L, lua_pushvalues, iArgs + 1); } +LuaReference +GetFuncArg(int n, lua_State* L) +{ + LuaReference ref; + lua_pushvalue(L, n); + ref.SetFromStack(L); + if (!lua_isfunction(L, n)) + luaL_typerror(L, n, lua_typename(L, LUA_TFUNCTION)); + return ref; +} + #include "ProductInfo.h" LuaFunction(ProductFamily, (std::string)PRODUCT_FAMILY); LuaFunction(ProductVersion, (std::string)product_version); diff --git a/src/LuaManager.h b/src/LuaManager.h index a4501d0cf6..29dd26b003 100644 --- a/src/LuaManager.h +++ b/src/LuaManager.h @@ -266,11 +266,11 @@ class LuaThreadVariable * before. If you break out of the loop early, you need to handle that * explicitly. */ #define FOREACH_LUATABLE(L, index) \ - \ -for(const int SM_UNIQUE_NAME(tab) = LuaHelpers::AbsIndex(L, index), \ - SM_UNIQUE_NAME(top) = (lua_pushnil(L), lua_gettop(L)); \ - lua_next(L, SM_UNIQUE_NAME(tab)) && (lua_pushvalue(L, -2), true); \ - lua_settop(L, SM_UNIQUE_NAME(top))) + \ + for (const int SM_UNIQUE_NAME(tab) = LuaHelpers::AbsIndex(L, index), \ + SM_UNIQUE_NAME(top) = (lua_pushnil(L), lua_gettop(L)); \ + lua_next(L, SM_UNIQUE_NAME(tab)) && (lua_pushvalue(L, -2), true); \ + lua_settop(L, SM_UNIQUE_NAME(top))) /** @brief Iterate over the array elements of a table. */ #define FOREACH_LUATABLEI(L, index, i) \ @@ -332,6 +332,8 @@ TableContainsOnlyStrings(lua_State* L, int index) return passed; } +LuaReference +GetFuncArg(int n, lua_State* L); #define SArg(n) (luaL_checkstring(L, (n))) #define BIArg(n) (MyLua_checkintboolean(L, (n))) #define IArg(n) (luaL_checkint(L, (n))) @@ -399,35 +401,34 @@ value_is_in_table(lua_State* L, int value_index, int table_index) } #define LuaFunction(func, expr) \ - \ -int LuaFunc_##func(lua_State* L); \ - \ -int LuaFunc_##func(lua_State* L) \ + \ + int LuaFunc_##func(lua_State* L); \ + \ + int LuaFunc_##func(lua_State* L) \ { \ LuaHelpers::Push(L, expr); \ return 1; \ - \ -} \ - \ -void LuaFunc_Register_##func(lua_State* L); \ - \ -void LuaFunc_Register_##func(lua_State* L) \ + } \ + \ + void LuaFunc_Register_##func(lua_State* L); \ + \ + void LuaFunc_Register_##func(lua_State* L) \ { \ lua_register(L, #func, LuaFunc_##func); \ } \ - \ -REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_##func); + \ + REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_##func); #define LUAFUNC_REGISTER_COMMON(func_name) \ - \ -void LuaFunc_Register_##func_name(lua_State* L); \ - \ -void LuaFunc_Register_##func_name(lua_State* L) \ + \ + void LuaFunc_Register_##func_name(lua_State* L); \ + \ + void LuaFunc_Register_##func_name(lua_State* L) \ { \ lua_register(L, #func_name, LuaFunc_##func_name); \ } \ - \ -REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_##func_name); + \ + REGISTER_WITH_LUA_FUNCTION(LuaFunc_Register_##func_name); #endif diff --git a/src/LuaReference.h b/src/LuaReference.h index fb4fd41b14..0101f158af 100644 --- a/src/LuaReference.h +++ b/src/LuaReference.h @@ -64,6 +64,8 @@ class LuaReference /* Return the referenced type, or LUA_TNONE if not set. */ int GetLuaType() const; + int GetIdentifier() { return m_iReference; } + std::string Serialize() const; template From a3488c0bef7b3e6c049d3ee0b78f7494c0139800 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 11:12:06 -0300 Subject: [PATCH 073/320] Fix chart leaderboards and add basic replaydata getting --- src/DownloadManager.cpp | 124 +++++++++++++++++++++++++++++++--------- src/DownloadManager.h | 18 +++++- 2 files changed, 114 insertions(+), 28 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 3d27f7ed8e..912bfbee69 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1387,6 +1387,74 @@ DownloadManager::RefreshCountryCodes() "/misc/countrycodes", vector>(), done, true); } +void +DownloadManager::RequestReplayData(string scoreid, + int userid, + string username, + string chartkey, + LuaReference callback) +{ + auto done = [scoreid, callback, userid, username, chartkey]( + HTTPRequest& req, CURLMsg*) { + try { + vector> replayData; + auto j = json::parse(req.result); + if (j.find("errors") != j.end()) + throw exception(); + auto replay = j.find("data"); + if (replay->size() > 1) + for (auto note : *replay) { + float timestamp = note[0]; + int offset = note[1]; // *1000.0f + int column = note[2]; + int type = note[3]; + replayData.emplace_back( + make_pair(note[0].get(), note[1].get())); + } + auto& lbd = DLMAN->chartLeaderboards[chartkey]; + auto it = + find_if(lbd.begin(), lbd.end(), [userid, username](auto& a) { + return a.userid == userid && a.username == username; + }); + if (it != lbd.end()) { + vector offsets; + std::transform( + replayData.begin(), + replayData.end(), + back_inserter(offsets), + [](pair& pair) { return pair.first; }); + it->hs.SetOffsetVector(offsets); + } + auto L = LUA->Get(); + callback.PushSelf(L); + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + lua_newtable(L); + for (unsigned i = 0; i < replayData.size(); ++i) { + auto& pair = replayData[i]; + lua_newtable(L); + lua_pushnumber(L, pair.first); + lua_rawseti(L, -1, 1); + lua_pushnumber(L, pair.second); + lua_rawseti(L, -1, 2); + lua_rawseti(L, -2, i + 1); + } + it->hs.PushSelf(L); + LuaHelpers::RunScriptOnStack( + L, Error, 2, 0, true); // 2 args, 0 results + LUA->Release(L); + } catch (exception e) { + LOG->Trace( + (string("Replay data request failed for") + scoreid + e.what()) + .c_str()); + } + }; + SendRequest("/replay/" + to_string(userid) + "/" + scoreid, + vector>(), + done, + true); +} + void DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) { @@ -1405,7 +1473,7 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) OnlineScore tmp; // tmp.songId = score.value("songId", 0); auto user = *(score.find("user")); - tmp.songId = score.value("songId", 0); + tmp.songId = score.value("songId", ""); tmp.username = user.value("userName", "").c_str(); tmp.avatar = user.value("avatar", "").c_str(); tmp.userid = user.value("userId", 0); @@ -1440,17 +1508,7 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) FOREACH_ENUM(Skillset, ss) tmp.SSRs[ss] = static_cast( ssrs.value(SkillsetToString(ss).c_str(), 0.0)); - - /*try { - auto replay = score["replay"]; - if (replay.size() > 1) - LOG->Trace(tmp.modifiers.c_str()); - for (auto pair : replay) - tmp.replayData.emplace_back(make_pair( - pair[0].get(), pair[1].get())); - } catch (exception e) { - // replaydata failed - } */ + tmp.hasReplay = score["hasReplay"]; // eo still has some old profiles with various edge issues that // unfortunately need to be handled here screen out old 11111 @@ -1505,12 +1563,6 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) } Message msg("ChartLeaderboardUpdate"); - vector leaderboardHS; - // This is like a functional map - transform(vec.begin(), - vec.end(), - back_inserter(leaderboardHS), - [](OnlineScore s) { return &(s.hs); }); if (!ref.IsNil() && ref.IsSet()) { Lua* L = LUA->Get(); @@ -1518,7 +1570,12 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) if (!lua_isnil(L, -1)) { RString Error = "Error running RequestChartLeaderBoard Finish Function: "; - LuaHelpers::CreateTableFromArray(leaderboardHS, L); + lua_newtable(L); + for (unsigned i = 0; i < vec.size(); ++i) { + auto& s = vec[i]; + s.Push(L); + lua_rawseti(L, -2, i + 1); + } LuaHelpers::RunScriptOnStack( L, Error, 1, 0, true); // 1 args, 0 results } @@ -2231,6 +2288,21 @@ class LunaDownloadManager : public Luna return 1; } + static int RequestOnlineScoreReplayData(T* p, lua_State* L) + { + OnlineHighScore* hs = + (OnlineHighScore*)GetPointerFromStack(L, "HighScore", 1); + int userid = hs->userid; + string username = hs->GetDisplayName(); + string scoreid = hs->scoreid; + string ck = hs->GetChartKey(); + LuaReference f; + if (lua_isfunction(L, -2)) + f = GetFuncArg(2, L); + DLMAN->RequestReplayData(scoreid, userid, username, ck, f); + return 0; + } + // This requests the leaderboard from online. This may cause lag. // Use this sparingly. // This will NOT request a leaderboard if it already exists for the @@ -2246,18 +2318,17 @@ class LunaDownloadManager : public Luna ref.SetFromStack(L); } if (leaderboardScores.size() != 0) { - vector leaderboardHS; - // This is like a functional map - transform(leaderboardScores.begin(), - leaderboardScores.end(), - back_inserter(leaderboardHS), - [](OnlineScore s) { return &(s.hs); }); if (!ref.IsNil()) { ref.PushSelf(L); if (!lua_isnil(L, -1)) { RString Error = "Error running RequestChartLeaderBoard Finish Function: "; - LuaHelpers::CreateTableFromArray(leaderboardHS, L); + lua_newtable(L); + for (unsigned i = 0; i < leaderboardScores.size(); ++i) { + auto& s = leaderboardScores[i]; + s.Push(L); + lua_rawseti(L, -2, i + 1); + } LuaHelpers::RunScriptOnStack( L, Error, 1, 0, true); // 1 args, 0 results } @@ -2348,6 +2419,7 @@ class LunaDownloadManager : public Luna ADD_METHOD(GetLastVersion); ADD_METHOD(GetRegisterPage); ADD_METHOD(RequestChartLeaderBoardFromOnline); + ADD_METHOD(RequestOnlineScoreReplayData); ADD_METHOD(GetChartLeaderBoard); // This does not actually request the leaderboard from online. // It gets the already retrieved data from DLMAN diff --git a/src/DownloadManager.h b/src/DownloadManager.h index d236536a07..dd9bf3cf14 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -133,6 +133,12 @@ class OnlineTopScore Difficulty difficulty; string steps; }; +struct OnlineHighScore : HighScore +{ + public: + int userid; + string scoreid; +}; class OnlineScore { public: @@ -148,7 +154,7 @@ class OnlineScore int marvelous{ 0 }; int minehits{ 0 }; int held{ 0 }; - int songId{ 0 }; + string songId; int letgo{ 0 }; bool valid{ false }; bool nocc{ false }; @@ -159,10 +165,13 @@ class OnlineScore string avatar; int userid; DateTime datetime; + bool hasReplay{ false }; vector> replayData; string countryCode; - HighScore hs; + OnlineHighScore hs; + void Push(lua_State* L) { hs.PushSelf(L); } }; + class DownloadManager { public: @@ -276,6 +285,11 @@ class DownloadManager bool currentrateonly = false; bool topscoresonly = true; void RefreshCountryCodes(); + void RequestReplayData(string scorekey, + int userid, + string username, + string chartkey, + LuaReference callback = LuaReference()); void RequestChartLeaderBoard(string chartkey, LuaReference ref = LuaReference()); void RefreshUserData(); From 4def604a58700e5fa8c817629388554f5cb6d83f Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 11:45:11 -0300 Subject: [PATCH 074/320] First approximation to chart leaderboard replays --- .../BGAnimations/superscoreboard.lua | 19 +++++++++++++++++-- src/Actor.cpp | 2 +- src/DownloadManager.cpp | 11 ++++++----- src/DownloadManager.h | 1 + src/HighScore.h | 2 +- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index 15b6d87c72..c8e6d7908f 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -28,7 +28,7 @@ local isGlobalRanking = true -- will eat any mousewheel inputs to scroll pages while mouse is over the background frame local function input(event) - if isOver(cheese:GetChild("FrameDisplay")) then -- visibility checks are built into isover now -mina + if isOver(cheese:GetChild("FrameDisplay")) then -- visibility checks are built into isover now -mina if event.DeviceInput.button == "DeviceButton_mousewheel up" and event.type == "InputEventType_FirstPress" then moving = true cheese:queuecommand("PrevPage") @@ -334,7 +334,11 @@ local function makeScoreDisplay(i) self:x(offx):zoomto(dwidth, pdh):halign(0) end, DisplayCommand = function(self) - self:diffuse(color("#111111CC")) + if hs:HasReplayData() then + self:diffuse(color("#555555CC")) + else + self:diffuse(color("#111111CC")) + end end, HighlightCommand = function(self) if isOver(self) and collapsed then @@ -342,6 +346,17 @@ local function makeScoreDisplay(i) else self:diffusealpha(0.6) end + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) and hs then + DLMAN:RequestOnlineScoreReplayData( + hs, + function() + SCREENMAN:SystemMessage("wabadub") + SCREENMAN:GetTopScreen():PlayReplay(hs) + end + ) + end end }, LoadFont("Common normal") .. diff --git a/src/Actor.cpp b/src/Actor.cpp index 137f078e82..aeb3b7b3e8 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -1755,7 +1755,7 @@ class LunaActor : public Luna int r = IArg(1); auto& l = p->delayedPeriodicFunctions; auto it = find_if( - l.begin(), l.end(), [r](auto& x) { return std::get<3>() == r; }); + l.begin(), l.end(), [r](auto& x) { return std::get<3>(x) == r; }); if (it != l.end()) { luaL_unref(L, LUA_REGISTRYINDEX, r); l.erase(it); diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 912bfbee69..7e6e656083 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1401,8 +1401,8 @@ DownloadManager::RequestReplayData(string scoreid, auto j = json::parse(req.result); if (j.find("errors") != j.end()) throw exception(); - auto replay = j.find("data"); - if (replay->size() > 1) + auto replay = j.find("data")->find("attributes")->find("replay"); + if (!replay->is_null() && replay->size() > 1) for (auto note : *replay) { float timestamp = note[0]; int offset = note[1]; // *1000.0f @@ -1434,9 +1434,9 @@ DownloadManager::RequestReplayData(string scoreid, auto& pair = replayData[i]; lua_newtable(L); lua_pushnumber(L, pair.first); - lua_rawseti(L, -1, 1); + lua_rawseti(L, -2, 1); lua_pushnumber(L, pair.second); - lua_rawseti(L, -1, 2); + lua_rawseti(L, -2, 2); lua_rawseti(L, -2, i + 1); } it->hs.PushSelf(L); @@ -1536,6 +1536,7 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) hs.SetChordCohesion(tmp.nocc); hs.SetWifeScore(tmp.wife); hs.SetMusicRate(tmp.rate); + hs.SetChartKey(chartkey); hs.SetTapNoteScore(TNS_W1, tmp.marvelous); hs.SetTapNoteScore(TNS_W2, tmp.perfect); @@ -2297,7 +2298,7 @@ class LunaDownloadManager : public Luna string scoreid = hs->scoreid; string ck = hs->GetChartKey(); LuaReference f; - if (lua_isfunction(L, -2)) + if (lua_isfunction(L, 2)) f = GetFuncArg(2, L); DLMAN->RequestReplayData(scoreid, userid, username, ck, f); return 0; diff --git a/src/DownloadManager.h b/src/DownloadManager.h index dd9bf3cf14..c567632859 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -170,6 +170,7 @@ class OnlineScore string countryCode; OnlineHighScore hs; void Push(lua_State* L) { hs.PushSelf(L); } + bool HasReplayData() { return hasReplay; } }; class DownloadManager diff --git a/src/HighScore.h b/src/HighScore.h index d06a94a510..20941b8a43 100644 --- a/src/HighScore.h +++ b/src/HighScore.h @@ -159,7 +159,7 @@ struct HighScore bool LoadReplayData(); bool LoadReplayDataBasic(); bool LoadReplayDataFull(); - bool HasReplayData(); + virtual bool HasReplayData(); void UnloadReplayData(); void ResetSkillsets(); From f866af2ebb76a799b339bd6942fe9db6adb4192d Mon Sep 17 00:00:00 2001 From: poco0317 Date: Mon, 26 Nov 2018 18:39:27 -0600 Subject: [PATCH 075/320] Fix the lack of radar values in all replays im pissed this took 3 hours to fix --- src/StageStats.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/StageStats.cpp b/src/StageStats.cpp index b688cbbc9e..086e04388c 100644 --- a/src/StageStats.cpp +++ b/src/StageStats.cpp @@ -655,6 +655,7 @@ StageStats::FinalizeScores(bool bSummary) if (PlayerAI::pScoreData) { mostrecentscorekey = PlayerAI::pScoreData->GetScoreKey(); SCOREMAN->PutScoreAtTheTop(mostrecentscorekey); + SCOREMAN->GetMostRecentScore()->SetRadarValues(hs.GetRadarValues()); } zzz->m_lastSong.FromSong(GAMESTATE->m_pCurSong); return; From a93ed097a87f926bca342b5ccad99d596d2170a3 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Mon, 26 Nov 2018 18:40:30 -0600 Subject: [PATCH 076/320] Allow empty tap types to be counted as taps for radar value calculation in replays for old replay support, probably a bad idea --- src/PlayerAI.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index d5b22f33c0..d93ba49395 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -531,12 +531,14 @@ PlayerAI::CalculateRadarValuesForReplay(RadarValues& rv, RadarValues& possibleRV continue; } tapsOnThisRow++; - if (trr.type == TapNoteType_Tap || trr.type == TapNoteType_HoldHead) + // We handle Empties as well because that's what old replays are loaded as. + if (trr.type == TapNoteType_Tap || trr.type == TapNoteType_HoldHead || trr.type == TapNoteType_Empty) { totalNotesHit++; tapsHit++; if (tapsOnThisRow == 2) { + // This is technically incorrect. jumpsHit++; } else if (tapsOnThisRow >= 3) From 17d61955128242761161dab04d839ad35b0222f4 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Mon, 26 Nov 2018 18:41:05 -0600 Subject: [PATCH 077/320] Fix crash when grabbing offset vectors for old replays --- src/PlayerStageStats.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/PlayerStageStats.cpp b/src/PlayerStageStats.cpp index ec2028ae78..5106dccb0c 100644 --- a/src/PlayerStageStats.cpp +++ b/src/PlayerStageStats.cpp @@ -1040,9 +1040,16 @@ LuaFunction(GetGradeFromPercent, GetGradeFromPercent(FArg(1))) auto& offs = p->m_vOffsetVector; auto& type = p->m_vTapNoteTypeVector; vector doot; - for (size_t i = 0; i < offs.size(); ++i) - if (type[i] != TapNoteType_Mine) + // type would not be empty in Full Replays (> v0.60) + if (!type.empty()) { + for (size_t i = 0; i < offs.size(); ++i) + if (type[i] != TapNoteType_Mine) + doot.emplace_back(offs[i] * 1000); + } else { + // But type is empty if the replay is old :( + for (size_t i = 0; i < offs.size(); ++i) doot.emplace_back(offs[i] * 1000); + } LuaHelpers::CreateTableFromArray(doot, L); return 1; } From f311816c82750205dec255ce854ecc9e6993b695 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 22:56:45 -0300 Subject: [PATCH 078/320] Update stepmania.nsi --- stepmania.nsi | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/stepmania.nsi b/stepmania.nsi index a29cd3aef6..cde4f18d92 100644 --- a/stepmania.nsi +++ b/stepmania.nsi @@ -545,17 +545,7 @@ Section "Main Section" SecMain ; documentation CreateDirectory "$INSTDIR\Docs" SetOutPath "$INSTDIR\Docs" - File "Docs\Licenses.txt" - File "Docs\credits.txt" - File "Docs\Changelog_sm-ssc.txt" - File "Docs\Changelog_sm5.txt" - File "Docs\Changelog_SSCformat.txt" - File "Docs\CommandLineArgs.txt" - File "Docs\CourseFormat.txt" - File "Docs\Userdocs\sm5_beginner.txt" - File /r /x CVS /x .svn "Docs\license-ext" - File /r /x CVS /x .svn "Docs\Luadoc" - File /r /x CVS /x .svn "Docs\Themerdocs" + File "LICENCE" ; Create Start Menu icons SetShellVarContext current # 'all' doesn't work on Win9x @@ -842,6 +832,7 @@ Section "Uninstall" Delete "$INSTDIR\Docs\CourseFormat.txt" Delete "$INSTDIR\Docs\credits.txt" Delete "$INSTDIR\Docs\Licenses.txt" + Delete "$INSTDIR\Docs\LICENSE" Delete "$INSTDIR\Docs\sm5_beginner.txt" RMDir "$INSTDIR\Docs" From fb8dcabee41dbc295fc49e3f2eff74803b4a9285 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 22:57:14 -0300 Subject: [PATCH 079/320] Delete Actor.cpp-1f841de5 --- src/Actor.cpp-1f841de5 | 2992 ---------------------------------------- 1 file changed, 2992 deletions(-) delete mode 100644 src/Actor.cpp-1f841de5 diff --git a/src/Actor.cpp-1f841de5 b/src/Actor.cpp-1f841de5 deleted file mode 100644 index 7efa07415f..0000000000 --- a/src/Actor.cpp-1f841de5 +++ /dev/null @@ -1,2992 +0,0 @@ -#include "global.h" -#include "Actor.h" -#include "ActorFrame.h" -#include "ActorUtil.h" -#include "GamePreferences.h" -#include "LuaBinding.h" -#include "LuaReference.h" -#include "MessageManager.h" -#include "Preference.h" -#include "RageDisplay.h" -#include "RageMath.h" -#include "RageTimer.h" -#include "RageUtil.h" -#include "ThemeManager.h" -#include "XmlFile.h" -#include -#include -#include -#include "FilterManager.h" -#include "LuaReference.h" - -static Preference g_bShowMasks("ShowMasks", false); -static const float default_effect_period = 1.0f; - -/** - * @brief Set up a hidden Actor that won't be drawn. - * - * It's useful to be able to construct a basic Actor in XML, in - * order to simply delay a Transition, or receive and send broadcasts. - * Since these actors will never draw, set them hidden by default. */ -class HiddenActor : public Actor -{ - public: - HiddenActor() { SetVisible(false); } - HiddenActor* Copy() const override; -}; -REGISTER_ACTOR_CLASS_WITH_NAME(HiddenActor, Actor); - -float Actor::g_fCurrentBGMTime = 0, Actor::g_fCurrentBGMBeat; -float Actor::g_fCurrentBGMTimeNoOffset = 0, - Actor::g_fCurrentBGMBeatNoOffset = 0; -vector Actor::g_vfCurrentBGMBeatPlayer(NUM_PlayerNumber, 0); -vector Actor::g_vfCurrentBGMBeatPlayerNoOffset(NUM_PlayerNumber, 0); - -Actor* -Actor::Copy() const -{ - return new Actor(*this); -} - -static const char* HorizAlignNames[] = { "Left", "Center", "Right" }; -XToString(HorizAlign); -LuaXType(HorizAlign); - -static const char* VertAlignNames[] = { "Top", "Middle", "Bottom" }; -XToString(VertAlign); -LuaXType(VertAlign); - -void -Actor::SetBGMTime(float fTime, - float fBeat, - float fTimeNoOffset, - float fBeatNoOffset) -{ - g_fCurrentBGMTime = fTime; - g_fCurrentBGMBeat = fBeat; - - /* This timer is generally only used for effects tied to the background - * music when GameSoundManager is aligning music beats. Alignment doesn't - * handle g_fVisualDelaySeconds. */ - g_fCurrentBGMTimeNoOffset = fTimeNoOffset; - g_fCurrentBGMBeatNoOffset = fBeatNoOffset; -} - -void -Actor::SetPlayerBGMBeat(PlayerNumber pn, float fBeat, float fBeatNoOffset) -{ - g_vfCurrentBGMBeatPlayer[pn] = fBeat; - g_vfCurrentBGMBeatPlayerNoOffset[pn] = fBeatNoOffset; -} - -void -Actor::InitState() -{ - this->StopTweening(); - - m_pTempState = nullptr; - - m_baseRotation = RageVector3(0, 0, 0); - m_baseScale = RageVector3(1, 1, 1); - m_fBaseAlpha = 1; - m_internalDiffuse = RageColor(1, 1, 1, 1); - m_internalGlow = RageColor(0, 0, 0, 0); - - m_start.Init(); - m_current.Init(); - - m_fHorizAlign = 0.5f; - m_fVertAlign = 0.5f; -#if defined(SSC_FUTURES) - for (unsigned i = 0; i < m_Effects.size(); ++i) - m_Effects[i] = no_effect; -#else - m_Effect = no_effect; -#endif - m_fSecsIntoEffect = 0; - m_fEffectDelta = 0; - SetEffectPeriod(default_effect_period); - m_fEffectOffset = 0; - m_EffectClock = CLOCK_TIMER; - m_vEffectMagnitude = RageVector3(0, 0, 10); - m_effectColor1 = RageColor(1, 1, 1, 1); - m_effectColor2 = RageColor(1, 1, 1, 1); - - m_bVisible = true; - m_fShadowLengthX = 0; - m_fShadowLengthY = 0; - m_ShadowColor = RageColor(0, 0, 0, 0.5f); - m_bIsAnimating = true; - m_fHibernateSecondsLeft = 0; - m_iDrawOrder = 0; - - m_bTextureWrapping = false; - m_bTextureFiltering = true; - m_texTranslate = RageVector2(0, 0); - - m_BlendMode = BLEND_NORMAL; - m_fZBias = 0; - m_bClearZBuffer = false; - m_ZTestMode = ZTEST_OFF; - m_bZWrite = false; - m_CullMode = CULL_NONE; -} - -static bool -GetMessageNameFromCommandName(const RString& sCommandName, - RString& sMessageNameOut) -{ - if (sCommandName.Right(7) == "Message") { - sMessageNameOut = sCommandName.Left(sCommandName.size() - 7); - return true; - } - - return false; -} - -Actor::Actor() -{ - m_pLuaInstance = new LuaClass; - Lua* L = LUA->Get(); - m_pLuaInstance->PushSelf(L); - lua_newtable(L); - lua_pushvalue(L, -1); - lua_setmetatable(L, -2); - lua_setfield(L, -2, "ctx"); - lua_pop(L, 1); - LUA->Release(L); - - m_size = RageVector2(1, 1); - InitState(); - m_pParent = nullptr; - m_FakeParent = nullptr; - m_bFirstUpdate = true; - m_tween_uses_effect_delta = false; -} - -Actor::~Actor() -{ - StopTweening(); - UnsubscribeAll(); - for (size_t i = 0; i < m_WrapperStates.size(); ++i) { - SAFE_DELETE(m_WrapperStates[i]); - } - m_WrapperStates.clear(); -} - -Actor::Actor(const Actor& cpy) - : MessageSubscriber(cpy) -{ - /* Don't copy an Actor in the middle of rendering. */ - ASSERT(cpy.m_pTempState == nullptr); - m_pTempState = nullptr; - -#define CPY(x) x = cpy.x - CPY(m_sName); - CPY(m_pParent); - CPY(m_FakeParent); - CPY(m_pLuaInstance); - - m_WrapperStates.resize(cpy.m_WrapperStates.size()); - for (size_t i = 0; i < m_WrapperStates.size(); ++i) { - m_WrapperStates[i] = - new ActorFrame(*dynamic_cast(cpy.m_WrapperStates[i])); - } - - CPY(m_baseRotation); - CPY(m_baseScale); - CPY(m_fBaseAlpha); - CPY(m_internalDiffuse); - CPY(m_internalGlow); - - CPY(m_size); - CPY(m_current); - CPY(m_start); - for (unsigned i = 0; i < cpy.m_Tweens.size(); ++i) - m_Tweens.push_back(new TweenStateAndInfo(*cpy.m_Tweens[i])); - - CPY(m_bFirstUpdate); - - CPY(m_fHorizAlign); - CPY(m_fVertAlign); -#if defined(SSC_FUTURES) - // I'm a bit worried about this -aj - for (unsigned i = 0; i < cpy.m_Effects.size(); ++i) - m_Effects.push_back((*cpy.m_Effects[i])); -#else - CPY(m_Effect); -#endif - CPY(m_fSecsIntoEffect); - CPY(m_fEffectDelta); - CPY(m_effect_ramp_to_half); - CPY(m_effect_hold_at_half); - CPY(m_effect_ramp_to_full); - CPY(m_effect_hold_at_full); - CPY(m_effect_hold_at_zero); - CPY(m_effect_period); - CPY(m_fEffectOffset); - CPY(m_EffectClock); - - CPY(m_effectColor1); - CPY(m_effectColor2); - CPY(m_vEffectMagnitude); - - CPY(m_bVisible); - CPY(m_fHibernateSecondsLeft); - CPY(m_fShadowLengthX); - CPY(m_fShadowLengthY); - CPY(m_ShadowColor); - CPY(m_bIsAnimating); - CPY(m_iDrawOrder); - - CPY(m_bTextureWrapping); - CPY(m_bTextureFiltering); - CPY(m_BlendMode); - CPY(m_bClearZBuffer); - CPY(m_ZTestMode); - CPY(m_bZWrite); - CPY(m_fZBias); - CPY(m_CullMode); - - CPY(m_mapNameToCommands); -#undef CPY -} - -/* XXX: This calls InitCommand, which must happen after all other - * initialization (eg. ActorFrame loading children). However, it - * also loads input variables, which should happen first. The - * former is more important. */ -void -Actor::LoadFromNode(const XNode* pNode) -{ - Lua* L = LUA->Get(); - FOREACH_CONST_Attr(pNode, pAttr) - { - // Load Name, if any. - const RString& sKeyName = pAttr->first; - const XNodeValue* pValue = pAttr->second; - if (EndsWith(sKeyName, "Command")) { - LuaReference* pRef = new LuaReference; - pValue->PushValue(L); - pRef->SetFromStack(L); - RString sCmdName = sKeyName.Left(sKeyName.size() - 7); - AddCommand(sCmdName, apActorCommands(pRef)); - } else if (sKeyName == "Name") - SetName(pValue->GetValue()); - else if (sKeyName == "BaseRotationX") - SetBaseRotationX(pValue->GetValue()); - else if (sKeyName == "BaseRotationY") - SetBaseRotationY(pValue->GetValue()); - else if (sKeyName == "BaseRotationZ") - SetBaseRotationZ(pValue->GetValue()); - else if (sKeyName == "BaseZoomX") - SetBaseZoomX(pValue->GetValue()); - else if (sKeyName == "BaseZoomY") - SetBaseZoomY(pValue->GetValue()); - else if (sKeyName == "BaseZoomZ") - SetBaseZoomZ(pValue->GetValue()); - } - - LUA->Release(L); - - // Don't recurse Init. It gets called once for every Actor when the - // Actor is loaded, and we don't want to call it again. - PlayCommandNoRecurse(Message("Init")); -} - -bool -Actor::PartiallyOpaque() -{ - return m_pTempState->diffuse[0].a > 0 || m_pTempState->diffuse[1].a > 0 || - m_pTempState->diffuse[2].a > 0 || m_pTempState->diffuse[3].a > 0 || - m_pTempState->glow.a > 0; -} - -bool -Actor::IsOver(float mx, float my) -{ - if (!IsVisible()) - return false; - - auto x = GetTrueX(); - auto y = GetTrueY(); - auto hal = GetHorizAlign(); - auto val = GetVertAlign(); - auto wi = GetZoomedWidth() * GetFakeParentOrParent()->GetTrueZoom(); - auto hi = GetZoomedHeight() * GetFakeParentOrParent()->GetTrueZoom(); - auto lr = x - (hal * wi); - auto rr = x + wi - (hal * wi); - auto ur = y - (val * hi); - auto br = ((y + hi) - (val * hi)); - bool withinX = mx >= lr && mx <= rr; - bool withinY = my >= ur && my <= br; - return withinX && withinY; -} -Actor* -Actor::GetFakeParentOrParent() -{ - if (!this) - return nullptr; - if (m_FakeParent) - return m_FakeParent; - if (m_pParent) - return m_pParent; - return nullptr; -} -float -Actor::GetTrueX() -{ - if (!this) - return 0.f; - auto* mfp = GetFakeParentOrParent(); - if (!mfp) - return GetX(); - return GetX() * mfp->GetTrueZoom() + mfp->GetTrueX(); -} - -float -Actor::GetTrueY() -{ - if (!this) - return 0.f; - auto* mfp = GetFakeParentOrParent(); - if (!mfp) - return GetY(); - return GetY() * mfp->GetTrueZoom() + mfp->GetTrueY(); -} -float -Actor::GetTrueZoom() -{ - if (!this) - return 1.f; - auto* mfp = GetFakeParentOrParent(); - if (!mfp) - return GetZoom(); - return GetZoom() * mfp->GetTrueZoom(); -} -bool -Actor::IsVisible() -{ - if (!this) - return false; - auto* mfp = GetFakeParentOrParent(); - if (!mfp) - return GetVisible(); - return GetVisible() && mfp->IsVisible(); -} -void -Actor::Draw() -{ - if (!m_bVisible || m_fHibernateSecondsLeft > 0 || this->EarlyAbortDraw()) { - return; // early abort - } - - if (m_FakeParent != nullptr) { - if (!m_FakeParent->m_bVisible || - m_FakeParent->m_fHibernateSecondsLeft > 0 || - m_FakeParent->EarlyAbortDraw()) { - return; - } - m_FakeParent->PreDraw(); - if (!m_FakeParent->PartiallyOpaque()) { - m_FakeParent->PostDraw(); - return; - } - } - - if (m_FakeParent != nullptr) { - m_FakeParent->BeginDraw(); - } - size_t wrapper_states_used = 0; - RageColor last_diffuse; - RageColor last_glow; - bool use_last_diffuse = false; - // dont_abort_draw exists because if one of the layers is invisible, - // there's no point in continuing. -Kyz - bool dont_abort_draw = true; - // abort_with_end_draw exists because PreDraw happens before the - // opaqueness test, so if we abort at the opaqueness test, there isn't - // a BeginDraw to match the EndDraw. -Kyz - bool abort_with_end_draw = true; - // It's more intuitive to apply the highest index wrappers first. - // On the lua side, it looks like this: - // wrapper[3] is the outermost frame. wrapper[2] is inside wrapper[3]. - // wrapper[1] is inside wrapper[2]. The actor is inside wrapper[1]. - // -Kyz - for (size_t i = m_WrapperStates.size(); i > 0 && dont_abort_draw; --i) { - Actor* state = m_WrapperStates[i - 1]; - if (!state->m_bVisible || state->m_fHibernateSecondsLeft > 0 || - state->EarlyAbortDraw()) { - dont_abort_draw = false; - } else { - state->PreDraw(); - if (state->PartiallyOpaque()) { - state->BeginDraw(); - last_diffuse = state->m_pTempState->diffuse[0]; - last_glow = state->m_pTempState->glow; - use_last_diffuse = true; - if (i > 1) { - m_WrapperStates[i - 2]->SetInternalDiffuse(last_diffuse); - m_WrapperStates[i - 2]->SetInternalGlow(last_glow); - } - } else { - dont_abort_draw = false; - abort_with_end_draw = false; - } - ++wrapper_states_used; - } - } - // call the most-derived versions - if (dont_abort_draw) { - if (use_last_diffuse) { - this->SetInternalDiffuse(last_diffuse); - this->SetInternalGlow(last_glow); - } - this->PreDraw(); - ASSERT(m_pTempState != nullptr); - if (PartiallyOpaque()) { - this->BeginDraw(); - this->DrawPrimitives(); - this->EndDraw(); - } - this->PostDraw(); - } - for (size_t i = 0; i < wrapper_states_used; ++i) { - Actor* state = m_WrapperStates[i]; - if (abort_with_end_draw) { - state->EndDraw(); - } - abort_with_end_draw = true; - state->PostDraw(); - state->m_pTempState = nullptr; - } - - if (m_FakeParent != nullptr) { - m_FakeParent->EndDraw(); - m_FakeParent->PostDraw(); - m_FakeParent->m_pTempState = nullptr; - } - m_pTempState = nullptr; -} - -void -Actor::PostDraw() // reset internal diffuse and glow -{ - m_internalDiffuse = RageColor(1, 1, 1, 1); - m_internalGlow.a = 0; -} - -void -Actor::PreDraw() // calculate actor properties -{ - // Somthing below may set m_pTempState to tempState - m_pTempState = &m_current; - - // set temporary drawing properties based on Effects - static TweenState tempState; - - // todo: account for SSC_FUTURES -aj - if (m_Effect == no_effect) { - } else { - m_pTempState = &tempState; - tempState = m_current; - - const float fTotalPeriod = GetEffectPeriod(); - ASSERT(fTotalPeriod > 0); - const float fTimeIntoEffect = - fmodfp(m_fSecsIntoEffect + m_fEffectOffset, fTotalPeriod); - - float fPercentThroughEffect; - const float rup_plus_ath = - m_effect_ramp_to_half + m_effect_hold_at_half; - const float rupath_plus_rdown = rup_plus_ath + m_effect_ramp_to_full; - const float rupathrdown_plus_atf = - rupath_plus_rdown + m_effect_hold_at_full; - if (fTimeIntoEffect < m_effect_ramp_to_half) { - fPercentThroughEffect = - SCALE(fTimeIntoEffect, 0, m_effect_ramp_to_half, 0.0f, 0.5f); - } else if (fTimeIntoEffect < rup_plus_ath) { - fPercentThroughEffect = 0.5f; - } else if (fTimeIntoEffect < rupath_plus_rdown) { - fPercentThroughEffect = SCALE( - fTimeIntoEffect, rup_plus_ath, rupath_plus_rdown, 0.5f, 1.0f); - } else if (fTimeIntoEffect < rupathrdown_plus_atf) { - fPercentThroughEffect = 1.0f; - } else { - fPercentThroughEffect = 0; - } - ASSERT_M(fPercentThroughEffect >= 0 && fPercentThroughEffect <= 1, - ssprintf("PercentThroughEffect: %f", fPercentThroughEffect)); - - bool bBlinkOn = fPercentThroughEffect > 0.5f; - float fPercentBetweenColors = - RageFastSin((fPercentThroughEffect + 0.25f) * 2 * PI) / 2 + 0.5f; - ASSERT_M(fPercentBetweenColors >= 0 && fPercentBetweenColors <= 1, - ssprintf("PercentBetweenColors: %f, PercentThroughEffect: %f", - fPercentBetweenColors, - fPercentThroughEffect)); - float fOriginalAlpha = tempState.diffuse[0].a; - - // todo: account for SSC_FUTURES -aj - switch (m_Effect) { - case diffuse_blink: - /* XXX: Should diffuse_blink and diffuse_shift multiply the - * tempState color? (That would have the same effect with - * 1,1,1,1, and allow tweening the diffuse while blinking and - * shifting.) */ - for (auto& i : tempState.diffuse) { - i = bBlinkOn ? m_effectColor1 : m_effectColor2; - i.a *= fOriginalAlpha; // multiply the alphas so we can fade - // even while an effect is playing - } - break; - case diffuse_shift: - for (auto& i : tempState.diffuse) { - i = m_effectColor1 * fPercentBetweenColors + - m_effectColor2 * (1.0f - fPercentBetweenColors); - i.a *= fOriginalAlpha; // multiply the alphas so we can fade - // even while an effect is playing - } - break; - case diffuse_ramp: - for (auto& i : tempState.diffuse) { - i = m_effectColor1 * fPercentThroughEffect + - m_effectColor2 * (1.0f - fPercentThroughEffect); - i.a *= fOriginalAlpha; // multiply the alphas so we can fade - // even while an effect is playing - } - break; - case glow_blink: - tempState.glow = bBlinkOn ? m_effectColor1 : m_effectColor2; - tempState.glow.a *= - fOriginalAlpha; // don't glow if the Actor is transparent! - break; - case glow_shift: - tempState.glow = - m_effectColor1 * fPercentBetweenColors + - m_effectColor2 * (1.0f - fPercentBetweenColors); - tempState.glow.a *= - fOriginalAlpha; // don't glow if the Actor is transparent! - break; - case glow_ramp: - tempState.glow = - m_effectColor1 * fPercentThroughEffect + - m_effectColor2 * (1.0f - fPercentThroughEffect); - tempState.glow.a *= - fOriginalAlpha; // don't glow if the Actor is transparent! - break; - case rainbow: - tempState.diffuse[0] = RageColor( - RageFastCos(fPercentBetweenColors * 2 * PI) * 0.5f + 0.5f, - RageFastCos(fPercentBetweenColors * 2 * PI + - PI * 2.0f / 3.0f) * - 0.5f + - 0.5f, - RageFastCos(fPercentBetweenColors * 2 * PI + - PI * 4.0f / 3.0f) * - 0.5f + - 0.5f, - fOriginalAlpha); - for (int i = 1; i < NUM_DIFFUSE_COLORS; i++) - tempState.diffuse[i] = tempState.diffuse[0]; - break; - case wag: - tempState.rotation += - m_vEffectMagnitude * - RageFastSin(fPercentThroughEffect * 2.0f * PI); - break; - case spin: - // nothing needs to be here - break; - case vibrate: - tempState.pos.x += - m_vEffectMagnitude.x * randomf(-1.0f, 1.0f) * GetZoom(); - tempState.pos.y += - m_vEffectMagnitude.y * randomf(-1.0f, 1.0f) * GetZoom(); - tempState.pos.z += - m_vEffectMagnitude.z * randomf(-1.0f, 1.0f) * GetZoom(); - break; - case bounce: { - float fPercentOffset = RageFastSin(fPercentThroughEffect * PI); - tempState.pos += m_vEffectMagnitude * fPercentOffset; - } break; - case bob: { - float fPercentOffset = - RageFastSin(fPercentThroughEffect * PI * 2); - tempState.pos += m_vEffectMagnitude * fPercentOffset; - } break; - case pulse: { - float fMinZoom = m_vEffectMagnitude[0]; - float fMaxZoom = m_vEffectMagnitude[1]; - float fPercentOffset = RageFastSin(fPercentThroughEffect * PI); - float fZoom = - SCALE(fPercentOffset, 0.f, 1.f, fMinZoom, fMaxZoom); - tempState.scale *= fZoom; - - // Use the color as a Vector3 to scale the effect for added - // control - RageColor c = SCALE( - fPercentOffset, 0.f, 1.f, m_effectColor1, m_effectColor2); - tempState.scale.x *= c.r; - tempState.scale.y *= c.g; - tempState.scale.z *= c.b; - } break; - default: - FAIL_M(ssprintf("Invalid effect: %i", m_Effect)); - } - } - - if (m_fBaseAlpha != 1) - m_internalDiffuse.a *= m_fBaseAlpha; - - if (m_internalDiffuse != RageColor(1, 1, 1, 1)) { - if (m_pTempState != &tempState) { - m_pTempState = &tempState; - tempState = m_current; - } - - for (auto& i : tempState.diffuse) { - i *= m_internalDiffuse; - } - } - - if (m_internalGlow.a > 0) { - if (m_pTempState != &tempState) { - m_pTempState = &tempState; - tempState = m_current; - } - - // Blend using Screen mode - tempState.glow = - tempState.glow + m_internalGlow - m_internalGlow * tempState.glow; - } -} - -void -Actor::BeginDraw() // set the world matrix -{ - DISPLAY->PushMatrix(); - - if (m_pTempState->pos.x != 0 || m_pTempState->pos.y != 0 || - m_pTempState->pos.z != 0) { - RageMatrix m; - RageMatrixTranslate( - &m, m_pTempState->pos.x, m_pTempState->pos.y, m_pTempState->pos.z); - DISPLAY->PreMultMatrix(m); - } - - { - /* The only time rotation and quat should normally be used - * simultaneously is for m_baseRotation. Most objects aren't rotated at - * all, so optimize that case. */ - const float fRotateX = m_pTempState->rotation.x + m_baseRotation.x; - const float fRotateY = m_pTempState->rotation.y + m_baseRotation.y; - const float fRotateZ = m_pTempState->rotation.z + m_baseRotation.z; - - if (fRotateX != 0 || fRotateY != 0 || fRotateZ != 0) { - RageMatrix m; - RageMatrixRotationXYZ(&m, fRotateX, fRotateY, fRotateZ); - DISPLAY->PreMultMatrix(m); - } - } - - // handle scaling - { - const float fScaleX = m_pTempState->scale.x * m_baseScale.x; - const float fScaleY = m_pTempState->scale.y * m_baseScale.y; - const float fScaleZ = m_pTempState->scale.z * m_baseScale.z; - - if (fScaleX != 1 || fScaleY != 1 || fScaleZ != 1) { - RageMatrix m; - RageMatrixScale(&m, fScaleX, fScaleY, fScaleZ); - DISPLAY->PreMultMatrix(m); - } - } - - // handle alignment; most actors have default alignment. - if (unlikely(m_fHorizAlign != 0.5f || m_fVertAlign != 0.5f)) { - float fX = - SCALE(m_fHorizAlign, 0.0f, 1.0f, +m_size.x / 2.0f, -m_size.x / 2.0f); - float fY = - SCALE(m_fVertAlign, 0.0f, 1.0f, +m_size.y / 2.0f, -m_size.y / 2.0f); - RageMatrix m; - RageMatrixTranslate(&m, fX, fY, 0); - DISPLAY->PreMultMatrix(m); - } - - if (m_pTempState->quat.x != 0 || m_pTempState->quat.y != 0 || - m_pTempState->quat.z != 0 || m_pTempState->quat.w != 1) { - RageMatrix mat; - RageMatrixFromQuat(&mat, m_pTempState->quat); - - DISPLAY->MultMatrix(mat); - } - - // handle skews - if (m_pTempState->fSkewX != 0) { - DISPLAY->SkewX(m_pTempState->fSkewX); - } - - if (m_pTempState->fSkewY != 0) { - DISPLAY->SkewY(m_pTempState->fSkewY); - } - - if (m_texTranslate.x != 0 || m_texTranslate.y != 0) { - DISPLAY->TexturePushMatrix(); - DISPLAY->TextureTranslate(m_texTranslate.x, m_texTranslate.y); - } -} - -void -Actor::SetGlobalRenderStates() -{ - // set Actor-defined render states - if (!g_bShowMasks.Get() || m_BlendMode != BLEND_NO_EFFECT) - DISPLAY->SetBlendMode(m_BlendMode); - DISPLAY->SetZWrite(m_bZWrite); - DISPLAY->SetZTestMode(m_ZTestMode); - - // BLEND_NO_EFFECT is used to draw masks to the Z-buffer, which always wants - // Z-bias enabled. - if (m_fZBias == 0 && m_BlendMode == BLEND_NO_EFFECT) - DISPLAY->SetZBias(1.0f); - else - DISPLAY->SetZBias(m_fZBias); - - if (m_bClearZBuffer) - DISPLAY->ClearZBuffer(); - DISPLAY->SetCullMode(m_CullMode); -} - -void -Actor::SetTextureRenderStates() -{ - DISPLAY->SetTextureWrapping(TextureUnit_1, m_bTextureWrapping); - DISPLAY->SetTextureFiltering(TextureUnit_1, m_bTextureFiltering); -} - -void -Actor::EndDraw() -{ - DISPLAY->PopMatrix(); - - if (m_texTranslate.x != 0 || m_texTranslate.y != 0) - DISPLAY->TexturePopMatrix(); -} - -void -Actor::CalcPercentThroughTween() -{ - TweenState& TS = m_Tweens[0]->state; - TweenInfo& TI = m_Tweens[0]->info; - const float percent_through = 1 - (TI.m_fTimeLeftInTween / TI.m_fTweenTime); - // distort the percentage if appropriate - float percent_along = TI.m_pTween->Tween(percent_through); - TweenState::MakeWeightedAverage(m_current, m_start, TS, percent_along); - UpdatePercentThroughTween(percent_along); -} - -void -Actor::UpdateTweening(float fDeltaTime) -{ - if (fDeltaTime < 0.0 && !m_Tweens.empty()) { - m_Tweens[0]->info.m_fTimeLeftInTween -= fDeltaTime; - CalcPercentThroughTween(); - return; - } - while (!m_Tweens.empty() // something to do - && fDeltaTime > 0) // something will change - { - // update current tween state - // earliest tween - TweenState& TS = m_Tweens[0]->state; - TweenInfo& TI = m_Tweens[0]->info; - - bool bBeginning = TI.m_fTimeLeftInTween == TI.m_fTweenTime; - - float fSecsToSubtract = min(TI.m_fTimeLeftInTween, fDeltaTime); - TI.m_fTimeLeftInTween -= fSecsToSubtract; - fDeltaTime -= fSecsToSubtract; - - RString sCommand = TI.m_sCommandName; - if (bBeginning) // we are just beginning this tween - { - m_start = m_current; // set the start position - SetCurrentTweenStart(); - } - - if (TI.m_fTimeLeftInTween == 0) // Current tween is over. Stop. - { - m_current = TS; - - // delete the head tween - delete m_Tweens.front(); - m_Tweens.erase(m_Tweens.begin()); - EraseHeadTween(); - } else // in the middle of tweening. Recalcute the current position. - { - CalcPercentThroughTween(); - } - - if (bBeginning) { - // Execute the command in this tween (if any). Do this last, and - // don't access TI or TS after, since this may modify the tweening - // queue. - if (!sCommand.empty()) { - if (sCommand.Left(1) == "!") - MESSAGEMAN->Broadcast(sCommand.substr(1)); - else - this->PlayCommand(sCommand); - } - } - } -} - -bool -Actor::IsFirstUpdate() const -{ - return m_bFirstUpdate; -} - -void -Actor::Update(float fDeltaTime) -{ - // LOG->Trace( "Actor::Update( %f )", fDeltaTime ); - ASSERT_M(fDeltaTime >= 0, ssprintf("DeltaTime: %f", fDeltaTime)); - - if (m_fHibernateSecondsLeft > 0) { - m_fHibernateSecondsLeft -= fDeltaTime; - if (m_fHibernateSecondsLeft > 0) { - return; - } - - // Grab the leftover time. - fDeltaTime = -m_fHibernateSecondsLeft; - m_fHibernateSecondsLeft = 0; - } - for (size_t i = 0; i < m_WrapperStates.size(); ++i) { - m_WrapperStates[i]->Update(fDeltaTime); - } - - this->UpdateInternal(fDeltaTime); -} - -static void -generic_global_timer_update(float new_time, - float& effect_delta_time, - float& time_into_effect) -{ - effect_delta_time = new_time - time_into_effect; - time_into_effect = new_time; -} - -void -Actor::UpdateInternal(float delta_time) -{ - if (m_bFirstUpdate) - m_bFirstUpdate = false; - - switch (m_EffectClock) { - case CLOCK_TIMER: - m_fSecsIntoEffect += delta_time; - m_fEffectDelta = delta_time; - // Wrap the counter, so it doesn't increase indefinitely (causing - // loss of precision if a screen is left to sit for a day). - if (m_fSecsIntoEffect > GetEffectPeriod()) { - m_fSecsIntoEffect -= GetEffectPeriod(); - } - break; - case CLOCK_TIMER_GLOBAL: - generic_global_timer_update( - static_cast(RageTimer::GetUsecsSinceStart()), - m_fEffectDelta, - m_fSecsIntoEffect); - break; - case CLOCK_BGM_BEAT: - generic_global_timer_update( - g_fCurrentBGMBeat, m_fEffectDelta, m_fSecsIntoEffect); - break; - case CLOCK_BGM_BEAT_PLAYER1: - generic_global_timer_update(g_vfCurrentBGMBeatPlayer[PLAYER_1], - m_fEffectDelta, - m_fSecsIntoEffect); - break; - case CLOCK_BGM_BEAT_PLAYER2: - generic_global_timer_update(g_vfCurrentBGMBeatPlayer[PLAYER_2], - m_fEffectDelta, - m_fSecsIntoEffect); - break; - case CLOCK_BGM_TIME: - generic_global_timer_update( - g_fCurrentBGMTime, m_fEffectDelta, m_fSecsIntoEffect); - break; - case CLOCK_BGM_BEAT_NO_OFFSET: - generic_global_timer_update( - g_fCurrentBGMBeatNoOffset, m_fEffectDelta, m_fSecsIntoEffect); - break; - case CLOCK_BGM_TIME_NO_OFFSET: - generic_global_timer_update( - g_fCurrentBGMTimeNoOffset, m_fEffectDelta, m_fSecsIntoEffect); - break; - default: - break; - } - - // update effect - // todo: account for SSC_FUTURES -aj - switch (m_Effect) { - case spin: - m_current.rotation += m_fEffectDelta * m_vEffectMagnitude; - wrap(m_current.rotation.x, 360); - wrap(m_current.rotation.y, 360); - wrap(m_current.rotation.z, 360); - break; - default: - break; - } - - if (m_tween_uses_effect_delta) { - delta_time = m_fEffectDelta; - } - this->UpdateTweening(delta_time); - - for (auto it = delayedFunctions.begin(); it != delayedFunctions.end(); - ++it) { - auto& delayedF = *it; - delayedF.second -= delta_time; - if (delayedF.second <= 0) { - delayedF.first(); - } - } - // Doing this in place did weird things - std::remove_if(delayedFunctions.begin(), - delayedFunctions.end(), - [](auto& x) { return x.second <= 0; }); - for (auto it = this->delayedPeriodicFunctions.begin(); - it != this->delayedPeriodicFunctions.end(); - ++it) { - auto& delayedF = *it; - std::get<1>(delayedF) -= delta_time; - if (std::get<1>(delayedF) <= 0) { - std::get<0>(delayedF)(); - std::get<1>(delayedF) = std::get<2>(delayedF); - } - } -} - -RString -Actor::GetLineage() const -{ - RString sPath; - - if (m_pParent) - sPath = m_pParent->GetLineage() + '/'; - sPath += ssprintf(" %s", typeid(*this).name(), m_sName.c_str()); - return sPath; -} - -void -Actor::AddWrapperState() -{ - auto* wrapper = new ActorFrame; - wrapper->InitState(); - m_WrapperStates.push_back(wrapper); -} - -void -Actor::RemoveWrapperState(size_t i) -{ - ASSERT(i < m_WrapperStates.size()); - SAFE_DELETE(m_WrapperStates[i]); - m_WrapperStates.erase(m_WrapperStates.begin() + i); -} - -Actor* -Actor::GetWrapperState(size_t i) -{ - ASSERT(i < m_WrapperStates.size()); - return m_WrapperStates[i]; -} - -void -Actor::BeginTweening(float time, ITween* pTween) -{ - ASSERT(time >= 0); - - // If the number of tweens to ever gets this large, there's probably an - // infinitely recursing ActorCommand. - if (m_Tweens.size() > 50 && !(GamePreferences::m_AutoPlay == PC_REPLAY)) { - LuaHelpers::ReportScriptErrorFmt( - "Tween overflow: \"%s\"; infinitely recursing ActorCommand?", - GetLineage().c_str()); - this->FinishTweening(); - } - - // add a new TweenState to the tail, and initialize it - m_Tweens.push_back(new TweenStateAndInfo); - - // latest - TweenState& TS = m_Tweens.back()->state; - TweenInfo& TI = m_Tweens.back()->info; - - if (m_Tweens.size() >= 2) // if there was already a TS on the stack - { - // initialize the new TS from the last TS in the list - TS = m_Tweens[m_Tweens.size() - 2]->state; - } else { - // This new TS is the only TS. - // Set our tween starting and ending values to the current position. - TS = m_current; - } - - TI.m_pTween = pTween; - TI.m_fTweenTime = time; - TI.m_fTimeLeftInTween = time; -} - -void -Actor::BeginTweening(float time, TweenType tt) -{ - ASSERT(time >= 0); - - ITween* pTween = ITween::CreateFromType(tt); - this->BeginTweening(time, pTween); -} - -void -Actor::StopTweening() -{ - for (unsigned i = 0; i < m_Tweens.size(); ++i) - delete m_Tweens[i]; - m_Tweens.clear(); -} - -void -Actor::FinishTweening() -{ - if (!m_Tweens.empty()) - m_current = DestTweenState(); - this->StopTweening(); -} - -void -Actor::HurryTweening(float factor) -{ - for (unsigned i = 0; i < m_Tweens.size(); ++i) { - m_Tweens[i]->info.m_fTimeLeftInTween *= factor; - m_Tweens[i]->info.m_fTweenTime *= factor; - } -} - -void -Actor::ScaleTo(const RectF& rect, StretchType st) -{ - // width and height of rectangle - float rect_width = rect.GetWidth(); - float rect_height = rect.GetHeight(); - - if (rect_width < 0) - SetRotationY(180); - if (rect_height < 0) - SetRotationX(180); - - // zoom fActor needed to scale the Actor to fill the rectangle - float fNewZoomX = fabsf(rect_width / m_size.x); - float fNewZoomY = fabsf(rect_height / m_size.y); - - float fNewZoom = 0.f; - switch (st) { - case cover: - fNewZoom = - fNewZoomX > fNewZoomY ? fNewZoomX : fNewZoomY; // use larger zoom - break; - case fit_inside: - fNewZoom = - fNewZoomX > fNewZoomY ? fNewZoomY : fNewZoomX; // use smaller zoom - break; - } - - SetX(rect.left + rect_width * m_fHorizAlign); - SetY(rect.top + rect_height * m_fVertAlign); - - SetZoom(fNewZoom); -} - -void -Actor::SetEffectClockString(const RString& s) -{ - if (s.EqualsNoCase("timer")) - this->SetEffectClock(CLOCK_TIMER); - else if (s.EqualsNoCase("timerglobal")) - this->SetEffectClock(CLOCK_TIMER_GLOBAL); - else if (s.EqualsNoCase("beat")) - this->SetEffectClock(CLOCK_BGM_BEAT); - else if (s.EqualsNoCase("music")) - this->SetEffectClock(CLOCK_BGM_TIME); - else if (s.EqualsNoCase("bgm")) - this->SetEffectClock(CLOCK_BGM_BEAT); // compat, deprecated - else if (s.EqualsNoCase("musicnooffset")) - this->SetEffectClock(CLOCK_BGM_TIME_NO_OFFSET); - else if (s.EqualsNoCase("beatnooffset")) - this->SetEffectClock(CLOCK_BGM_BEAT_NO_OFFSET); -} - -void -Actor::StretchTo(const RectF& r) -{ - // width and height of rectangle - float width = r.GetWidth(); - float height = r.GetHeight(); - - // center of the rectangle - float cx = r.left + width / 2.0f; - float cy = r.top + height / 2.0f; - - // zoom fActor needed to scale the Actor to fill the rectangle - float fNewZoomX = width / m_size.x; - float fNewZoomY = height / m_size.y; - - SetXY(cx, cy); - SetZoomX(fNewZoomX); - SetZoomY(fNewZoomY); -} - -void -Actor::RecalcEffectPeriod() -{ - m_effect_period = m_effect_ramp_to_half + m_effect_hold_at_half + - m_effect_ramp_to_full + m_effect_hold_at_full + - m_effect_hold_at_zero; -} - -void -Actor::SetEffectPeriod(float time) -{ - ASSERT(time > 0); - m_effect_ramp_to_half = time / 2; - m_effect_hold_at_half = 0; - m_effect_ramp_to_full = time / 2; - m_effect_hold_at_full = 0; - m_effect_hold_at_zero = 0; - RecalcEffectPeriod(); -} - -bool -Actor::SetEffectTiming(float ramp_toh, - float at_half, - float ramp_tof, - float at_full, - float at_zero, - RString& err) -{ - // No negative timings - if (ramp_toh < 0 || at_half < 0 || ramp_tof < 0 || at_full < 0 || - at_zero < 0) { - err = ssprintf("Effect timings (%f,%f,%f,%f,%f) must not be negative;", - ramp_toh, - at_half, - ramp_tof, - at_zero, - at_full); - return false; - } - // and at least one positive timing. - if (ramp_toh <= 0 && at_half <= 0 && ramp_tof <= 0 && at_full <= 0 && - at_zero <= 0) { - err = ssprintf("Effect timings (0,0,0,0,0) must not all be zero;"); - return false; - } - m_effect_ramp_to_half = ramp_toh; - m_effect_hold_at_half = at_half; - m_effect_ramp_to_full = ramp_tof; - m_effect_hold_at_full = at_full; - m_effect_hold_at_zero = at_zero; - RecalcEffectPeriod(); - return true; -} - -bool -Actor::SetEffectHoldAtFull(float haf, RString& err) -{ - return SetEffectTiming(m_effect_ramp_to_half, - m_effect_hold_at_half, - m_effect_ramp_to_full, - haf, - m_effect_hold_at_zero, - err); -} - -// effect "macros" - -void -Actor::ResetEffectTimeIfDifferent(Effect new_effect) -{ - if (m_Effect != new_effect) { - m_Effect = new_effect; - m_fSecsIntoEffect = 0; - } -} - -void -Actor::SetEffectDiffuseBlink(float fEffectPeriodSeconds, - const RageColor& c1, - const RageColor& c2) -{ - ASSERT(fEffectPeriodSeconds > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(diffuse_blink); - SetEffectPeriod(fEffectPeriodSeconds); - m_effectColor1 = c1; - m_effectColor2 = c2; -} - -void -Actor::SetEffectDiffuseShift(float fEffectPeriodSeconds, - const RageColor& c1, - const RageColor& c2) -{ - ASSERT(fEffectPeriodSeconds > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(diffuse_shift); - SetEffectPeriod(fEffectPeriodSeconds); - m_effectColor1 = c1; - m_effectColor2 = c2; -} - -void -Actor::SetEffectDiffuseRamp(float fEffectPeriodSeconds, - const RageColor& c1, - const RageColor& c2) -{ - ASSERT(fEffectPeriodSeconds > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(diffuse_ramp); - SetEffectPeriod(fEffectPeriodSeconds); - m_effectColor1 = c1; - m_effectColor2 = c2; -} - -void -Actor::SetEffectGlowBlink(float fEffectPeriodSeconds, - const RageColor& c1, - const RageColor& c2) -{ - ASSERT(fEffectPeriodSeconds > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(glow_blink); - SetEffectPeriod(fEffectPeriodSeconds); - m_effectColor1 = c1; - m_effectColor2 = c2; -} - -void -Actor::SetEffectGlowShift(float fEffectPeriodSeconds, - const RageColor& c1, - const RageColor& c2) -{ - ASSERT(fEffectPeriodSeconds > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(glow_shift); - SetEffectPeriod(fEffectPeriodSeconds); - m_effectColor1 = c1; - m_effectColor2 = c2; -} - -void -Actor::SetEffectGlowRamp(float fEffectPeriodSeconds, - const RageColor& c1, - const RageColor& c2) -{ - ASSERT(fEffectPeriodSeconds > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(glow_ramp); - SetEffectPeriod(fEffectPeriodSeconds); - m_effectColor1 = c1; - m_effectColor2 = c2; -} - -void -Actor::SetEffectRainbow(float fEffectPeriodSeconds) -{ - ASSERT(fEffectPeriodSeconds > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(rainbow); - SetEffectPeriod(fEffectPeriodSeconds); -} - -void -Actor::SetEffectWag(float fPeriod, const RageVector3& vect) -{ - ASSERT(fPeriod > 0); - // todo: account for SSC_FUTURES -aj - ResetEffectTimeIfDifferent(wag); - SetEffectPeriod(fPeriod); - m_vEffectMagnitude = vect; -} - -void -Actor::SetEffectBounce(float fPeriod, const RageVector3& vect) -{ - ASSERT(fPeriod > 0); - // todo: account for SSC_FUTURES -aj - m_Effect = bounce; - SetEffectPeriod(fPeriod); - m_vEffectMagnitude = vect; - m_fSecsIntoEffect = 0; -} - -void -Actor::SetEffectBob(float fPeriod, const RageVector3& vect) -{ - ASSERT(fPeriod > 0); - // todo: account for SSC_FUTURES -aj - if (m_Effect != bob || GetEffectPeriod() != fPeriod) { - m_Effect = bob; - SetEffectPeriod(fPeriod); - m_fSecsIntoEffect = 0; - } - m_vEffectMagnitude = vect; -} - -void -Actor::SetEffectSpin(const RageVector3& vect) -{ - // todo: account for SSC_FUTURES -aj - m_Effect = spin; - m_vEffectMagnitude = vect; -} - -void -Actor::SetEffectVibrate(const RageVector3& vect) -{ - // todo: account for SSC_FUTURES -aj - m_Effect = vibrate; - m_vEffectMagnitude = vect; -} - -void -Actor::SetEffectPulse(float fPeriod, float fMinZoom, float fMaxZoom) -{ - ASSERT(fPeriod > 0); - // todo: account for SSC_FUTURES -aj - m_Effect = pulse; - SetEffectPeriod(fPeriod); - m_vEffectMagnitude[0] = fMinZoom; - m_vEffectMagnitude[1] = fMaxZoom; -} - -void -Actor::AddRotationH(float rot) -{ - RageQuatMultiply( - &DestTweenState().quat, DestTweenState().quat, RageQuatFromH(rot)); -} - -void -Actor::AddRotationP(float rot) -{ - RageQuatMultiply( - &DestTweenState().quat, DestTweenState().quat, RageQuatFromP(rot)); -} - -void -Actor::AddRotationR(float rot) -{ - RageQuatMultiply( - &DestTweenState().quat, DestTweenState().quat, RageQuatFromR(rot)); -} - -void -Actor::RunCommands(const LuaReference& cmds, const LuaReference* pParamTable) -{ - if (!cmds.IsSet() || cmds.IsNil()) { - LuaHelpers::ReportScriptErrorFmt( - "RunCommands: commands for %s are unset or nil", - GetLineage().c_str()); - return; - } - - Lua* L = LUA->Get(); - - // function - cmds.PushSelf(L); - if (lua_isnil(L, -1)) { - LuaHelpers::ReportScriptErrorFmt( - "RunCommands: Error compiling commands for %s", GetLineage().c_str()); - LUA->Release(L); - return; - } - - // 1st parameter - this->PushSelf(L); - - // 2nd parameter - if (pParamTable == nullptr) - lua_pushnil(L); - else - pParamTable->PushSelf(L); - - // call function with 2 arguments and 0 results - RString Error = "Error playing command:"; - LuaHelpers::RunScriptOnStack(L, Error, 2, 0, true); - - LUA->Release(L); -} - -float -Actor::GetTweenTimeLeft() const -{ - float tot = 0; - - tot += m_fHibernateSecondsLeft; - - for (unsigned i = 0; i < m_Tweens.size(); ++i) - tot += m_Tweens[i]->info.m_fTimeLeftInTween; - - return tot; -} - -/* This is a hack to change all tween states while leaving existing tweens - * alone. - * - * Hmm. Most commands actually act on a TweenStateAndInfo, not the Actor itself. - * Conceptually, it wouldn't be hard to give TweenState a presence in Lua, so - * we can simply say eg. "for x in states(Actor) do x.SetDiffuseColor(c) end". - * However, we'd then have to give every TweenState a userdata in Lua while it's - * being manipulated, which would add overhead ... */ -void -Actor::SetGlobalDiffuseColor(const RageColor& c) -{ - for (int i = 0; i < NUM_DIFFUSE_COLORS; i++) // color, not alpha - { - for (unsigned ts = 0; ts < m_Tweens.size(); ++ts) { - m_Tweens[ts]->state.diffuse[i].r = c.r; - m_Tweens[ts]->state.diffuse[i].g = c.g; - m_Tweens[ts]->state.diffuse[i].b = c.b; - } - m_current.diffuse[i].r = c.r; - m_current.diffuse[i].g = c.g; - m_current.diffuse[i].b = c.b; - m_start.diffuse[i].r = c.r; - m_start.diffuse[i].g = c.g; - m_start.diffuse[i].b = c.b; - } -} - -void -Actor::SetDiffuseColor(const RageColor& c) -{ - for (auto& i : DestTweenState().diffuse) { - i.r = c.r; - i.g = c.g; - i.b = c.b; - } -} - -void -Actor::TweenState::Init() -{ - pos = RageVector3(0, 0, 0); - rotation = RageVector3(0, 0, 0); - quat = RageVector4(0, 0, 0, 1); - scale = RageVector3(1, 1, 1); - fSkewX = 0; - fSkewY = 0; - crop = RectF(0, 0, 0, 0); - fade = RectF(0, 0, 0, 0); - for (auto& i : diffuse) - i = RageColor(1, 1, 1, 1); - glow = RageColor(1, 1, 1, 0); - aux = 0; -} - -bool -Actor::TweenState::operator==(const TweenState& other) const -{ -#define COMPARE(x) \ - if ((x) != other.x) \ - return false; - COMPARE(pos); - COMPARE(rotation); - COMPARE(quat); - COMPARE(scale); - COMPARE(fSkewX); - COMPARE(fSkewY); - COMPARE(crop); - COMPARE(fade); - for (unsigned i = 0; i < ARRAYLEN(diffuse); i++) - COMPARE(diffuse[i]); - COMPARE(glow); - COMPARE(aux); -#undef COMPARE - return true; -} - -void -Actor::TweenState::MakeWeightedAverage(TweenState& average_out, - const TweenState& ts1, - const TweenState& ts2, - float fPercentBetween) -{ - average_out.pos = lerp(fPercentBetween, ts1.pos, ts2.pos); - average_out.scale = lerp(fPercentBetween, ts1.scale, ts2.scale); - average_out.rotation = lerp(fPercentBetween, ts1.rotation, ts2.rotation); - RageQuatSlerp(&average_out.quat, ts1.quat, ts2.quat, fPercentBetween); - average_out.fSkewX = lerp(fPercentBetween, ts1.fSkewX, ts2.fSkewX); - average_out.fSkewY = lerp(fPercentBetween, ts1.fSkewY, ts2.fSkewY); - - average_out.crop.left = lerp(fPercentBetween, ts1.crop.left, ts2.crop.left); - average_out.crop.top = lerp(fPercentBetween, ts1.crop.top, ts2.crop.top); - average_out.crop.right = - lerp(fPercentBetween, ts1.crop.right, ts2.crop.right); - average_out.crop.bottom = - lerp(fPercentBetween, ts1.crop.bottom, ts2.crop.bottom); - - average_out.fade.left = lerp(fPercentBetween, ts1.fade.left, ts2.fade.left); - average_out.fade.top = lerp(fPercentBetween, ts1.fade.top, ts2.fade.top); - average_out.fade.right = - lerp(fPercentBetween, ts1.fade.right, ts2.fade.right); - average_out.fade.bottom = - lerp(fPercentBetween, ts1.fade.bottom, ts2.fade.bottom); - - for (int i = 0; i < NUM_DIFFUSE_COLORS; ++i) - average_out.diffuse[i] = - lerp(fPercentBetween, ts1.diffuse[i], ts2.diffuse[i]); - - average_out.glow = lerp(fPercentBetween, ts1.glow, ts2.glow); - average_out.aux = lerp(fPercentBetween, ts1.aux, ts2.aux); -} - -void -Actor::Sleep(float time) -{ - ASSERT(time >= 0); - - BeginTweening(time, TWEEN_LINEAR); - BeginTweening(0, TWEEN_LINEAR); -} - -void -Actor::QueueCommand(const RString& sCommandName) -{ - BeginTweening(0, TWEEN_LINEAR); - TweenInfo& TI = m_Tweens.back()->info; - TI.m_sCommandName = sCommandName; -} - -void -Actor::QueueMessage(const RString& sMessageName) -{ - // Hack: use "!" as a marker to broadcast a command, instead of playing a - // command, so we don't have to add yet another element to every tween - // state for this rarely-used command. - BeginTweening(0, TWEEN_LINEAR); - TweenInfo& TI = m_Tweens.back()->info; - TI.m_sCommandName = "!" + sMessageName; -} - -void -Actor::AddCommand(const RString& sCmdName, apActorCommands apac, bool warn) -{ - if (HasCommand(sCmdName) && warn) { - RString sWarning = - GetLineage() + "'s command '" + sCmdName + "' defined twice"; - LuaHelpers::ReportScriptError(sWarning, "COMMAND_DEFINED_TWICE"); - } - - RString sMessage; - if (GetMessageNameFromCommandName(sCmdName, sMessage)) { - SubscribeToMessage(sMessage); - m_mapNameToCommands[sMessage] = - apac; // sCmdName w/o "Message" at the end - } else { - m_mapNameToCommands[sCmdName] = apac; - } -} - -bool -Actor::HasCommand(const RString& sCmdName) const -{ - return GetCommand(sCmdName) != nullptr; -} - -const apActorCommands* -Actor::GetCommand(const RString& sCommandName) const -{ - map::const_iterator it = - m_mapNameToCommands.find(sCommandName); - if (it == m_mapNameToCommands.end()) - return nullptr; - return &it->second; -} - -void -Actor::HandleMessage(const Message& msg) -{ - PlayCommandNoRecurse(msg); -} - -void -Actor::PlayCommandNoRecurse(const Message& msg) -{ - const apActorCommands* pCmd = GetCommand(msg.GetName()); - if (pCmd != NULL && (*pCmd)->IsSet() && !(*pCmd)->IsNil()) { - RunCommands(*pCmd, &msg.GetParamTable()); - } -} - -void -Actor::PushContext(lua_State* L) -{ - // self.ctx should already exist - m_pLuaInstance->PushSelf(L); - lua_getfield(L, -1, "ctx"); - lua_remove(L, -2); -} - -void -Actor::SetParent(Actor* pParent) -{ - m_pParent = pParent; - - Lua* L = LUA->Get(); - int iTop = lua_gettop(L); - - this->PushContext(L); - lua_pushstring(L, "__index"); - pParent->PushContext(L); - lua_settable(L, -3); - - lua_settop(L, iTop); - LUA->Release(L); -} - -Actor::TweenInfo::TweenInfo() -{ - m_pTween = nullptr; -} - -Actor::TweenInfo::~TweenInfo() -{ - delete m_pTween; -} - -Actor::TweenInfo::TweenInfo(const TweenInfo& cpy) -{ - m_pTween = nullptr; - *this = cpy; -} - -Actor::TweenInfo& -Actor::TweenInfo::operator=(const TweenInfo& rhs) -{ - delete m_pTween; - m_pTween = (rhs.m_pTween != nullptr ? rhs.m_pTween->Copy() : nullptr); - m_fTimeLeftInTween = rhs.m_fTimeLeftInTween; - m_fTweenTime = rhs.m_fTweenTime; - m_sCommandName = rhs.m_sCommandName; - return *this; -} - -void -Actor::SetTimeout(function f, float ms) -{ - delayedFunctions.emplace_back(make_pair(f, ms)); - return; -} - -void -Actor::SetInterval(function f, float ms, function fRemove) -{ - delayedPeriodicFunctions.emplace_back(make_tuple(f, ms, ms, fRemove)); - return; -} - -// lua start -#include "LuaBinding.h" - -/** @brief Allow Lua to have access to the Actor. */ -class LunaActor : public Luna -{ - public: - static int name(T* p, lua_State* L) - { - p->SetName(SArg(1)); - COMMON_RETURN_SELF; - } - static int setTimeout(T* p, lua_State* L) - { - auto f = GetFuncArg(1, L); - std::function execF = [f]() { - Lua* L = LUA->Get(); - f.PushSelf(L); - if (!lua_isnil(L, -1)) { - RString Error = - "Error running RequestChartLeaderBoard Finish Function: "; - LuaHelpers::RunScriptOnStack( - L, Error, 0, 0, true); // 1 args, 0 results - } - LUA->Release(L); - }; - p->SetTimeout(execF, FArg(2)); - COMMON_RETURN_SELF; - } - static int setInterval(T* p, lua_State* L) - { - lua_pushvalue(L, 1); - auto f = luaL_ref(L, LUA_REGISTRYINDEX); - std::function execF = [f]() { - Lua* L = LUA->Get(); - lua_rawgeti(L, LUA_REGISTRYINDEX, f); - if (!lua_isnil(L, -1)) { - RString Error = - "Error running RequestChartLeaderBoard Finish Function: "; - LuaHelpers::RunScriptOnStack( - L, Error, 0, 0, true); // 1 args, 0 results - } - LUA->Release(L); - }; - p->SetInterval(execF, FArg(2), f); - lua_pushnumber(L, f); - return 1; - } - static int clearInterval(T* p, lua_State* L) - { - int r = IArg(1); - auto& l = p->delayedPeriodicFunctions; - auto it = find_if( - l.begin(), l.end(), [r](auto& x) { return std::get<3>() == r; }); - if (it != l.end()) { - luaL_unref(L, LUA_REGISTRYINDEX, r); - l.erase(it); - } else { - LuaHelpers::ReportScriptError( - "Interval function not found (When triying to clearInterval() )"); - } - return 0; - } - static int sleep(T* p, lua_State* L) - { - float fTime = FArg(1); - if (fTime < 0) { - LuaHelpers::ReportScriptErrorFmt( - "Lua: sleep(%f): time must not be negative", fTime); - COMMON_RETURN_SELF; - } - p->Sleep(fTime); - COMMON_RETURN_SELF; - } - static int linear(T* p, lua_State* L) - { - float fTime = FArg(1); - if (fTime < 0) { - LuaHelpers::ReportScriptErrorFmt( - "Lua: linear(%f): tween time must not be negative", fTime); - COMMON_RETURN_SELF; - } - p->BeginTweening(fTime, TWEEN_LINEAR); - COMMON_RETURN_SELF; - } - static int accelerate(T* p, lua_State* L) - { - float fTime = FArg(1); - if (fTime < 0) { - LuaHelpers::ReportScriptErrorFmt( - "Lua: accelerate(%f): tween time must not be negative", fTime); - COMMON_RETURN_SELF; - } - p->BeginTweening(fTime, TWEEN_ACCELERATE); - COMMON_RETURN_SELF; - } - static int decelerate(T* p, lua_State* L) - { - float fTime = FArg(1); - if (fTime < 0) { - LuaHelpers::ReportScriptErrorFmt( - "Lua: decelerate(%f): tween time must not be negative", fTime); - COMMON_RETURN_SELF; - } - p->BeginTweening(fTime, TWEEN_DECELERATE); - COMMON_RETURN_SELF; - } - static int spring(T* p, lua_State* L) - { - float fTime = FArg(1); - if (fTime < 0) { - LuaHelpers::ReportScriptErrorFmt( - "Lua: spring(%f): tween time must not be negative", fTime); - COMMON_RETURN_SELF; - } - p->BeginTweening(fTime, TWEEN_SPRING); - COMMON_RETURN_SELF; - } - static int tween(T* p, lua_State* L) - { - float fTime = FArg(1); - if (fTime < 0) { - LuaHelpers::ReportScriptErrorFmt( - "Lua: tween(%f): tween time must not be negative", fTime); - COMMON_RETURN_SELF; - } - ITween* pTween = ITween::CreateFromStack(L, 2); - if (pTween != nullptr) { - p->BeginTweening(fTime, pTween); - } - COMMON_RETURN_SELF; - } - static int stoptweening(T* p, lua_State* L) - { - p->StopTweening(); - COMMON_RETURN_SELF; - } - static int finishtweening(T* p, lua_State* L) - { - p->FinishTweening(); - COMMON_RETURN_SELF; - } - static int hurrytweening(T* p, lua_State* L) - { - float time = FArg(1); - if (time < 0.0f) { - luaL_error(L, "Tweening hurry factor cannot be negative. %f", time); - } - p->HurryTweening(time); - COMMON_RETURN_SELF; - } - static int GetTweenTimeLeft(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetTweenTimeLeft()); - return 1; - } - static int x(T* p, lua_State* L) - { - p->SetX(FArg(1)); - COMMON_RETURN_SELF; - } - static int y(T* p, lua_State* L) - { - p->SetY(FArg(1)); - COMMON_RETURN_SELF; - } - static int z(T* p, lua_State* L) - { - p->SetZ(FArg(1)); - COMMON_RETURN_SELF; - } - static int xy(T* p, lua_State* L) - { - p->SetXY(FArg(1), FArg(2)); - COMMON_RETURN_SELF; - } - static int addx(T* p, lua_State* L) - { - p->AddX(FArg(1)); - COMMON_RETURN_SELF; - } - static int addy(T* p, lua_State* L) - { - p->AddY(FArg(1)); - COMMON_RETURN_SELF; - } - static int addz(T* p, lua_State* L) - { - p->AddZ(FArg(1)); - COMMON_RETURN_SELF; - } - static int zoom(T* p, lua_State* L) - { - p->SetZoom(FArg(1)); - COMMON_RETURN_SELF; - } - static int zoomx(T* p, lua_State* L) - { - p->SetZoomX(FArg(1)); - COMMON_RETURN_SELF; - } - static int zoomy(T* p, lua_State* L) - { - p->SetZoomY(FArg(1)); - COMMON_RETURN_SELF; - } - static int zoomz(T* p, lua_State* L) - { - p->SetZoomZ(FArg(1)); - COMMON_RETURN_SELF; - } - static int zoomto(T* p, lua_State* L) - { - p->ZoomTo(FArg(1), FArg(2)); - COMMON_RETURN_SELF; - } - static int zoomtowidth(T* p, lua_State* L) - { - p->ZoomToWidth(FArg(1)); - COMMON_RETURN_SELF; - } - static int zoomtoheight(T* p, lua_State* L) - { - p->ZoomToHeight(FArg(1)); - COMMON_RETURN_SELF; - } - static int setsize(T* p, lua_State* L) - { - p->SetWidth(FArg(1)); - p->SetHeight(FArg(2)); - COMMON_RETURN_SELF; - } - static int SetWidth(T* p, lua_State* L) - { - p->SetWidth(FArg(1)); - COMMON_RETURN_SELF; - } - static int SetHeight(T* p, lua_State* L) - { - p->SetHeight(FArg(1)); - COMMON_RETURN_SELF; - } - static int basealpha(T* p, lua_State* L) - { - p->SetBaseAlpha(FArg(1)); - COMMON_RETURN_SELF; - } - static int basezoom(T* p, lua_State* L) - { - p->SetBaseZoom(FArg(1)); - COMMON_RETURN_SELF; - } - static int basezoomx(T* p, lua_State* L) - { - p->SetBaseZoomX(FArg(1)); - COMMON_RETURN_SELF; - } - static int basezoomy(T* p, lua_State* L) - { - p->SetBaseZoomY(FArg(1)); - COMMON_RETURN_SELF; - } - static int basezoomz(T* p, lua_State* L) - { - p->SetBaseZoomZ(FArg(1)); - COMMON_RETURN_SELF; - } - static int stretchto(T* p, lua_State* L) - { - p->StretchTo(RectF(FArg(1), FArg(2), FArg(3), FArg(4))); - COMMON_RETURN_SELF; - } - static int cropleft(T* p, lua_State* L) - { - p->SetCropLeft(FArg(1)); - COMMON_RETURN_SELF; - } - static int croptop(T* p, lua_State* L) - { - p->SetCropTop(FArg(1)); - COMMON_RETURN_SELF; - } - static int cropright(T* p, lua_State* L) - { - p->SetCropRight(FArg(1)); - COMMON_RETURN_SELF; - } - static int cropbottom(T* p, lua_State* L) - { - p->SetCropBottom(FArg(1)); - COMMON_RETURN_SELF; - } - static int fadeleft(T* p, lua_State* L) - { - p->SetFadeLeft(FArg(1)); - COMMON_RETURN_SELF; - } - static int fadetop(T* p, lua_State* L) - { - p->SetFadeTop(FArg(1)); - COMMON_RETURN_SELF; - } - static int faderight(T* p, lua_State* L) - { - p->SetFadeRight(FArg(1)); - COMMON_RETURN_SELF; - } - static int fadebottom(T* p, lua_State* L) - { - p->SetFadeBottom(FArg(1)); - COMMON_RETURN_SELF; - } - static int diffuse(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuse(c); - COMMON_RETURN_SELF; - } - static int diffuseupperleft(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseUpperLeft(c); - COMMON_RETURN_SELF; - } - static int diffuseupperright(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseUpperRight(c); - COMMON_RETURN_SELF; - } - static int diffuselowerleft(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseLowerLeft(c); - COMMON_RETURN_SELF; - } - static int diffuselowerright(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseLowerRight(c); - COMMON_RETURN_SELF; - } - static int diffuseleftedge(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseLeftEdge(c); - COMMON_RETURN_SELF; - } - static int diffuserightedge(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseRightEdge(c); - COMMON_RETURN_SELF; - } - static int diffusetopedge(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseTopEdge(c); - COMMON_RETURN_SELF; - } - static int diffusebottomedge(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseBottomEdge(c); - COMMON_RETURN_SELF; - } - static int diffusealpha(T* p, lua_State* L) - { - p->SetDiffuseAlpha(FArg(1)); - COMMON_RETURN_SELF; - } - static int diffusecolor(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetDiffuseColor(c); - COMMON_RETURN_SELF; - } - static int glow(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetGlow(c); - COMMON_RETURN_SELF; - } - static int aux(T* p, lua_State* L) - { - p->SetAux(FArg(1)); - COMMON_RETURN_SELF; - } - static int getaux(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetAux()); - return 1; - } - static int rotationx(T* p, lua_State* L) - { - p->SetRotationX(FArg(1)); - COMMON_RETURN_SELF; - } - static int rotationy(T* p, lua_State* L) - { - p->SetRotationY(FArg(1)); - COMMON_RETURN_SELF; - } - static int rotationz(T* p, lua_State* L) - { - p->SetRotationZ(FArg(1)); - COMMON_RETURN_SELF; - } - static int addrotationx(T* p, lua_State* L) - { - p->AddRotationX(FArg(1)); - COMMON_RETURN_SELF; - } - static int addrotationy(T* p, lua_State* L) - { - p->AddRotationY(FArg(1)); - COMMON_RETURN_SELF; - } - static int addrotationz(T* p, lua_State* L) - { - p->AddRotationZ(FArg(1)); - COMMON_RETURN_SELF; - } - static int getrotation(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetRotationX()); - lua_pushnumber(L, p->GetRotationY()); - lua_pushnumber(L, p->GetRotationZ()); - return 3; - } - static int baserotationx(T* p, lua_State* L) - { - p->SetBaseRotationX(FArg(1)); - COMMON_RETURN_SELF; - } - static int baserotationy(T* p, lua_State* L) - { - p->SetBaseRotationY(FArg(1)); - COMMON_RETURN_SELF; - } - static int baserotationz(T* p, lua_State* L) - { - p->SetBaseRotationZ(FArg(1)); - COMMON_RETURN_SELF; - } - static int skewx(T* p, lua_State* L) - { - p->SetSkewX(FArg(1)); - COMMON_RETURN_SELF; - } - static int skewy(T* p, lua_State* L) - { - p->SetSkewY(FArg(1)); - COMMON_RETURN_SELF; - } - static int heading(T* p, lua_State* L) - { - p->AddRotationH(FArg(1)); - COMMON_RETURN_SELF; - } - static int pitch(T* p, lua_State* L) - { - p->AddRotationP(FArg(1)); - COMMON_RETURN_SELF; - } - static int roll(T* p, lua_State* L) - { - p->AddRotationR(FArg(1)); - COMMON_RETURN_SELF; - } - static int shadowlength(T* p, lua_State* L) - { - p->SetShadowLength(FArg(1)); - COMMON_RETURN_SELF; - } - static int shadowlengthx(T* p, lua_State* L) - { - p->SetShadowLengthX(FArg(1)); - COMMON_RETURN_SELF; - } - static int shadowlengthy(T* p, lua_State* L) - { - p->SetShadowLengthY(FArg(1)); - COMMON_RETURN_SELF; - } - static int shadowcolor(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetShadowColor(c); - COMMON_RETURN_SELF; - } - static int horizalign(T* p, lua_State* L) - { - p->SetHorizAlign(Enum::Check(L, 1)); - COMMON_RETURN_SELF; - } - static int vertalign(T* p, lua_State* L) - { - p->SetVertAlign(Enum::Check(L, 1)); - COMMON_RETURN_SELF; - } - static int halign(T* p, lua_State* L) - { - p->SetHorizAlign(FArg(1)); - COMMON_RETURN_SELF; - } - static int valign(T* p, lua_State* L) - { - p->SetVertAlign(FArg(1)); - COMMON_RETURN_SELF; - } - static int diffuseblink(T* p, lua_State* L) - { - p->SetEffectDiffuseBlink( - 1.0f, RageColor(0.5f, 0.5f, 0.5f, 0.5f), RageColor(1, 1, 1, 1)); - COMMON_RETURN_SELF; - } - static int diffuseshift(T* p, lua_State* L) - { - p->SetEffectDiffuseShift( - 1.0f, RageColor(0, 0, 0, 1), RageColor(1, 1, 1, 1)); - COMMON_RETURN_SELF; - } - static int diffuseramp(T* p, lua_State* L) - { - p->SetEffectDiffuseRamp( - 1.0f, RageColor(0, 0, 0, 1), RageColor(1, 1, 1, 1)); - COMMON_RETURN_SELF; - } - static int glowblink(T* p, lua_State* L) - { - p->SetEffectGlowBlink( - 1.0f, RageColor(1, 1, 1, 0.2f), RageColor(1, 1, 1, 0.8f)); - COMMON_RETURN_SELF; - } - static int glowshift(T* p, lua_State* L) - { - p->SetEffectGlowShift( - 1.0f, RageColor(1, 1, 1, 0.2f), RageColor(1, 1, 1, 0.8f)); - COMMON_RETURN_SELF; - } - static int glowramp(T* p, lua_State* L) - { - p->SetEffectGlowRamp( - 1.0f, RageColor(1, 1, 1, 0.2f), RageColor(1, 1, 1, 0.8f)); - COMMON_RETURN_SELF; - } - static int rainbow(T* p, lua_State* L) - { - p->SetEffectRainbow(2.0f); - COMMON_RETURN_SELF; - } - static int wag(T* p, lua_State* L) - { - p->SetEffectWag(2.0f, RageVector3(0, 0, 20)); - COMMON_RETURN_SELF; - } - static int bounce(T* p, lua_State* L) - { - p->SetEffectBounce(2.0f, RageVector3(0, 20, 0)); - COMMON_RETURN_SELF; - } - static int bob(T* p, lua_State* L) - { - p->SetEffectBob(2.0f, RageVector3(0, 20, 0)); - COMMON_RETURN_SELF; - } - static int pulse(T* p, lua_State* L) - { - p->SetEffectPulse(2.0f, 0.5f, 1.0f); - COMMON_RETURN_SELF; - } - static int spin(T* p, lua_State* L) - { - p->SetEffectSpin(RageVector3(0, 0, 180)); - COMMON_RETURN_SELF; - } - static int vibrate(T* p, lua_State* L) - { - p->SetEffectVibrate(RageVector3(10, 10, 10)); - COMMON_RETURN_SELF; - } - static int stopeffect(T* p, lua_State* L) - { - p->StopEffect(); - COMMON_RETURN_SELF; - } - static int effectcolor1(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetEffectColor1(c); - COMMON_RETURN_SELF; - } - static int effectcolor2(T* p, lua_State* L) - { - RageColor c; - c.FromStackCompat(L, 1); - p->SetEffectColor2(c); - COMMON_RETURN_SELF; - } - static int effectperiod(T* p, lua_State* L) - { - float fPeriod = FArg(1); - if (fPeriod <= 0) { - LuaHelpers::ReportScriptErrorFmt( - "Effect period (%f) must be positive; ignoring", fPeriod); - COMMON_RETURN_SELF; - } - p->SetEffectPeriod(FArg(1)); - COMMON_RETURN_SELF; - } - static int effecttiming(T* p, lua_State* L) - { - float rth = FArg(1); - float hah = FArg(2); - float rtf = FArg(3); - float haz = FArg(4); - // Compatibility: hold_at_full is optional. - float haf = 0; - if (lua_isnumber(L, 5) != 0) { - haf = FArg(5); - } - RString err; - if (!p->SetEffectTiming(rth, hah, rtf, haf, haz, err)) { - luaL_error(L, err.c_str()); - } - COMMON_RETURN_SELF; - } - static int effect_hold_at_full(T* p, lua_State* L) - { - RString err; - if (!p->SetEffectHoldAtFull(FArg(1), err)) { - luaL_error(L, err.c_str()); - } - COMMON_RETURN_SELF; - } - static int effectoffset(T* p, lua_State* L) - { - p->SetEffectOffset(FArg(1)); - COMMON_RETURN_SELF; - } - static int effectclock(T* p, lua_State* L) - { - p->SetEffectClockString(SArg(1)); - COMMON_RETURN_SELF; - } - static int effectmagnitude(T* p, lua_State* L) - { - p->SetEffectMagnitude(RageVector3(FArg(1), FArg(2), FArg(3))); - COMMON_RETURN_SELF; - } - static int geteffectmagnitude(T* p, lua_State* L) - { - RageVector3 v = p->GetEffectMagnitude(); - lua_pushnumber(L, v[0]); - lua_pushnumber(L, v[1]); - lua_pushnumber(L, v[2]); - return 3; - } - GETTER_SETTER_BOOL_METHOD(tween_uses_effect_delta); - static int scaletocover(T* p, lua_State* L) - { - p->ScaleToCover(RectF(FArg(1), FArg(2), FArg(3), FArg(4))); - COMMON_RETURN_SELF; - } - static int scaletofit(T* p, lua_State* L) - { - p->ScaleToFitInside(RectF(FArg(1), FArg(2), FArg(3), FArg(4))); - COMMON_RETURN_SELF; - } - static int animate(T* p, lua_State* L) - { - p->EnableAnimation(BIArg(1)); - COMMON_RETURN_SELF; - } - static int play(T* p, lua_State* L) - { - p->EnableAnimation(true); - COMMON_RETURN_SELF; - } - static int pause(T* p, lua_State* L) - { - p->EnableAnimation(false); - COMMON_RETURN_SELF; - } - static int setstate(T* p, lua_State* L) - { - p->SetState(IArg(1)); - COMMON_RETURN_SELF; - } - static int GetNumStates(T* p, lua_State* L) - { - LuaHelpers::Push(L, p->GetNumStates()); - return 1; - } - static int texturetranslate(T* p, lua_State* L) - { - p->SetTextureTranslate(FArg(1), FArg(2)); - COMMON_RETURN_SELF; - } - static int texturewrapping(T* p, lua_State* L) - { - p->SetTextureWrapping(BIArg(1)); - COMMON_RETURN_SELF; - } - static int SetTextureFiltering(T* p, lua_State* L) - { - p->SetTextureFiltering(BArg(1)); - COMMON_RETURN_SELF; - } - static int blend(T* p, lua_State* L) - { - p->SetBlendMode(Enum::Check(L, 1)); - COMMON_RETURN_SELF; - } - static int zbuffer(T* p, lua_State* L) - { - p->SetUseZBuffer(BIArg(1)); - COMMON_RETURN_SELF; - } - static int ztest(T* p, lua_State* L) - { - p->SetZTestMode((BIArg(1)) ? ZTEST_WRITE_ON_PASS : ZTEST_OFF); - COMMON_RETURN_SELF; - } - static int ztestmode(T* p, lua_State* L) - { - p->SetZTestMode(Enum::Check(L, 1)); - COMMON_RETURN_SELF; - } - static int zwrite(T* p, lua_State* L) - { - p->SetZWrite(BIArg(1)); - COMMON_RETURN_SELF; - } - static int zbias(T* p, lua_State* L) - { - p->SetZBias(FArg(1)); - COMMON_RETURN_SELF; - } - static int clearzbuffer(T* p, lua_State* L) - { - p->SetClearZBuffer(BIArg(1)); - COMMON_RETURN_SELF; - } - static int backfacecull(T* p, lua_State* L) - { - p->SetCullMode((BIArg(1)) ? CULL_BACK : CULL_NONE); - COMMON_RETURN_SELF; - } - static int cullmode(T* p, lua_State* L) - { - p->SetCullMode(Enum::Check(L, 1)); - COMMON_RETURN_SELF; - } - static int visible(T* p, lua_State* L) - { - p->SetVisible(BIArg(1)); - COMMON_RETURN_SELF; - } - static int hibernate(T* p, lua_State* L) - { - p->SetHibernate(FArg(1)); - COMMON_RETURN_SELF; - } - static int draworder(T* p, lua_State* L) - { - p->SetDrawOrder(IArg(1)); - COMMON_RETURN_SELF; - } - static int playcommand(T* p, lua_State* L) - { - if (!lua_istable(L, 2) && !lua_isnoneornil(L, 2)) - luaL_typerror(L, 2, "table or nil"); - - LuaReference ParamTable; - lua_pushvalue(L, 2); - ParamTable.SetFromStack(L); - - Message msg(SArg(1), ParamTable); - p->HandleMessage(msg); - - COMMON_RETURN_SELF; - } - static int queuecommand(T* p, lua_State* L) - { - p->QueueCommand(SArg(1)); - COMMON_RETURN_SELF; - } - static int queuemessage(T* p, lua_State* L) - { - p->QueueMessage(SArg(1)); - COMMON_RETURN_SELF; - } - static int addcommand(T* p, lua_State* L) - { - auto* pRef = new LuaReference; - pRef->SetFromStack(L); - p->AddCommand(SArg(1), apActorCommands(pRef)); - COMMON_RETURN_SELF; - } - static int GetCommand(T* p, lua_State* L) - { - const apActorCommands* pCommand = p->GetCommand(SArg(1)); - if (pCommand == nullptr) - lua_pushnil(L); - else - (*pCommand)->PushSelf(L); - - return 1; - } - static int RunCommandsRecursively(T* p, lua_State* L) - { - luaL_checktype(L, 1, LUA_TFUNCTION); - if (!lua_istable(L, 2) && !lua_isnoneornil(L, 2)) - luaL_typerror(L, 2, "table or nil"); - - LuaReference ref; - lua_pushvalue(L, 1); - ref.SetFromStack(L); - - LuaReference ParamTable; - lua_pushvalue(L, 2); - ParamTable.SetFromStack(L); - - p->RunCommandsRecursively(ref, &ParamTable); - COMMON_RETURN_SELF; - } - - static int GetX(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetX()); - return 1; - } - static int GetY(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetY()); - return 1; - } - static int GetZ(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetZ()); - return 1; - } - static int GetDestX(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetDestX()); - return 1; - } - static int GetDestY(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetDestY()); - return 1; - } - static int GetDestZ(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetDestZ()); - return 1; - } - static int GetWidth(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetUnzoomedWidth()); - return 1; - } - static int GetHeight(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetUnzoomedHeight()); - return 1; - } - static int GetZoomedWidth(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetZoomedWidth()); - return 1; - } - static int GetZoomedHeight(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetZoomedHeight()); - return 1; - } - static int GetZoom(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetZoom()); - return 1; - } - static int GetZoomX(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetZoomX()); - return 1; - } - static int GetZoomY(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetZoomY()); - return 1; - } - static int GetZoomZ(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetZoomZ()); - return 1; - } - static int GetBaseZoomX(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetBaseZoomX()); - return 1; - } - static int GetBaseZoomY(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetBaseZoomY()); - return 1; - } - static int GetBaseZoomZ(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetBaseZoomZ()); - return 1; - } - static int GetRotationX(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetRotationX()); - return 1; - } - static int GetRotationY(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetRotationY()); - return 1; - } - static int GetRotationZ(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetRotationZ()); - return 1; - } - static int GetSecsIntoEffect(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetSecsIntoEffect()); - return 1; - } - static int GetEffectDelta(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetEffectDelta()); - return 1; - } - DEFINE_METHOD(GetDiffuse, GetDiffuse()) - DEFINE_METHOD(GetGlow, GetGlow()) - static int GetDiffuseAlpha(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetDiffuseAlpha()); - return 1; - } - static int GetVisible(T* p, lua_State* L) - { - lua_pushboolean(L, p->GetVisible()); - return 1; - } - static int GetHAlign(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetHorizAlign()); - return 1; - } - static int GetVAlign(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetVertAlign()); - return 1; - } - - static int GetName(T* p, lua_State* L) - { - lua_pushstring(L, p->GetName()); - return 1; - } - static int GetParent(T* p, lua_State* L) - { - Actor* pParent = p->GetParent(); - if (pParent == nullptr) - lua_pushnil(L); - else - pParent->PushSelf(L); - return 1; - } - static int GetFakeParent(T* p, lua_State* L) - { - Actor* fake = p->GetFakeParent(); - if (fake == nullptr) { - lua_pushnil(L); - } else { - fake->PushSelf(L); - } - return 1; - } - static int SetFakeParent(T* p, lua_State* L) - { - if (lua_isnoneornil(L, 1)) { - p->SetFakeParent(NULL); - } else { - Actor* fake = Luna::check(L, 1); - p->SetFakeParent(fake); - } - COMMON_RETURN_SELF; - } - static int AddWrapperState(T* p, lua_State* L) - { - p->AddWrapperState(); - p->GetWrapperState(p->GetNumWrapperStates() - 1)->PushSelf(L); - return 1; - } - static size_t get_state_index(T* p, lua_State* L, int stack_index) - { - // Lua is one indexed. - int i = IArg(stack_index) - 1; - const auto si = static_cast(i); - if (i < 0 || si >= p->GetNumWrapperStates()) { - luaL_error(L, "%d is not a valid wrapper state index.", i + 1); - } - return si; - } - static int RemoveWrapperState(T* p, lua_State* L) - { - size_t si = get_state_index(p, L, 1); - p->RemoveWrapperState(si); - COMMON_RETURN_SELF; - } - static int GetNumWrapperStates(T* p, lua_State* L) - { - lua_pushnumber(L, p->GetNumWrapperStates()); - return 1; - } - static int GetWrapperState(T* p, lua_State* L) - { - size_t si = get_state_index(p, L, 1); - p->GetWrapperState(si)->PushSelf(L); - return 1; - } - static int Draw(T* p, lua_State* L) - { - LUA->YieldLua(); - p->Draw(); - LUA->UnyieldLua(); - COMMON_RETURN_SELF; - } - - static int SaveXY(T* p, lua_State* L) - { // in the future arguments should be optional and default to getx, gety if - // no explicit coords are provided - mina - FILTERMAN->savepos(p->GetName(), IArg(1), IArg(2)); - COMMON_RETURN_SELF; - } - - static int LoadXY(T* p, lua_State* L) - { - auto doot = FILTERMAN->loadpos(p->GetName()); - p->SetX(static_cast(doot.first)); - p->SetY(static_cast(doot.second)); - COMMON_RETURN_SELF; - } - static int IsOver(T* p, lua_State* L) - { - lua_pushboolean(L, p->IsOver(FArg(1), FArg(2))); - return 1; - } - DEFINE_METHOD(GetTrueX, GetTrueX()); - DEFINE_METHOD(GetTrueY, GetTrueY()); - DEFINE_METHOD(GetTrueZoom, GetTrueZoom()); - DEFINE_METHOD(IsVisible, IsVisible()); - LunaActor() - { - ADD_METHOD(name); - ADD_METHOD(setInterval); - ADD_METHOD(setTimeout); - ADD_METHOD(name); - ADD_METHOD(sleep); - ADD_METHOD(linear); - ADD_METHOD(accelerate); - ADD_METHOD(decelerate); - ADD_METHOD(spring); - ADD_METHOD(tween); - ADD_METHOD(stoptweening); - ADD_METHOD(finishtweening); - ADD_METHOD(hurrytweening); - ADD_METHOD(GetTweenTimeLeft); - ADD_METHOD(x); - ADD_METHOD(y); - ADD_METHOD(z); - ADD_METHOD(xy); - ADD_METHOD(addx); - ADD_METHOD(addy); - ADD_METHOD(addz); - ADD_METHOD(zoom); - ADD_METHOD(zoomx); - ADD_METHOD(zoomy); - ADD_METHOD(zoomz); - ADD_METHOD(zoomto); - ADD_METHOD(zoomtowidth); - ADD_METHOD(zoomtoheight); - ADD_METHOD(setsize); - ADD_METHOD(SetWidth); - ADD_METHOD(SetHeight); - ADD_METHOD(basealpha); - ADD_METHOD(basezoom); - ADD_METHOD(basezoomx); - ADD_METHOD(basezoomy); - ADD_METHOD(basezoomz); - ADD_METHOD(stretchto); - ADD_METHOD(cropleft); - ADD_METHOD(croptop); - ADD_METHOD(cropright); - ADD_METHOD(cropbottom); - ADD_METHOD(fadeleft); - ADD_METHOD(fadetop); - ADD_METHOD(faderight); - ADD_METHOD(fadebottom); - ADD_METHOD(diffuse); - ADD_METHOD(diffuseupperleft); - ADD_METHOD(diffuseupperright); - ADD_METHOD(diffuselowerleft); - ADD_METHOD(diffuselowerright); - ADD_METHOD(diffuseleftedge); - ADD_METHOD(diffuserightedge); - ADD_METHOD(diffusetopedge); - ADD_METHOD(diffusebottomedge); - ADD_METHOD(diffusealpha); - ADD_METHOD(diffusecolor); - ADD_METHOD(glow); - ADD_METHOD(aux); - ADD_METHOD(getaux); - ADD_METHOD(rotationx); - ADD_METHOD(rotationy); - ADD_METHOD(rotationz); - ADD_METHOD(addrotationx); - ADD_METHOD(addrotationy); - ADD_METHOD(addrotationz); - ADD_METHOD(getrotation); - ADD_METHOD(baserotationx); - ADD_METHOD(baserotationy); - ADD_METHOD(baserotationz); - ADD_METHOD(skewx); - ADD_METHOD(skewy); - ADD_METHOD(heading); - ADD_METHOD(pitch); - ADD_METHOD(roll); - ADD_METHOD(shadowlength); - ADD_METHOD(shadowlengthx); - ADD_METHOD(shadowlengthy); - ADD_METHOD(shadowcolor); - ADD_METHOD(horizalign); - ADD_METHOD(vertalign); - ADD_METHOD(halign); - ADD_METHOD(valign); - ADD_METHOD(diffuseblink); - ADD_METHOD(diffuseshift); - ADD_METHOD(diffuseramp); - ADD_METHOD(glowblink); - ADD_METHOD(glowshift); - ADD_METHOD(glowramp); - ADD_METHOD(rainbow); - ADD_METHOD(wag); - ADD_METHOD(bounce); - ADD_METHOD(bob); - ADD_METHOD(pulse); - ADD_METHOD(spin); - ADD_METHOD(vibrate); - ADD_METHOD(stopeffect); - ADD_METHOD(effectcolor1); - ADD_METHOD(effectcolor2); - ADD_METHOD(effectperiod); - ADD_METHOD(effecttiming); - ADD_METHOD(effect_hold_at_full); - ADD_METHOD(effectoffset); - ADD_METHOD(effectclock); - ADD_METHOD(effectmagnitude); - ADD_METHOD(geteffectmagnitude); - ADD_GET_SET_METHODS(tween_uses_effect_delta); - ADD_METHOD(scaletocover); - ADD_METHOD(scaletofit); - ADD_METHOD(animate); - ADD_METHOD(play); - ADD_METHOD(pause); - ADD_METHOD(setstate); - ADD_METHOD(GetNumStates); - ADD_METHOD(texturetranslate); - ADD_METHOD(texturewrapping); - ADD_METHOD(SetTextureFiltering); - ADD_METHOD(blend); - ADD_METHOD(zbuffer); - ADD_METHOD(ztest); - ADD_METHOD(ztestmode); - ADD_METHOD(zwrite); - ADD_METHOD(zbias); - ADD_METHOD(clearzbuffer); - ADD_METHOD(backfacecull); - ADD_METHOD(cullmode); - ADD_METHOD(visible); - ADD_METHOD(hibernate); - ADD_METHOD(draworder); - ADD_METHOD(playcommand); - ADD_METHOD(queuecommand); - ADD_METHOD(queuemessage); - ADD_METHOD(addcommand); - ADD_METHOD(GetCommand); - ADD_METHOD(RunCommandsRecursively); - - ADD_METHOD(GetX); - ADD_METHOD(GetY); - ADD_METHOD(GetZ); - ADD_METHOD(GetDestX); - ADD_METHOD(GetDestY); - ADD_METHOD(GetDestZ); - ADD_METHOD(GetWidth); - ADD_METHOD(GetHeight); - ADD_METHOD(GetZoomedWidth); - ADD_METHOD(GetZoomedHeight); - ADD_METHOD(GetZoom); - ADD_METHOD(GetZoomX); - ADD_METHOD(GetZoomY); - ADD_METHOD(GetZoomZ); - ADD_METHOD(GetRotationX); - ADD_METHOD(GetRotationY); - ADD_METHOD(GetRotationZ); - ADD_METHOD(GetBaseZoomX); - ADD_METHOD(GetBaseZoomY); - ADD_METHOD(GetBaseZoomZ); - ADD_METHOD(GetSecsIntoEffect); - ADD_METHOD(GetEffectDelta); - ADD_METHOD(GetDiffuse); - ADD_METHOD(GetDiffuseAlpha); - ADD_METHOD(GetGlow); - ADD_METHOD(GetVisible); - ADD_METHOD(GetHAlign); - ADD_METHOD(GetVAlign); - - ADD_METHOD(GetName); - ADD_METHOD(GetParent); - ADD_METHOD(GetFakeParent); - ADD_METHOD(SetFakeParent); - ADD_METHOD(AddWrapperState); - ADD_METHOD(RemoveWrapperState); - ADD_METHOD(GetNumWrapperStates); - ADD_METHOD(GetWrapperState); - - ADD_METHOD(Draw); - - ADD_METHOD(SaveXY); - ADD_METHOD(LoadXY); - - ADD_METHOD(GetTrueX); - ADD_METHOD(GetTrueY); - ADD_METHOD(GetTrueZoom); - ADD_METHOD(IsVisible); - ADD_METHOD(IsOver); - } -}; - -LUA_REGISTER_INSTANCED_BASE_CLASS(Actor) -// lua end - -/* - * (c) 2001-2004 Chris Danford - * All rights reserved. - * - * 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, and/or sell copies of the Software, and to permit persons to - * whom the Software is furnished to do so, provided that the above - * copyright notice(s) and this permission notice appear in all copies of - * the Software and that both the above copyright notice(s) and this - * permission notice appear in supporting documentation. - * - * 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT - * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ From b71dae544b51c17a5f77bc9b4253df2f3ef6e72b Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 26 Nov 2018 23:00:26 -0300 Subject: [PATCH 080/320] Update stepmania.nsi --- stepmania.nsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stepmania.nsi b/stepmania.nsi index cde4f18d92..dbbcb16b19 100644 --- a/stepmania.nsi +++ b/stepmania.nsi @@ -546,6 +546,9 @@ Section "Main Section" SecMain CreateDirectory "$INSTDIR\Docs" SetOutPath "$INSTDIR\Docs" File "LICENCE" + File "Docs\legacy\Licenses.txt" + File "Docs\legacy\credits.txt" + File /r /x CVS /x .svn "Docs\legacy\license-ext" ; Create Start Menu icons SetShellVarContext current # 'all' doesn't work on Win9x From c512d3a8c5a16394e2009b964a86f7d1a9149edc Mon Sep 17 00:00:00 2001 From: Nicolas Date: Tue, 27 Nov 2018 00:20:41 -0300 Subject: [PATCH 081/320] Fix type of updateFInterval --- src/ActorFrame.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ActorFrame.h b/src/ActorFrame.h index b7c0010abf..e22cfb99b4 100644 --- a/src/ActorFrame.h +++ b/src/ActorFrame.h @@ -154,8 +154,8 @@ class ActorFrame : public Actor LuaReference m_UpdateFunction; LuaReference m_DrawFunction; - int m_fUpdateFInterval{ 0 }; - float secsSinceLuaUpdateFWasRun{ 0.016f }; + float m_fUpdateFInterval{ 0.016f }; + float secsSinceLuaUpdateFWasRun{ 0.0f }; // state effects float m_fUpdateRate; float m_fFOV; // -1 = no change From d5d51a087267295f6e7d4756d608fcc446ec41b4 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 20:50:20 -0500 Subject: [PATCH 082/320] get online replay viewing for 0.6 replays sort of working (not crashing) it should be relatively easy to get pre 0.6 replays working once this is finished since online highscores send timestamps instead of noterows we match nerv noterows with replay data offsets before feeding everything into setupscore since online replay highscores aren't actually in the profile, they aren't contained within scoreman, this adds a hacky way to temporarily store and retrieve online highscores that we don't want written to the profile, this involve dumb bool setting in stagestats, screenselect, and nothing actually clears the temp replay highscore, it just gets overwritten im 99% sure the changes in the evalscreen and the scoreman gettempreplayscore function are no longer needed and can be purged but i dont want to test that and we may need them if we change how things work there is a less than faithful conversion with online score playbacks, the change in player.cpp is because we're getting occasional nonsensical tns enums (-123123), and this results in replays failing out which is what the gameplay check is for --- .../ScreenEvaluation decorations/default.lua | 9 +- .../ScreenNetEvaluation decorations.lua | 9 +- .../BGAnimations/superscoreboard.lua | 1 - src/DownloadManager.cpp | 28 +++--- src/HighScore.cpp | 11 +++ src/HighScore.h | 2 + src/Player.cpp | 12 ++- src/PlayerAI.cpp | 2 +- src/ScoreManager.cpp | 3 +- src/ScoreManager.h | 10 +- src/ScreenGameplay.cpp | 8 +- src/ScreenSelectMusic.cpp | 93 ++++++++++++------- src/StageStats.cpp | 12 ++- 13 files changed, 140 insertions(+), 60 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/default.lua index 51d57cfa78..dd80212435 100644 --- a/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/default.lua @@ -119,6 +119,9 @@ function scoreBoard(pn, position) local judge = enabledCustomWindows and 0 or GetTimingDifficulty() local pss = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn) local score = SCOREMAN:GetMostRecentScore() + if not score then + score = SCOREMAN:GetTempReplayScore() + end local dvt = pss:GetOffsetVector() local totalTaps = pss:GetTotalTaps() @@ -543,6 +546,10 @@ end t[#t + 1] = LoadActor("../offsetplot") +local score = SCOREMAN:GetMostRecentScore() +if not score then + score = SCOREMAN:GetTempReplayScore() +end -- Discord thingies local largeImageTooltip = GetPlayerOrMachineProfile(PLAYER_1):GetDisplayName() .. @@ -557,7 +564,7 @@ local state = string.format("%05.2f", GAMESTATE:GetCurrentSteps(PLAYER_1):GetMSD(getCurRateValue(), 1)) .. " - " .. string.format("%05.2f%%", notShit.floor(pssP1:GetWifeScore() * 10000) / 100) .. - " " .. THEME:GetString("Grade", ToEnumShortString(SCOREMAN:GetMostRecentScore():GetWifeGrade())) + " " .. THEME:GetString("Grade", ToEnumShortString(score:GetWifeGrade())) GAMESTATE:UpdateDiscordPresence(largeImageTooltip, detail, state, 0) return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua index 61763d5497..c7776889ca 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua @@ -110,6 +110,9 @@ function scoreBoard(pn, position) local judge = enabledCustomWindows and 0 or GetTimingDifficulty() local pss = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn) local score = SCOREMAN:GetMostRecentScore() + if not score then + score = SCOREMAN:GetTempReplayScore() + end local dvt = pss:GetOffsetVector() local totalTaps = pss:GetTotalTaps() local smallest, largest @@ -530,6 +533,10 @@ end t[#t + 1] = LoadActor("offsetplot") +local score = SCOREMAN:GetMostRecentScore() +if not score then + score = SCOREMAN:GetTempReplayScore() +end -- Discord thingies local largeImageTooltip = GetPlayerOrMachineProfile(PLAYER_1):GetDisplayName() .. @@ -544,7 +551,7 @@ local state = string.format("%05.2f", GAMESTATE:GetCurrentSteps(PLAYER_1):GetMSD(getCurRateValue(), 1)) .. " - " .. string.format("%05.2f%%", notShit.floor(pssP1:GetWifeScore() * 10000) / 100) .. - " " .. THEME:GetString("Grade", ToEnumShortString(SCOREMAN:GetMostRecentScore():GetWifeGrade())) + " " .. THEME:GetString("Grade", ToEnumShortString(score:GetWifeGrade())) GAMESTATE:UpdateDiscordPresence(largeImageTooltip, detail, state, 0) return t diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index c8e6d7908f..9c44191caa 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -352,7 +352,6 @@ local function makeScoreDisplay(i) DLMAN:RequestOnlineScoreReplayData( hs, function() - SCREENMAN:SystemMessage("wabadub") SCREENMAN:GetTopScreen():PlayReplay(hs) end ) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 7e6e656083..6e7453516d 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1398,18 +1398,25 @@ DownloadManager::RequestReplayData(string scoreid, HTTPRequest& req, CURLMsg*) { try { vector> replayData; + + vector timestamps; + vector offsets; + vector tracks; + vector types; + auto j = json::parse(req.result); if (j.find("errors") != j.end()) throw exception(); auto replay = j.find("data")->find("attributes")->find("replay"); if (!replay->is_null() && replay->size() > 1) - for (auto note : *replay) { - float timestamp = note[0]; - int offset = note[1]; // *1000.0f - int column = note[2]; - int type = note[3]; + for (auto& note : *replay) { replayData.emplace_back( make_pair(note[0].get(), note[1].get())); + + timestamps.emplace_back(note[0].get()); + offsets.emplace_back(note[1].get() / 1000.f); + tracks.emplace_back(note[2].get()); + types.emplace_back(static_cast(note[3].get())); } auto& lbd = DLMAN->chartLeaderboards[chartkey]; auto it = @@ -1417,19 +1424,16 @@ DownloadManager::RequestReplayData(string scoreid, return a.userid == userid && a.username == username; }); if (it != lbd.end()) { - vector offsets; - std::transform( - replayData.begin(), - replayData.end(), - back_inserter(offsets), - [](pair& pair) { return pair.first; }); + it->hs.SetOnlineReplayTimestampVector(timestamps); it->hs.SetOffsetVector(offsets); + it->hs.SetTrackVector(tracks); + it->hs.SetTapNoteTypeVector(types); } auto L = LUA->Get(); callback.PushSelf(L); RString Error = "Error running RequestChartLeaderBoard Finish Function: "; - lua_newtable(L); + lua_newtable(L); // dunno whats going on here -mina for (unsigned i = 0; i < replayData.size(); ++i) { auto& pair = replayData[i]; lua_newtable(L); diff --git a/src/HighScore.cpp b/src/HighScore.cpp index 226609e549..e3ef15436c 100644 --- a/src/HighScore.cpp +++ b/src/HighScore.cpp @@ -52,6 +52,7 @@ struct HighScoreImpl vector vTrackVector; vector vTapNoteTypeVector; vector vHoldReplayDataVector; + vector vOnlineReplayTimestampVector; vector vRescoreJudgeVector; unsigned int iMaxCombo; // maximum combo obtained [SM5 alpha 1a+] StageAward stageAward; // stage award [SM5 alpha 1a+] @@ -1104,6 +1105,11 @@ HighScore::GetCopyOfHoldReplayDataVector() const { return m_Impl->vHoldReplayDataVector; } +vector +HighScore::GetCopyOfSetOnlineReplayTimestampVector() const +{ + return m_Impl->vOnlineReplayTimestampVector; +} const vector& HighScore::GetOffsetVector() const { @@ -1333,6 +1339,11 @@ HighScore::SetHoldReplayDataVector(const vector& v) m_Impl->vHoldReplayDataVector = v; } void +HighScore::SetOnlineReplayTimestampVector(const vector& v) +{ + m_Impl->vOnlineReplayTimestampVector = v; +} +void HighScore::SetScoreKey(const string& sk) { m_Impl->ScoreKey = sk; diff --git a/src/HighScore.h b/src/HighScore.h index 20941b8a43..3e2b4d2933 100644 --- a/src/HighScore.h +++ b/src/HighScore.h @@ -62,6 +62,7 @@ struct HighScore vector GetCopyOfTrackVector() const; vector GetCopyOfTapNoteTypeVector() const; vector GetCopyOfHoldReplayDataVector() const; + vector GetCopyOfSetOnlineReplayTimestampVector() const; string GetScoreKey() const; int GetTopScore() const; int GetReplayType() const; @@ -115,6 +116,7 @@ struct HighScore void SetTrackVector(const vector& v); void SetTapNoteTypeVector(const vector& v); void SetHoldReplayDataVector(const vector& v); + void SetOnlineReplayTimestampVector(const vector& v); void SetScoreKey(const string& ck); void SetRescoreJudgeVector(const vector& v); void SetAliveSeconds(float f); diff --git a/src/Player.cpp b/src/Player.cpp index 66f1ec1415..69834490e9 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1,4 +1,4 @@ -#include "global.h" +#include "global.h" #include "ActorUtil.h" #include "AdjustSync.h" #include "ArrowEffects.h" @@ -2399,7 +2399,7 @@ Player::Step(int col, iRowOfOverlappingNoteOrRow = row; } fNoteOffset = PlayerAI::GetTapNoteOffsetForReplay( - pTN, iRowOfOverlappingNoteOrRow, col); + pTN, iRowOfOverlappingNoteOrRow, col); if (fNoteOffset == -2.f) // we hit a mine { score = TNS_HitMine; @@ -2829,9 +2829,11 @@ Player::CrossedRows(int iLastRowCrossed, this->m_Timing->IsJudgableAtRow(iRow)) { if ((m_pPlayerState->m_PlayerController == PC_REPLAY && PlayerAI::GetReplayType() != 2) || - m_pPlayerState->m_PlayerController == PC_AUTOPLAY || m_pPlayerState->m_PlayerController == PC_CPU) { + m_pPlayerState->m_PlayerController == PC_AUTOPLAY || + m_pPlayerState->m_PlayerController == PC_CPU) { Step(iTrack, iRow, now, false, false); - if (m_pPlayerState->m_PlayerController == PC_AUTOPLAY || m_pPlayerState->m_PlayerController == PC_CPU) { + if (m_pPlayerState->m_PlayerController == PC_AUTOPLAY || + m_pPlayerState->m_PlayerController == PC_CPU) { if (m_pPlayerStageStats) m_pPlayerStageStats->m_bDisqualified = true; } @@ -3228,6 +3230,8 @@ Player::SetJudgment(int iRow, TapNoteScore tns, float fTapNoteOffset) { + if (tns < 0 || tns > NUM_TapNoteScore) + tns = TNS_Miss; // dont know why or how this crashes -mina if (tns == TNS_Miss) AddNoteToReplayData( GAMESTATE->CountNotesSeparately() ? iTrack : -1, &tn, iRow); diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index d5b22f33c0..f5933484c1 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -202,7 +202,7 @@ PlayerAI::SetScoreData(HighScore* pHighScore) // Generate vectors made of pregenerated HoldReplayResults referenced by the // song row in a map - for (int i = 0; i < (int)replayHoldVector.size(); i++) { + for (size_t i = 0; i < replayHoldVector.size(); i++) { // Create or append to the vector if (m_ReplayHoldMap.count(replayHoldVector[i].row) != 0) { m_ReplayHoldMap[replayHoldVector[i].row].push_back( diff --git a/src/ScoreManager.cpp b/src/ScoreManager.cpp index 211b7c0d37..f85c6db016 100644 --- a/src/ScoreManager.cpp +++ b/src/ScoreManager.cpp @@ -852,7 +852,7 @@ class LunaScoreManager : public Luna last->PushSelf(L); return 1; } - + DEFINE_METHOD(GetTempReplayScore, tempscoreforonlinereplayviewing); LunaScoreManager() { ADD_METHOD(GetScoresByKey); @@ -860,6 +860,7 @@ class LunaScoreManager : public Luna ADD_METHOD(ValidateAllScores); ADD_METHOD(GetTopSSRHighScore); ADD_METHOD(GetMostRecentScore); + ADD_METHOD(GetTempReplayScore); } }; diff --git a/src/ScoreManager.h b/src/ScoreManager.h index 762c339280..46b46f8aa3 100644 --- a/src/ScoreManager.h +++ b/src/ScoreManager.h @@ -173,7 +173,12 @@ class ScoreManager vector GetSortedKeys(); void PushSelf(lua_State* L); - HighScore* GetMostRecentScore() { return AllScores.back(); } + HighScore* GetMostRecentScore() + { + if (camefromreplay) + return tempscoreforonlinereplayviewing; + return AllScores.back(); + } void PutScoreAtTheTop(string scorekey) { auto score = ScoresByKey[scorekey]; @@ -205,6 +210,9 @@ class ScoreManager void PurgeProfileScores( const string& profileID = PROFILEMAN->GetProfile(PLAYER_1)->m_sProfileID); + bool camefromreplay = false; + HighScore* tempscoreforonlinereplayviewing; + private: unordered_map> pscores; // Profile scores diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 699f799be9..f66496fdf4 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1562,9 +1562,11 @@ ScreenGameplay::Update(float fDeltaTime) } if (bAllFailed) { - m_pSoundMusic->StopPlaying(); - SCREENMAN->PostMessageToTopScreen(SM_NotesEnded, 0); - m_LyricDisplay.Stop(); + if (!GamePreferences::m_AutoPlay == PC_REPLAY) { + m_pSoundMusic->StopPlaying(); + SCREENMAN->PostMessageToTopScreen(SM_NotesEnded, 0); + m_LyricDisplay.Stop(); + } } // Update living players' alive time diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 6c78dcfc15..a7e5db64d3 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -42,7 +42,7 @@ #include "PlayerAI.h" #include "PlayerOptions.h" #include "NoteData.h" -#include "Player.h" +#include "Player.h" #include "NoteDataUtil.h" static const char* SelectionStateNames[] = { "SelectingSong", @@ -1096,7 +1096,7 @@ ScreenSelectMusic::SelectCurrent(PlayerNumber pn) // a song was selected if (m_MusicWheel.GetSelectedSong() != nullptr) { if (SAMPLE_MUSIC_PREVIEW_MODE == - SampleMusicPreviewMode_StartToPreview) { + SampleMusicPreviewMode_StartToPreview) { // start playing the preview music. g_bSampleMusicWaiting = true; CheckBackgroundRequests(true); @@ -1698,6 +1698,32 @@ class LunaScreenSelectMusic : public Luna { // get the highscore from lua and make the AI load it HighScore* hs = Luna::check(L, 1); + + // we get timestamps not noterows when getting online replays from the + // site, since order is deterministic we'll just auto set the noterows + // from the existing, if the score was cc off then we need to fill in + // extra rows for each tap in the chord -mina + auto timestamps = hs->GetCopyOfSetOnlineReplayTimestampVector(); + + if (!timestamps.empty()) { + GAMESTATE->SetProcessedTimingData( + GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData()); + + vector ihatemylife; + auto nd = GAMESTATE->m_pCurSteps[PLAYER_1]->GetNoteData(); + auto nerv = nd.BuildAndGetNerv(); + if (!hs->GetChordCohesion()) { + for (auto r : nerv) + for (int i = 0; i < nd.GetNumTapNotesInRow(r); ++i) + ihatemylife.emplace_back(r); + } else { + for (auto r : nerv) + ihatemylife.emplace_back(r); + } + GAMESTATE->SetProcessedTimingData(nullptr); + hs->SetNoteRowVector(ihatemylife); + } + PlayerAI::SetScoreData(hs); // prepare old mods to return to @@ -1781,37 +1807,38 @@ class LunaScreenSelectMusic : public Luna // construct the current stage stats and stuff to the best of our // ability - StageStats ss; - RadarValues rv; - NoteData nd; - Steps* steps = GAMESTATE->m_pCurSteps[PLAYER_1]; - steps->GetNoteData(nd); - float songlength = GAMESTATE->m_pCurSong->m_fMusicLengthSeconds; - ss.Init(); - auto score = SCOREMAN->GetMostRecentScore(); - score->LoadReplayData(); - PlayerAI::SetScoreData(score); - - auto& pss = ss.m_player[0]; - pss.m_HighScore = *score; - pss.CurWifeScore = score->GetWifeScore(); - pss.m_fWifeScore = score->GetWifeScore(); - pss.m_vNoteRowVector = score->GetNoteRowVector(); - pss.m_vOffsetVector = score->GetOffsetVector(); - pss.m_vTapNoteTypeVector = score->GetTapNoteTypeVector(); - pss.m_vTrackVector = score->GetTrackVector(); - // score->UnloadReplayData(); - pss.m_iSongsPassed = 1; - pss.m_iSongsPlayed = 1; - GAMESTATE->SetProcessedTimingData( - GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData()); - NoteDataUtil::CalculateRadarValues(nd, songlength, rv); - pss.m_radarPossible += rv; - RadarValues realRV; - PlayerAI::CalculateRadarValuesForReplay(realRV, rv); - score->SetRadarValues(realRV); - pss.m_radarActual += realRV; - GAMESTATE->SetProcessedTimingData(NULL); + StageStats ss; + RadarValues rv; + NoteData nd; + Steps* steps = GAMESTATE->m_pCurSteps[PLAYER_1]; + steps->GetNoteData(nd); + float songlength = GAMESTATE->m_pCurSong->m_fMusicLengthSeconds; + ss.Init(); + SCOREMAN->camefromreplay = false; // disallow viewing online score eval screens -mina + auto score = SCOREMAN->GetMostRecentScore(); + score->LoadReplayData(); + PlayerAI::SetScoreData(score); + + auto& pss = ss.m_player[0]; + pss.m_HighScore = *score; + pss.CurWifeScore = score->GetWifeScore(); + pss.m_fWifeScore = score->GetWifeScore(); + pss.m_vNoteRowVector = score->GetNoteRowVector(); + pss.m_vOffsetVector = score->GetOffsetVector(); + pss.m_vTapNoteTypeVector = score->GetTapNoteTypeVector(); + pss.m_vTrackVector = score->GetTrackVector(); + // score->UnloadReplayData(); + pss.m_iSongsPassed = 1; + pss.m_iSongsPlayed = 1; + GAMESTATE->SetProcessedTimingData( + GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData()); + NoteDataUtil::CalculateRadarValues(nd, songlength, rv); + pss.m_radarPossible += rv; + RadarValues realRV; + PlayerAI::CalculateRadarValuesForReplay(realRV, rv); + score->SetRadarValues(realRV); + pss.m_radarActual += realRV; + GAMESTATE->SetProcessedTimingData(nullptr); pss.everusedautoplay = true; for (int i = TNS_Miss; i < NUM_TapNoteScore; i++) { pss.m_iTapNoteScores[i] = score->GetTapNoteScore((TapNoteScore)i); diff --git a/src/StageStats.cpp b/src/StageStats.cpp index b688cbbc9e..70a6d46560 100644 --- a/src/StageStats.cpp +++ b/src/StageStats.cpp @@ -607,6 +607,7 @@ FillInHighScore(const PlayerStageStats& pss, void StageStats::FinalizeScores(bool bSummary) { + SCOREMAN->camefromreplay = false; // if we're viewing an online replay this gets set to true -mina if (PREFSMAN->m_sTestInitialScreen.Get() != "") { FOREACH_PlayerNumber(pn) { @@ -653,8 +654,15 @@ StageStats::FinalizeScores(bool bSummary) Profile* zzz = PROFILEMAN->GetProfile(PLAYER_1); if (GamePreferences::m_AutoPlay != PC_HUMAN) { if (PlayerAI::pScoreData) { - mostrecentscorekey = PlayerAI::pScoreData->GetScoreKey(); - SCOREMAN->PutScoreAtTheTop(mostrecentscorekey); + if (!PlayerAI::pScoreData->GetCopyOfSetOnlineReplayTimestampVector() + .empty()) { + SCOREMAN->tempscoreforonlinereplayviewing = + PlayerAI::pScoreData; + SCOREMAN->camefromreplay = true; + } else { // dont do this if the replay was from online or bad stuff happens -mina + mostrecentscorekey = PlayerAI::pScoreData->GetScoreKey(); + SCOREMAN->PutScoreAtTheTop(mostrecentscorekey); + } } zzz->m_lastSong.FromSong(GAMESTATE->m_pCurSong); return; From bd692cc1788ff35d048878d7369884b1b112dc39 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Mon, 26 Nov 2018 22:53:50 -0500 Subject: [PATCH 083/320] fill in radar values for replay highscores --- src/StageStats.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/StageStats.cpp b/src/StageStats.cpp index 70a6d46560..71724d0fef 100644 --- a/src/StageStats.cpp +++ b/src/StageStats.cpp @@ -658,10 +658,14 @@ StageStats::FinalizeScores(bool bSummary) .empty()) { SCOREMAN->tempscoreforonlinereplayviewing = PlayerAI::pScoreData; + SCOREMAN->tempscoreforonlinereplayviewing->SetRadarValues( + hs.GetRadarValues()); SCOREMAN->camefromreplay = true; } else { // dont do this if the replay was from online or bad stuff happens -mina mostrecentscorekey = PlayerAI::pScoreData->GetScoreKey(); SCOREMAN->PutScoreAtTheTop(mostrecentscorekey); + SCOREMAN->GetMostRecentScore()->SetRadarValues( + hs.GetRadarValues()); } } zzz->m_lastSong.FromSong(GAMESTATE->m_pCurSong); From 005753bae8dca433a6b05566971658c4926adc8d Mon Sep 17 00:00:00 2001 From: Nicolas Date: Tue, 27 Nov 2018 01:38:43 -0300 Subject: [PATCH 084/320] Experimental getGlyphRect(idx) in preparation for chat hyperlinks --- src/BitmapText.cpp | 18 ++++++++++++++++++ src/BitmapText.h | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/BitmapText.cpp b/src/BitmapText.cpp index 15d0e369cf..fa78d2c777 100644 --- a/src/BitmapText.cpp +++ b/src/BitmapText.cpp @@ -1435,6 +1435,23 @@ ColorBitmapText::SetMaxLines(int iNumLines, int iDirection) class LunaBitmapText : public Luna { public: + static int getGlyphRect(T* p, lua_State* L) + { + int idx = (IArg(1) - 1) * 4; // lua idx start at 1 and 4 verts per glyph + if (idx < 0 || idx >= p->m_aVertices.size()) { + lua_pushnil(L); + return 1; + } + for (int i = 0; i < 4; i++) { + lua_newtable(L); + auto& v = p->m_aVertices[idx + i].p; + lua_pushnumber(L, v.x); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, v.y); + lua_rawseti(L, -2, 2); + } + return 4; + } static int wrapwidthpixels(T* p, lua_State* L) { p->SetWrapWidthPixels(IArg(1)); @@ -1541,6 +1558,7 @@ class LunaBitmapText : public Luna LunaBitmapText() { + ADD_METHOD(getGlyphRect); ADD_METHOD(wrapwidthpixels); ADD_METHOD(maxwidth); ADD_METHOD(maxheight); diff --git a/src/BitmapText.h b/src/BitmapText.h index a003c88149..c53d01691d 100644 --- a/src/BitmapText.h +++ b/src/BitmapText.h @@ -146,6 +146,8 @@ class BitmapText : public Actor // Commands void PushSelf(lua_State* L) override; + vector m_aVertices; + protected: Font* m_pFont; bool m_bUppercase; @@ -163,8 +165,6 @@ class BitmapText : public Actor float m_fDistortion; int m_iVertSpacing; - vector m_aVertices; - vector m_vpFontPageTextures; map m_mAttributes; bool m_bHasGlowAttribute; From 13581f79df2220776f2033c14b36da2fd896fc7f Mon Sep 17 00:00:00 2001 From: Nicolas Date: Tue, 27 Nov 2018 01:42:19 -0300 Subject: [PATCH 085/320] clang format --- src/ActorMultiVertex.cpp | 20 +- src/AnnouncerManager.cpp | 4 +- src/CreateZip.cpp | 14 +- src/CubicSpline.cpp | 50 +++-- src/DBProfile.cpp | 29 ++- src/DifficultyList.cpp | 6 +- src/DownloadManager.cpp | 5 +- src/EnumHelper.h | 159 ++++++++-------- src/FilterManager.cpp | 3 +- src/Foreach.h | 105 ++++++----- src/GameLoop.cpp | 2 +- src/GameSoundManager.cpp | 4 +- src/GameState.cpp | 4 +- src/GameState.h | 4 +- src/GameplayAssist.cpp | 9 +- src/Grade.h | 4 +- src/InputMapper.cpp | 43 ++--- src/LuaBinding.h | 175 ++++++++---------- src/Model.cpp | 7 +- src/MusicWheel.cpp | 3 +- src/NoteData.cpp | 4 +- src/NoteDisplay.cpp | 3 +- src/NoteField.cpp | 8 +- src/NoteSkinManager.cpp | 2 +- src/NoteTypes.h | 6 +- src/NotesLoaderBMS.cpp | 8 +- src/NotesLoaderDWI.cpp | 3 +- src/NotesLoaderJson.cpp | 18 +- src/Player.cpp | 2 +- src/PlayerAI.cpp | 83 ++++----- src/PlayerAI.h | 21 ++- src/PlayerOptions.cpp | 3 +- src/PlayerStageStats.cpp | 3 +- src/PrefsManager.cpp | 3 +- src/PrefsManager.h | 3 +- src/Profile.cpp | 9 +- src/ProfileManager.h | 5 +- src/RageDisplay_GLES2.cpp | 4 +- src/RageDisplay_GLES2.h | 4 +- src/RageDisplay_OGL.cpp | 30 +-- src/RageDisplay_OGL.h | 7 +- src/RageSound.cpp | 9 +- src/RageSoundPosMap.cpp | 22 +-- src/RageSoundReader_MP3.cpp | 3 +- src/RageSoundReader_WAV.cpp | 7 +- src/RageSurfaceUtils_Palettize.cpp | 30 +-- src/RageSurface_Load_BMP.cpp | 7 +- src/RageTexture.cpp | 5 +- src/RageThreads.cpp | 32 ++-- src/ScoreKeeper.h | 2 +- src/ScoreKeeperNormal.cpp | 20 +- src/ScoreManager.h | 5 +- src/ScreenEvaluation.cpp | 43 ++--- src/ScreenGameplay.cpp | 171 ++++++++--------- src/ScreenInstallOverlay.cpp | 4 +- src/ScreenManager.cpp | 7 +- src/ScreenMapControllers.cpp | 4 +- src/ScreenOptions.cpp | 3 +- src/ScreenOptionsMasterPrefs.cpp | 3 +- src/ScreenProfileSave.cpp | 3 +- src/ScreenSelectMaster.cpp | 17 +- src/ScreenSelectMusic.cpp | 3 +- src/ScreenSelectMusic.h | 6 +- src/Song.cpp | 3 +- src/Song.h | 3 +- src/SongCacheIndex.cpp | 37 ++-- src/Sprite.cpp | 15 +- src/StageStats.cpp | 10 +- src/StdString.h | 6 +- src/StepMania.cpp | 37 ++-- src/Steps.cpp | 33 +++- src/ThemeManager.cpp | 7 +- src/XMLProfile.cpp | 4 +- src/arch/ArchHooks/ArchHooks_Win32.cpp | 4 +- .../InputHandler/InputHandler_DirectInput.cpp | 11 +- .../InputHandler_DirectInputHelper.cpp | 4 +- .../LowLevelWindow/LowLevelWindow_Win32.cpp | 2 +- .../LowLevelWindow/LowLevelWindow_X11.cpp | 2 +- src/arch/MovieTexture/MovieTexture.cpp | 4 +- src/arch/MovieTexture/MovieTexture_FFMpeg.cpp | 4 +- src/arch/Sound/RageSoundDriver.cpp | 2 +- .../RageSoundDriver_Generic_Software.cpp | 11 +- src/arch/Sound/RageSoundDriver_OSS.cpp | 30 +-- src/arch/Sound/RageSoundDriver_WaveOut.cpp | 2 +- src/archutils/Unix/BacktraceNames.cpp | 50 ++--- src/archutils/Win32/Crash.cpp | 2 +- src/archutils/Win32/DebugInfoHunt.cpp | 36 ++-- src/archutils/Win32/GraphicsWindow.cpp | 3 +- src/archutils/Win32/ddk/dbghelp.h | 24 ++- src/archutils/Win32/ddk/hidpi.h | 6 +- src/archutils/Win32/ddk/setupapi.h | 3 +- src/libtomcrypt/src/headers/tomcrypt_hash.h | 12 +- src/libtomcrypt/src/headers/tomcrypt_macros.h | 40 ++-- 93 files changed, 866 insertions(+), 826 deletions(-) diff --git a/src/ActorMultiVertex.cpp b/src/ActorMultiVertex.cpp index 65b1795b95..8afa2cbb2c 100644 --- a/src/ActorMultiVertex.cpp +++ b/src/ActorMultiVertex.cpp @@ -223,14 +223,14 @@ ActorMultiVertex::DrawPrimitives() m_pTempState->diffuse[0].a > 0) { for (size_t i = 0; i < TS.vertices.size(); i++) { - // RageVColor uses a uint8_t for each channel. 0-255. - // RageColor uses a float. 0-1. - // So each channel of the RageVColor needs to be converted to a float, - // multiplied by the channel from the RageColor, then the result - // converted to uint8_t. If implicit conversion is allowed to happen, - // sometimes the compiler decides to turn the RageColor into a uint8_t, - // which makes any value other than 1 into 0. Thus, the explicit - // conversions. -Kyz + // RageVColor uses a uint8_t for each channel. 0-255. + // RageColor uses a float. 0-1. + // So each channel of the RageVColor needs to be converted to a + // float, multiplied by the channel from the RageColor, then the + // result converted to uint8_t. If implicit conversion is allowed + // to happen, sometimes the compiler decides to turn the RageColor + // into a uint8_t, which makes any value other than 1 into 0. Thus, + // the explicit conversions. -Kyz #define MULT_COLOR_ELEMENTS(color_a, color_b) \ color_a = static_cast(static_cast(color_a) * (color_b)); // RageVColor * RageColor @@ -967,8 +967,8 @@ class LunaActorMultiVertex : public Luna if (tex == nullptr) { luaL_error(L, "The texture must be set before adding states."); } - // State looks like this: - // {{left, top, right, bottom}, delay} + // State looks like this: + // {{left, top, right, bottom}, delay} #define DATA_ERROR(i) \ if (!lua_istable(L, i)) { \ luaL_error(L, \ diff --git a/src/AnnouncerManager.cpp b/src/AnnouncerManager.cpp index 4bb8a0976d..ab5af5189a 100644 --- a/src/AnnouncerManager.cpp +++ b/src/AnnouncerManager.cpp @@ -138,8 +138,8 @@ AnnouncerManager::GetPathTo(const RString& sAnnouncerName, return AnnouncerPath + aliases[i][1] + "/"; } - /* No announcer directory matched. In debug, create the directory by - * its preferred name. */ + /* No announcer directory matched. In debug, create the directory by + * its preferred name. */ #ifdef DEBUG LOG->Trace("The announcer in '%s' is missing the folder '%s'.", AnnouncerPath.c_str(), diff --git a/src/CreateZip.cpp b/src/CreateZip.cpp index 2e53d2f6d6..8961708967 100644 --- a/src/CreateZip.cpp +++ b/src/CreateZip.cpp @@ -360,25 +360,23 @@ using IPos = unsigned int; // A Pos is an index in the character window. Pos is // Output a 16 bit value to the bit stream, lower (oldest) byte first #define PUTSHORT(state, w) \ - \ -{ \ + \ + { \ if ((state).bs.out_offset >= (state).bs.out_size - 1) \ (state).flush_outbuf( \ (state).param, (state).bs.out_buf, &(state).bs.out_offset); \ (state).bs.out_buf[(state).bs.out_offset++] = (char)((w)&0xff); \ (state).bs.out_buf[(state).bs.out_offset++] = (char)((ush)(w) >> 8); \ - \ -} + } #define PUTBYTE(state, b) \ - \ -{ \ + \ + { \ if ((state).bs.out_offset >= (state).bs.out_size) \ (state).flush_outbuf( \ (state).param, (state).bs.out_buf, &(state).bs.out_offset); \ (state).bs.out_buf[(state).bs.out_offset++] = (char)(b); \ - \ -} + } using lutime_t = int; // define it ourselves since we don't include time.h diff --git a/src/CubicSpline.cpp b/src/CubicSpline.cpp index e2fb0dccaa..5e1f5f5dce 100644 --- a/src/CubicSpline.cpp +++ b/src/CubicSpline.cpp @@ -456,11 +456,11 @@ CubicSpline::p_and_tfrac_from_t(float t, return 0.0f; \ } #define DECLARE_P_AND_TFRAC \ - \ -size_t p = 0; \ + \ + size_t p = 0; \ float tfrac = 0.0f; \ - \ -p_and_tfrac_from_t(t, loop, p, tfrac); + \ + p_and_tfrac_from_t(t, loop, p, tfrac); float CubicSpline::evaluate(float t, bool loop) const @@ -678,17 +678,16 @@ CubicSplineN::solve() } #define CSN_EVAL_SOMETHING(something) \ - \ -void CubicSplineN::something(float t, vector& v) const \ - \ -{ \ + \ + void CubicSplineN::something(float t, vector& v) const \ + \ + { \ for (spline_cont_t::const_iterator spline = m_splines.begin(); \ spline != m_splines.end(); \ ++spline) { \ v.push_back(spline->something(t, m_loop)); \ } \ - \ -} + } CSN_EVAL_SOMETHING(evaluate); CSN_EVAL_SOMETHING(evaluate_derivative); @@ -698,16 +697,15 @@ CSN_EVAL_SOMETHING(evaluate_third_derivative); #undef CSN_EVAL_SOMETHING #define CSN_EVAL_RV_SOMETHING(something) \ - \ -void CubicSplineN::something(float t, RageVector3& v) const \ - \ -{ \ + \ + void CubicSplineN::something(float t, RageVector3& v) const \ + \ + { \ ASSERT(m_splines.size() == 3); \ v.x = m_splines[0].something(t, m_loop); \ v.y = m_splines[1].something(t, m_loop); \ v.z = m_splines[2].something(t, m_loop); \ - \ -} + } CSN_EVAL_RV_SOMETHING(evaluate); CSN_EVAL_RV_SOMETHING(evaluate_derivative); @@ -818,21 +816,15 @@ CubicSplineN::dimension() const // m_dirty is set before the member so that the set_dirty that is created // can actually be used to set the dirty flag. -Kyz #define SET_GET_MEM(member, name) \ - \ -void CubicSplineN::set_##name(bool b) \ - \ -{ \ + \ + void CubicSplineN::set_##name(bool b) \ + \ + { \ m_dirty = true; \ (member) = b; \ - \ -} \ - \ -bool CubicSplineN::get_##name() const \ - \ -{ \ - return member; \ - \ -} + } \ + \ + bool CubicSplineN::get_##name() const { return member; } SET_GET_MEM(m_loop, loop); SET_GET_MEM(m_polygonal, polygonal); diff --git a/src/DBProfile.cpp b/src/DBProfile.cpp index 9941d3b7aa..bfebf7aeea 100644 --- a/src/DBProfile.cpp +++ b/src/DBProfile.cpp @@ -103,7 +103,7 @@ DBProfile::LoadGeneralData(SQLite::Database* db) loadingProfile->m_iTotalHands = gDataQuery.getColumn(21); loadingProfile->m_iTotalLifts = gDataQuery.getColumn(22); loadingProfile->m_fPlayerRating = - static_cast(static_cast(gDataQuery.getColumn(23))); + static_cast(static_cast(gDataQuery.getColumn(23))); SQLite::Statement modifierQuery(*db, "SELECT * FROM defaultmodifiers"); while (modifierQuery.executeStep()) { @@ -115,7 +115,8 @@ DBProfile::LoadGeneralData(SQLite::Database* db) SQLite::Statement skillsetsQuery(*db, "SELECT * FROM playerskillsets"); while (skillsetsQuery.executeStep()) { int skillsetNum = skillsetsQuery.getColumn(1); - float skillsetValue = static_cast(static_cast(skillsetsQuery.getColumn(2))); + float skillsetValue = + static_cast(static_cast(skillsetsQuery.getColumn(2))); loadingProfile->m_fPlayerSkillsets[skillsetNum] = skillsetValue; } @@ -327,15 +328,19 @@ DBProfile::LoadPlayerScores(SQLite::Database* db) HighScore& hs = scores[key].ScoresByRate[rate].scores[ScoreKey]; hs.SetSSRCalcVersion(query.getColumn(6)); hs.SetGrade(static_cast(static_cast(query.getColumn(7)))); - hs.SetWifeScore(static_cast(static_cast(query.getColumn(8)))); - hs.SetSSRNormPercent(static_cast(static_cast(query.getColumn(9)))); + hs.SetWifeScore( + static_cast(static_cast(query.getColumn(8)))); + hs.SetSSRNormPercent( + static_cast(static_cast(query.getColumn(9)))); hs.SetMusicRate(scores[key].KeyToRate(rate)); - hs.SetJudgeScale(static_cast(static_cast(query.getColumn(10)))); + hs.SetJudgeScale( + static_cast(static_cast(query.getColumn(10)))); hs.SetChordCohesion(static_cast(query.getColumn(11)) != 0); hs.SetEtternaValid(static_cast(query.getColumn(12)) != 0); hs.SetChartKey(key); hs.SetScoreKey(ScoreKey); - hs.SetSurviveSeconds(static_cast(static_cast(query.getColumn(13)))); + hs.SetSurviveSeconds( + static_cast(static_cast(query.getColumn(13)))); hs.SetMaxCombo(query.getColumn(14)); hs.SetModifiers(query.getColumn(15)); DateTime d; @@ -356,7 +361,8 @@ DBProfile::LoadPlayerScores(SQLite::Database* db) if (hs.GetWifeScore() > 0.f) { FOREACH_ENUM(Skillset, ss) hs.SetSkillsetSSR(ss, - static_cast(static_cast(query.getColumn(index++)))); + static_cast( + static_cast(query.getColumn(index++)))); } hs.SetValidationKey(ValidationKey_Brittle, static_cast(query.getColumn(index++))); @@ -426,7 +432,8 @@ DBProfile::LoadScoreGoals(SQLite::Database* db) ScoreGoal sg; sg.rate = static_cast(static_cast(query.getColumn(1))); sg.priority = query.getColumn(2); - sg.percent = static_cast(static_cast(query.getColumn(3))); + sg.percent = + static_cast(static_cast(query.getColumn(3))); sg.timeassigned.FromString( static_cast(query.getColumn(4))); sg.timeachieved.FromString( @@ -884,7 +891,8 @@ DBProfile::SavePlayerScores(SQLite::Database* db, insertScoresAtRate.bind(4, ratePair->second.PBptr->GetScoreKey()); insertScoresAtRate.exec(); - scoresAtRateID = (int)sqlite3_last_insert_rowid(db->getHandle()); + scoresAtRateID = + (int)sqlite3_last_insert_rowid(db->getHandle()); } FOREACHUM(string, HighScore, ratePair->second.scores, i) { @@ -999,7 +1007,8 @@ DBProfile::SavePlayerScores(SQLite::Database* db, insertOffset.exec(); } } - } catch (std::exception) { // No replay data for this score } + } catch (std::exception) { // No replay data for + // this score } hs->UnloadReplayData(); } } diff --git a/src/DifficultyList.cpp b/src/DifficultyList.cpp index 5d6dd05d83..b1186e127d 100644 --- a/src/DifficultyList.cpp +++ b/src/DifficultyList.cpp @@ -385,12 +385,14 @@ class LunaStepsDisplayList : public Luna p->SetFromGameState(); COMMON_RETURN_SELF; } - static int GetCurrentIndex(T* p, lua_State* L){ + static int GetCurrentIndex(T* p, lua_State* L) + { lua_pushnumber(L, p->GetCurrentRowIndex(PLAYER_1)); return 1; } - LunaStepsDisplayList() { + LunaStepsDisplayList() + { ADD_METHOD(setfromgamestate); ADD_METHOD(GetCurrentIndex); } diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 6e7453516d..9ba99f4447 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1416,7 +1416,8 @@ DownloadManager::RequestReplayData(string scoreid, timestamps.emplace_back(note[0].get()); offsets.emplace_back(note[1].get() / 1000.f); tracks.emplace_back(note[2].get()); - types.emplace_back(static_cast(note[3].get())); + types.emplace_back( + static_cast(note[3].get())); } auto& lbd = DLMAN->chartLeaderboards[chartkey]; auto it = @@ -1433,7 +1434,7 @@ DownloadManager::RequestReplayData(string scoreid, callback.PushSelf(L); RString Error = "Error running RequestChartLeaderBoard Finish Function: "; - lua_newtable(L); // dunno whats going on here -mina + lua_newtable(L); // dunno whats going on here -mina for (unsigned i = 0; i < replayData.size(); ++i) { auto& pair = replayData[i]; lua_newtable(L); diff --git a/src/EnumHelper.h b/src/EnumHelper.h index e06d5f4f84..3827b8c72b 100644 --- a/src/EnumHelper.h +++ b/src/EnumHelper.h @@ -81,35 +81,33 @@ EnumToString(int iVal, unique_ptr* pNameCache); // XToString helper #define XToString(X) \ - \ -const RString& X##ToString(X x); \ - \ -COMPILE_ASSERT(NUM_##X == ARRAYLEN(X##Names)); \ - \ -const RString& X##ToString(X x) \ - \ -{ \ + \ + const RString& X##ToString(X x); \ + \ + COMPILE_ASSERT(NUM_##X == ARRAYLEN(X##Names)); \ + \ + const RString& X##ToString(X x) \ + \ + { \ static unique_ptr as_##X##Name[NUM_##X + 2]; \ return EnumToString(x, NUM_##X, X##Names, as_##X##Name); \ - \ -} \ - \ -namespace StringConversion \ + } \ + \ + namespace StringConversion { \ + template<> \ + RString ToString(const X& value) \ { \ - template<> \ - RString ToString(const X& value) \ - { \ - return X##ToString(value); \ - } \ + return X##ToString(value); \ + } \ } #define XToLocalizedString(X) \ - \ -const RString& X##ToLocalizedString(X x); \ - \ -const RString& X##ToLocalizedString(X x) \ - \ -{ \ + \ + const RString& X##ToLocalizedString(X x); \ + \ + const RString& X##ToLocalizedString(X x) \ + \ + { \ static unique_ptr g_##X##Name[NUM_##X]; \ if (g_##X##Name[0].get() == NULL) { \ for (unsigned i = 0; i < NUM_##X; ++i) { \ @@ -119,45 +117,42 @@ const RString& X##ToLocalizedString(X x) \ } \ } \ return g_##X##Name[x]->GetValue(); \ - \ -} + } #define StringToX(X) \ - \ -X StringTo##X(const RString&); \ - \ -X StringTo##X(const RString& s) \ - \ -{ \ + \ + X StringTo##X(const RString&); \ + \ + X StringTo##X(const RString& s) \ + \ + { \ for (unsigned i = 0; i < ARRAYLEN(X##Names); ++i) \ if (!s.CompareNoCase(X##Names[i])) \ return (X)i; \ return X##_Invalid; \ - \ -} \ - \ -namespace StringConversion \ - \ -{ \ - template<> \ - bool FromString(const RString& sValue, X& out) \ - { \ - out = StringTo##X(sValue); \ - return out != X##_Invalid; \ - } \ - \ -} + } \ + \ + namespace StringConversion \ + \ + { \ + template<> \ + bool FromString(const RString& sValue, X& out) \ + { \ + out = StringTo##X(sValue); \ + return out != X##_Invalid; \ + } \ + } // currently unused #define LuaDeclareType(X) #define LuaXType(X) \ - \ -template struct EnumTraits; \ - \ -static void Lua##X(lua_State* L) \ - \ -{ \ + \ + template struct EnumTraits; \ + \ + static void Lua##X(lua_State* L) \ + \ + { \ lua_newtable(L); \ FOREACH_ENUM(X, i) \ { \ @@ -188,38 +183,36 @@ static void Lua##X(lua_State* L) \ EnumTraits::StringToEnum.PushSelf(L); \ Enum::SetMetatable( \ L, EnumTraits::EnumToString, EnumTraits::StringToEnum, #X); \ - \ -} \ - \ -REGISTER_WITH_LUA_FUNCTION(Lua##X); \ - \ -template<> \ - X EnumTraits::Invalid = X##_Invalid; \ - \ -template<> const char* EnumTraits::szName = #X; \ - \ -namespace LuaHelpers \ - \ -{ \ - template<> \ - bool FromStack(lua_State * L, X & Object, int iOffset) \ - { \ - Object = Enum::Check(L, iOffset, true); \ - return Object != EnumTraits::Invalid; \ - } \ - \ -} \ - \ -namespace LuaHelpers \ - \ -{ \ - template<> \ - void Push(lua_State * L, const X& Object) \ - { \ - Enum::Push(L, Object); \ - } \ - \ -} + } \ + \ + REGISTER_WITH_LUA_FUNCTION(Lua##X); \ + \ + template<> \ + X EnumTraits::Invalid = X##_Invalid; \ + \ + template<> \ + const char* EnumTraits::szName = #X; \ + \ + namespace LuaHelpers \ + \ + { \ + template<> \ + bool FromStack(lua_State * L, X& Object, int iOffset) \ + { \ + Object = Enum::Check(L, iOffset, true); \ + return Object != EnumTraits::Invalid; \ + } \ + } \ + \ + namespace LuaHelpers \ + \ + { \ + template<> \ + void Push(lua_State * L, const X& Object) \ + { \ + Enum::Push(L, Object); \ + } \ + } #endif diff --git a/src/FilterManager.cpp b/src/FilterManager.cpp index 419c467433..523c57f751 100644 --- a/src/FilterManager.cpp +++ b/src/FilterManager.cpp @@ -182,7 +182,8 @@ class LunaFilterManager : public Luna lua_pushnumber(L, p->watte[SArg(1)].second); return 1; } - static int savepos(T* p, lua_State* L) { + static int savepos(T* p, lua_State* L) + { p->watte[SArg(1)].first = IArg(2); p->watte[SArg(1)].second = IArg(3); return 0; diff --git a/src/Foreach.h b/src/Foreach.h index ef8ee764d4..a2fa3bcab5 100644 --- a/src/Foreach.h +++ b/src/Foreach.h @@ -3,98 +3,101 @@ /** @brief General foreach loop iterating over a vector. */ #define FOREACH(elemType, vect, var) \ - \ -for(vector::iterator var = (vect).begin(); (var) != (vect).end(); \ - ++(var)) + \ + for (vector::iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a vector, using a constant * iterator. */ #define FOREACH_CONST(elemType, vect, var) \ - \ -for(vector::const_iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (vector::const_iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a deque. */ #define FOREACHD(elemType, vect, var) \ - \ -for(deque::iterator var = (vect).begin(); (var) != (vect).end(); \ - ++(var)) + \ + for (deque::iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a deque, using a constant * iterator. */ #define FOREACHD_CONST(elemType, vect, var) \ - \ -for(deque::const_iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (deque::const_iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a set. */ #define FOREACHS(elemType, vect, var) \ - \ -for(set::iterator var = (vect).begin(); (var) != (vect).end(); \ - ++(var)) + \ + for (set::iterator var = (vect).begin(); (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a set, using a constant iterator. */ #define FOREACHS_CONST(elemType, vect, var) \ - \ -for(set::const_iterator var = (vect).begin(); (var) != (vect).end(); \ - ++(var)) + \ + for (set::const_iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a list. */ #define FOREACHL(elemType, vect, var) \ - \ -for(list::iterator var = (vect).begin(); (var) != (vect).end(); \ - ++(var)) + \ + for (list::iterator var = (vect).begin(); (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a list, using a constant * iterator. */ #define FOREACHL_CONST(elemType, vect, var) \ - \ -for(list::const_iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (list::const_iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a map. */ #define FOREACHM(keyType, valType, vect, var) \ - \ -for(map::iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (map::iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a map, using a constant iterator. */ #define FOREACHM_CONST(keyType, valType, vect, var) \ - \ -for(map::const_iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (map::const_iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a multimap. */ #define FOREACHMM(keyType, valType, vect, var) \ - \ -for(multimap::iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (multimap::iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over a multimap, using a constant * iterator. */ #define FOREACHMM_CONST(keyType, valType, vect, var) \ - \ -for(multimap::const_iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (multimap::const_iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over an unordered map. */ #define FOREACHUM(keyType, valType, vect, var) \ - \ -for(unordered_map::iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (unordered_map::iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) /** @brief General foreach loop iterating over an unordered map. blah blah const * blah*/ #define FOREACHUM_CONST(keyType, valType, vect, var) \ - \ -for(unordered_map::const_iterator var = (vect).begin(); \ - (var) != (vect).end(); \ - ++(var)) + \ + for (unordered_map::const_iterator var = (vect).begin(); \ + (var) != (vect).end(); \ + ++(var)) #endif diff --git a/src/GameLoop.cpp b/src/GameLoop.cpp index 6cb355a244..442a708299 100644 --- a/src/GameLoop.cpp +++ b/src/GameLoop.cpp @@ -96,7 +96,7 @@ ChangeAppPri() } #endif - // If this is a debug build, don't. It makes the VC debugger sluggish. + // If this is a debug build, don't. It makes the VC debugger sluggish. #if defined(WIN32) && defined(DEBUG) return false; #else diff --git a/src/GameSoundManager.cpp b/src/GameSoundManager.cpp index 975dc4a21b..43a3e58962 100644 --- a/src/GameSoundManager.cpp +++ b/src/GameSoundManager.cpp @@ -806,7 +806,9 @@ class LunaGameSoundManager : public Luna CLAMP(fVol, 0.0f, 1.0f); pRet->Set(fVol); SOUNDMAN->SetMixVolume(); - p->DimMusic(FArg(1), 0.01f); // lazy hack to update volume without changing songs - mina + p->DimMusic( + FArg(1), + 0.01f); // lazy hack to update volume without changing songs - mina return 0; } static int PlayOnce(T* p, lua_State* L) diff --git a/src/GameState.cpp b/src/GameState.cpp index a782f29034..773df7d2ef 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -145,8 +145,8 @@ GameState::GameState() m_Environment = new LuaTable; - m_bDopefish = false; - + m_bDopefish = false; + m_bIsChartPreviewActive = false; sExpandedSectionName = ""; diff --git a/src/GameState.h b/src/GameState.h index 11a1f83d85..bec7302242 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -364,8 +364,8 @@ class GameState BroadcastOnChange m_sEditLocalProfileID; Profile* GetEditLocalProfile(); - bool m_bDopefish; - + bool m_bDopefish; + bool m_bIsChartPreviewActive; // Discord Rich Presence diff --git a/src/GameplayAssist.cpp b/src/GameplayAssist.cpp index 9675d7269d..04ec98c112 100644 --- a/src/GameplayAssist.cpp +++ b/src/GameplayAssist.cpp @@ -42,7 +42,8 @@ GameplayAssist::PlayTicks(const NoteData& nd, const PlayerState* ps) // float fPositionSeconds = GAMESTATE->m_Position.m_fMusicSeconds; fPositionSeconds += SOUNDMAN->GetPlayLatency() + - static_cast(CommonMetrics::TICK_EARLY_SECONDS) + 0.250f; + static_cast(CommonMetrics::TICK_EARLY_SECONDS) + + 0.250f; const TimingData& timing = *GAMESTATE->m_pCurSteps[ps->m_PlayerNumber]->GetTimingData(); const float fSongBeat = @@ -72,7 +73,8 @@ GameplayAssist::PlayTicks(const NoteData& nd, const PlayerState* ps) RageSoundParams p; p.m_StartTime = position.m_LastBeatUpdate + - (fSecondsUntil - static_cast(CommonMetrics::TICK_EARLY_SECONDS)); + (fSecondsUntil - + static_cast(CommonMetrics::TICK_EARLY_SECONDS)); m_soundAssistClap.Play(false, &p); } } @@ -116,7 +118,8 @@ GameplayAssist::PlayTicks(const NoteData& nd, const PlayerState* ps) RageSoundParams p; p.m_StartTime = position.m_LastBeatUpdate + - (fSecondsUntil - static_cast(CommonMetrics::TICK_EARLY_SECONDS)); + (fSecondsUntil - + static_cast(CommonMetrics::TICK_EARLY_SECONDS)); if (bIsMeasure) m_soundAssistMetronomeMeasure.Play(false, &p); else diff --git a/src/Grade.h b/src/Grade.h index dc8a520f64..9c96e19bcb 100644 --- a/src/Grade.h +++ b/src/Grade.h @@ -92,8 +92,8 @@ Grade GetNextPossibleGrade(Grade g); /** @brief Loop through each possible Grade. */ #define FOREACH_PossibleGrade(g) \ - \ -for(Grade g = (Grade)(0); g != Grade_Invalid; g = GetNextPossibleGrade(g)) + \ + for (Grade g = (Grade)(0); g != Grade_Invalid; g = GetNextPossibleGrade(g)) #endif diff --git a/src/InputMapper.cpp b/src/InputMapper.cpp index 69935b8c27..113d2b105d 100644 --- a/src/InputMapper.cpp +++ b/src/InputMapper.cpp @@ -49,27 +49,28 @@ InputMapper::ClearAllMappings() UpdateTempDItoGI(); } -static const AutoMappings g_DefaultKeyMappings = AutoMappings( - "", - "", - "", - AutoMappingEntry(0, KEY_LEFT, GAME_BUTTON_MENULEFT, false), - AutoMappingEntry(0, KEY_RIGHT, GAME_BUTTON_MENURIGHT, false), - AutoMappingEntry(0, KEY_UP, GAME_BUTTON_MENUUP, false), - AutoMappingEntry(0, KEY_DOWN, GAME_BUTTON_MENUDOWN, false), - AutoMappingEntry(0, KEY_ENTER, GAME_BUTTON_START, false), - AutoMappingEntry(0, KEY_SLASH, GAME_BUTTON_SELECT, false), - AutoMappingEntry(0, KEY_ESC, GAME_BUTTON_BACK, false), - AutoMappingEntry(0, KEY_KP_C4, GAME_BUTTON_MENULEFT, true), - AutoMappingEntry(0, KEY_KP_C6, GAME_BUTTON_MENURIGHT, true), - AutoMappingEntry(0, KEY_KP_C8, GAME_BUTTON_MENUUP, true), - AutoMappingEntry(0, KEY_KP_C2, GAME_BUTTON_MENUDOWN, true), - AutoMappingEntry(0, KEY_KP_ENTER, GAME_BUTTON_START, true), - AutoMappingEntry(0, KEY_KP_C0, GAME_BUTTON_SELECT, true), - //AutoMappingEntry(0, KEY_HYPHEN, GAME_BUTTON_BACK, true), // laptop keyboards. // what? -poco - AutoMappingEntry(0, KEY_F1, GAME_BUTTON_COIN, false), - AutoMappingEntry(0, KEY_SCRLLOCK, GAME_BUTTON_OPERATOR, false), - AutoMappingEntry(0, KEY_ACCENT, GAME_BUTTON_RESTART, false)); +static const AutoMappings g_DefaultKeyMappings = + AutoMappings("", + "", + "", + AutoMappingEntry(0, KEY_LEFT, GAME_BUTTON_MENULEFT, false), + AutoMappingEntry(0, KEY_RIGHT, GAME_BUTTON_MENURIGHT, false), + AutoMappingEntry(0, KEY_UP, GAME_BUTTON_MENUUP, false), + AutoMappingEntry(0, KEY_DOWN, GAME_BUTTON_MENUDOWN, false), + AutoMappingEntry(0, KEY_ENTER, GAME_BUTTON_START, false), + AutoMappingEntry(0, KEY_SLASH, GAME_BUTTON_SELECT, false), + AutoMappingEntry(0, KEY_ESC, GAME_BUTTON_BACK, false), + AutoMappingEntry(0, KEY_KP_C4, GAME_BUTTON_MENULEFT, true), + AutoMappingEntry(0, KEY_KP_C6, GAME_BUTTON_MENURIGHT, true), + AutoMappingEntry(0, KEY_KP_C8, GAME_BUTTON_MENUUP, true), + AutoMappingEntry(0, KEY_KP_C2, GAME_BUTTON_MENUDOWN, true), + AutoMappingEntry(0, KEY_KP_ENTER, GAME_BUTTON_START, true), + AutoMappingEntry(0, KEY_KP_C0, GAME_BUTTON_SELECT, true), + // AutoMappingEntry(0, KEY_HYPHEN, GAME_BUTTON_BACK, true), // + // laptop keyboards. // what? -poco + AutoMappingEntry(0, KEY_F1, GAME_BUTTON_COIN, false), + AutoMappingEntry(0, KEY_SCRLLOCK, GAME_BUTTON_OPERATOR, false), + AutoMappingEntry(0, KEY_ACCENT, GAME_BUTTON_RESTART, false)); void InputMapper::AddDefaultMappingsForCurrentGameIfUnmapped() diff --git a/src/LuaBinding.h b/src/LuaBinding.h index cdfe0c4b37..bacb2ffb1e 100644 --- a/src/LuaBinding.h +++ b/src/LuaBinding.h @@ -209,149 +209,134 @@ class LuaClass : public LuaTable return 1; #define GET_SET_BOOL_METHOD(method_name, bool_name) \ - \ -static int get_##method_name(T* p, lua_State* L) \ - \ -{ \ + \ + static int get_##method_name(T* p, lua_State* L) \ + \ + { \ lua_pushboolean(L, p->bool_name); \ return 1; \ - \ -} \ - \ -static int set_##method_name(T* p, lua_State* L) \ - \ -{ \ + } \ + \ + static int set_##method_name(T* p, lua_State* L) \ + \ + { \ p->bool_name = lua_toboolean(L, 1) != 0; \ COMMON_RETURN_SELF; \ - \ -} + } #define GETTER_SETTER_BOOL_METHOD(bool_name) \ - \ -static int get_##bool_name(T* p, lua_State* L) \ - \ -{ \ + \ + static int get_##bool_name(T* p, lua_State* L) \ + \ + { \ lua_pushboolean(L, p->get_##bool_name()); \ return 1; \ - \ -} \ - \ -static int set_##bool_name(T* p, lua_State* L) \ - \ -{ \ + } \ + \ + static int set_##bool_name(T* p, lua_State* L) \ + \ + { \ p->set_##bool_name(lua_toboolean(L, 1) != 0); \ COMMON_RETURN_SELF; \ - \ -} + } #define GET_SET_FLOAT_METHOD(method_name, float_name) \ - \ -static int get_##method_name(T* p, lua_State* L) \ - \ -{ \ + \ + static int get_##method_name(T* p, lua_State* L) \ + \ + { \ lua_pushnumber(L, p->float_name); \ return 1; \ - \ -} \ - \ -static int set_##method_name(T* p, lua_State* L) \ - \ -{ \ + } \ + \ + static int set_##method_name(T* p, lua_State* L) \ + \ + { \ p->float_name = FArg(1); \ COMMON_RETURN_SELF; \ - \ -} + } #define GET_SET_INT_METHOD(method_name, int_name) \ - \ -static int get_##method_name(T* p, lua_State* L) \ - \ -{ \ + \ + static int get_##method_name(T* p, lua_State* L) \ + \ + { \ lua_pushinteger(L, p->int_name); \ return 1; \ - \ -} \ - \ -static int set_##method_name(T* p, lua_State* L) \ - \ -{ \ + } \ + \ + static int set_##method_name(T* p, lua_State* L) \ + \ + { \ p->int_name = IArg(1); \ COMMON_RETURN_SELF; \ - \ -} + } #define GETTER_SETTER_FLOAT_METHOD(float_name) \ - \ -static int get_##float_name(T* p, lua_State* L) \ - \ -{ \ + \ + static int get_##float_name(T* p, lua_State* L) \ + \ + { \ lua_pushnumber(L, p->get_##float_name()); \ return 1; \ - \ -} \ - \ -static int set_##float_name(T* p, lua_State* L) \ - \ -{ \ + } \ + \ + static int set_##float_name(T* p, lua_State* L) \ + \ + { \ p->set_##float_name(FArg(1)); \ COMMON_RETURN_SELF; \ - \ -} + } #define GET_SET_ENUM_METHOD(method_name, enum_name, val_name) \ - \ -static int get_##method_name(T* p, lua_State* L) \ - \ -{ \ + \ + static int get_##method_name(T* p, lua_State* L) \ + \ + { \ Enum::Push(L, p->val_name); \ return 1; \ - \ -} \ - \ -static int set_##method_name(T* p, lua_State* L) \ - \ -{ \ + } \ + \ + static int set_##method_name(T* p, lua_State* L) \ + \ + { \ p->val_name = Enum::Check(L, 1); \ COMMON_RETURN_SELF; \ - \ -} + } #define GETTER_SETTER_ENUM_METHOD(enum_name, val_name) \ - \ -static int get_##val_name(T* p, lua_State* L) \ - \ -{ \ + \ + static int get_##val_name(T* p, lua_State* L) \ + \ + { \ Enum::Push(L, p->get_##val_name()); \ return 1; \ - \ -} \ - \ -static int set_##val_name(T* p, lua_State* L) \ - \ -{ \ + } \ + \ + static int set_##val_name(T* p, lua_State* L) \ + \ + { \ p->set_##val_name(Enum::Check(L, 1)); \ COMMON_RETURN_SELF; \ - \ -} + } #define ADD_METHOD(method_name) AddMethod(#method_name, method_name) #define ADD_GET_SET_METHODS(method_name) \ ADD_METHOD(get_##method_name); \ ADD_METHOD(set_##method_name); #define LUA_SET_MEMBER(member, arg_conv) \ - \ -static int set_##member(T* p, lua_State* L) \ - \ -{ \ + \ + static int set_##member(T* p, lua_State* L) \ + \ + { \ p->m_##member = arg_conv(1); \ COMMON_RETURN_SELF; \ - \ -} + } #define GET_SET_MEMBER(member, arg_conv) \ - \ -DEFINE_METHOD(get_##member, m_##member); \ - \ -LUA_SET_MEMBER(member, arg_conv); + \ + DEFINE_METHOD(get_##member, m_##member); \ + \ + LUA_SET_MEMBER(member, arg_conv); #define LUA_REGISTER_NAMESPACE(T) \ static void Register##T(lua_State* L) \ @@ -362,7 +347,7 @@ LUA_SET_MEMBER(member, arg_conv); REGISTER_WITH_LUA_FUNCTION(Register##T) #define LIST_METHOD(method_name) \ { \ - #method_name, method_name \ +#method_name, method_name \ } // Explicitly separates the stack into args and return values. diff --git a/src/Model.cpp b/src/Model.cpp index ca296f2af7..9f325aaba2 100644 --- a/src/Model.cpp +++ b/src/Model.cpp @@ -623,7 +623,8 @@ void Model::SetPosition(float fSeconds) { m_fCurFrame = FRAMES_PER_SECOND * fSeconds; - m_fCurFrame = clamp(m_fCurFrame, 0, static_cast(m_pCurAnimation->nTotalFrames)); + m_fCurFrame = + clamp(m_fCurFrame, 0, static_cast(m_pCurAnimation->nTotalFrames)); } void @@ -647,7 +648,9 @@ Model::AdvanceFrame(float fDeltaTime) static_cast(m_pCurAnimation->nTotalFrames)); else m_fCurFrame = - clamp(m_fCurFrame, 0, static_cast(m_pCurAnimation->nTotalFrames)); + clamp(m_fCurFrame, + 0, + static_cast(m_pCurAnimation->nTotalFrames)); } SetBones(m_pCurAnimation, m_fCurFrame, m_vpBones); diff --git a/src/MusicWheel.cpp b/src/MusicWheel.cpp index f20beab33b..2602681f5d 100644 --- a/src/MusicWheel.cpp +++ b/src/MusicWheel.cpp @@ -1002,7 +1002,8 @@ MusicWheel::readyWheelItemsData(SortOrder so, bool searching, RString findme) m_WheelItemDatasStatus[so] = VALID; if (PREFSMAN->m_verbose_log > 0) - LOG->Trace("MusicWheel sorting took: %f", timer.GetTimeSinceStart()); + LOG->Trace("MusicWheel sorting took: %f", + timer.GetTimeSinceStart()); } } diff --git a/src/NoteData.cpp b/src/NoteData.cpp index 45c123363a..94a8f3fe07 100644 --- a/src/NoteData.cpp +++ b/src/NoteData.cpp @@ -1506,7 +1506,7 @@ NoteData::_all_tracks_iterator::~_all_tracks_iterator() template NoteData::_all_tracks_iterator& - NoteData::_all_tracks_iterator::operator++() // preincrement +NoteData::_all_tracks_iterator::operator++() // preincrement { m_PrevCurrentRows[m_iTrack] = Row(); if (m_bReverse) { @@ -1523,7 +1523,7 @@ NoteData::_all_tracks_iterator& template NoteData::_all_tracks_iterator - NoteData::_all_tracks_iterator::operator++(int) // postincrement +NoteData::_all_tracks_iterator::operator++(int) // postincrement { _all_tracks_iterator ret(*this); operator++(); diff --git a/src/NoteDisplay.cpp b/src/NoteDisplay.cpp index b8ca279b66..6cf12baeb8 100644 --- a/src/NoteDisplay.cpp +++ b/src/NoteDisplay.cpp @@ -217,7 +217,8 @@ MakeNoteResource(const RString& sButton, NOTESKIN->GetCurrentNoteSkin(), sElementAndType, pn, gc); map::iterator it = - g_NoteResource["4th"].find(nsap); // i cant figure out how color changes what actors are loaded... -mina + g_NoteResource["4th"].find(nsap); // i cant figure out how color changes + // what actors are loaded... -mina if (it == g_NoteResource[Color].end()) { auto* pRes = new NoteResource(nsap); diff --git a/src/NoteField.cpp b/src/NoteField.cpp index ded2d3b43c..bb80fd0b72 100644 --- a/src/NoteField.cpp +++ b/src/NoteField.cpp @@ -361,7 +361,7 @@ NoteField::Update(float fDeltaTime) { if (!this->GetVisible() || !GAMESTATE->m_pCurSong) return; - + if (m_bFirstUpdate) { m_pCurDisplay->m_ReceptorArrowRow.PlayCommand("On"); } @@ -827,7 +827,7 @@ NoteField::DrawPrimitives() { if (!this->GetVisible() || !GAMESTATE->m_pCurSong) return; - + // LOG->Trace( "NoteField::DrawPrimitives()" ); // This should be filled in on the first update. @@ -1131,8 +1131,8 @@ NoteField::FadeToFail() // don't fade all over again if this is called twice } - // A few functions and macros to take care of processing the callback - // return values, since the code would be identical in all of them. -Kyz +// A few functions and macros to take care of processing the callback +// return values, since the code would be identical in all of them. -Kyz #define OPEN_CALLBACK_BLOCK(member_name) \ if (!from_lua && !(member_name).IsNil()) { \ diff --git a/src/NoteSkinManager.cpp b/src/NoteSkinManager.cpp index 0cd8bbb394..40eaa8d611 100644 --- a/src/NoteSkinManager.cpp +++ b/src/NoteSkinManager.cpp @@ -201,7 +201,7 @@ NoteSkinManager::LoadNoteSkinDataRecursive(const RString& sNoteSkinName_, if (!GetFileContents(sFile, sScript)) continue; - if(PREFSMAN->m_verbose_log > 1) + if (PREFSMAN->m_verbose_log > 1) LOG->Trace("Load script \"%s\"", sFile.c_str()); Lua* L = LUA->Get(); diff --git a/src/NoteTypes.h b/src/NoteTypes.h index 698f657d18..4804f162f4 100644 --- a/src/NoteTypes.h +++ b/src/NoteTypes.h @@ -250,9 +250,9 @@ struct HoldReplayResult struct TapReplayResult { int row; - int track; // column - float offset; // 0 - TapNoteType type; // typically mines, holds, rolls, etc + int track; // column + float offset; // 0 + TapNoteType type; // typically mines, holds, rolls, etc int offsetAdjustedRow; // row assigned later on for full replays }; diff --git a/src/NotesLoaderBMS.cpp b/src/NotesLoaderBMS.cpp index 799c5476e4..3948d4cbaf 100644 --- a/src/NotesLoaderBMS.cpp +++ b/src/NotesLoaderBMS.cpp @@ -582,9 +582,11 @@ BMSChart::Load(const RString& chartPath) RString value = data.substr(2 * i, 2); if (value != "00") { value.MakeLower(); - BMSObject o = { - channel, measure, static_cast(i) / count, flag, value - }; + BMSObject o = { channel, + measure, + static_cast(i) / count, + flag, + value }; objects.push_back(o); } } diff --git a/src/NotesLoaderDWI.cpp b/src/NotesLoaderDWI.cpp index 013bae1f02..f3256ae65b 100644 --- a/src/NotesLoaderDWI.cpp +++ b/src/NotesLoaderDWI.cpp @@ -396,7 +396,8 @@ ParseNoteData(RString& step1, RString& step2, Steps& out, const RString& path) i++; } - const int iIndex = BeatToNoteRow(static_cast(fCurrentBeat)); + const int iIndex = + BeatToNoteRow(static_cast(fCurrentBeat)); i--; do { c = sStepData[i++]; diff --git a/src/NotesLoaderJson.cpp b/src/NotesLoaderJson.cpp index 69e701e42e..97977edfad 100644 --- a/src/NotesLoaderJson.cpp +++ b/src/NotesLoaderJson.cpp @@ -172,9 +172,12 @@ Deserialize(Song& out, const Json::Value& root) out.m_sLyricsFile = root["LyricsFile"].asString(); out.m_sCDTitleFile = root["CDTitle"].asString(); out.m_sMusicFile = root["Music"].asString(); - out.m_SongTiming.m_fBeat0OffsetInSeconds = static_cast(root["Offset"].asDouble()); - out.m_fMusicSampleStartSeconds = static_cast(root["SampleStart"].asDouble()); - out.m_fMusicSampleLengthSeconds = static_cast(root["SampleLength"].asDouble()); + out.m_SongTiming.m_fBeat0OffsetInSeconds = + static_cast(root["Offset"].asDouble()); + out.m_fMusicSampleStartSeconds = + static_cast(root["SampleStart"].asDouble()); + out.m_fMusicSampleLengthSeconds = + static_cast(root["SampleLength"].asDouble()); RString sSelectable = root["Selectable"].asString(); if (sSelectable.EqualsNoCase("YES")) out.m_SelectionDisplay = out.SHOW_ALWAYS; @@ -184,7 +187,8 @@ Deserialize(Song& out, const Json::Value& root) out.m_sSongFileName = root["SongFileName"].asString(); out.m_bHasMusic = root["HasMusic"].asBool(); out.m_bHasBanner = root["HasBanner"].asBool(); - out.m_fMusicLengthSeconds = static_cast(root["MusicLengthSeconds"].asDouble()); + out.m_fMusicLengthSeconds = + static_cast(root["MusicLengthSeconds"].asDouble()); RString sDisplayBPMType = root["DisplayBpmType"].asString(); if (sDisplayBPMType == "*") @@ -193,8 +197,10 @@ Deserialize(Song& out, const Json::Value& root) out.m_DisplayBPMType = DISPLAY_BPM_SPECIFIED; if (out.m_DisplayBPMType == DISPLAY_BPM_SPECIFIED) { - out.m_fSpecifiedBPMMin = static_cast(root["SpecifiedBpmMin"].asDouble()); - out.m_fSpecifiedBPMMax = static_cast(root["SpecifiedBpmMax"].asDouble()); + out.m_fSpecifiedBPMMin = + static_cast(root["SpecifiedBpmMin"].asDouble()); + out.m_fSpecifiedBPMMax = + static_cast(root["SpecifiedBpmMax"].asDouble()); } Deserialize(out.m_SongTiming, root["TimingData"]); diff --git a/src/Player.cpp b/src/Player.cpp index 69834490e9..bfa9064480 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -3231,7 +3231,7 @@ Player::SetJudgment(int iRow, float fTapNoteOffset) { if (tns < 0 || tns > NUM_TapNoteScore) - tns = TNS_Miss; // dont know why or how this crashes -mina + tns = TNS_Miss; // dont know why or how this crashes -mina if (tns == TNS_Miss) AddNoteToReplayData( GAMESTATE->CountNotesSeparately() ? iTrack : -1, &tn, iRow); diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index 9f2bda0236..d03c27c265 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -161,8 +161,7 @@ PlayerAI::SetScoreData(HighScore* pHighScore) m_ReplayTapMap.clear(); m_ReplayHoldMap.clear(); - if (!successful) - { + if (!successful) { return; } @@ -227,12 +226,10 @@ PlayerAI::SetUpExactTapMap(TimingData* timing) pReplayTiming = timing; // For every row in the replay data... - for (auto& row : m_ReplayTapMap) - { + for (auto& row : m_ReplayTapMap) { // Get the current time and go over all taps on this row... float rowTime = timing->WhereUAtBro(row.first); - for (TapReplayResult& trr : row.second) - { + for (TapReplayResult& trr : row.second) { // Find the time adjusted for offset // Then the beat according to that time // Then the noterow according to that beat @@ -242,19 +239,14 @@ PlayerAI::SetUpExactTapMap(TimingData* timing) trr.offsetAdjustedRow = tapRow; // And put that into the exacttapmap :) - if (m_ReplayExactTapMap.count(tapRow) != 0) - { + if (m_ReplayExactTapMap.count(tapRow) != 0) { m_ReplayExactTapMap[tapRow].push_back(trr); - } - else - { + } else { vector trrVector = { trr }; m_ReplayExactTapMap[tapRow] = trrVector; } } - } - } void @@ -280,7 +272,8 @@ PlayerAI::RemoveTapFromVectors(int row, int col) auto& trr = m_ReplayExactTapMap[row][i]; if (trr.track == col) { // delete - m_ReplayExactTapMap[row].erase(m_ReplayExactTapMap[row].begin() + i); + m_ReplayExactTapMap[row].erase( + m_ReplayExactTapMap[row].begin() + i); if (m_ReplayExactTapMap[row].empty()) m_ReplayExactTapMap.erase(row); } @@ -293,10 +286,8 @@ PlayerAI::GetAdjustedRowFromUnadjustedCoordinates(int row, int col) { int output = -1; - if (m_ReplayTapMap.count(row) != 0) - { - for (TapReplayResult& trr : m_ReplayTapMap[row]) - { + if (m_ReplayTapMap.count(row) != 0) { + for (TapReplayResult& trr : m_ReplayTapMap[row]) { if (trr.track == col) output = trr.offsetAdjustedRow; } @@ -333,7 +324,6 @@ PlayerAI::TapExistsAtThisRow(int noteRow) } else { return m_ReplayTapMap.count(noteRow) != 0; } - } bool @@ -465,10 +455,9 @@ PlayerAI::GetTapNoteOffsetForReplay(TapNote* pTN, int noteRow, int col) // This is only reached if we have column data. noteRow = GetAdjustedRowFromUnadjustedCoordinates(noteRow, col); - if (m_ReplayExactTapMap.count(noteRow) != 0) - { - for (int i = 0; i < (int)m_ReplayExactTapMap[noteRow] - .size(); i++) // go over all elements in the row + if (m_ReplayExactTapMap.count(noteRow) != 0) { + for (int i = 0; i < (int)m_ReplayExactTapMap[noteRow].size(); + i++) // go over all elements in the row { auto trr = m_ReplayExactTapMap[noteRow][i]; if (trr.track == @@ -481,7 +470,7 @@ PlayerAI::GetTapNoteOffsetForReplay(TapNote* pTN, int noteRow, int col) continue; } m_ReplayExactTapMap[noteRow].erase( - m_ReplayExactTapMap[noteRow].begin() + i); + m_ReplayExactTapMap[noteRow].begin() + i); if (m_ReplayExactTapMap[noteRow].empty()) m_ReplayExactTapMap.erase(noteRow); return -trr.offset; @@ -494,7 +483,8 @@ PlayerAI::GetTapNoteOffsetForReplay(TapNote* pTN, int noteRow, int col) } void -PlayerAI::CalculateRadarValuesForReplay(RadarValues& rv, RadarValues& possibleRV) +PlayerAI::CalculateRadarValuesForReplay(RadarValues& rv, + RadarValues& possibleRV) { // We will do this thoroughly just in case someone decides to use the other // categories we don't currently use @@ -509,40 +499,34 @@ PlayerAI::CalculateRadarValuesForReplay(RadarValues& rv, RadarValues& possibleRV int minesMissed = possibleRV[RadarCategory_Mines]; // For every row recorded... - for (auto& row : m_ReplayTapMap) - { + for (auto& row : m_ReplayTapMap) { int tapsOnThisRow = 0; // For every tap on these rows... - for (TapReplayResult& trr : row.second) - { - if (trr.type == TapNoteType_Fake) - { + for (TapReplayResult& trr : row.second) { + if (trr.type == TapNoteType_Fake) { fakes--; continue; } - if (trr.type == TapNoteType_Mine) - { + if (trr.type == TapNoteType_Mine) { minesMissed--; continue; } - if (trr.type == TapNoteType_Lift) - { + if (trr.type == TapNoteType_Lift) { liftsHit++; continue; } tapsOnThisRow++; - // We handle Empties as well because that's what old replays are loaded as. - if (trr.type == TapNoteType_Tap || trr.type == TapNoteType_HoldHead || trr.type == TapNoteType_Empty) - { + // We handle Empties as well because that's what old replays are + // loaded as. + if (trr.type == TapNoteType_Tap || + trr.type == TapNoteType_HoldHead || + trr.type == TapNoteType_Empty) { totalNotesHit++; tapsHit++; - if (tapsOnThisRow == 2) - { + if (tapsOnThisRow == 2) { // This is technically incorrect. jumpsHit++; - } - else if (tapsOnThisRow >= 3) - { + } else if (tapsOnThisRow >= 3) { handsHit++; } continue; @@ -551,18 +535,13 @@ PlayerAI::CalculateRadarValuesForReplay(RadarValues& rv, RadarValues& possibleRV } // For every hold recorded... - for (auto& row : m_ReplayHoldMap) - { + for (auto& row : m_ReplayHoldMap) { // For every hold on this row... - for (HoldReplayResult& hrr : row.second) - { - if (hrr.subType == TapNoteSubType_Hold) - { + for (HoldReplayResult& hrr : row.second) { + if (hrr.subType == TapNoteSubType_Hold) { holdsHeld--; continue; - } - else if (hrr.subType == TapNoteSubType_Roll) - { + } else if (hrr.subType == TapNoteSubType_Roll) { rollsHeld--; continue; } diff --git a/src/PlayerAI.h b/src/PlayerAI.h index 6299320f96..22c35c17df 100644 --- a/src/PlayerAI.h +++ b/src/PlayerAI.h @@ -29,8 +29,8 @@ class PlayerAI static map> m_ReplayHoldMap; // A map with indices for each row of the chart, pointing to nothing or a // Normal Result. However, note that the rows within are actually calculated - // so that they are adjusted for offsets relative to the actual replay data/notedata. - // This map is only useful for charts with column data. + // so that they are adjusted for offsets relative to the actual replay + // data/notedata. This map is only useful for charts with column data. static map> m_ReplayExactTapMap; static void InitFromDisk(); @@ -44,8 +44,11 @@ class PlayerAI static bool DetermineIfHoldDropped(int noteRow, int col); // Returns the column that needs to be tapped. // Returns -1 if no column needs to be tapped. - static int DetermineNextTapColumn(int noteRow, int searchRowDistance, TimingData* timing); - // Literally get the next row in the replay data. Disregard offset calculations. + static int DetermineNextTapColumn(int noteRow, + int searchRowDistance, + TimingData* timing); + // Literally get the next row in the replay data. Disregard offset + // calculations. static int GetNextRowNoOffsets(int currentRow); // Reset and populate the ReplayExactTapMap. // This is meant to be run once Gameplay begins. @@ -56,15 +59,17 @@ class PlayerAI // Build a list of columns/tracks to tap based on the given noterow. static vector GetTapsToTapForRow(int noteRow); static int GetReplayType(); - // Build a list of columns/tracks that happened at or before the given noterow. - // (if we lag and somehow skip rows) + // Build a list of columns/tracks that happened at or before the given + // noterow. (if we lag and somehow skip rows) static vector GetTapsAtOrBeforeRow(int noteRow); // Given a column and row, retrieve the adjusted row. static int GetAdjustedRowFromUnadjustedCoordinates(int row, int col); // Remove a given Tap from the fallback and Full replay data vectors static void RemoveTapFromVectors(int row, int col); - // Go through the replay data to fill out the radar values for the eval screen - static void CalculateRadarValuesForReplay(RadarValues& rv, RadarValues& possibleRV); + // Go through the replay data to fill out the radar values for the eval + // screen + static void CalculateRadarValuesForReplay(RadarValues& rv, + RadarValues& possibleRV); }; #endif diff --git a/src/PlayerOptions.cpp b/src/PlayerOptions.cpp index 42d84cd3ab..99fa97a9dc 100644 --- a/src/PlayerOptions.cpp +++ b/src/PlayerOptions.cpp @@ -404,8 +404,7 @@ PlayerOptions::ResetModsToStringVector(vector mods) { RString error; ResetToggleableMods(); - for (RString mod : mods) - { + for (RString mod : mods) { FromOneModString(mod, error); } } diff --git a/src/PlayerStageStats.cpp b/src/PlayerStageStats.cpp index 5106dccb0c..22fac8389e 100644 --- a/src/PlayerStageStats.cpp +++ b/src/PlayerStageStats.cpp @@ -319,7 +319,8 @@ PlayerStageStats::MakePercentScore(int iActual, int iPossible) // TRICKY: printf will round, but we want to truncate. Otherwise, we may // display a percent score that's too high and doesn't match up with the // calculated grade. - float fTruncInterval = powf(0.1f, static_cast(iPercentTotalDigits) - 1); + float fTruncInterval = + powf(0.1f, static_cast(iPercentTotalDigits) - 1); // TRICKY: ftruncf is rounding 1.0000000 to 0.99990004. Give a little boost // to fPercentDancePoints to correct for this. diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index 2bd7d6f200..3f5b48ed09 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -234,8 +234,7 @@ PrefsManager::PrefsManager() /* Debug: */ m_bLogToDisk("LogToDisk", true) - , - m_verbose_log("VerboseLogging", 1) + , m_verbose_log("VerboseLogging", 1) , #if defined(DEBUG) m_bForceLogFlush("ForceLogFlush", true) diff --git a/src/PrefsManager.h b/src/PrefsManager.h index 03dd4df402..b82a44c36e 100644 --- a/src/PrefsManager.h +++ b/src/PrefsManager.h @@ -263,7 +263,8 @@ class PrefsManager Preference m_bPseudoLocalize; Preference m_show_theme_errors; - Preference m_verbose_log; // levels 0, 1, and 2 where higher numbers means more logging + Preference m_verbose_log; // levels 0, 1, and 2 where higher numbers + // means more logging #if !defined(WITHOUT_NETWORKING) Preference diff --git a/src/Profile.cpp b/src/Profile.cpp index b226e8ebf2..a8cfc257cb 100644 --- a/src/Profile.cpp +++ b/src/Profile.cpp @@ -927,7 +927,8 @@ Profile::LoadAllFromDir(const RString& sDir, // Not critical if this fails LoadEditableDataFromDir(sDir); - /* we dont really need to be doing this automatically anymore, maybe reinstituting as a "migrate replay" button would be worth doing -mina + /* we dont really need to be doing this automatically anymore, maybe + reinstituting as a "migrate replay" button would be worth doing -mina // move old profile specific replays to the new aggregate folder RString oldreplaydir = sDir + "ReplayData/"; @@ -2197,8 +2198,10 @@ class LunaScoreGoal : public Luna return 1; } - static int Delete(T* p, lua_State *L) { - PROFILEMAN->GetProfile(PLAYER_1)->RemoveGoal(p->chartkey, p->timeassigned); + static int Delete(T* p, lua_State* L) + { + PROFILEMAN->GetProfile(PLAYER_1)->RemoveGoal(p->chartkey, + p->timeassigned); return 0; } diff --git a/src/ProfileManager.h b/src/ProfileManager.h index ea11abe499..545e65380c 100644 --- a/src/ProfileManager.h +++ b/src/ProfileManager.h @@ -144,8 +144,9 @@ class ProfileManager // of a signature // failure) bool m_bLastLoadWasFromLastGood - [NUM_PLAYERS]; // if true, then m_bLastLoadWasTamperedOrCorrupt is also - // true + [NUM_PLAYERS]; // if true, then + // m_bLastLoadWasTamperedOrCorrupt + // is also true mutable bool m_bNeedToBackUpLastLoad[NUM_PLAYERS]; // if true, back up // profile on next save bool m_bNewProfile[NUM_PLAYERS]; diff --git a/src/RageDisplay_GLES2.cpp b/src/RageDisplay_GLES2.cpp index d1fbd1f419..6b6d655094 100644 --- a/src/RageDisplay_GLES2.cpp +++ b/src/RageDisplay_GLES2.cpp @@ -231,8 +231,8 @@ RageDisplay_GLES2::Init(const VideoModeParams& p, /* Pretty-print the extension string: */ LOG->Info("OGL Extensions:"); { - // glGetString(GL_EXTENSIONS) doesn't work for GL3 core profiles. - // this will be useful in the future. + // glGetString(GL_EXTENSIONS) doesn't work for GL3 core profiles. + // this will be useful in the future. #if 0 vector extensions; const char *ext = 0; diff --git a/src/RageDisplay_GLES2.h b/src/RageDisplay_GLES2.h index ed4d8364d7..76ab6c01ad 100644 --- a/src/RageDisplay_GLES2.h +++ b/src/RageDisplay_GLES2.h @@ -24,8 +24,8 @@ class RageDisplay_GLES2 : public RageDisplay bool realtime = false) override; bool SupportsPerVertexMatrixScale() override; virtual intptr_t CreateTexture(RagePixelFormat pixfmt, - RageSurface* img, - bool bGenerateMipMaps) override; + RageSurface* img, + bool bGenerateMipMaps) override; void UpdateTexture(intptr_t iTexHandle, RageSurface* img, int xoffset, diff --git a/src/RageDisplay_OGL.cpp b/src/RageDisplay_OGL.cpp index b1189869a3..c4936d966b 100644 --- a/src/RageDisplay_OGL.cpp +++ b/src/RageDisplay_OGL.cpp @@ -241,8 +241,7 @@ TurnOffHardwareVBO() RageDisplay_Legacy::RageDisplay_Legacy() { - if (PREFSMAN->m_verbose_log > 1) - { + if (PREFSMAN->m_verbose_log > 1) { LOG->Trace("RageDisplay_Legacy::RageDisplay_Legacy()"); LOG->MapLog("renderer", "Current renderer: OpenGL"); } @@ -300,7 +299,7 @@ CompileShader(GLenum ShaderType, RString sFile, vector asDefines) } } - if(PREFSMAN->m_verbose_log > 1) + if (PREFSMAN->m_verbose_log > 1) LOG->Trace("Compiling shader %s", sFile.c_str()); GLhandleARB hShader = glCreateShaderObjectARB(ShaderType); vector apData; @@ -487,7 +486,7 @@ static LocalizedString GLDIRECT_IS_NOT_COMPATIBLE("RageDisplay_Legacy", "be disabled."); RString RageDisplay_Legacy::Init(const VideoModeParams& p, - bool bAllowUnacceleratedRenderer) + bool bAllowUnacceleratedRenderer) { g_pWind = LowLevelWindow::Create(); @@ -498,8 +497,7 @@ RageDisplay_Legacy::Init(const VideoModeParams& p, // Log driver details g_pWind->LogDebugInformation(); - if (PREFSMAN->m_verbose_log > 1) - { + if (PREFSMAN->m_verbose_log > 1) { LOG->Info("OGL Vendor: %s", glGetString(GL_VENDOR)); LOG->Info("OGL Renderer: %s", glGetString(GL_RENDERER)); LOG->Info("OGL Version: %s", glGetString(GL_VERSION)); @@ -510,7 +508,8 @@ RageDisplay_Legacy::Init(const VideoModeParams& p, /* Pretty-print the extension string: */ LOG->Info("OGL Extensions:"); { - const char* szExtensionString = (const char*)glGetString(GL_EXTENSIONS); + const char* szExtensionString = + (const char*)glGetString(GL_EXTENSIONS); vector asExtensions; split(szExtensionString, " ", asExtensions); sort(asExtensions.begin(), asExtensions.end()); @@ -523,7 +522,8 @@ RageDisplay_Legacy::Init(const VideoModeParams& p, split(asExtensions[i], "_", asBits); RString sThisType; if (asBits.size() > 2) - sThisType = join("_", asBits.begin(), asBits.begin() + 2); + sThisType = + join("_", asBits.begin(), asBits.begin() + 2); if (i > iNextToPrint && sThisType != sType) break; sType = sThisType; @@ -540,13 +540,14 @@ RageDisplay_Legacy::Init(const VideoModeParams& p, while (iNextToPrint <= iLastToPrint) { vector asBits; split(asExtensions[iNextToPrint], "_", asBits); - RString sShortExt = join("_", asBits.begin() + 2, asBits.end()); + RString sShortExt = + join("_", asBits.begin() + 2, asBits.end()); sList += sShortExt; if (iNextToPrint < iLastToPrint) sList += ", "; if (iNextToPrint == iLastToPrint || sList.size() + asExtensions[iNextToPrint + 1].size() > - 120) { + 120) { LOG->Info("%s", sList.c_str()); sList = " "; } @@ -611,15 +612,14 @@ CheckPalettedTextures() FlushGLErrors(); #define GL_CHECK_ERROR(f) \ - \ -{ \ + \ + { \ GLenum glError = glGetError(); \ if (glError != GL_NO_ERROR) { \ sError = ssprintf(f " failed (%s)", GLToString(glError).c_str()); \ break; \ } \ - \ -} + } glTexImage2D(GL_PROXY_TEXTURE_2D, 0, @@ -2313,7 +2313,7 @@ RageDisplay_Legacy::CreateTexture(RagePixelFormat pixfmt, ASSERT(iRealFormat == GL_RGBA8); } - if(PREFSMAN->m_verbose_log > 1) + if (PREFSMAN->m_verbose_log > 1) LOG->Trace( "%s (format %s, %ix%i, format %s, type %s, pixfmt %i, imgpixfmt %i)", bGenerateMipMaps ? "gluBuild2DMipmaps" : "glTexImage2D", diff --git a/src/RageDisplay_OGL.h b/src/RageDisplay_OGL.h index 0093ed1bd4..3c721b72ec 100644 --- a/src/RageDisplay_OGL.h +++ b/src/RageDisplay_OGL.h @@ -13,13 +13,12 @@ do { \ } while (glGetError() != GL_NO_ERROR) #define AssertNoGLError() \ - \ -{ \ + \ + { \ GLenum error = glGetError(); \ ASSERT_M(error == GL_NO_ERROR, \ RageDisplay_Legacy_Helpers::GLToString(error)); \ - \ -} + } #if defined(DEBUG) || !defined(GL_GET_ERROR_IS_SLOW) #define DebugFlushGLErrors() FlushGLErrors() diff --git a/src/RageSound.cpp b/src/RageSound.cpp index c3732c6fe4..b849b2cfe7 100644 --- a/src/RageSound.cpp +++ b/src/RageSound.cpp @@ -360,7 +360,8 @@ RageSound::StartPlaying(float fGiven, bool forcedTime) /* If m_StartTime is in the past, then we probably set a start time but took * too long loading. We don't want that; log it, since it can be unobvious. */ - if (!m_Param.m_StartTime.IsZero() && m_Param.m_StartTime.Ago() > 0 && PREFSMAN->m_verbose_log > 1) + if (!m_Param.m_StartTime.IsZero() && m_Param.m_StartTime.Ago() > 0 && + PREFSMAN->m_verbose_log > 1) LOG->Trace("Sound \"%s\" has a start time %f seconds in the past", GetLoadedFilePath().c_str(), m_Param.m_StartTime.Ago()); @@ -388,12 +389,10 @@ RageSound::StartPlaying(float fGiven, bool forcedTime) void RageSound::SetPositionSeconds(float fGiven) { - if (m_bPlaying) - { + if (m_bPlaying) { Stop(); - //SetPositionFrames(lround(fGiven * samplerate())); + // SetPositionFrames(lround(fGiven * samplerate())); StartPlaying(fGiven, true); - } } diff --git a/src/RageSoundPosMap.cpp b/src/RageSoundPosMap.cpp index 908899d7b1..98508a5ee8 100644 --- a/src/RageSoundPosMap.cpp +++ b/src/RageSoundPosMap.cpp @@ -185,17 +185,17 @@ pos_map_queue::Search(int64_t iSourceFrame, bool* bApproximate) const } } - /* - * The frame is out of the range of data we've actually sent. - * Return the closest position. - * - * There are three cases when this happens: - * 1. Before the first CommitPlayingPosition call. - * 2. After GetDataToPlay returns EOF and the sound has flushed, but - * before SoundStopped has been called. - * 3. Underflow; we'll be given a larger frame number than we know - * about. - */ + /* + * The frame is out of the range of data we've actually sent. + * Return the closest position. + * + * There are three cases when this happens: + * 1. Before the first CommitPlayingPosition call. + * 2. After GetDataToPlay returns EOF and the sound has flushed, but + * before SoundStopped has been called. + * 3. Underflow; we'll be given a larger frame number than we know + * about. + */ #if defined(WIN32) #define I64F "%I64i" #elif defined(__x86_64__) diff --git a/src/RageSoundReader_MP3.cpp b/src/RageSoundReader_MP3.cpp index a029758e47..e3fccb87dd 100644 --- a/src/RageSoundReader_MP3.cpp +++ b/src/RageSoundReader_MP3.cpp @@ -657,7 +657,8 @@ RageSoundReader_MP3::Open(RageFileBasic* pFile) if (mad->length == -1) { /* If vbr and !xing, this is just an estimate. */ int bps = mad->bitrate / 8; - float secs = static_cast(mad->filesize - mad->header_bytes) / bps; + float secs = + static_cast(mad->filesize - mad->header_bytes) / bps; mad->length = (int)(secs * 1000.f); } diff --git a/src/RageSoundReader_WAV.cpp b/src/RageSoundReader_WAV.cpp index 9e0effb0ff..e6c08122fe 100644 --- a/src/RageSoundReader_WAV.cpp +++ b/src/RageSoundReader_WAV.cpp @@ -470,14 +470,13 @@ ReadString(RageFileBasic& f, int iSize, RString& sError) } #define FATAL_ERROR(s) \ - \ -{ \ + \ + { \ if (sError.size() == 0) \ sError = (s); \ SetError(sError); \ return OPEN_FATAL_ERROR; \ - \ -} + } RageSoundReader_FileReader::OpenResult RageSoundReader_WAV::Open(RageFileBasic* pFile) diff --git a/src/RageSurfaceUtils_Palettize.cpp b/src/RageSurfaceUtils_Palettize.cpp index 1d45e40504..79f7720307 100644 --- a/src/RageSurfaceUtils_Palettize.cpp +++ b/src/RageSurfaceUtils_Palettize.cpp @@ -495,21 +495,21 @@ mediancut(acolorhist_item* achv, int colors, int sum, int maxval, int newcolors) return acolormap; } - /* - * libpam3.c - pam (portable alpha map) utility library part 3 - * - * Colormap routines. - * - * Copyright (C) 1989, 1991 by Jef Poskanzer. - * Copyright (C) 1997 by Greg Roelofs. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation for any purpose and without fee is hereby granted, provided - * that the above copyright notice appear in all copies and that both that - * copyright notice and this permission notice appear in supporting - * documentation. This software is provided "as is" without express or - * implied warranty. - */ +/* + * libpam3.c - pam (portable alpha map) utility library part 3 + * + * Colormap routines. + * + * Copyright (C) 1989, 1991 by Jef Poskanzer. + * Copyright (C) 1997 by Greg Roelofs. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. This software is provided "as is" without express or + * implied warranty. + */ #define pam_hashapixel(p) \ (((unsigned)PAM_GETR(p) * 33023 + (unsigned)PAM_GETG(p) * 30013 + \ diff --git a/src/RageSurface_Load_BMP.cpp b/src/RageSurface_Load_BMP.cpp index f706472e66..aa54d58b05 100644 --- a/src/RageSurface_Load_BMP.cpp +++ b/src/RageSurface_Load_BMP.cpp @@ -17,13 +17,12 @@ enum /* When returning error, the first error encountered takes priority. */ #define FATAL_ERROR(s) \ - \ -{ \ + \ + { \ if (sError.size() == 0) \ sError = (s); \ return RageSurfaceUtils::OPEN_FATAL_ERROR; \ - \ -} + } static RageSurfaceUtils::OpenResult LoadBMP(RageFile& f, RageSurface*& img, RString& sError) diff --git a/src/RageTexture.cpp b/src/RageTexture.cpp index db997c683c..248253e3db 100644 --- a/src/RageTexture.cpp +++ b/src/RageTexture.cpp @@ -39,13 +39,14 @@ RageTexture::CreateFrameRects() { RectF frect( (i + 0) / static_cast(m_iFramesWide) * m_iImageWidth / - static_cast(m_iTextureWidth), // these will all be between 0.0 and 1.0 + static_cast( + m_iTextureWidth), // these will all be between 0.0 and 1.0 (j + 0) / static_cast(m_iFramesHigh) * m_iImageHeight / static_cast(m_iTextureHeight), (i + 1) / static_cast(m_iFramesWide) * m_iImageWidth / static_cast(m_iTextureWidth), (j + 1) / static_cast(m_iFramesHigh) * m_iImageHeight / - static_cast(m_iTextureHeight)); + static_cast(m_iTextureHeight)); m_TextureCoordRects.push_back(frect); // the index of this array // element will be (i + // j*m_iFramesWide) diff --git a/src/RageThreads.cpp b/src/RageThreads.cpp index 673575445b..667b43f4c9 100644 --- a/src/RageThreads.cpp +++ b/src/RageThreads.cpp @@ -485,22 +485,22 @@ Checkpoints::GetLogs(char* pBuf, int iSize, const char* delim) } } - /* - * "Safe" mutexes: locking the same mutex more than once from the same - * thread is refcounted and does not deadlock. - * - * Only actually lock the mutex once; when we do so, remember which thread - * locked it. Then, when we lock in the future, only increment a counter, - * with no locks. - * - * We must be holding the real mutex to write to LockedBy and LockCnt. - * However, we can look at LockedBy to see if it's us that owns it (in which - * case, we already hold the mutex). - * - * In Windows, this helps smooth out performance: for some reason, Windows - * likes to yank the scheduler away from a thread that locks a mutex that it - * already owns. - */ +/* + * "Safe" mutexes: locking the same mutex more than once from the same + * thread is refcounted and does not deadlock. + * + * Only actually lock the mutex once; when we do so, remember which thread + * locked it. Then, when we lock in the future, only increment a counter, + * with no locks. + * + * We must be holding the real mutex to write to LockedBy and LockCnt. + * However, we can look at LockedBy to see if it's us that owns it (in which + * case, we already hold the mutex). + * + * In Windows, this helps smooth out performance: for some reason, Windows + * likes to yank the scheduler away from a thread that locks a mutex that it + * already owns. + */ #if 0 static const int MAX_MUTEXES = 256; diff --git a/src/ScoreKeeper.h b/src/ScoreKeeper.h index 9897c6a333..21c3bee652 100644 --- a/src/ScoreKeeper.h +++ b/src/ScoreKeeper.h @@ -31,7 +31,7 @@ class ScoreKeeper /* If true, doubles count as 2+ in stat counts; if false, doubles count as * only one. */ /* (not yet) */ - // bool Stats_DoublesCount; + // bool Stats_DoublesCount; public: ScoreKeeper(PlayerState* pPlayerState, PlayerStageStats* pPlayerStageStats); diff --git a/src/ScoreKeeperNormal.cpp b/src/ScoreKeeperNormal.cpp index b3e7a6514e..2fcd1c4fca 100644 --- a/src/ScoreKeeperNormal.cpp +++ b/src/ScoreKeeperNormal.cpp @@ -187,16 +187,16 @@ ScoreKeeperNormal::OnNextSong(int iSongInCourseIndex, static int GetScore(int p, int Z, int64_t S, int n) { -/* There's a problem with the scoring system described below. Z/S is truncated - * to an int. However, in some cases we can end up with very small base scores. - * Each song in a 50-song nonstop course will be worth 2mil, which is a base of - * 200k; Z/S will end up being zero. - * - * If we rearrange the equation to (p*Z*n) / S, this problem goes away. - * (To do that, we need to either use 64-bit ints or rearrange it a little - * more and use floats, since p*Z*n won't fit a 32-bit int.) However, this - * changes the scoring rules slightly. - */ + /* There's a problem with the scoring system described below. Z/S is + * truncated to an int. However, in some cases we can end up with very small + * base scores. Each song in a 50-song nonstop course will be worth 2mil, + * which is a base of 200k; Z/S will end up being zero. + * + * If we rearrange the equation to (p*Z*n) / S, this problem goes away. + * (To do that, we need to either use 64-bit ints or rearrange it a little + * more and use floats, since p*Z*n won't fit a 32-bit int.) However, this + * changes the scoring rules slightly. + */ #if 0 // This is the actual method described below. diff --git a/src/ScoreManager.h b/src/ScoreManager.h index 46b46f8aa3..70fd7d73c5 100644 --- a/src/ScoreManager.h +++ b/src/ScoreManager.h @@ -185,7 +185,10 @@ class ScoreManager std::swap(score, AllScores.back()); } const vector& GetAllScores() { return AllScores; } - const unordered_map& GetScoresByKey(){return ScoresByKey;} + const unordered_map& GetScoresByKey() + { + return ScoresByKey; + } const vector& GetAllProfileScores( const string& profileID = PROFILEMAN->GetProfile(PLAYER_1)->m_sProfileID) { diff --git a/src/ScreenEvaluation.cpp b/src/ScreenEvaluation.cpp index 4553862749..42259234c1 100644 --- a/src/ScreenEvaluation.cpp +++ b/src/ScreenEvaluation.cpp @@ -435,8 +435,7 @@ ScreenEvaluation::Init() m_sprPossibleBar[p][r].GetUnzoomedWidth() * actual * fDivider); - float value = 100.f * - m_sprActualBar[p][r].GetUnzoomedWidth() / + float value = 100.f * m_sprActualBar[p][r].GetUnzoomedWidth() / m_sprPossibleBar[p][r].GetUnzoomedWidth(); LOG->Trace("Radar bar %d of 5 - %f percent", r, value); @@ -763,26 +762,24 @@ ScreenEvaluation::Input(const InputEventPlus& input) CodeDetector::EnteredCode(input.GameI.controller, CODE_SAVE_SCREENSHOT2)) { PlayerNumber pn = input.pn; - bool bHoldingShift = - (INPUTFILTER->IsBeingPressed( - DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) || - INPUTFILTER->IsBeingPressed( - DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT))); + bool bHoldingShift = (INPUTFILTER->IsBeingPressed( + DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) || + INPUTFILTER->IsBeingPressed( + DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT))); RString sDir; RString sFileName; // To save a screenshot to your own profile you must hold shift // and press the button it saves compressed so you don't end up // with an inflated profile size - // Otherwise, you can tap away at the screenshot button without holding shift. - if (bHoldingShift && PROFILEMAN->IsPersistentProfile(pn)) - { - if (!m_bSavedScreenshot[pn]) - { + // Otherwise, you can tap away at the screenshot button without + // holding shift. + if (bHoldingShift && PROFILEMAN->IsPersistentProfile(pn)) { + if (!m_bSavedScreenshot[pn]) { Profile* pProfile = PROFILEMAN->GetProfile(pn); sDir = PROFILEMAN->GetProfileDir((ProfileSlot)pn) + - "Screenshots/"; - sFileName = - StepMania::SaveScreenshot(sDir, bHoldingShift, true, "", ""); + "Screenshots/"; + sFileName = StepMania::SaveScreenshot( + sDir, bHoldingShift, true, "", ""); if (!sFileName.empty()) { RString sPath = sDir + sFileName; @@ -797,9 +794,7 @@ ScreenEvaluation::Input(const InputEventPlus& input) } m_bSavedScreenshot[pn] = true; } - } - else - { + } else { sDir = "Screenshots/"; sFileName = StepMania::SaveScreenshot(sDir, bHoldingShift, true, "", ""); @@ -863,9 +858,15 @@ ScreenEvaluation::HandleMenuStart() GAMEMAN->m_bResetModifiers = false; const vector oldturns = GAMEMAN->m_vTurnsToReset; if (GAMEMAN->m_bResetTurns) { - GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetSong().ResetModsToStringVector(oldturns); - GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetCurrent().ResetModsToStringVector(oldturns); - GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetPreferred().ResetModsToStringVector(oldturns); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .ResetModsToStringVector(oldturns); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .ResetModsToStringVector(oldturns); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .ResetModsToStringVector(oldturns); GAMEMAN->m_bResetTurns = false; GAMEMAN->m_vTurnsToReset.clear(); } diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index f66496fdf4..d944bf218d 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1705,42 +1705,42 @@ ScreenGameplay::Update(float fDeltaTime) if (GAMEMAN->m_bResetModifiers) { float oldRate = GAMEMAN->m_fPreviousRate; const RString mods = GAMEMAN->m_sModsToReset; - /* - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetSong() - .FromString("clearall"); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetCurrent() - .FromString("clearall"); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetPreferred() - .FromString("clearall"); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetSong() - .FromString(mods); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetCurrent() - .FromString(mods); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetPreferred() - .FromString(mods); - */ - const vector oldturns = - GAMEMAN->m_vTurnsToReset; - if (GAMEMAN->m_bResetTurns) { - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetSong() - .ResetModsToStringVector(oldturns); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetCurrent() - .ResetModsToStringVector(oldturns); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetPreferred() - .ResetModsToStringVector(oldturns); - GAMEMAN->m_bResetTurns = false; - GAMEMAN->m_vTurnsToReset.clear(); - } - GAMESTATE->m_SongOptions.GetSong().m_fMusicRate = + /* + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .FromString("clearall"); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .FromString("clearall"); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .FromString("clearall"); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .FromString(mods); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .FromString(mods); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .FromString(mods); + */ + const vector oldturns = + GAMEMAN->m_vTurnsToReset; + if (GAMEMAN->m_bResetTurns) { + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .ResetModsToStringVector(oldturns); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .ResetModsToStringVector(oldturns); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .ResetModsToStringVector(oldturns); + GAMEMAN->m_bResetTurns = false; + GAMEMAN->m_vTurnsToReset.clear(); + } + GAMESTATE->m_SongOptions.GetSong().m_fMusicRate = oldRate; GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate = oldRate; @@ -2053,41 +2053,41 @@ ScreenGameplay::Input(const InputEventPlus& input) if (GamePreferences::m_AutoPlay == PC_REPLAY) { if (GAMEMAN->m_bResetModifiers) { float oldRate = GAMEMAN->m_fPreviousRate; - const RString mods = GAMEMAN->m_sModsToReset; - /* - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetSong() - .FromString("clearall"); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetCurrent() - .FromString("clearall"); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetPreferred() - .FromString("clearall"); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetSong() - .FromString(mods); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetCurrent() - .FromString(mods); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetPreferred() - .FromString(mods); - */ - const vector oldturns = - GAMEMAN->m_vTurnsToReset; - if (GAMEMAN->m_bResetTurns) { - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetSong() - .ResetModsToStringVector(oldturns); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetCurrent() - .ResetModsToStringVector(oldturns); - GAMESTATE->m_pPlayerState[PLAYER_1] - ->m_PlayerOptions.GetPreferred() - .ResetModsToStringVector(oldturns); - GAMEMAN->m_bResetTurns = false; - GAMEMAN->m_vTurnsToReset.clear(); + const RString mods = GAMEMAN->m_sModsToReset; + /* + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .FromString("clearall"); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .FromString("clearall"); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .FromString("clearall"); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .FromString(mods); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .FromString(mods); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .FromString(mods); + */ + const vector oldturns = + GAMEMAN->m_vTurnsToReset; + if (GAMEMAN->m_bResetTurns) { + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .ResetModsToStringVector(oldturns); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .ResetModsToStringVector(oldturns); + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .ResetModsToStringVector(oldturns); + GAMEMAN->m_bResetTurns = false; + GAMEMAN->m_vTurnsToReset.clear(); } GAMESTATE->m_SongOptions.GetSong().m_fMusicRate = oldRate; @@ -2233,19 +2233,19 @@ ScreenGameplay::SaveStats() NoteDataWithScoring::GetActualRadarValues(nd, pss, fMusicLen, rv); pss.m_radarActual += rv; GAMESTATE->SetProcessedTimingData(NULL); - } - if (GamePreferences::m_AutoPlay.Get() == PC_REPLAY) { - // We need to replace the newly created replay data with the actual old - // data Because to keep consistently lazy practices, we can just hack - // things together instead of fixing the real issue -poco - // (doing this fixes a lot of issues in the eval screen) - PlayerStageStats* pss = m_vPlayerInfo[PLAYER_1].GetPlayerStageStats(); - HighScore* hs = PlayerAI::pScoreData; - pss->m_vHoldReplayData = hs->GetHoldReplayDataVector(); - pss->m_vNoteRowVector = hs->GetNoteRowVector(); - pss->m_vOffsetVector = hs->GetOffsetVector(); - pss->m_vTapNoteTypeVector = hs->GetTapNoteTypeVector(); - pss->m_vTrackVector = hs->GetTrackVector(); + } + if (GamePreferences::m_AutoPlay.Get() == PC_REPLAY) { + // We need to replace the newly created replay data with the actual old + // data Because to keep consistently lazy practices, we can just hack + // things together instead of fixing the real issue -poco + // (doing this fixes a lot of issues in the eval screen) + PlayerStageStats* pss = m_vPlayerInfo[PLAYER_1].GetPlayerStageStats(); + HighScore* hs = PlayerAI::pScoreData; + pss->m_vHoldReplayData = hs->GetHoldReplayDataVector(); + pss->m_vNoteRowVector = hs->GetNoteRowVector(); + pss->m_vOffsetVector = hs->GetOffsetVector(); + pss->m_vTapNoteTypeVector = hs->GetTapNoteTypeVector(); + pss->m_vTrackVector = hs->GetTrackVector(); } } @@ -3012,7 +3012,8 @@ class LunaScreenGameplay : public Luna static int SetReplayPosition(T* p, lua_State* L) { float newpos = FArg(1); - if (GAMESTATE->GetPaused() && GamePreferences::m_AutoPlay == PC_REPLAY) { + if (GAMESTATE->GetPaused() && + GamePreferences::m_AutoPlay == PC_REPLAY) { p->SetSongPosition(newpos); } /* diff --git a/src/ScreenInstallOverlay.cpp b/src/ScreenInstallOverlay.cpp index 4b1f8ad761..c38d09094e 100644 --- a/src/ScreenInstallOverlay.cpp +++ b/src/ScreenInstallOverlay.cpp @@ -192,7 +192,7 @@ DoInstalls(CommandLineActions::CommandLineArgs args) #if !defined(WITHOUT_NETWORKING) DLMAN->DownloadAndInstallPack(s); #else - // TODO: Figure out a meaningful log message. + // TODO: Figure out a meaningful log message. #endif } else if (IsPackageFile(s)) { InstallSmzipOsArg(s); @@ -279,7 +279,7 @@ ScreenInstallOverlay::Update(float fDeltaTime) } MESSAGEMAN->Broadcast(msg); } - + #endif } diff --git a/src/ScreenManager.cpp b/src/ScreenManager.cpp index 25f38ca85c..0bda11ce6f 100644 --- a/src/ScreenManager.cpp +++ b/src/ScreenManager.cpp @@ -919,13 +919,12 @@ ScreenManager::ZeroNextUpdate() /** @brief Offer a quick way to play any critical sound. */ #define PLAY_CRITICAL(snd) \ - \ -{ \ + \ + { \ RageSoundParams p; \ p.m_bIsCriticalSound = true; \ (snd).Play(false, &p); \ - \ -} + } /* Always play these sounds, even if we're in a silent attract loop. */ void diff --git a/src/ScreenMapControllers.cpp b/src/ScreenMapControllers.cpp index 633329ccaf..93b8d87d0f 100644 --- a/src/ScreenMapControllers.cpp +++ b/src/ScreenMapControllers.cpp @@ -214,8 +214,8 @@ ScreenMapControllers::Init() m_LineScroller.SetName("LineScroller"); ActorUtil::LoadAllCommands(m_LineScroller, m_sName); - m_LineScroller.SetNumItemsToDraw(static_cast(m_LineScroller.GetNumChildren()) * - 2); + m_LineScroller.SetNumItemsToDraw( + static_cast(m_LineScroller.GetNumChildren()) * 2); m_LineScroller.Load2(); this->AddChild(&m_LineScroller); diff --git a/src/ScreenOptions.cpp b/src/ScreenOptions.cpp index 4c5f7bba31..52da808296 100644 --- a/src/ScreenOptions.cpp +++ b/src/ScreenOptions.cpp @@ -470,7 +470,8 @@ ScreenOptions::TweenCursor(PlayerNumber pn) GetWidthXY(pn, iRow, iChoiceWithFocus, iWidth, iX, iY); OptionsCursor& cursor = m_Cursor[pn]; - if (cursor.GetDestX() != static_cast(iX) || cursor.GetDestY() != static_cast(iY) || + if (cursor.GetDestX() != static_cast(iX) || + cursor.GetDestY() != static_cast(iY) || cursor.GetBarWidth() != iWidth) { cursor.StopTweening(); cursor.BeginTweening(CURSOR_TWEEN_SECONDS); diff --git a/src/ScreenOptionsMasterPrefs.cpp b/src/ScreenOptionsMasterPrefs.cpp index 3c62ba011f..181a3fd078 100644 --- a/src/ScreenOptionsMasterPrefs.cpp +++ b/src/ScreenOptionsMasterPrefs.cpp @@ -59,7 +59,8 @@ FindClosestEntry(T value, const U* mapping, unsigned cnt) for (unsigned i = 0; i < cnt; ++i) { const U val = mapping[i]; - float dist = value < val ? static_cast(val - value) : static_cast(value - val); + float dist = value < val ? static_cast(val - value) + : static_cast(value - val); if (have_best && best_dist < dist) continue; diff --git a/src/ScreenProfileSave.cpp b/src/ScreenProfileSave.cpp index b485526dd5..48362207ab 100644 --- a/src/ScreenProfileSave.cpp +++ b/src/ScreenProfileSave.cpp @@ -21,7 +21,8 @@ ScreenProfileSave::Input(const InputEventPlus& input) void ScreenProfileSave::Continue() { - DLMAN->chartLeaderboards.clear(); // clear cached leaderboard scores when saving after gameplay -mina + DLMAN->chartLeaderboards.clear(); // clear cached leaderboard scores when + // saving after gameplay -mina GAMESTATE->SavePlayerProfiles(); SCREENMAN->ZeroNextUpdate(); diff --git a/src/ScreenSelectMaster.cpp b/src/ScreenSelectMaster.cpp index 4b48d89e89..11819c9dd9 100644 --- a/src/ScreenSelectMaster.cpp +++ b/src/ScreenSelectMaster.cpp @@ -40,17 +40,13 @@ OPTION_ORDER_NAME(size_t dir) REGISTER_SCREEN_CLASS(ScreenSelectMaster); #define GetActiveElementPlayerNumbers(vpns) \ - \ -if(SHARED_SELECTION) \ - { \ + \ + if (SHARED_SELECTION) { \ (vpns).push_back(PLAYER_1); \ - \ -} \ - else \ - { \ + \ + } else { \ FOREACH_HumanPlayer(p)(vpns).push_back(p); \ - \ -} + } ScreenSelectMaster::ScreenSelectMaster() { @@ -1017,7 +1013,8 @@ ScreenSelectMaster::TweenOnScreen() m_vsprScroll[*p][c]->FinishTweening(); } - m_Scroller[*p].SetCurrentAndDestinationItem(static_cast(m_iChoice[*p])); + m_Scroller[*p].SetCurrentAndDestinationItem( + static_cast(m_iChoice[*p])); } } diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index a7e5db64d3..1a568a5a2a 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1814,7 +1814,8 @@ class LunaScreenSelectMusic : public Luna steps->GetNoteData(nd); float songlength = GAMESTATE->m_pCurSong->m_fMusicLengthSeconds; ss.Init(); - SCOREMAN->camefromreplay = false; // disallow viewing online score eval screens -mina + SCOREMAN->camefromreplay = + false; // disallow viewing online score eval screens -mina auto score = SCOREMAN->GetMostRecentScore(); score->LoadReplayData(); PlayerAI::SetScoreData(score); diff --git a/src/ScreenSelectMusic.h b/src/ScreenSelectMusic.h index 52e1baa1b1..9979c362aa 100644 --- a/src/ScreenSelectMusic.h +++ b/src/ScreenSelectMusic.h @@ -65,8 +65,8 @@ class ScreenSelectMusic : public ScreenWithMenuElements int GetSelectionState(); // Generate and Display a "fake" NoteField ActorFrame on the Screen. - // It functions relatively normally, according to the currently playing music. - // It automatically deletes any other pre-existing Preview NoteField. + // It functions relatively normally, according to the currently playing + // music. It automatically deletes any other pre-existing Preview NoteField. void GeneratePreviewNoteField(); // Manually delete a Preview NoteField. // Note: This is triggered by a DeletePreviewNoteField Message. @@ -78,7 +78,7 @@ class ScreenSelectMusic : public ScreenWithMenuElements NoteData m_PreviewNoteData; NoteField* m_pPreviewNoteField; - void ChangeSteps(PlayerNumber pn, int dir); + void ChangeSteps(PlayerNumber pn, int dir); // Lua void PushSelf(lua_State* L) override; diff --git a/src/Song.cpp b/src/Song.cpp index b508fe1101..54cae5c6b9 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -2056,7 +2056,8 @@ Song::Borp() PlayParams.pTiming = nullptr; PlayParams.bForceLoop = true; PlayParams.fStartSecond = m_fMusicSampleStartSeconds; - PlayParams.fLengthSeconds = GetLastSecond() - m_fMusicSampleStartSeconds + 2.f; + PlayParams.fLengthSeconds = + GetLastSecond() - m_fMusicSampleStartSeconds + 2.f; PlayParams.fFadeOutLengthSeconds = 1.f; PlayParams.bAlignBeat = true; PlayParams.bApplyMusicRate = true; diff --git a/src/Song.h b/src/Song.h index d9ede3b4c0..82e92b101b 100644 --- a/src/Song.h +++ b/src/Song.h @@ -441,7 +441,8 @@ class Song // plays music for chart preview and is available to lua -mina void Borp(); - // plays just normal preview, for those annoying places in lua where it doesnt play properly -mina + // plays just normal preview, for those annoying places in lua where it + // doesnt play properly -mina void Norf(); bool SongCompleteForStyle(const Style* st) const; diff --git a/src/SongCacheIndex.cpp b/src/SongCacheIndex.cpp index 50146bde9f..8a25a85bb5 100644 --- a/src/SongCacheIndex.cpp +++ b/src/SongCacheIndex.cpp @@ -887,7 +887,8 @@ SongCacheIndex::SongFromStatement(Song* song, SQLite::Statement& query) SSCLoader loader; int songid = query.getColumn(0); int index = 1; - song->m_fVersion = static_cast(static_cast(query.getColumn(index++))); + song->m_fVersion = + static_cast(static_cast(query.getColumn(index++))); song->m_sMainTitle = static_cast(query.getColumn(index++)); song->m_sSubTitle = static_cast(query.getColumn(index++)); song->m_sArtist = static_cast(query.getColumn(index++)); @@ -916,11 +917,11 @@ SongCacheIndex::SongFromStatement(Song* song, SQLite::Statement& query) loader.ProcessInstrumentTracks( *song, static_cast(query.getColumn(index++))); song->m_SongTiming.m_fBeat0OffsetInSeconds = - static_cast(static_cast(query.getColumn(index++))); + static_cast(static_cast(query.getColumn(index++))); song->m_fMusicSampleStartSeconds = - static_cast(static_cast(query.getColumn(index++))); + static_cast(static_cast(query.getColumn(index++))); song->m_fMusicSampleLengthSeconds = - static_cast(static_cast(query.getColumn(index++))); + static_cast(static_cast(query.getColumn(index++))); int selection = static_cast(query.getColumn(index++)); if (selection == 0) @@ -930,8 +931,10 @@ SongCacheIndex::SongFromStatement(Song* song, SQLite::Statement& query) int bpmminIndex = index++; int bpmmaxIndex = index++; - float BPMmin = static_cast(static_cast(query.getColumn(bpmminIndex))); - float BPMmax = static_cast(static_cast(query.getColumn(bpmmaxIndex))); + float BPMmin = + static_cast(static_cast(query.getColumn(bpmminIndex))); + float BPMmax = + static_cast(static_cast(query.getColumn(bpmmaxIndex))); if (query.isColumnNull(bpmminIndex) || query.isColumnNull(bpmmaxIndex)) { if (query.isColumnNull(bpmminIndex) && query.isColumnNull(bpmmaxIndex)) song->m_DisplayBPMType = DISPLAY_BPM_ACTUAL; @@ -973,7 +976,8 @@ SongCacheIndex::SongFromStatement(Song* song, SQLite::Statement& query) static_cast(query.getColumn(index++)), title); - song->SetSpecifiedLastSecond(static_cast(static_cast(query.getColumn(index++)))); + song->SetSpecifiedLastSecond( + static_cast(static_cast(query.getColumn(index++)))); string animations = static_cast(query.getColumn(index++)); string animationstwo = static_cast(query.getColumn(index++)); @@ -994,12 +998,15 @@ SongCacheIndex::SongFromStatement(Song* song, SQLite::Statement& query) keysounds = keysounds.substr(1); } split(keysounds, ",", song->m_vsKeysoundFile); - song->SetFirstSecond(static_cast(static_cast(query.getColumn(index++)))); - song->SetLastSecond(static_cast(static_cast(query.getColumn(index++)))); + song->SetFirstSecond( + static_cast(static_cast(query.getColumn(index++)))); + song->SetLastSecond( + static_cast(static_cast(query.getColumn(index++)))); song->m_sSongFileName = static_cast(query.getColumn(index++)); song->m_bHasMusic = static_cast(query.getColumn(index++)) != 0; song->m_bHasBanner = static_cast(query.getColumn(index++)) != 0; - song->m_fMusicLengthSeconds = static_cast(static_cast(query.getColumn(index++))); + song->m_fMusicLengthSeconds = + static_cast(static_cast(query.getColumn(index++))); int dirhash = query.getColumn(index++); string dir = query.getColumn(index++); song->SetSongDir(dir); @@ -1068,8 +1075,8 @@ SongCacheIndex::SongFromStatement(Song* song, SQLite::Statement& query) TimingData stepsTiming = TimingData(song->m_SongTiming.m_fBeat0OffsetInSeconds); // Load timing data - stepsTiming.m_fBeat0OffsetInSeconds = - static_cast(static_cast(qTiming.getColumn(timingIndex++))); + stepsTiming.m_fBeat0OffsetInSeconds = static_cast( + static_cast(qTiming.getColumn(timingIndex++))); SSCLoader::ProcessBPMs( stepsTiming, static_cast(qTiming.getColumn(timingIndex++)), @@ -1133,8 +1140,10 @@ SongCacheIndex::SongFromStatement(Song* song, SQLite::Statement& query) int bpmminIndex = stepsIndex++; int bpmmaxIndex = stepsIndex++; - float BPMmin = static_cast(static_cast(qSteps.getColumn(bpmminIndex))); - float BPMmax = static_cast(static_cast(qSteps.getColumn(bpmmaxIndex))); + float BPMmin = static_cast( + static_cast(qSteps.getColumn(bpmminIndex))); + float BPMmax = static_cast( + static_cast(qSteps.getColumn(bpmmaxIndex))); if (qSteps.isColumnNull(bpmminIndex) || qSteps.isColumnNull(bpmmaxIndex)) { if (qSteps.isColumnNull(bpmminIndex) && diff --git a/src/Sprite.cpp b/src/Sprite.cpp index 244266227c..9de8f83f32 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -922,14 +922,15 @@ void Sprite::SetCustomImageRect(RectF rectImageCoords) { // Convert to a rectangle in texture coordinate space. - rectImageCoords.left *= - m_pTexture->GetImageWidth() / static_cast(m_pTexture->GetTextureWidth()); - rectImageCoords.right *= - m_pTexture->GetImageWidth() / static_cast(m_pTexture->GetTextureWidth()); - rectImageCoords.top *= - m_pTexture->GetImageHeight() / static_cast(m_pTexture->GetTextureHeight()); + rectImageCoords.left *= m_pTexture->GetImageWidth() / + static_cast(m_pTexture->GetTextureWidth()); + rectImageCoords.right *= m_pTexture->GetImageWidth() / + static_cast(m_pTexture->GetTextureWidth()); + rectImageCoords.top *= m_pTexture->GetImageHeight() / + static_cast(m_pTexture->GetTextureHeight()); rectImageCoords.bottom *= - m_pTexture->GetImageHeight() / static_cast(m_pTexture->GetTextureHeight()); + m_pTexture->GetImageHeight() / + static_cast(m_pTexture->GetTextureHeight()); SetCustomTextureRect(rectImageCoords); } diff --git a/src/StageStats.cpp b/src/StageStats.cpp index 71724d0fef..c2e40837bf 100644 --- a/src/StageStats.cpp +++ b/src/StageStats.cpp @@ -21,7 +21,7 @@ #include "Song.h" #include "GamePreferences.h" -#ifndef _WIN32 +#ifndef _WIN32 #include #endif @@ -236,7 +236,7 @@ uint16_t getCpuHash() { uint32_t cpuinfo[4] = { 0, 0, 0, 0 }; - __get_cpuid(0, &cpuinfo[0], &cpuinfo[1], &cpuinfo[2], &cpuinfo[3]); + __get_cpuid(0, &cpuinfo[0], &cpuinfo[1], &cpuinfo[2], &cpuinfo[3]); uint16_t hash = 0; uint32_t* ptr = (&cpuinfo[0]); for (uint32_t i = 0; i < 4; i++) @@ -607,7 +607,8 @@ FillInHighScore(const PlayerStageStats& pss, void StageStats::FinalizeScores(bool bSummary) { - SCOREMAN->camefromreplay = false; // if we're viewing an online replay this gets set to true -mina + SCOREMAN->camefromreplay = + false; // if we're viewing an online replay this gets set to true -mina if (PREFSMAN->m_sTestInitialScreen.Get() != "") { FOREACH_PlayerNumber(pn) { @@ -661,7 +662,8 @@ StageStats::FinalizeScores(bool bSummary) SCOREMAN->tempscoreforonlinereplayviewing->SetRadarValues( hs.GetRadarValues()); SCOREMAN->camefromreplay = true; - } else { // dont do this if the replay was from online or bad stuff happens -mina + } else { // dont do this if the replay was from online or bad stuff + // happens -mina mostrecentscorekey = PlayerAI::pScoreData->GetScoreKey(); SCOREMAN->PutScoreAtTheTop(mostrecentscorekey); SCOREMAN->GetMostRecentScore()->SetRadarValues( diff --git a/src/StdString.h b/src/StdString.h index 06b28962be..e7df9a0c57 100644 --- a/src/StdString.h +++ b/src/StdString.h @@ -547,8 +547,8 @@ class CStdStr : public std::basic_string MYTYPE& assign(const CT* pC, MYSIZE nChars) { - // Q172398 only fix -- erase before assigning, but not if we're - // assigning from our own buffer + // Q172398 only fix -- erase before assigning, but not if we're + // assigning from our own buffer #if defined(_MSC_VER) && (_MSC_VER < 1200) if (!this->empty() && @@ -618,7 +618,7 @@ class CStdStr : public std::basic_string return *this; } - // addition operators -- global friend functions. + // addition operators -- global friend functions. #if defined(_MSC_VER) && _MSC_VER < 1300 /* VC6, not VC7 */ /* work around another stupid vc6 bug */ diff --git a/src/StepMania.cpp b/src/StepMania.cpp index a39f50a4ea..1689a8310d 100644 --- a/src/StepMania.cpp +++ b/src/StepMania.cpp @@ -528,19 +528,18 @@ struct VideoCardDefaults 2048, false // broken, causes black screen ), - VideoCardDefaults( - "Savage", - "d3d", - // OpenGL is unusable on my Savage IV with even the latest drivers. - // It draws 30 frames of gibberish then crashes. This happens even with - // simple NeHe demos. -Chris - 640, - 480, - 16, - 16, - 16, - 2048, - false), + VideoCardDefaults("Savage", + "d3d", + // OpenGL is unusable on my Savage IV with even the latest + // drivers. It draws 30 frames of gibberish then crashes. + // This happens even with simple NeHe demos. -Chris + 640, + 480, + 16, + 16, + 16, + 2048, + false), VideoCardDefaults( "XPERT@PLAY|IIC|RAGE PRO|RAGE LT PRO", // Rage Pro chip, Rage IIC chip "d3d", @@ -1504,12 +1503,12 @@ HandleGlobalInputs(const InputEventPlus& input) &input.InputList) || INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LALT), &input.InputList))) { - // alt-enter - /* In OS X, this is a menu item and will be handled as such. This will - * happen first and then the lower priority GUI thread will happen second, - * causing the window to toggle twice. Another solution would be to put - * a timer in ArchHooks::SetToggleWindowed() and just not set the bool - * it if it's been less than, say, half a second. */ + // alt-enter + /* In OS X, this is a menu item and will be handled as such. This will + * happen first and then the lower priority GUI thread will happen + * second, causing the window to toggle twice. Another solution would be + * to put a timer in ArchHooks::SetToggleWindowed() and just not set the + * bool it if it's been less than, say, half a second. */ #if !defined(MACOSX) ArchHooks::SetToggleWindowed(); #endif diff --git a/src/Steps.cpp b/src/Steps.cpp index f1c738e715..d945953e3f 100644 --- a/src/Steps.cpp +++ b/src/Steps.cpp @@ -688,7 +688,10 @@ Steps::SetCachedRadarValues(const RadarValues& rv) } vector -Steps::GetNPSVector(NoteData& nd, vector nerv, vector etaner, float rate) +Steps::GetNPSVector(NoteData& nd, + vector nerv, + vector etaner, + float rate) { vector doot(static_cast(etaner.back())); int notecounter = 0; @@ -714,10 +717,15 @@ Steps::GetNPSVector(NoteData& nd, vector nerv, vector etaner, float } vector -Steps::GetCNPSVector(NoteData& nd, vector nerv, vector etaner, int chordsize, float rate) +Steps::GetCNPSVector(NoteData& nd, + vector nerv, + vector etaner, + int chordsize, + float rate) { vector doot(static_cast(etaner.back())); - int chordnotecounter = 0; // number of NOTES inside chords of this size, so 5 jumps = 10 notes, 3 hands = 9 notes, etc + int chordnotecounter = 0; // number of NOTES inside chords of this size, so + // 5 jumps = 10 notes, 3 hands = 9 notes, etc int lastinterval = 0; int curinterval = 0; @@ -911,16 +919,27 @@ class LunaSteps : public Luna const vector& etaner = p->GetTimingData()->BuildAndGetEtaner(nerv); - // directly using CreateTableFromArray(p->GetNPSVector(nd, nerv, etaner), L) produced tables full of 0 values for ???? reason -mina + // directly using CreateTableFromArray(p->GetNPSVector(nd, nerv, + // etaner), L) produced tables full of 0 values for ???? reason -mina vector scroot = p->GetNPSVector(nd, nerv, etaner, rate); lua_newtable(L); LuaHelpers::CreateTableFromArray(scroot, L); lua_rawseti(L, -2, 1); for (int i = 1; i < nd.GetNumTracks(); ++i) { - scroot = p->GetCNPSVector(nd, nerv, etaner, i + 1, rate);// sort of confusing: the luatable pos/chordsize are i + 1 - LuaHelpers::CreateTableFromArray(scroot, L); // but we're iterating over tracks which are 0 indexed - lua_rawseti(L, -2, i + 1); // so jumps are position 2 and 2 notes each when i = 1 -mina + scroot = p->GetCNPSVector( + nd, + nerv, + etaner, + i + 1, + rate); // sort of confusing: the luatable pos/chordsize are i + 1 + LuaHelpers::CreateTableFromArray( + scroot, L); // but we're iterating over tracks which are 0 indexed + lua_rawseti( + L, + -2, + i + + 1); // so jumps are position 2 and 2 notes each when i = 1 -mina } nd.UnsetNerv(); p->GetTimingData()->UnsetEtaner(); diff --git a/src/ThemeManager.cpp b/src/ThemeManager.cpp index 67d0e9a4be..13e0103c86 100644 --- a/src/ThemeManager.cpp +++ b/src/ThemeManager.cpp @@ -388,8 +388,7 @@ ThemeManager::LoadThemeMetrics(const RString& sThemeName_, g_pLoadedThemeData->iniMetrics.SetValue(sBits[0], sBits[1], sBits[2]); } - if (PREFSMAN->m_verbose_log > 1) - { + if (PREFSMAN->m_verbose_log > 1) { LOG->MapLog("theme", "Theme: %s", m_sCurThemeName.c_str()); LOG->MapLog("language", "Language: %s", m_sCurLanguage.c_str()); } @@ -1499,8 +1498,8 @@ class LunaThemeManager : public Luna lua_pushstring(L, pi.sMatchingElement); return 3; } - // GENERAL_GET_PATH uses lua_toboolean instead of BArg because that - // makes it optional. -Kyz + // GENERAL_GET_PATH uses lua_toboolean instead of BArg because that + // makes it optional. -Kyz #define GENERAL_GET_PATH(get_path_name) \ static int get_path_name(T* p, lua_State* L) \ { \ diff --git a/src/XMLProfile.cpp b/src/XMLProfile.cpp index 14eb7ca933..f4ec14eac3 100644 --- a/src/XMLProfile.cpp +++ b/src/XMLProfile.cpp @@ -621,7 +621,9 @@ XMLProfile::SaveEttGeneralDataCreateNode(const Profile* profile) const pGeneralDataNode->AppendChild("SortOrder", SortOrderToString(profile->m_SortOrder)); - if (profile->m_LastDifficulty < 0) // force set difficulty to current steps if this is somehow -1 for ??? reasons -mina + if (profile->m_LastDifficulty < + 0) // force set difficulty to current steps if this is somehow -1 for + // ??? reasons -mina pGeneralDataNode->AppendChild( "LastDifficulty", DifficultyToString( diff --git a/src/arch/ArchHooks/ArchHooks_Win32.cpp b/src/arch/ArchHooks/ArchHooks_Win32.cpp index 4e381c290f..2381b2bdc0 100644 --- a/src/arch/ArchHooks/ArchHooks_Win32.cpp +++ b/src/arch/ArchHooks/ArchHooks_Win32.cpp @@ -265,8 +265,8 @@ ArchHooks_Win32::GetClipboard() return ""; } - // And finally, we have a char (or wchar_t) array of the clipboard - // contents, pointed to by sToPaste. (Hopefully.) + // And finally, we have a char (or wchar_t) array of the clipboard + // contents, pointed to by sToPaste. (Hopefully.) #ifdef UNICODE ret = WStringToRString(wstring() + *lpstr); diff --git a/src/arch/InputHandler/InputHandler_DirectInput.cpp b/src/arch/InputHandler/InputHandler_DirectInput.cpp index 018e34bdf7..02c23b2e38 100644 --- a/src/arch/InputHandler/InputHandler_DirectInput.cpp +++ b/src/arch/InputHandler/InputHandler_DirectInput.cpp @@ -27,11 +27,12 @@ EnumDevicesCallback(const DIDEVICEINSTANCE* pdidInstance, void* pContext) DIDevice device; if (PREFSMAN->m_verbose_log > 1) - LOG->Info("DInput: Enumerating device - Type: 0x%08X Instance Name: \"%s\" " - "Product Name: \"%s\"", - pdidInstance->dwDevType, - pdidInstance->tszInstanceName, - pdidInstance->tszProductName); + LOG->Info( + "DInput: Enumerating device - Type: 0x%08X Instance Name: \"%s\" " + "Product Name: \"%s\"", + pdidInstance->dwDevType, + pdidInstance->tszInstanceName, + pdidInstance->tszProductName); switch (GET_DIDEVICE_TYPE(pdidInstance->dwDevType)) { case DI8DEVTYPE_JOYSTICK: diff --git a/src/arch/InputHandler/InputHandler_DirectInputHelper.cpp b/src/arch/InputHandler/InputHandler_DirectInputHelper.cpp index 9c6df9f21c..f1f4a78cfc 100644 --- a/src/arch/InputHandler/InputHandler_DirectInputHelper.cpp +++ b/src/arch/InputHandler/InputHandler_DirectInputHelper.cpp @@ -35,8 +35,8 @@ bool DIDevice::Open() { m_sName = ConvertACPToUTF8(JoystickInst.tszProductName); - - if(PREFSMAN->m_verbose_log > 1) + + if (PREFSMAN->m_verbose_log > 1) LOG->Trace("Opening device '%s'", m_sName.c_str()); buffered = true; diff --git a/src/arch/LowLevelWindow/LowLevelWindow_Win32.cpp b/src/arch/LowLevelWindow/LowLevelWindow_Win32.cpp index d1e7425c11..e98cf2f67e 100644 --- a/src/arch/LowLevelWindow/LowLevelWindow_Win32.cpp +++ b/src/arch/LowLevelWindow/LowLevelWindow_Win32.cpp @@ -135,7 +135,7 @@ DumpPixelFormat(const PIXELFORMATDESCRIPTOR& pfd) if (bInvalidFormat) LOG->Warn("Invalid format: %s", str.c_str()); else if (PREFSMAN->m_verbose_log > 1) - LOG->Info("%s", str.c_str()); + LOG->Info("%s", str.c_str()); } /* This function does not reset the video mode if it fails, because we might be diff --git a/src/arch/LowLevelWindow/LowLevelWindow_X11.cpp b/src/arch/LowLevelWindow/LowLevelWindow_X11.cpp index 3503dbbd12..9d34ac685e 100644 --- a/src/arch/LowLevelWindow/LowLevelWindow_X11.cpp +++ b/src/arch/LowLevelWindow/LowLevelWindow_X11.cpp @@ -358,7 +358,7 @@ LowLevelWindow_X11::SwapBuffers() glXSwapBuffers(Dpy, Win); if (true) { - // Disable the screensaver. + // Disable the screensaver. #if defined(HAVE_LIBXTST) // This causes flicker. // XForceScreenSaver( Dpy, ScreenSaverReset ); diff --git a/src/arch/MovieTexture/MovieTexture.cpp b/src/arch/MovieTexture/MovieTexture.cpp index d0695f7a48..eb974f2ce3 100644 --- a/src/arch/MovieTexture/MovieTexture.cpp +++ b/src/arch/MovieTexture/MovieTexture.cpp @@ -32,8 +32,8 @@ RageMovieTexture::GetFourCC(const RString& fn, RString& handler, RString& type) return true; } - // Not very pretty but should do all the same error checking without - // iostream + // Not very pretty but should do all the same error checking without + // iostream #define HANDLE_ERROR(x) \ { \ LOG->Warn("Error reading %s: %s", fn.c_str(), x); \ diff --git a/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp b/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp index 04fbf8fb17..d4af116628 100644 --- a/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp +++ b/src/arch/MovieTexture/MovieTexture_FFMpeg.cpp @@ -295,8 +295,8 @@ MovieDecoder_FFMpeg::DecodePacket(float fTargetTime) } if (m_Frame->pkt_dts != AV_NOPTS_VALUE) { - m_fTimestamp = - static_cast(m_Frame->pkt_dts * av_q2d(m_pStream->time_base)); + m_fTimestamp = static_cast(m_Frame->pkt_dts * + av_q2d(m_pStream->time_base)); } else { /* If the timestamp is zero, this frame is to be played at the * time of the last frame plus the length of the last frame. */ diff --git a/src/arch/Sound/RageSoundDriver.cpp b/src/arch/Sound/RageSoundDriver.cpp index d55cbbf9b5..8f22812b2f 100644 --- a/src/arch/Sound/RageSoundDriver.cpp +++ b/src/arch/Sound/RageSoundDriver.cpp @@ -52,7 +52,7 @@ RageSoundDriver::Create(const RString& drivers) const RString sError = pRet->Init(); if (sError.empty()) { - if(PREFSMAN->m_verbose_log > 1) + if (PREFSMAN->m_verbose_log > 1) LOG->Info("Sound driver: %s", Driver->c_str()); return pRet; } diff --git a/src/arch/Sound/RageSoundDriver_Generic_Software.cpp b/src/arch/Sound/RageSoundDriver_Generic_Software.cpp index 3e3fe465a1..c39ba45986 100644 --- a/src/arch/Sound/RageSoundDriver_Generic_Software.cpp +++ b/src/arch/Sound/RageSoundDriver_Generic_Software.cpp @@ -323,13 +323,12 @@ RageSoundDriver::Update() /* Lockless: only Mix() can write to underruns. */ int current_underruns = underruns; if (current_underruns > logged_underruns) { - if (PREFSMAN->m_verbose_log > 1) - { + if (PREFSMAN->m_verbose_log > 1) { LOG->MapLog("GenericMixingUnderruns", - "Mixing underruns: %i", - current_underruns - logged_underruns); + "Mixing underruns: %i", + current_underruns - logged_underruns); LOG->Trace("Mixing underruns: %i", - current_underruns - logged_underruns); + current_underruns - logged_underruns); } logged_underruns = current_underruns; @@ -406,7 +405,7 @@ RageSoundDriver::StopMixing(RageSoundBase* pSound) break; if (i == ARRAYLEN(m_Sounds)) { m_Mutex.Unlock(); - if(PREFSMAN->m_verbose_log > 1) + if (PREFSMAN->m_verbose_log > 1) LOG->Trace("not stopping a sound because it's not playing"); return; } diff --git a/src/arch/Sound/RageSoundDriver_OSS.cpp b/src/arch/Sound/RageSoundDriver_OSS.cpp index 7677e73a63..4a166dd603 100644 --- a/src/arch/Sound/RageSoundDriver_OSS.cpp +++ b/src/arch/Sound/RageSoundDriver_OSS.cpp @@ -128,21 +128,21 @@ RageSoundDriver_OSS::CheckOSSVersion(int fd) } #endif - /* - * Find out if /dev/dsp is really ALSA emulating it. ALSA's OSS - * emulation has been buggy. If we got here, we probably failed to init - * ALSA. The only case I've seen of this so far was not having access - * to /dev/snd devices. - */ - /* Reliable but only too recently available: - if (ioctl(fd, OSS_ALSAEMULVER, &ver) == 0 && ver ) */ - - /* - * Ack. We can't just check for /proc/asound, since a few systems have - * ALSA loaded but actually use OSS. ALSA returns a specific version; - * check that, too. It looks like that version is potentially a valid - * OSS version, so check both. - */ + /* + * Find out if /dev/dsp is really ALSA emulating it. ALSA's OSS + * emulation has been buggy. If we got here, we probably failed to init + * ALSA. The only case I've seen of this so far was not having access + * to /dev/snd devices. + */ + /* Reliable but only too recently available: + if (ioctl(fd, OSS_ALSAEMULVER, &ver) == 0 && ver ) */ + + /* + * Ack. We can't just check for /proc/asound, since a few systems have + * ALSA loaded but actually use OSS. ALSA returns a specific version; + * check that, too. It looks like that version is potentially a valid + * OSS version, so check both. + */ #ifndef FORCE_OSS #define ALSA_SNDRV_OSS_VERSION ((3 << 16) | (8 << 8) | (1 << 4) | (0)) if (version == ALSA_SNDRV_OSS_VERSION && diff --git a/src/arch/Sound/RageSoundDriver_WaveOut.cpp b/src/arch/Sound/RageSoundDriver_WaveOut.cpp index 3801a1f352..8c728df701 100644 --- a/src/arch/Sound/RageSoundDriver_WaveOut.cpp +++ b/src/arch/Sound/RageSoundDriver_WaveOut.cpp @@ -159,7 +159,7 @@ RageSoundDriver_WaveOut::Init() m_aBuffers[b].dwFlags |= WHDR_DONE; } - if(PREFSMAN->m_verbose_log > 1) + if (PREFSMAN->m_verbose_log > 1) LOG->Info("WaveOut software mixing at %i hz", m_iSampleRate); /* We have a very large writeahead; make sure we have a large enough decode diff --git a/src/archutils/Unix/BacktraceNames.cpp b/src/archutils/Unix/BacktraceNames.cpp index 136dec2eb9..cbc7b29654 100644 --- a/src/archutils/Unix/BacktraceNames.cpp +++ b/src/archutils/Unix/BacktraceNames.cpp @@ -138,31 +138,31 @@ BacktraceNames::FromAddr(void* const p) } #elif defined(BACKTRACE_LOOKUP_METHOD_DARWIN_DYLD) - /* - Copyright (c) 2002 Jorge Acereda & - Peter O'Gorman - - 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. - - Cleaned and adapted. -glenn - */ +/* +Copyright (c) 2002 Jorge Acereda & + Peter O'Gorman + +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. + + Cleaned and adapted. -glenn +*/ #include #include diff --git a/src/archutils/Win32/Crash.cpp b/src/archutils/Win32/Crash.cpp index f60ac6cad6..25a24eb418 100644 --- a/src/archutils/Win32/Crash.cpp +++ b/src/archutils/Win32/Crash.cpp @@ -553,7 +553,7 @@ CrashHandler::do_backtrace(const void** buf, pStackBase = (char*)pTib->StackBase; } - // Walk up the stack. + // Walk up the stack. #if _WIN64 const char* lpAddr = (const char*)pContext->Rip; const void* data = (void*)pContext->Rip; diff --git a/src/archutils/Win32/DebugInfoHunt.cpp b/src/archutils/Win32/DebugInfoHunt.cpp index 59c8b03204..08735da9f3 100644 --- a/src/archutils/Win32/DebugInfoHunt.cpp +++ b/src/archutils/Win32/DebugInfoHunt.cpp @@ -11,15 +11,14 @@ static void LogVideoDriverInfo(VideoDriverInfo info) { - if (PREFSMAN->m_verbose_log > 1) - { + if (PREFSMAN->m_verbose_log > 1) { LOG->Info("Video driver: %s [%s]", - info.sDescription.c_str(), - info.sProvider.c_str()); + info.sDescription.c_str(), + info.sProvider.c_str()); LOG->Info(" %s, %s [%s]", - info.sVersion.c_str(), - info.sDate.c_str(), - info.sDeviceID.c_str()); + info.sVersion.c_str(), + info.sDate.c_str(), + info.sDeviceID.c_str()); } } @@ -50,7 +49,8 @@ GetDisplayDriverDebugInfo() if (!GetVideoDriverInfo(i, info)) break; - if (sPrimaryDeviceName == "") // failed to get primary display name (NT4) + if (sPrimaryDeviceName == + "") // failed to get primary display name (NT4) { LogVideoDriverInfo(info); LoggedSomething = true; @@ -294,16 +294,16 @@ GetSoundDriverDebugInfo() LOG->Info(wo_ssprintf(ret, "waveOutGetDevCaps(%i) failed", i)); continue; } - if(PREFSMAN->m_verbose_log > 1) - LOG->Info("Sound device %i: %s, %i.%i, MID %i, PID %i %s", - i, - caps.szPname, - HIBYTE(caps.vDriverVersion), - LOBYTE(caps.vDriverVersion), - caps.wMid, - caps.wPid, - caps.dwSupport & WAVECAPS_SAMPLEACCURATE ? "" - : "(INACCURATE)"); + if (PREFSMAN->m_verbose_log > 1) + LOG->Info( + "Sound device %i: %s, %i.%i, MID %i, PID %i %s", + i, + caps.szPname, + HIBYTE(caps.vDriverVersion), + LOBYTE(caps.vDriverVersion), + caps.wMid, + caps.wPid, + caps.dwSupport & WAVECAPS_SAMPLEACCURATE ? "" : "(INACCURATE)"); } } diff --git a/src/archutils/Win32/GraphicsWindow.cpp b/src/archutils/Win32/GraphicsWindow.cpp index 22834704f1..0fd4e2e447 100644 --- a/src/archutils/Win32/GraphicsWindow.cpp +++ b/src/archutils/Win32/GraphicsWindow.cpp @@ -82,7 +82,8 @@ GraphicsWindow_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) sStr += (sStr.size() ? ", " : "") + *it; if (PREFSMAN != NULL && PREFSMAN->m_verbose_log > 1) - LOG->MapLog("LOST_FOCUS", "Lost focus to: %s", sStr.c_str()); + LOG->MapLog( + "LOST_FOCUS", "Lost focus to: %s", sStr.c_str()); } if (!g_bD3D && !g_CurrentParams.windowed && diff --git a/src/archutils/Win32/ddk/dbghelp.h b/src/archutils/Win32/ddk/dbghelp.h index 7d707d0922..f84bbf6e12 100644 --- a/src/archutils/Win32/ddk/dbghelp.h +++ b/src/archutils/Win32/ddk/dbghelp.h @@ -330,7 +330,8 @@ typedef struct _MODLOAD_DATA // StackWalking API // -typedef enum { +typedef enum +{ AddrMode1616, AddrMode1632, AddrModeReal, @@ -717,7 +718,8 @@ typedef BOOL(CALLBACK* PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess, // // symbol type enumeration // -typedef enum { +typedef enum +{ SymNone = 0, SymCoff, SymCv, @@ -1412,7 +1414,8 @@ SymEnumSymbolsForAddr(IN HANDLE hProcess, IN PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback, IN PVOID UserContext); -typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO { +typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO +{ TI_GET_SYMTAG, TI_GET_SYMNAME, TI_GET_LENGTH, @@ -1691,7 +1694,8 @@ typedef struct _MINIDUMP_STRING // the system and is reserved for program-specific information. // -typedef enum _MINIDUMP_STREAM_TYPE { +typedef enum _MINIDUMP_STREAM_TYPE +{ UnusedStream = 0, ReservedStream0 = 1, @@ -2116,7 +2120,8 @@ typedef struct _MINIDUMP_USER_STREAM_INFORMATION // Callback support. // -typedef enum _MINIDUMP_CALLBACK_TYPE { +typedef enum _MINIDUMP_CALLBACK_TYPE +{ ModuleCallback, ThreadCallback, ThreadExCallback, @@ -2151,7 +2156,8 @@ typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK ULONG ThreadId; } MINIDUMP_INCLUDE_THREAD_CALLBACK, *PMINIDUMP_INCLUDE_THREAD_CALLBACK; -typedef enum _THREAD_WRITE_FLAGS { +typedef enum _THREAD_WRITE_FLAGS +{ ThreadWriteThread = 0x0001, ThreadWriteStack = 0x0002, ThreadWriteContext = 0x0004, @@ -2179,7 +2185,8 @@ typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK ULONG64 BaseOfImage; } MINIDUMP_INCLUDE_MODULE_CALLBACK, *PMINIDUMP_INCLUDE_MODULE_CALLBACK; -typedef enum _MODULE_WRITE_FLAGS { +typedef enum _MODULE_WRITE_FLAGS +{ ModuleWriteModule = 0x0001, ModuleWriteDataSeg = 0x0002, ModuleWriteMiscRecord = 0x0004, @@ -2258,7 +2265,8 @@ typedef struct _MINIDUMP_CALLBACK_OUTPUT // of memory to be included in the dump. // -typedef enum _MINIDUMP_TYPE { +typedef enum _MINIDUMP_TYPE +{ MiniDumpNormal = 0x0000, MiniDumpWithDataSegs = 0x0001, MiniDumpWithFullMemory = 0x0002, diff --git a/src/archutils/Win32/ddk/hidpi.h b/src/archutils/Win32/ddk/hidpi.h index 1901a1295f..b37bd2cfe5 100644 --- a/src/archutils/Win32/ddk/hidpi.h +++ b/src/archutils/Win32/ddk/hidpi.h @@ -34,7 +34,8 @@ Module Name: #define HIDP_LINK_COLLECTION_ROOT ((USHORT)-1) #define HIDP_LINK_COLLECTION_UNSPECIFIED ((USHORT)0) -typedef enum _HIDP_REPORT_TYPE { +typedef enum _HIDP_REPORT_TYPE +{ HidP_Input, HidP_Output, HidP_Feature @@ -1584,7 +1585,8 @@ NTSTATUS __stdcall HidP_UsageAndPageListDifference( // // Produce Make or Break Codes // -typedef enum _HIDP_KEYBOARD_DIRECTION { +typedef enum _HIDP_KEYBOARD_DIRECTION +{ HidP_Keyboard_Break, HidP_Keyboard_Make } HIDP_KEYBOARD_DIRECTION; diff --git a/src/archutils/Win32/ddk/setupapi.h b/src/archutils/Win32/ddk/setupapi.h index a1446ebd28..d38ece0972 100644 --- a/src/archutils/Win32/ddk/setupapi.h +++ b/src/archutils/Win32/ddk/setupapi.h @@ -3479,7 +3479,8 @@ SetupRemoveFileLogEntryW(IN HSPFILELOG FileLogHandle, // // Items retrievable from SetupQueryFileLog() // -typedef enum { +typedef enum +{ SetupFileLogSourceFilename, SetupFileLogChecksum, SetupFileLogDiskTagfile, diff --git a/src/libtomcrypt/src/headers/tomcrypt_hash.h b/src/libtomcrypt/src/headers/tomcrypt_hash.h index 65c01fa0f9..10a8e896e5 100644 --- a/src/libtomcrypt/src/headers/tomcrypt_hash.h +++ b/src/libtomcrypt/src/headers/tomcrypt_hash.h @@ -437,10 +437,11 @@ hash_file(int hash, /* a simple macro for making hash "process" functions */ #define HASH_PROCESS(func_name, compress_name, state_var, block_size) \ - \ -int func_name(hash_state* md, const unsigned char* in, unsigned long inlen) \ - \ -{ \ + \ + int func_name( \ + hash_state* md, const unsigned char* in, unsigned long inlen) \ + \ + { \ unsigned long n; \ int err; \ LTC_ARGCHK(md != NULL); \ @@ -475,8 +476,7 @@ int func_name(hash_state* md, const unsigned char* in, unsigned long inlen) \ } \ } \ return CRYPT_OK; \ - \ -} + } /* $Source$ */ /* $Revision: 24839 $ */ diff --git a/src/libtomcrypt/src/headers/tomcrypt_macros.h b/src/libtomcrypt/src/headers/tomcrypt_macros.h index 894bee087f..3189a27326 100644 --- a/src/libtomcrypt/src/headers/tomcrypt_macros.h +++ b/src/libtomcrypt/src/headers/tomcrypt_macros.h @@ -108,18 +108,18 @@ typedef unsigned long ulong32; defined(__i386__) || defined(__x86_64__)))) #define STORE32H(x, y) \ - \ -asm __volatile__("bswapl %0 \n\t" \ - "movl %0,(%1)\n\t" \ - "bswapl %0 \n\t" ::"r"(x), \ - "r"(y)); + \ + asm __volatile__("bswapl %0 \n\t" \ + "movl %0,(%1)\n\t" \ + "bswapl %0 \n\t" ::"r"(x), \ + "r"(y)); #define LOAD32H(x, y) \ - \ -asm __volatile__("movl (%1),%0\n\t" \ - "bswapl %0\n\t" \ - : "=r"(x) \ - : "r"(y)); + \ + asm __volatile__("movl (%1),%0\n\t" \ + "bswapl %0\n\t" \ + : "=r"(x) \ + : "r"(y)); #else @@ -145,18 +145,18 @@ asm __volatile__("movl (%1),%0\n\t" \ #if !defined(LTC_NO_BSWAP) && (defined(__GNUC__) && defined(__x86_64__)) #define STORE64H(x, y) \ - \ -asm __volatile__("bswapq %0 \n\t" \ - "movq %0,(%1)\n\t" \ - "bswapq %0 \n\t" ::"r"(x), \ - "r"(y)); + \ + asm __volatile__("bswapq %0 \n\t" \ + "movq %0,(%1)\n\t" \ + "bswapq %0 \n\t" ::"r"(x), \ + "r"(y)); #define LOAD64H(x, y) \ - \ -asm __volatile__("movq (%1),%0\n\t" \ - "bswapq %0\n\t" \ - : "=r"(x) \ - : "r"(y)); + \ + asm __volatile__("movq (%1),%0\n\t" \ + "bswapq %0\n\t" \ + : "=r"(x) \ + : "r"(y)); #else From fefadeb5344f82098804cd71c3fdf8abaca6a1a4 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 27 Nov 2018 00:45:52 -0500 Subject: [PATCH 086/320] Solved the issue where a song located directly in the Songs folder would crash the game instantly, it now loads into a group called "Songs" fixes maybe set group for stray songs in the song folders as "Ungrouped Songs" also efficiency changes --- src/Player.cpp | 2 +- src/Song.cpp | 2 +- src/SongManager.cpp | 364 ++++++++++++++++++++++++-------------------- src/SongManager.h | 4 +- 4 files changed, 199 insertions(+), 173 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index bfa9064480..e4d834fcbd 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -3523,7 +3523,7 @@ Player::RenderAllNotesIgnoreScores() // Find the tapnote we are on TapNote* pTN = NULL; NoteData::iterator iter = m_NoteData.FindTapNote(track, row); - DEBUG_ASSERT(iter != m_NoteData.end(col)); + DEBUG_ASSERT(iter != m_NoteData.end(track)); pTN = &iter->second; // Reset the score so it can be visible diff --git a/src/Song.cpp b/src/Song.cpp index 54cae5c6b9..a6820002bb 100644 --- a/src/Song.cpp +++ b/src/Song.cpp @@ -379,7 +379,7 @@ Song::FinalizeLoading() // save group name vector sDirectoryParts; split(m_sSongDir, "/", sDirectoryParts, false); - ASSERT(sDirectoryParts.size() >= 4); /* e.g. "/Songs/Slow/Taps/" */ + // ASSERT(sDirectoryParts.size() >= 4); /* e.g. "/Songs/Slow/Taps/" */ m_sGroupName = sDirectoryParts[sDirectoryParts.size() - 3]; // second from last item ASSERT(m_sGroupName != ""); diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 52ec6b778c..2a798e9556 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -37,6 +37,16 @@ #include "arch/LoadingWindow/LoadingWindow.h" #include "ScreenManager.h" +struct SongDir { + RString path; + SongDir(RString path) : path(path) {} +}; +struct Group { + RString name; + vector songs; + Group(RString name) : name(name) {} +}; + SongManager* SONGMAN = NULL; // global and accessible from anywhere in our program @@ -135,66 +145,74 @@ SongManager::DifferentialReload() int SongManager::DifferentialReloadDir(string dir) { - if (dir.substr(dir.size()) != "/") + if (dir.back() != '/') dir += "/"; int newsongs = 0; - vector arrayGroupDirs; - GetDirListing(dir + "*", arrayGroupDirs, true); - StripCvsAndSvn(arrayGroupDirs); - StripMacResourceForks(arrayGroupDirs); - SortRStringArray(arrayGroupDirs); + vector folders; + GetDirListing(dir + "*", folders, true); + StripCvsAndSvn(folders); + StripMacResourceForks(folders); + SortRStringArray(folders); - vector> arrayGroupSongDirs; + vector groups; + Group unknownGroup("Unknown Group"); int groupIndex, songCount, songIndex; groupIndex = 0; songCount = 0; - FOREACH_CONST(RString, arrayGroupDirs, s) - { - RString sGroupDirName = *s; - SanityCheckGroupDir(dir + sGroupDirName); - - vector arraySongDirs; - GetDirListing(dir + sGroupDirName + "/*", arraySongDirs, true, true); - StripCvsAndSvn(arraySongDirs); - StripMacResourceForks(arraySongDirs); - SortRStringArray(arraySongDirs); + for (const auto& folder : folders) { + if (IsSongDir(dir + folder)) { + songCount++; + unknownGroup.songs.emplace_back(SongDir(folder)); + } + else { + vector songdirs; + GetDirListing(dir + folder + "/*", songdirs, true, true); + StripCvsAndSvn(songdirs); + StripMacResourceForks(songdirs); + SortRStringArray(songdirs); + Group group(folder); + for (auto& song : songdirs) { + group.songs.emplace_back(SongDir(song)); + } - arrayGroupSongDirs.emplace_back(arraySongDirs); - songCount += arraySongDirs.size(); + groups.emplace_back(group); + songCount += group.songs.size(); + } } - + if (!unknownGroup.songs.empty()) { + groups.emplace_back(unknownGroup); + songCount += unknownGroup.songs.size(); + } + if (songCount == 0) return 0; groupIndex = 0; songIndex = 0; - FOREACH_CONST(RString, arrayGroupDirs, s) - { - RString sGroupDirName = *s; - vector& arraySongDirs = arrayGroupSongDirs[groupIndex++]; + for (auto& group : groups) { + vector& songDirs = group.songs; int loaded = 0; - SongPointerVector& index_entry = m_mapSongGroupIndex[sGroupDirName]; - RString group_base_name = Basename(sGroupDirName); - for (size_t j = 0; j < arraySongDirs.size(); ++j) { - RString sSongDirName = arraySongDirs[j]; - + SongPointerVector& index_entry = m_mapSongGroupIndex[group.name]; + RString group_base_name = Basename(group.name); + for (auto& songDir : songDirs) { // skip any dir we've already loaded -mina - RString hur = sSongDirName + "/"; + RString hur = songDir.path + "/"; hur.MakeLower(); if (m_SongsByDir.count(hur)) continue; Song* pNewSong = new Song; - if (!pNewSong->LoadFromSongDir(sSongDirName)) { + if (!pNewSong->LoadFromSongDir(songDir.path)) { delete pNewSong; continue; } - + if (group.name == "Unknown Group") + pNewSong->m_sGroupName = "Ungrouped Songs"; AddSongToList(pNewSong); AddKeyedPointers(pNewSong); @@ -202,7 +220,7 @@ SongManager::DifferentialReloadDir(string dir) Message msg("DFRUpdate"); msg.SetParam("txt", - "Loading:\n" + sGroupDirName + "\n" + + "Loading:\n" + group.name + "\n" + pNewSong->GetMainTitle()); MESSAGEMAN->Broadcast(msg); SCREENMAN->Draw(); // not sure if this needs to be handled better @@ -217,10 +235,10 @@ SongManager::DifferentialReloadDir(string dir) continue; LOG->Trace("Differential load of %i songs from \"%s\"", loaded, - (dir + sGroupDirName).c_str()); + (dir + group.name).c_str()); - AddGroup(dir, sGroupDirName); - IMAGECACHE->CacheImage("Banner", GetSongGroupBannerPath(sGroupDirName)); + AddGroup(dir, group.name); + IMAGECACHE->CacheImage("Banner", GetSongGroupBannerPath(dir + group.name)); } return newsongs; } @@ -235,14 +253,14 @@ split(vector& v, size_t elementsPerThread) { std::vector> ranges; if (elementsPerThread <= 0 || elementsPerThread >= v.size()) { - ranges.push_back(std::make_pair(v.begin(), v.end())); + ranges.emplace_back(std::make_pair(v.begin(), v.end())); return ranges; } size_t range_count = (v.size() + 1) / elementsPerThread + 1; size_t ePT = v.size() / range_count; if (ePT == 0) { - ranges.push_back(std::make_pair(v.begin(), v.end())); + ranges.emplace_back(std::make_pair(v.begin(), v.end())); return ranges; } size_t i; @@ -250,9 +268,9 @@ split(vector& v, size_t elementsPerThread) it b = v.begin(); for (i = 0; i < v.size() - ePT; i += ePT) - ranges.push_back(std::make_pair(b + i, b + i + ePT)); + ranges.emplace_back(std::make_pair(b + i, b + i + ePT)); - ranges.push_back(std::make_pair(b + i, v.end())); + ranges.emplace_back(std::make_pair(b + i, v.end())); return ranges; } @@ -633,25 +651,24 @@ static LocalizedString FOLDER_CONTAINS_MUSIC_FILES( "must " "reside in a group folder. For example, \"Songs/Originals/My " "Song\"."); -void -SongManager::SanityCheckGroupDir(const RString& sDir) const -{ - // Check to see if they put a song directly inside the group folder. - vector arrayFiles; - GetDirListing(sDir + "/*", arrayFiles); - const vector& audio_exts = - ActorUtil::GetTypeExtensionList(FT_Sound); - FOREACH(RString, arrayFiles, fname) - { - const RString ext = GetExtension(*fname); - FOREACH_CONST(RString, audio_exts, aud) +bool +SongManager::IsSongDir(const RString& sDir) +{ + // Check to see if they put a song directly inside the group folder. + vector arrayFiles; + GetDirListing(sDir + "/*", arrayFiles); + const vector& audio_exts = + ActorUtil::GetTypeExtensionList(FT_Sound); + for (auto& fname : arrayFiles) { - if (ext == *aud) { - RageException::Throw(FOLDER_CONTAINS_MUSIC_FILES.GetValue(), - sDir.c_str()); - } + const RString ext = GetExtension(fname); + for (auto& aud : audio_exts) { + if (ext == aud) { + return true; + } + } } - } + return false; } bool @@ -737,121 +754,130 @@ static LocalizedString LOADING_SONGS("SongManager", "Loading songs..."); void SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) { - vector arrayGroupDirs; - GetDirListing(sDir + "*", arrayGroupDirs, true); - StripCvsAndSvn(arrayGroupDirs); - StripMacResourceForks(arrayGroupDirs); - SortRStringArray(arrayGroupDirs); - vector> arrayGroupSongDirs; - int songCount = 0; - if (ld != nullptr) { - ld->SetIndeterminate(false); - ld->SetTotalWork(arrayGroupDirs.size()); - ld->SetText("Sanity checking groups"); - } - int groupsChecked = 0; - int onePercent = std::max(static_cast(arrayGroupDirs.size() / 100), 1); - FOREACH_CONST(RString, arrayGroupDirs, s) - { - RString sGroupDirName = *s; - SanityCheckGroupDir(sDir + sGroupDirName); - vector arraySongDirs; - GetDirListing(sDir + sGroupDirName + "/*", arraySongDirs, true, true); - StripCvsAndSvn(arraySongDirs); - StripMacResourceForks(arraySongDirs); - SortRStringArray(arraySongDirs); - arrayGroupSongDirs.emplace_back(arraySongDirs); - songCount += arraySongDirs.size(); - if (ld != nullptr && groupsChecked % onePercent == 0) - ld->SetProgress(++groupsChecked); - } - - if (ld != nullptr) { - ld->SetIndeterminate(false); - ld->SetTotalWork(arrayGroupDirs.size()); - ld->SetText("Loading Songs From Disk\n"); - ld->SetProgress(0); - } - int groupIndex = 0; - onePercent = std::max(static_cast(arrayGroupDirs.size() / 100), 1); - - function*>>, - vectorIt*>>>, - ThreadData*)> - callback = - [&sDir](std::pair*>>, - vectorIt*>>> workload, - ThreadData* data) { - auto pair = - static_cast*>(data->data); - auto onePercent = pair->first; - auto ld = pair->second; - int counter = 0; - int lastUpdate = 0; - for (auto it = workload.first; it != workload.second; it++) { - auto pair = *it; - auto& sGroupDirName = *(it->first); - counter++; - vector& arraySongDirs = *(it->second); - if (counter % onePercent == 0) { - data->_progress += counter - lastUpdate; - lastUpdate = counter; - data->setUpdated(true); + vector songFolders; + GetDirListing(sDir + "*", songFolders, true); + StripCvsAndSvn(songFolders); + StripMacResourceForks(songFolders); + SortRStringArray(songFolders); + int songCount = 0; + if (ld != nullptr) { + ld->SetIndeterminate(false); + ld->SetTotalWork(songFolders.size()); + ld->SetText("Checking song folders"); + } + vector groups; + auto unknownGroup = Group(RString("Unknown Group")); + int foldersChecked = 0; + int onePercent = std::max(static_cast(songFolders.size() / 100), 1); + for (const auto& folder : songFolders) + { + if (IsSongDir(sDir + folder)) { + auto s = SongDir(sDir + folder); + unknownGroup.songs.emplace_back(s); } - int loaded = 0; - SongPointerVector& index_entry = - SONGMAN->m_mapSongGroupIndex[sGroupDirName]; - RString group_base_name = Basename(sGroupDirName); - for (size_t j = 0; j < arraySongDirs.size(); ++j) { - RString sSongDirName = arraySongDirs[j]; - RString hur = sSongDirName + "/"; - hur.MakeLower(); - if (SONGMAN->m_SongsByDir.count(hur)) - continue; - Song* pNewSong = new Song; - if (!pNewSong->LoadFromSongDir(sSongDirName)) { - delete pNewSong; - continue; - } - { - std::lock_guard lk(diskLoadSongMutex); - SONGMAN->AddSongToList(pNewSong); - SONGMAN->AddKeyedPointers(pNewSong); - } - index_entry.emplace_back(pNewSong); - loaded++; + else { + vector songPaths; + auto group = Group(folder); + GetDirListing(sDir + folder + "/*", songPaths, true, true); + StripCvsAndSvn(songPaths); + StripMacResourceForks(songPaths); + SortRStringArray(songPaths); + for (auto& song : songPaths) { + group.songs.emplace_back(SongDir(song)); + } + songCount += group.songs.size(); + groups.emplace_back(group); + if (ld != nullptr && foldersChecked % onePercent == 0) + ld->SetProgress(++foldersChecked); } - if (!loaded) - continue; - LOG->Trace("Loaded %i songs from \"%s\"", - loaded, - (sDir + sGroupDirName).c_str()); - { - std::lock_guard lk(diskLoadGroupMutex); - SONGMAN->AddGroup(sDir, sGroupDirName); - IMAGECACHE->CacheImage( - "Banner", SONGMAN->GetSongGroupBannerPath(sGroupDirName)); + } + if (!unknownGroup.songs.empty()) groups.emplace_back(unknownGroup); + + if (ld != nullptr) { + ld->SetIndeterminate(false); + ld->SetTotalWork(groups.size()); + ld->SetText("Loading Songs From Disk\n"); + ld->SetProgress(0); + } + int groupIndex = 0; + onePercent = std::max(static_cast(groups.size() / 100), 1); + + auto callback = + [&sDir](std::pair, + vectorIt> workload, + ThreadData* data) { + auto pair = + static_cast*>(data->data); + auto onePercent = pair->first; + auto ld = pair->second; + int counter = 0; + int lastUpdate = 0; + for (auto it = workload.first; it != workload.second; it++) { + auto pair = *it; + auto& sGroupName = it->name; + counter++; + vector& arraySongDirs = it->songs; + if (counter % onePercent == 0) { + data->_progress += counter - lastUpdate; + lastUpdate = counter; + data->setUpdated(true); + } + int loaded = 0; + SongPointerVector& index_entry = + SONGMAN->m_mapSongGroupIndex[sGroupName]; + RString group_base_name = sGroupName; + for (auto sSongDirName : arraySongDirs) { + RString hur = sSongDirName.path + "/"; + hur.MakeLower(); + if (SONGMAN->m_SongsByDir.count(hur)) + continue; + Song* pNewSong = new Song; + if (!pNewSong->LoadFromSongDir(sSongDirName.path)) { + delete pNewSong; + continue; + } + if (sGroupName == "Unknown Group") + pNewSong->m_sGroupName = "Ungrouped Songs"; + { + std::lock_guard lk(diskLoadSongMutex); + SONGMAN->AddSongToList(pNewSong); + SONGMAN->AddKeyedPointers(pNewSong); + } + index_entry.emplace_back(pNewSong); + loaded++; + } + if (!loaded) + continue; + LOG->Trace("Loaded %i songs from \"%s\"", + loaded, + (sDir + sGroupName).c_str()); + { + std::lock_guard lk(diskLoadGroupMutex); + SONGMAN->AddGroup(sDir, sGroupName); + IMAGECACHE->CacheImage( + "Banner", SONGMAN->GetSongGroupBannerPath(sDir + sGroupName)); + } } - } }; - auto onUpdate = [ld](int progress) { - if (ld) - ld->SetProgress(progress); - }; - vector*>> workload; - for (int i = 0; i < (int)arrayGroupDirs.size(); i++) { - workload.emplace_back( - make_pair(&arrayGroupDirs[i], &arrayGroupSongDirs[i])); - } - parallelExecution*>>( - workload, - onUpdate, - callback, - (void*)new pair(onePercent, ld)); + auto onUpdate = [ld](int progress) { + if (ld != nullptr) + ld->SetProgress(progress); + }; + vector workload; + for (auto& group : groups) { + workload.emplace_back(group); + } - if (ld != nullptr) { - ld->SetIndeterminate(true); - } + if (!workload.empty()) + parallelExecution( + workload, + onUpdate, + callback, + (void*)new pair(onePercent, ld)); + + if (ld != nullptr) { + ld->SetIndeterminate(true); + } } void @@ -1024,9 +1050,9 @@ SongManager::GetSongGroupColor(const RString& sSongGroup, } } - ASSERT_M(0, + /*ASSERT_M(0, ssprintf("requested color for song group '%s' that doesn't exist", - sSongGroup.c_str())); + sSongGroup.c_str()));*/ return RageColor(1, 1, 1, 1); } diff --git a/src/SongManager.h b/src/SongManager.h index fe94c5e7eb..cc5978f3d2 100644 --- a/src/SongManager.h +++ b/src/SongManager.h @@ -1,4 +1,4 @@ -#ifndef SONGMANAGER_H +#ifndef SONGMANAGER_H #define SONGMANAGER_H class LoadingWindow; @@ -171,7 +171,7 @@ class SongManager protected: void LoadStepManiaSongDir(RString sDir, LoadingWindow* ld); void LoadDWISongDir(const RString& sDir); - void SanityCheckGroupDir(const RString& sDir) const; + bool IsSongDir(const RString& sDir); bool AddGroup(const RString& sDir, const RString& sGroupDirName); void AddSongToList(Song* new_song); From 676bc31cad801245b0c7c6092d165adc68dc6aad Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 27 Nov 2018 01:26:40 -0500 Subject: [PATCH 087/320] auto iterate to 0.64.0 --- CMake/SMDefs.cmake | 2 +- Data/splash.png | Bin 9846 -> 9814 bytes Themes/_fallback/Graphics/Common splash.png | Bin 9846 -> 9814 bytes src/GameState.h | 2 +- src/ProductInfo.inc | 2 +- stepmania.nsi | 2 +- 6 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMake/SMDefs.cmake b/CMake/SMDefs.cmake index edae1df02f..b6ba9ce6e2 100644 --- a/CMake/SMDefs.cmake +++ b/CMake/SMDefs.cmake @@ -1,6 +1,6 @@ # Set up version numbers according to the new scheme. set(SM_VERSION_MAJOR 0) -set(SM_VERSION_MINOR 63) +set(SM_VERSION_MINOR 64) set(SM_VERSION_PATCH 0) set(SM_VERSION_TRADITIONAL "${SM_VERSION_MAJOR}.${SM_VERSION_MINOR}.${SM_VERSION_PATCH}") diff --git a/Data/splash.png b/Data/splash.png index 768517017e8fc47baa241e1723afee751ddd8b45..ac2401af2b8ab1d842e5804227728dafc47c4ef9 100644 GIT binary patch literal 9814 zcmYj%2RxN;*#ARTR%Ne9c1T$vBbjB(3Yl5iB-=qoc9Ok9$jC0qI7W6HBP8RHRW{k< zod5lt-~0c(ug@n(&T-$@zP{hyS~T2)sAg8aB4C^!s)PQb5%|3Hw}EeKk*fFP+f2%>k(`l=%h z-XOA4Q&9x3;OkhS5dmHp=)18dgAS06{|7|>l9*K1LvFvd2y7&0}itG0d>FM+a9=ql5D}qU5tAvkqf+2U=xZF=&m&QvtluZE8r-Xgy}1k zkZKKomB|L-mI_huH4>|fvOVb2Lw`JE^LCXx*X@4WD`n1C1Yh1Ad{^+{ya&2WATQ9? zZ2;fW^;)ZrU^A9~VOwgkWl%J;?N`y==wGS0oAB4STYE#nO+0i?RNyA@dVTO&Q%&>G zsrj4F%y9yfeTbMvPIX>>5uwySM|we_j{Al&k+*_V%}oXq5Z43->M)>~I)J%-MR}VSt_>|%+utgs>}SXui(%Irdef~Q8ErUT2C6zT zJuF+e2fvRWOepS?28)%S=Qm9C#dFGC4b~&GA^OC^0rdvfl>icYl&6Y$SofImy4i6t zwgm4uZo1C;>!Nkfxie7X)~kBbcB~isU4iIn&jr^i=2rwuxtRLWmOWKUMkw@JDJ$Va z{qNWWf~B0(OAz0bD2>u4OXS+$tt&cecO;)eB%vStrpqbmeu9{Y?rgvOuOBT^u@kAN zHaFoQi3 zH6bR&nyIwZYN0Dm*UZF)#;5Gs8Is#xvp{E1-I&Lswr8eXqmXBKWawF6_1n*%#Yg+N zHm2$?$;ik=)XTkCXE5`bCxkqO#x4+3(gbdXci+(K);-ulBiEO_m%pcn##cLx7TF+9 zr_h)PRnF6<0lgdHLdY{J?8yZ3mb7%%Aqxiw$B-xm@_fV9{bbKU;p?7%t#vmgC)LG{ z3F?IIE0mGLGc$2dg&*%V4;1mxM=9dx2JBvpXOVpKZlPlnF%x(=11$&r zRA#t(H5-flw}P^pscdOs&Cbr2@ZMx;0msHpH670SGbUs{C@6Ax)xD6GkTjEa8 zo}Hem_1MHjq?^x8Uwh!Bq66}{0K3hWQBLX-@tszxg}M^%zZJ)= zKh@VWOQpn@mNKxggcUica#Bh7Y+u8iqOpUB+41p+%}tlHB_Tvxj*LIKT%^+LMg^W8*v!1JyrexU`rONlaimDD;Qr5+z`Hli znqC2mf#`cg5j?!5Zf?$&6LjK0PDyFi9e|j9uTGgh((&MW7OCeXLd|YZmz}ZfBOv_z3P;@DX-rc6T3@Qe7pO=L5&0*m$9-ar>oAzHj z>K4*72pA|MZ_7OKa}O;%3h<0yS)Z)sV(VYnnfu)tL%31vw?9qx`(%GjDfbRTmPr-+ zR7@Z{a5V!nvx2|>!L5W@?LR^j*>}B}Ms)s&jQC?+n|6r0y1JJA*KIBJP}|$LKwuMU zj4luS(4BUv&+GD@uhtXuZ+qR=Ca-w?3b>5NdZ98&oqGp(nboDf@tSpd6fhWM^n=>` z6=s@;heu5cg*iXH5~b+2J=Yc+hi!NCU;9`;_oDG1Wu?Hk?`Q!nmhBF_N_)m>hmWDY zJDLg8adMEUO{!&mMrw~k2Huc)U&H;>&ip%4wy`pf83t7k930Zg_>-w-2M(>w`#w2N zcr26sk!eff(HgvCdu%ooF3X{>UmbY*0>u5d1$WagZg|5Ve1+cJ--oRV1qnYQ8?HQG z9V?57FLbTH_1Bp_Ffb6*0^n1Ty=m$wg2C*&cd%J8oom^Su{B~@C!RuF=yzphWFXr> zVnujpJpbp3k~w6MjZ8;A&e2oYLaz|wzi8lqYMtl?#0KDoc*QNvPkNL*7^90>Evr;V z{;_HwPaiVR36Ec(rxr7c##jk)vPg-Gr|gR~M|xq-e48*QYtXI=9%0_Hu)9#x0?sN7S5s3SwvHTRfmSzj> z<)Ds^zWk+k86Ub|JwIxdPn15G{jiYSxvcbts7439c|f99W_WKvlw!L!&AZpUVWp*i zHaELU9u+TZ#LRwinRU|adY*?)zq{2$eQ!B0%{130zquI}jgh$|KAtkHV?NX_=+Dz= zZ3ZQjb&qn1j3aOls5-In@pR8)&rc5*PzX%z{Dv>^y(Yr z`+?*=E}yLB49U?=6BUAg&1edUq0Qz)v)H&e8}eRyVfE3esTftxH)1iE6*;VAaKn6Z zGPgOaLW#^8s2-PEwL18eqkyYX{hks->ZN&mmHoZiE2Y$MTYmP?gs%Sjc80h$f)#kU zv^2v1OSpw?+LyHLlE)7Wm8pO1HLQbJ>Yu!IbHkF0>LSbC7vvd5dG+;o7G#xkhuded z?WsY+>EAkI=-nrtcqcy>A|1Q%oog|?!}9EW3xPUn=w9fRe40NB$}a|k$zojp_|eny zv(w1xlhVCoWv2A1!!3{1*-t>``ZSw4 zP1X=XHJbe+z2hBBOicH^z3&A5%S1o@VJS+QSaMkTZ=)WaUt3!{WRiP@!w7{LleK^@EoBm>R^tYZ| zJh#S~2+}16jeDbf+`c!NSrdxq=yO@cZs|_*np8eSRC~X8vFs%MsD#GMcPTmR(O~d; zZ$R%;DjvKRTxA@KgkcGK)#REk@v+~K2Q&86&(*Mf{Av0>u@X~&sM zMTs9n@f!?dJ%2JXNmGDQV5d);mNivjVjAxljW^`~BscIN{coWR*@K*Z6;7(Q2G14J zUn*N;$sSKmVq{Eu%``@y#FwqjO=Y0zuc@h813W!_T9^8}YwN+L zAQkgtUuw2U6P-8YO1S6$@vk&IUx)%#%uG+=2r0YxdUjF0malw2Gbu@LQ1s(+QjY@= zntzE_im;!g^Pnq5*U9P)<7oPB^Ur;COo2**mAyR)D2spo{OS1`Sh3jPqyurFR7XYk z_V%7`oUg4&yUpE`_iPu*Tk}0$N>$tBTUOgt=T7=J#(sKwTJ5=_c?JO4pgrAlk;ISc z&&9v12K1+PYd_2X$jZkjmM6w$dv5ES*Gek%NKH;Votk1i1|WWugUoy`H#?_grtz_} z*#2sb2l%1|x@O|B+^D63A<1niTXj3(jCVxP77{B9&0$WrP+v7#78^h}ey_{tgl-AM zxGLuiKhlyRv~cx&CLi5yU{`PpxJu3T^SlkXwA>Qx}7 zUu+nUqtrC&1`PIkoW7q7?6&vo@m58rw9%H)zB(CymC}~&c5ic04odTQn-ZKu_UJlf ztJl}Bm^U`#p<~Y_+uHP3Jv{759H-{enx#!N{-VD!s0y{UquQ*IE$`lxmMS6t44e(p z)U;lyjBr>R{|I`t$@txgNVdTonaqFFep}M1QGB25o_t>qo1HaVpJ}|~7`mqW{cK=2 zp9w&Fd42%xxmUOwL%i5MZ8?)g_HQ8Vllh2(4Xt#l$7Y0e)N!thrf6J_)?@fV8Vh9s5-Dfr^LXo= zS@2-@cqRA3(cfd5m+9zqRZgoTqvK6;;dI68iT6xQOa{Y4>C99R2ss$K7-k4W5VQI~ zC3>XY32dm6#-Zu3LeOmPkBTZRW!;sM8UmOPWG-WT7M!smncS5(tzf z;eOpw!O|05nou5i|kOdu32DUbKcVZN^_*k(UP|6uBmMF1N9OAVC7W#0ntGd)zDuf zo^~T9_Pf)dOTR464Pv^t%o{d)3Ye6U{2>nj(AgyR23|_b`>=F3}YSz z1qGjf19#{H?Zh-XI1;2o0f>iM0fMgyDqh%;01YH6Cx=yCQ}Z{-ntzAB4v7V(k2C=3 zdCp!0(-hI{Vy)b+wwJ^^d!t&`PoEN0wwyehb>#onlmTonFUAlomd6A*tw@P_t8L=l zH%S@U_Z>OVeDPe&(0TaV%APpQ>xs9Vpzj&Arl9uBwl4ACEJ$+5s((!&Hdm~CdrI`v zeSf2ljt&^Gx6ivNQ=nu|1$0aF+UD25{R*RXS);VImR)Z?ONDcLuXZ_1eRh`oM-QlC z0tjHH1UZa^ng7Noo7`euJ`f|nTSG4R#*MbNLVz2H7$m6|>PAFU|3%4|i#^OX?fy|5 zvHbNjK$=!=ZdDeeO;lb)(Vd<5tK>Ju7HA3WFZP(zqt}uU;T@cB>T2JwBtC+I^q=X2<|OIym60Ff%xWvdrUF<0{JD3FLBQVVK0-Nt z&&$h;c27N)C26H)GG4#ud?>eUI1q4Wy6|lk6_pq!x)DRi9|iZ#1NUiV&$bm54(}m0 zm2aOk{@vJk^0r@R{gYsmq3xNiulAi&ksmd80c(Fabm?sCDwYFK%Mn!$s<>9?RR8Rk zjv-}V%F?$4BHvH|0-HSXie-w8nN%>u* z(P{-Az=Zt(=+}t$O=Allq;7%l#oCbSZfjxh68-V#F)U&*1``B$yv@1kXx*D<=gfum z_4KC)8z$9j2Kuz%hmM{e5@ls&kJ*>%rw50JAcntbSC{AI<%Pz(5*hrQx7`(r9fe0f z-=#)CUs_rHPW$8Jnc;c>kQ~3YP%U-YaIs&}(9p1#Y=>bUurjWXvX6NqDX+FKE^@wD z{}~bzf(HorthV*+@bGQqR%`3MSug5?jj2d`Q7Q8gpTg}LeN*~Je8lVG5!|i?zzC1^ z3AtBN{&hv?zymc%!f%gPnpJDu_!Oq)QPezN)+7Q?o)4=D&_4u}wdMR^>iEqlz(0WZ z{j76%G$=+4FdG|Yn^=118#Mzf>!3+*RYAdpjg5_?KLrT}i(lzrKzZ_7!7oW>WA zhf*nIoEep$<<9_+_UGs4F)3Ha`w4|O(XuDUkiaiZb3$R}wTa5^ZZ<^Lj;zycljK^E zmdrlQtnbRz4x6mQ&6yaOe4tH&{wZs^;t?bblY8gu>Q090^G220(N_qD7*nSA|fJM zt{^(;LSg-Z-aY^;t#IIjp%YBU zaWbD~OZ$3Ewo47$KiBDbg2g(KX>9o;q^};7qTzao^F}5j}-{q+2UdS&gv%f}(rU zjG`zFOmw_f`&2wYf_%fr9HS679}=yvuC@b%oUOhnEzPf}aCzLp3I=6SiYe!U)N0J9 zfLchbeFj0~bGlKVdVUT_g0jEA|KPv4goKWToism$RW(EV{4KMlf6?ka z&Q~wy-vh(AQ0wma0c>MqBQxmqx!A+5IOh2spIgGhHBROnYIB>DwZvea)s>_r8>J<8 zPJ=z_mh*_{=15fSLTTm7Hh*_3r-@RuN-qNa4t>7qt*uWB(gZjVSnZ~R!@TZxm9Y`~ zVgBuC{BLJEVDLh{*Z<^%9%`wNm2c~Ni+w@@3YgJ7z~xfSgQ5T^W0CQradvj@FY0^( zrVe*stn;oO!Ts;=XmMWYjm^d_+4b3GX5`6O<#P7{e>(7(C77*A_#X)P`TM)?F7_&k zQNS}c$n#>%R`X#FdxxID*z0q1YVEl?DKMYzBexwguHB_rcu4($f>g3{+MPC(H}nvV zV9UJYs_g12q^zPsA6|vZks;FJE7x<6WX{MQR8rINtf8GrTe(DZbc81c14)u(6W zWo2cHM0;n)|LmU`%WiyVX_0jl3LPgZ)9cy?MZToO3REG;#v zcex5$Tu1q7Tzq^!5{a1nWd6m?vL!L0d!ZlG=(m5P!mK&kM|x09sI@b+s%>E7Xek&! zV*K6NJR)IYnkB_!k*N_sQ%U_+P6R}9{epSG4&kp~zl6p2z#O+VPa*P_gv2Xq9?ff) zN#^n*S=)JX1KxOkKm9XY@UzKRBqAbW8~6=Bt^an9n1QUcbnO1xgf(D2IC5bDbOVFd z_U&!A2NMhl-C$-cQ^^Aks_ter5$#5TstOPPf{y#mZ#D+yq9TWfbwtI)EJ0iG*=$(( zCR@i=0@e@c;#S9hfJr1j{+?fGfZ0a!a}Ji@0D+{wM{(_yhl0L-`IAO*yHGRWVK|ck z+`7)1AVk{h?d4_T`~yH*H|+W01*qj@wM;1)tEaEz?7UI4jcE@Q=AyKf%1v|}IvjJn z^pq)c3lKFQ^79iR^Oo3!?u3<%v9%61>23_(HF19-mhY&2mi*&MCOPraL%?T}*|ueV zjk|#A&tE_395yl5YC~U}MvZIQZFoXff8pIv@#&`52lpTF#~n~Kn+`@o0AOIuPw>St z=(zSlElIEyQhf<8A6PFXwd~kgyc+MxU9i}X`l$B+UT!#S8-~Ecsa%FTA?^fE*g=*F z$2_hRj~c-3SHft1&V|K<1MHwFz>6J0Mo%wMKv1gP&9*JN%(DCN34Cc}*#2gLiqW>J zK0!p(LJ`w3y+p?TdnGk^K@-NJ*RhAxXTLr9o4=PcGkEnQJsT}w{w&Fh*pk~wgLhKB>17|tenh3ng9~2ub@v;{C!TrP*54NOU1GylR^lglcBE4Y z;z6)2IN#yuSL0s)@1ocDA8BKDuo3zc`CJfuy<&JlE4~nafP2wH4kju#;pG7e6Vm9# zs4O%pAhO8q(O+U=Ja`YKC(2sXe*L(Hn~qGO);wT@!S&hsCz$582R*3^^TlDQ;iI%O z>#q5CwBkxGNuFf&L#EVlp`QP``@nz;zKgIxFC5Q^`YqB<+9o|r|B4Ay>Yb#&7rz;N zdX;kf5-jTtx;tedv>vH(k7(YBT|*q9x03t`RiL9mVIn2IToz)SC~(PP+vRsNUb+dr zwRNcb5&ba+Np<8Hkk2I$3h#Mn)c|fU($r)+b;)JffHLhy^F6j?sKrX77wWbWgyDmA}hfX>*qd3g#C{y}bQ)#f=tc z*yx54Fihof{ZJ_C8c7MDib$rqj{KhUXDw~Ia43A+DLvU8TzGwIqI@|_l((w2e{oAp zIdu1u`*c;|dzAYT`?<{ckL3DZoGp~*EG><+&0UsUA1qhh?TqX5IbU-v}w|I69v~T@`m%6t(^LUqXaof*V zHN{LdScM?Mn~ujH8SJ=4oQiI=V==$_jJnd{ShUdsvDjtdJ05c<=>ga{i#O0iUwU1v zoEJcdkmEwJrmOd?s)HX6k(axX*e9$F%n0aMRF`y2U9c?6E z5x<%8SUhGKUNQ~7Q>Y{8c#Zo+31Hz0Fi8pXxGEbteKFWU{N*_5MeGGwWnSxbw+`H@ zxtNO=v4JR4+q|v`xk(0IWGx01>c1nL;9CFxSIwI54KSpU(UoV#7{M@{A~E%(o5`~L6s8*wPlQ8f0W~80 zPt~Utd#*O&dSsoJc19bCXh@V`$-LXLD^RU2EEMPA$GQ{?*nRe5P^~mANz2Z6nS;g3 z_=OUaa56-KP4nYyco##7o3%}S?ptG|@B5U_xvG#{Z-fi=KFUjv^6qWYE|eQYysCUq zN51(%9=B}PtqaS?)x1d^ig|?C)0aw#Q;XBB6pEqnPNcY{W!DdjtC)S{grouLm?59{ zq<&p|YtNMgVoXRUM&+)R8Z1lUiZU-hylmF%vbxb}RekH**)Dz8#bX6nU*fgHd@dRa zI1u|t*~-4VJ!AhtBv55?!)`du>dSx&hXJlAip_(mLUaU9DJ8L3>>Wb>`r%uBAQr`A zrW3RN?$H=C8!PqmGQkz%EyYc`PzsMq#!B9Mj#a|lv1Dy4$$-T>KBS^6^vE3U)7QKl z_8e4SLTh|kLYK1Xee9?zhk;3hjCFwzf525-*?dbeb_;{1*@cVT#U&|I@dggbJ9e&C z&ZAfJZQc^#1jZ*0aBBt2U2o&iT|4aE8Mv^yB|nMiFqn+W!ugo2l>Hb59@jW{2OgZT zw6L#82DG}v{P-d+vv|o$+hCV!#WHt$9cANzX8Fd}q5Mg$L0#+{*u7zHPHt_T_u(=^ z_ZE489OFXNdcaX=x0ES)oJ)htmp#lAO(O8lF%+r;BQf4z`|?eAH&Zghy@agwSZJp4}oocf2T%Y z``Tf&`-{5@1%{aGDrIG@i_;!6G=goSa1UdD`-}uTL40*2Gs{6dt}FQLLA*xUQiC$? zc7+gHvmyY4vh6>Z0THHa`bR|uyNphl3?_Q4jo?bmP7a=OXa!F~7?vAcTQvc*4DWWl z<9`xG>(u#NX{4}?!$9m|zrLe2fO}-p%so*~72ANDdioXixZn-L%_ZruQ3Oj{j9ODg z{Cc?KrcvU-;|g1GMOTP-I_x@hbKhPcJtERzyEbE z_ApovA{q&S;&etVc5+3Vz?eIOqr>)sXDl~E^5qt z13V8=2$vMAPWS3-POlq9EAk;hyyLas{xYnvMJWs|KlP;c!06}|Z85+Wcx-c@^fA%y z4QZVM|MS2N_1n>MxNuo@mf)VZc?E*b-86FQrrp8^&&-+jtB#vAf-lM7kTTL?*>1-} z!Z{6gYG>W^iFezsKo#H3B09KNyl{so!G&q!LKq8-zS>(ae@u2X3*dGNI_|=F!OB$U z;}(d$0Hejb6J+md#F?mO6b}F5G(SM%o*pqE|K9-(lakt8d?%kV9-`vCP{+z{R7x8K z?A~$)&qBmfY0+nz)TF#wLF_6*1CG91TE=w*75~{|+fe=pp+CfBjPK1oNuXB=;x8nx zL1**77FkXLTBI%9B8w$CL3Y+DZ06jCIPEIljSC&#*Tm_1CBP~9c}$5wr;D}yt~j_l zTVLP8!$ry!80aca3X<6yB-k?c$USbm42=T5YuF=1$LbB$MH)c>C69G1LQ+d`P53S1 o)k4Y>(7wF?-WDD2bA>Q+NBciZI=I#n;YYk4C}}EI+_wn*f5l7rUH||9 literal 9846 zcmYki1z42d^FF+!bT6@T4D()k(Q7yDW!8| z+5Mlz@9%nFuS*x<;W_8b+;h)8GbiS$wkk0J0|5jAAy!vY(uF`U!IzLkJY4W^9ERNz z_`r62r1b~_sZAtA*x-Qw-?3BE)q+3*I3bYG*AU2G@U75o2*gJK0@<~OKqNCD5L)+~ zFFMlT2e`Hxs!HG!{DCXBhJX)zcQq3)2!xOV{TE|mF&F`XaLlPIJ<|7^+sl0gH8((_ zmVNW`9g_#OvOcD0>e@HX=l_~1vFK^~`4^jbHTJ{!#FTvJC+bueyx3w5!fynr7Ut~w zWfPU~BI64E){ytbaUUu;K9gs^BsahPRiqJCOgj1B@Z>3L%E=Ymk|61cyW?hFPNq;k zEuN?s%hJVCX5iA6m+Y3;`^H95-0(Yiw)onH@nZRF=0mM+*T&eiu2jYov9Y;NdZzd3Bd&{9&`*#XP}WA`#>f z+1H2CmD=^#`@-1Lg&gjVx|y%%IWK%Te=<#rEa{AO+`NUxCX(>wCM|D-lubwx*io(c zFnD&$^Ozz>)bY_(GR7UeaAPHoQ)Dhl)CZY+;IwpfS>;(uLn{e`MN}O%&?D?eWW`Dx z&rmbBHlDcWbhDS|OcmO@M+!!{+pS8F+$<8@O~ja^xvzo+$+|wyW}4lo@$lvF#}77I z?J@ZGfGsP+%1^C<>5~clbn}K7t(H21{alA(T#(a4%IXj15G(sdV z035Zhv7=e?-x81v>#*1|uyE=9r#z;ZzOM7GF=?H-&R#}3zxnq~Zq5N&ap0yJw2Gk- zQXJq#oytvd!IH8YhG||AwZQhkF(f^Vd2HgwJ79;x zHJuOoUlFKxR{Jd|$h%M96?8U6Jeug>_HGY#DPKzodFr@cnYT@O7UnBFoh{~;c0BjFsM7*t71a=I#}KdUFei-@tG@5x!YL7-_SaA`p}4-G zf!>hM35C4g-rt{YzaC8CI$De6$29gUW0v;&wBp4tYuF)~=C#rpM$Heaa~$3DiQ_eE zth}6GMxKkkR><6P;iSM1I-4@O+>%4Ztgf!+Y>B`8Lw7d`FZiN$*~Z&jKb>!H>GbsU z4o&P%M;=u8t+l|L>T15P>qp@SE}Swy-}KsEo=!gTKwKVGZpr!`t|a%hWZ3bR*3^)a z%3fN}ZHYa67(Qbe$Xj!j84otFhJc^Uwg>vojW%pmr+Y6uw$HpoBK+Hq`WT&HRw_sb z;D&~V?d|PO_{rAMUej{P;%58Bl1AWyHv?M|Ug7vX2M31<*E)oK znFx2SF_Bf!k#g4s7Zt(kT5s&-pSsbB;Qg1awe~|aFXrm;8O2<`c6Q27uRFze=E($l zGeY+0e@z;not?4LnX56+wfWZ-$SBGzXA(1terRfhc<`{7)tBa()4r`Feu`zCZu<%JjI;X z>3w~X{&lK}%)HG<&TekEAVKFp9VHG%S61#wN=kkTK_TPj`SvkX?vi`Ie7QSOB2yGJ z+u%&gXW91V>Aly0Diw)Cmkuy6T?X`p;j{23) z@*128BNfC0PVbT2mVAFcSHG9%w}ual%capFg$9Z)KJEwB6-wSPDZOt#v%DmL8a%y_ zocqwWo=@xaS=e+$xPnqTdzgOol+)cRl_v|-L{>*`u z@h8^F*jIvBSXdbu8J*KrnLW~`iUsZFfq{WOI|CQ=PVJ}}tB~82l$2%6tvcINLekQ4 zNlD~Ncaz>{nkG!{{Fu7rlT9mk;G=seE{--$d*DTh3qoY=NE~?>E!Vl@y=nhoa(sFk z7oric7CWAIb$aTpvnAoa0#PU+BVm!vX*{wDa&c=vqsh^B99d26rGsbxiXpa~U7-Oa zT}3UxzqFs+dUPwa;?KiMhjj`GVj;+!hJ@Mn=cn~5{cmcw)Yy}o)SaA6@OY>xmxj-5 ztwtK0XFhKdLS?#y97jGf)S2^d2jwS~m!th>TT2H5fzP}-w1jirk{!Ma-$;1^LA)rT zDYCelsxb1otugQFF)?rZ_wQe_7$x`P4RwoA8JgHt5WHnu=J#AL6ztxYt^UXh6oljE z=H`NMlNV-~N_8&G%x~TQqH!S+hZsKoND+Wy7F((Nb{iwZ@dR4^9DNkg{Nb^6dIv~- z`Z2Jm%cU|cMWc4~`SEvOCfK|Gx;*P?17%moVq#+A@||QVkB&Ur&gYyVo~jtfF$$2* z{l!*tB3zHtZ5;?9al_=!cODF_L}s=QA=%|_LOwI3s^r7?#Dlp8Lf|R?$e#^YDfbl$ zZt*6v>h(A&js6{1Wl;t}xw2y2)jtra12b9D56AfLVu)omLzi>4VaUZZ`9X|NeBU#a zGacAs-sr~0$5mR_A7csytCI?axH}`cYV6)F73JK3AUhDpLviyDv^QgWZNC&k;7Y9e z2FgZ8v??kpx+Tia=1nd_oOY7S2j6pjm+?rhNf6-ksw`?6#?m}{=%FO6T`#mL6$b#3X41m2FWAdnDhQroKE?%Specg7*S%npb zF`cD}i{~#vs`Sh zt_RGgZ!opkGklA!=WFEaC-INJOk{s38Mc@6KYlhH<>61t1K_kVnDR#H?re*feZ|5gM-nm zuBEvzWDYz(zSA(|&7|}{eKBep`#uN>-@;*Gqy4wTZj>{o=aXx!(EFk>A2eK3dgv6r z6lV|D8AORcm6hRZmkK$~o&rknyIhU-VVU`7KvQhM=3-lPfhA?Ou|3B-3a2hEF7B<1 zvmLLbAkT8rij&HsMTCW4qlx>x38qz{=tgzd;=pRX^`JvhRaLd4NtQR@ROv3c^wpob z*?K2R0E&l8>1yoZ;Akc7up~8X=EPeU3tpt*U3Ut{q0>ih1_nNvF~6u7^Jb3e9*X45 zc`esF>5VL#2s3C&u|0}?f5?=-CBX!xaxh+fcFZ3~NiyK(neoaJEi<$%`z)BR)tdtZ zzeB`xwJjn&PdPt0Q6)>KZ0bd63~7s zA;vS;G2!7(g@R)9)SXlP{2|9?2f^N`t%fE4lGl2BEs1e)8##OL?$b}ac|C28X0wu{ zsYhW8JbgbaiO#CgI!@0BgLA8KohE&q!4^_)IYVm|WaH;F8kD@{Nlp;yjzqxQ&c_3M zdd<_%ZAbM#i&4Z_ulL3KZ5Kp;a$A;tG2h7ROx^inFvyh3dZyY!gD7;#$@6Cbs&iCE zwJOWD02*M{x0Z%LsMk^vO~ zx(5T|(2Z|)V|iB~X%lu_m`=&%q4%u}B&ai%=#JLNgX}KJ8bJy5V$F31*_fOtI!KkS zWryCU)2C3k7ZQ=2ob-aZ_h(`)hBo9p*07_ZqQ*ehJwHE>n|IX68=}G)JBb6l@ujs@ z=p5PL1q7Nvjl}BC*l8PJ66FgjFAm?n^&@?s0VFc`^!$9Swx3zUnMPPBsZ7(GGfpjN zC=~#_u!`pXebE9DT9s=D|AI~;F}+y1r!kWoHPj#vHdTr#YpjfXT@b0P`HPco$C!)_ zRVr@N+}6q)Qtt3t5sAwf`6%{?7_t|dE2#nPKgwSi41oyP@$g~DFh(gs;{JP|o)A>g zYR|U(I4IO(GV>U}byq#-+f>hETAYD1w4Hze@&4rjCFCwEH$9A98aU9DC1g5!p0VG0 zAPYFOay!?#hZL~YP=ITdZ{F}%Kv8_pUUrYs@LABT(C#W#4h540x$$IVk^Wq-QNqKr|p{4D`h&X@hW&1Nyr2oM#9iL+0Tfnp&Tkn6FTen_aCB-L-@ zxi2|A#b9>rCKyG8L8o({|2EvvcSz;m&L+C61AgOeyw%^{vvJZ11sWWQL{_faS6$RJ z%?`m(*KQCwxqJnIV<}34NN*ONnd{j8bs){5&dx($o{p{k25i~?^{dkJ;z0$!m9Sgy z)Y#p3f0R{zIT_Y69+{m5g8xmm=g8jP9$GmM47}MNhymh~S=@xofvzdz@qOEe7@)9; zMP14q8+jnck7Z_*Mhb~TbyANfY@TH_zdI}=pCTr-XycfaI8kp7I_jkr6ckM2CVIa^ zFLQl5=|2@Ulc!q1gT(;Pz3-jDIe#q`aQa_$>NQA%N2PMt_>e=y$!Mtyd&9{yGj^!E zI~ice(kJ;NvttaY(5v%#H!MirtMi{ZGmRkh*(qY;gcK&aoW;lPaf1@_mw~kqeJfP6 z%!9FMTzByjRXDed{hq1$9W1etBAp(qK#@|<{9(!d>16!L zX3B>~#KO+$X14Ujh}6MKrehw)J6VE)Gvt#z>CBnym|j~PE=&dk3-Wu?Eqa6orECoG zwpZtS+kgIi9UCKC@>`GRSpEr!U6t7%+rq*E5(=cB143K1NC(7lVQVYndK>TiUHuYsfTi zxe|!y`iJPUPfgo47`KWzs8pQB1yWC|TYXoIq1ITl2}9udh-X2Jx+zwAMRT0W7muYN ziXWl*jJ=wZKaTfoh)GH906pU2MmUK`gNy?L-9NgfzrP<8BA>O5zP~2dn0vmFy--G9 zdRyw{vtcW7AW8v%8KsZDQu=|)&?qQRjU7mmsEAvno5I>aBhxW4X_{$0Oj6tC*8V7S zVLo+F7{_S$|Vx zvfBE!c4B(k@CN}_k{bI|(WIg*dFaT1iv#HQx>G}D~ z%WGs?6i2<|du=O6M@P$1rBOlu{p=lM_yXx(%kE-nU7eRYUdW3Vl^<+aT^dw)xlhk# ztk#PXWhZ<{>$j?D+hN(cQoekHzwVvR(Jb?@1=mUcmx;nD|9Km<4|)%9kQWIka^46Y zb$0US1YJ(4fw>XR9Tk`MLdzy3%8ZckJ8wMi`hh0Mx4#XtFLY6fPd)JjHm7NX~nk3<)ae;sgsLqtd{3{37={$?Dj$_n3x+ibbuD>WTJ$7=#YC*u!ee zx7dKyAlfC+=@UA5ru=r&Rx(Sk`%4~9U0Z`p+Ud_Sb2^te5%+hb{`V(y2-QAUcZUdpE zXfX9d)U>FyoEvz+1F!>=)Jvl4>uZg)+tc50_&H}}=irbBKef$p9#W#)6kPd1$>%q! zXg%0;J+JEZ(N=y)-uW!Bq<^X~A1;nVbH;*QA7qT`9g4xt#Hh*fLHNN|bwNjfkE17O zbiK(J_t~Y|Z`sPD4hcEzy5({H=jRXD{QSJf_84o9gcmNbz29EL%;68cC%jJ0t*xzs z!1Qw}X3mcY!<=nAtXYX_$VsBpE2Tb^Ki@qG3k&18dLW9ixVR|pcX$U>oB;s=Ae-{9 z9QCt|KF8EI=-t@Zcncf-{{5pNi>9iX86z-it=E?JpJkX_6)Qb6vt=!FXnFa6Wo2D0 zUR#F0{J&%pP=2rQQRD0p0% znJNM4Od1gpA;ES_MHhbx6)sEo{p~`_g4j08}il)kpvUjK9huj}kcsLqXjP zcB^&f&|vxJI7)^g{w@_k)uowan%Ft19KyZNrO9>iZPRjaVDIvB@RbW%vHpg0a&fJC zwh*<;t-8~7S(DYY9TQlB4i>tlLQ1;+E8VKEoRC6`TVAt7Rk>tt+GtO^u?hI zefq%^6bs+89IbUXT+2(6Q=rxBt*3618;uFrNnHJjEd8K+sE69$-R&;ZE7e6UwfPH~ z^U)^UmTI)MlF?WJp-&rl{-;atiA?0E>=hA9@TJXkafV{S)45Sl@)*%2Ox>l4ts0|> zS2?;`MlqL{^X;sv7LC6b)G?rT>wt60q7YvDLpZI*BH!Nyj?*b)bT4rNx?8{aX7QI6 z5-gx4-?jT5WkG~Cl9DuYzme6eNI==3XG95fjF}+ses?6{_Rh}z?MvWky4$xS%gdWV zQCjOb%8b|)gQ>^wr3-;n*RwgCEuc2h&j1+eEdj^oeZJv_Pz3U!v zad983@G{ECXJ(r{*zyARTiWV_Kx6_=wK%#^WqCz~=3Si`|IP38(ubW`8px7z?&%t< z#6;P@_tt~$?CgN*v+~%ZUz6BW1welbuw~EI$!b9~ zb9ZTeaF!r~_yJw4%Y35^6pDu?&d^Avh@U@y#$BPc2PoO-7#O;*4q&7Z5IeU(`_()B z&#;m(189~QJx(0m>RC^e>tNS|wYT5qZ$G67zW!}h(;S@GA5mK?C@d;!3tZ|4N_wLg zdPYXkpqbUVbz%dIM90E1nss80ojP`P5kS?<>k6>+FwwtWe~1O?i~Tjzpt!0kKBfZ$ zTj%+IeF?js@ z7YBEvYZY*UV^lKjCpgNL=4J3VFnv&9SfD0D`nF`8#>-(T>ZKwiNE{MpAE%<{C+~3G zKv)OB5HTKl8LyYg(Hi0;L)E!xmgyGY!$)diI4{MGvo#Smh_f0X;;$Y(gMG0yO=j*fB8qUcV1m&%U zV5A15lgb~qRwh*F==0SP^3)IvGFMx~wzy@mI3u7@g>d8itO@0x~M z)BL5PCm%GBAtv?!|6VeeCsN=-h9M%pmt_EQGh3N%&LBwH7|H^}mto5zb-T8*bHiA4 znEmz{r_jBb;Zz<8!29DOf`uNuUEtiJaV==!egGU0E>fIQ`S@lnl`=f6Pt*J%qketD z#C3NYh56h{QuOd<8s4NOg`>x6_OU4jT|_NIefJ5*c2ndK2WJEA;cSo~x2(`YAa$_N z2K$!wcmPT2M?E|2Neg-WnccL!ce>Y#xXplhoFeV!OrMK^-m>fD2eT?ptr;7kd9-kh zhcg<_xJN_jHEyhGV(Tbt%zE+7kATiJh!xF{-V&g!*UqsB>oqrx$w6E0o(6Zp#lacG zvSPt*9XP%Di#Nr(pUp+OWi`RgPAEvx^R(a=#t=xxSD$7VbaW&?^J*^g$c57L{PW(; z5Rej7=e*QUX=Zlo-vXm)oTRUON?j7Tb@P@4;Gb3|qN$fHTPPs`VS^#L-tj+txn&_Y z(o^ZD4nD56mi#`pDkQ@;1y8&jeH!V_@d@KBJtp)3PscFBCOTzs5eku?wPN7u^HAPD z#)X9Pc%`p+rEa=Y-z@SraspONuPZ{(8ecHN5fZZ=B_9ERq%OIoq%nZ^?-4XkaQ^_D zNDY_hY$c&gqINaJ`onG<6M;|DY#a}zUvN5}K_5Y4-UU5}&2J@`s(G81M1BKAVpl^# z0K~N3ZZgjyx$Bx6AYN5M@lBGh(v`?w>+36ATAi8M=xzjyEL-DOo();8HCH#*pNMZD z)5x(|i3v2_h2VklU^uAA1c12X#T2ZG3~dl8c0toOwhq_>8Rz?HTW%FQP%FDRi7}{< z9e$IGKluVz9jEYAK%?w)XU|4HEz4=9wcwxy!vz=ux~GDo8r%6X>@8Xx-uVW>aW$M< zFH;$#dk1rrcF7C>`3!W;4@5?u6xnMz8KTV4+40U}W-h|c@Ch^RDK#n_=vnH1jz`g9 zz|FW9)8pRboh|Vj)Nho%{(}lN3hOZs;OV0uWXi61a|mntBAw>Ji7r0|^}qn7%PQ+^ zE&kb@Fn+7@J`Tk7bGGr!C+&J7i<>umtQF#~bO)WB+?xy$t+C(70;wLcikdQK{vQyX zq~F0V4t%gIo&8_O6WZqu7qyro4`GXLl)R6`ZlLOfmcuOX@W#Q9WKrcWUgjG}WrvzhwnOc{Xg+Q7M4gF@(qd+h{&sp$h77=knU zXC}JxNNyv7N!>A3vAj7dyUD$4GfUQ~pxXZ%MhC-ZJTknND0o@jZakc<-+dY4(#d!I zxmhTqi=hUAYrU6stg*p^2M#5GO_OTjLZ2QRtZAh>T8k6c=GBf5mC6^{Wo5$-3asL|#pR_H?;*Dij~*X0V-H zNYRI4y#6&0-M0TXdsZ8H;fY&yR#j+E^$&@-|6hqeWtC^w2Ve0Rf_1NoaFC?vb__$| z++27HlG2*Ua6#Eb%uR*;J8nQz4Z}OtBRsZ*6Ysl{PF;}0~nq=F{e2|&dKeJC)S#X)EjH3adAWkE`VvT{u z*ZDsj!c1Cn+OX5x5yLr%CvSoGO2I&jL@HwU9Sm_W#|`&lT5%|(rn^a%uR$zXYjuLe z>02W3e{+WBM+yHjFonKMq3c?Q5dKr9v~@?hn9u%8osBUeQplO(6m(5 zt1{_=U}J^9%gcCZM7xn)KS63U{vtdTyTjy@>piaHxA08?tQ^}AQ{*b0(gi+j3pY$eqwJW+4 z%?HbINWFQ7HV0iOF6;>?iZs_Ga||UIRpaOX(CixrmI82~GvwED+XzNcKV{HbiA8sC zMAL6NIQGbgFK8rcQf^-I7+jKB_;*af7&S==#PJQacxP|`h+)p)+z+N)`6jC2yS~T2)sAg8aB4C^!s)PQb5%|3Hw}EeKk*fFP+f2%>k(`l=%h z-XOA4Q&9x3;OkhS5dmHp=)18dgAS06{|7|>l9*K1LvFvd2y7&0}itG0d>FM+a9=ql5D}qU5tAvkqf+2U=xZF=&m&QvtluZE8r-Xgy}1k zkZKKomB|L-mI_huH4>|fvOVb2Lw`JE^LCXx*X@4WD`n1C1Yh1Ad{^+{ya&2WATQ9? zZ2;fW^;)ZrU^A9~VOwgkWl%J;?N`y==wGS0oAB4STYE#nO+0i?RNyA@dVTO&Q%&>G zsrj4F%y9yfeTbMvPIX>>5uwySM|we_j{Al&k+*_V%}oXq5Z43->M)>~I)J%-MR}VSt_>|%+utgs>}SXui(%Irdef~Q8ErUT2C6zT zJuF+e2fvRWOepS?28)%S=Qm9C#dFGC4b~&GA^OC^0rdvfl>icYl&6Y$SofImy4i6t zwgm4uZo1C;>!Nkfxie7X)~kBbcB~isU4iIn&jr^i=2rwuxtRLWmOWKUMkw@JDJ$Va z{qNWWf~B0(OAz0bD2>u4OXS+$tt&cecO;)eB%vStrpqbmeu9{Y?rgvOuOBT^u@kAN zHaFoQi3 zH6bR&nyIwZYN0Dm*UZF)#;5Gs8Is#xvp{E1-I&Lswr8eXqmXBKWawF6_1n*%#Yg+N zHm2$?$;ik=)XTkCXE5`bCxkqO#x4+3(gbdXci+(K);-ulBiEO_m%pcn##cLx7TF+9 zr_h)PRnF6<0lgdHLdY{J?8yZ3mb7%%Aqxiw$B-xm@_fV9{bbKU;p?7%t#vmgC)LG{ z3F?IIE0mGLGc$2dg&*%V4;1mxM=9dx2JBvpXOVpKZlPlnF%x(=11$&r zRA#t(H5-flw}P^pscdOs&Cbr2@ZMx;0msHpH670SGbUs{C@6Ax)xD6GkTjEa8 zo}Hem_1MHjq?^x8Uwh!Bq66}{0K3hWQBLX-@tszxg}M^%zZJ)= zKh@VWOQpn@mNKxggcUica#Bh7Y+u8iqOpUB+41p+%}tlHB_Tvxj*LIKT%^+LMg^W8*v!1JyrexU`rONlaimDD;Qr5+z`Hli znqC2mf#`cg5j?!5Zf?$&6LjK0PDyFi9e|j9uTGgh((&MW7OCeXLd|YZmz}ZfBOv_z3P;@DX-rc6T3@Qe7pO=L5&0*m$9-ar>oAzHj z>K4*72pA|MZ_7OKa}O;%3h<0yS)Z)sV(VYnnfu)tL%31vw?9qx`(%GjDfbRTmPr-+ zR7@Z{a5V!nvx2|>!L5W@?LR^j*>}B}Ms)s&jQC?+n|6r0y1JJA*KIBJP}|$LKwuMU zj4luS(4BUv&+GD@uhtXuZ+qR=Ca-w?3b>5NdZ98&oqGp(nboDf@tSpd6fhWM^n=>` z6=s@;heu5cg*iXH5~b+2J=Yc+hi!NCU;9`;_oDG1Wu?Hk?`Q!nmhBF_N_)m>hmWDY zJDLg8adMEUO{!&mMrw~k2Huc)U&H;>&ip%4wy`pf83t7k930Zg_>-w-2M(>w`#w2N zcr26sk!eff(HgvCdu%ooF3X{>UmbY*0>u5d1$WagZg|5Ve1+cJ--oRV1qnYQ8?HQG z9V?57FLbTH_1Bp_Ffb6*0^n1Ty=m$wg2C*&cd%J8oom^Su{B~@C!RuF=yzphWFXr> zVnujpJpbp3k~w6MjZ8;A&e2oYLaz|wzi8lqYMtl?#0KDoc*QNvPkNL*7^90>Evr;V z{;_HwPaiVR36Ec(rxr7c##jk)vPg-Gr|gR~M|xq-e48*QYtXI=9%0_Hu)9#x0?sN7S5s3SwvHTRfmSzj> z<)Ds^zWk+k86Ub|JwIxdPn15G{jiYSxvcbts7439c|f99W_WKvlw!L!&AZpUVWp*i zHaELU9u+TZ#LRwinRU|adY*?)zq{2$eQ!B0%{130zquI}jgh$|KAtkHV?NX_=+Dz= zZ3ZQjb&qn1j3aOls5-In@pR8)&rc5*PzX%z{Dv>^y(Yr z`+?*=E}yLB49U?=6BUAg&1edUq0Qz)v)H&e8}eRyVfE3esTftxH)1iE6*;VAaKn6Z zGPgOaLW#^8s2-PEwL18eqkyYX{hks->ZN&mmHoZiE2Y$MTYmP?gs%Sjc80h$f)#kU zv^2v1OSpw?+LyHLlE)7Wm8pO1HLQbJ>Yu!IbHkF0>LSbC7vvd5dG+;o7G#xkhuded z?WsY+>EAkI=-nrtcqcy>A|1Q%oog|?!}9EW3xPUn=w9fRe40NB$}a|k$zojp_|eny zv(w1xlhVCoWv2A1!!3{1*-t>``ZSw4 zP1X=XHJbe+z2hBBOicH^z3&A5%S1o@VJS+QSaMkTZ=)WaUt3!{WRiP@!w7{LleK^@EoBm>R^tYZ| zJh#S~2+}16jeDbf+`c!NSrdxq=yO@cZs|_*np8eSRC~X8vFs%MsD#GMcPTmR(O~d; zZ$R%;DjvKRTxA@KgkcGK)#REk@v+~K2Q&86&(*Mf{Av0>u@X~&sM zMTs9n@f!?dJ%2JXNmGDQV5d);mNivjVjAxljW^`~BscIN{coWR*@K*Z6;7(Q2G14J zUn*N;$sSKmVq{Eu%``@y#FwqjO=Y0zuc@h813W!_T9^8}YwN+L zAQkgtUuw2U6P-8YO1S6$@vk&IUx)%#%uG+=2r0YxdUjF0malw2Gbu@LQ1s(+QjY@= zntzE_im;!g^Pnq5*U9P)<7oPB^Ur;COo2**mAyR)D2spo{OS1`Sh3jPqyurFR7XYk z_V%7`oUg4&yUpE`_iPu*Tk}0$N>$tBTUOgt=T7=J#(sKwTJ5=_c?JO4pgrAlk;ISc z&&9v12K1+PYd_2X$jZkjmM6w$dv5ES*Gek%NKH;Votk1i1|WWugUoy`H#?_grtz_} z*#2sb2l%1|x@O|B+^D63A<1niTXj3(jCVxP77{B9&0$WrP+v7#78^h}ey_{tgl-AM zxGLuiKhlyRv~cx&CLi5yU{`PpxJu3T^SlkXwA>Qx}7 zUu+nUqtrC&1`PIkoW7q7?6&vo@m58rw9%H)zB(CymC}~&c5ic04odTQn-ZKu_UJlf ztJl}Bm^U`#p<~Y_+uHP3Jv{759H-{enx#!N{-VD!s0y{UquQ*IE$`lxmMS6t44e(p z)U;lyjBr>R{|I`t$@txgNVdTonaqFFep}M1QGB25o_t>qo1HaVpJ}|~7`mqW{cK=2 zp9w&Fd42%xxmUOwL%i5MZ8?)g_HQ8Vllh2(4Xt#l$7Y0e)N!thrf6J_)?@fV8Vh9s5-Dfr^LXo= zS@2-@cqRA3(cfd5m+9zqRZgoTqvK6;;dI68iT6xQOa{Y4>C99R2ss$K7-k4W5VQI~ zC3>XY32dm6#-Zu3LeOmPkBTZRW!;sM8UmOPWG-WT7M!smncS5(tzf z;eOpw!O|05nou5i|kOdu32DUbKcVZN^_*k(UP|6uBmMF1N9OAVC7W#0ntGd)zDuf zo^~T9_Pf)dOTR464Pv^t%o{d)3Ye6U{2>nj(AgyR23|_b`>=F3}YSz z1qGjf19#{H?Zh-XI1;2o0f>iM0fMgyDqh%;01YH6Cx=yCQ}Z{-ntzAB4v7V(k2C=3 zdCp!0(-hI{Vy)b+wwJ^^d!t&`PoEN0wwyehb>#onlmTonFUAlomd6A*tw@P_t8L=l zH%S@U_Z>OVeDPe&(0TaV%APpQ>xs9Vpzj&Arl9uBwl4ACEJ$+5s((!&Hdm~CdrI`v zeSf2ljt&^Gx6ivNQ=nu|1$0aF+UD25{R*RXS);VImR)Z?ONDcLuXZ_1eRh`oM-QlC z0tjHH1UZa^ng7Noo7`euJ`f|nTSG4R#*MbNLVz2H7$m6|>PAFU|3%4|i#^OX?fy|5 zvHbNjK$=!=ZdDeeO;lb)(Vd<5tK>Ju7HA3WFZP(zqt}uU;T@cB>T2JwBtC+I^q=X2<|OIym60Ff%xWvdrUF<0{JD3FLBQVVK0-Nt z&&$h;c27N)C26H)GG4#ud?>eUI1q4Wy6|lk6_pq!x)DRi9|iZ#1NUiV&$bm54(}m0 zm2aOk{@vJk^0r@R{gYsmq3xNiulAi&ksmd80c(Fabm?sCDwYFK%Mn!$s<>9?RR8Rk zjv-}V%F?$4BHvH|0-HSXie-w8nN%>u* z(P{-Az=Zt(=+}t$O=Allq;7%l#oCbSZfjxh68-V#F)U&*1``B$yv@1kXx*D<=gfum z_4KC)8z$9j2Kuz%hmM{e5@ls&kJ*>%rw50JAcntbSC{AI<%Pz(5*hrQx7`(r9fe0f z-=#)CUs_rHPW$8Jnc;c>kQ~3YP%U-YaIs&}(9p1#Y=>bUurjWXvX6NqDX+FKE^@wD z{}~bzf(HorthV*+@bGQqR%`3MSug5?jj2d`Q7Q8gpTg}LeN*~Je8lVG5!|i?zzC1^ z3AtBN{&hv?zymc%!f%gPnpJDu_!Oq)QPezN)+7Q?o)4=D&_4u}wdMR^>iEqlz(0WZ z{j76%G$=+4FdG|Yn^=118#Mzf>!3+*RYAdpjg5_?KLrT}i(lzrKzZ_7!7oW>WA zhf*nIoEep$<<9_+_UGs4F)3Ha`w4|O(XuDUkiaiZb3$R}wTa5^ZZ<^Lj;zycljK^E zmdrlQtnbRz4x6mQ&6yaOe4tH&{wZs^;t?bblY8gu>Q090^G220(N_qD7*nSA|fJM zt{^(;LSg-Z-aY^;t#IIjp%YBU zaWbD~OZ$3Ewo47$KiBDbg2g(KX>9o;q^};7qTzao^F}5j}-{q+2UdS&gv%f}(rU zjG`zFOmw_f`&2wYf_%fr9HS679}=yvuC@b%oUOhnEzPf}aCzLp3I=6SiYe!U)N0J9 zfLchbeFj0~bGlKVdVUT_g0jEA|KPv4goKWToism$RW(EV{4KMlf6?ka z&Q~wy-vh(AQ0wma0c>MqBQxmqx!A+5IOh2spIgGhHBROnYIB>DwZvea)s>_r8>J<8 zPJ=z_mh*_{=15fSLTTm7Hh*_3r-@RuN-qNa4t>7qt*uWB(gZjVSnZ~R!@TZxm9Y`~ zVgBuC{BLJEVDLh{*Z<^%9%`wNm2c~Ni+w@@3YgJ7z~xfSgQ5T^W0CQradvj@FY0^( zrVe*stn;oO!Ts;=XmMWYjm^d_+4b3GX5`6O<#P7{e>(7(C77*A_#X)P`TM)?F7_&k zQNS}c$n#>%R`X#FdxxID*z0q1YVEl?DKMYzBexwguHB_rcu4($f>g3{+MPC(H}nvV zV9UJYs_g12q^zPsA6|vZks;FJE7x<6WX{MQR8rINtf8GrTe(DZbc81c14)u(6W zWo2cHM0;n)|LmU`%WiyVX_0jl3LPgZ)9cy?MZToO3REG;#v zcex5$Tu1q7Tzq^!5{a1nWd6m?vL!L0d!ZlG=(m5P!mK&kM|x09sI@b+s%>E7Xek&! zV*K6NJR)IYnkB_!k*N_sQ%U_+P6R}9{epSG4&kp~zl6p2z#O+VPa*P_gv2Xq9?ff) zN#^n*S=)JX1KxOkKm9XY@UzKRBqAbW8~6=Bt^an9n1QUcbnO1xgf(D2IC5bDbOVFd z_U&!A2NMhl-C$-cQ^^Aks_ter5$#5TstOPPf{y#mZ#D+yq9TWfbwtI)EJ0iG*=$(( zCR@i=0@e@c;#S9hfJr1j{+?fGfZ0a!a}Ji@0D+{wM{(_yhl0L-`IAO*yHGRWVK|ck z+`7)1AVk{h?d4_T`~yH*H|+W01*qj@wM;1)tEaEz?7UI4jcE@Q=AyKf%1v|}IvjJn z^pq)c3lKFQ^79iR^Oo3!?u3<%v9%61>23_(HF19-mhY&2mi*&MCOPraL%?T}*|ueV zjk|#A&tE_395yl5YC~U}MvZIQZFoXff8pIv@#&`52lpTF#~n~Kn+`@o0AOIuPw>St z=(zSlElIEyQhf<8A6PFXwd~kgyc+MxU9i}X`l$B+UT!#S8-~Ecsa%FTA?^fE*g=*F z$2_hRj~c-3SHft1&V|K<1MHwFz>6J0Mo%wMKv1gP&9*JN%(DCN34Cc}*#2gLiqW>J zK0!p(LJ`w3y+p?TdnGk^K@-NJ*RhAxXTLr9o4=PcGkEnQJsT}w{w&Fh*pk~wgLhKB>17|tenh3ng9~2ub@v;{C!TrP*54NOU1GylR^lglcBE4Y z;z6)2IN#yuSL0s)@1ocDA8BKDuo3zc`CJfuy<&JlE4~nafP2wH4kju#;pG7e6Vm9# zs4O%pAhO8q(O+U=Ja`YKC(2sXe*L(Hn~qGO);wT@!S&hsCz$582R*3^^TlDQ;iI%O z>#q5CwBkxGNuFf&L#EVlp`QP``@nz;zKgIxFC5Q^`YqB<+9o|r|B4Ay>Yb#&7rz;N zdX;kf5-jTtx;tedv>vH(k7(YBT|*q9x03t`RiL9mVIn2IToz)SC~(PP+vRsNUb+dr zwRNcb5&ba+Np<8Hkk2I$3h#Mn)c|fU($r)+b;)JffHLhy^F6j?sKrX77wWbWgyDmA}hfX>*qd3g#C{y}bQ)#f=tc z*yx54Fihof{ZJ_C8c7MDib$rqj{KhUXDw~Ia43A+DLvU8TzGwIqI@|_l((w2e{oAp zIdu1u`*c;|dzAYT`?<{ckL3DZoGp~*EG><+&0UsUA1qhh?TqX5IbU-v}w|I69v~T@`m%6t(^LUqXaof*V zHN{LdScM?Mn~ujH8SJ=4oQiI=V==$_jJnd{ShUdsvDjtdJ05c<=>ga{i#O0iUwU1v zoEJcdkmEwJrmOd?s)HX6k(axX*e9$F%n0aMRF`y2U9c?6E z5x<%8SUhGKUNQ~7Q>Y{8c#Zo+31Hz0Fi8pXxGEbteKFWU{N*_5MeGGwWnSxbw+`H@ zxtNO=v4JR4+q|v`xk(0IWGx01>c1nL;9CFxSIwI54KSpU(UoV#7{M@{A~E%(o5`~L6s8*wPlQ8f0W~80 zPt~Utd#*O&dSsoJc19bCXh@V`$-LXLD^RU2EEMPA$GQ{?*nRe5P^~mANz2Z6nS;g3 z_=OUaa56-KP4nYyco##7o3%}S?ptG|@B5U_xvG#{Z-fi=KFUjv^6qWYE|eQYysCUq zN51(%9=B}PtqaS?)x1d^ig|?C)0aw#Q;XBB6pEqnPNcY{W!DdjtC)S{grouLm?59{ zq<&p|YtNMgVoXRUM&+)R8Z1lUiZU-hylmF%vbxb}RekH**)Dz8#bX6nU*fgHd@dRa zI1u|t*~-4VJ!AhtBv55?!)`du>dSx&hXJlAip_(mLUaU9DJ8L3>>Wb>`r%uBAQr`A zrW3RN?$H=C8!PqmGQkz%EyYc`PzsMq#!B9Mj#a|lv1Dy4$$-T>KBS^6^vE3U)7QKl z_8e4SLTh|kLYK1Xee9?zhk;3hjCFwzf525-*?dbeb_;{1*@cVT#U&|I@dggbJ9e&C z&ZAfJZQc^#1jZ*0aBBt2U2o&iT|4aE8Mv^yB|nMiFqn+W!ugo2l>Hb59@jW{2OgZT zw6L#82DG}v{P-d+vv|o$+hCV!#WHt$9cANzX8Fd}q5Mg$L0#+{*u7zHPHt_T_u(=^ z_ZE489OFXNdcaX=x0ES)oJ)htmp#lAO(O8lF%+r;BQf4z`|?eAH&Zghy@agwSZJp4}oocf2T%Y z``Tf&`-{5@1%{aGDrIG@i_;!6G=goSa1UdD`-}uTL40*2Gs{6dt}FQLLA*xUQiC$? zc7+gHvmyY4vh6>Z0THHa`bR|uyNphl3?_Q4jo?bmP7a=OXa!F~7?vAcTQvc*4DWWl z<9`xG>(u#NX{4}?!$9m|zrLe2fO}-p%so*~72ANDdioXixZn-L%_ZruQ3Oj{j9ODg z{Cc?KrcvU-;|g1GMOTP-I_x@hbKhPcJtERzyEbE z_ApovA{q&S;&etVc5+3Vz?eIOqr>)sXDl~E^5qt z13V8=2$vMAPWS3-POlq9EAk;hyyLas{xYnvMJWs|KlP;c!06}|Z85+Wcx-c@^fA%y z4QZVM|MS2N_1n>MxNuo@mf)VZc?E*b-86FQrrp8^&&-+jtB#vAf-lM7kTTL?*>1-} z!Z{6gYG>W^iFezsKo#H3B09KNyl{so!G&q!LKq8-zS>(ae@u2X3*dGNI_|=F!OB$U z;}(d$0Hejb6J+md#F?mO6b}F5G(SM%o*pqE|K9-(lakt8d?%kV9-`vCP{+z{R7x8K z?A~$)&qBmfY0+nz)TF#wLF_6*1CG91TE=w*75~{|+fe=pp+CfBjPK1oNuXB=;x8nx zL1**77FkXLTBI%9B8w$CL3Y+DZ06jCIPEIljSC&#*Tm_1CBP~9c}$5wr;D}yt~j_l zTVLP8!$ry!80aca3X<6yB-k?c$USbm42=T5YuF=1$LbB$MH)c>C69G1LQ+d`P53S1 o)k4Y>(7wF?-WDD2bA>Q+NBciZI=I#n;YYk4C}}EI+_wn*f5l7rUH||9 literal 9846 zcmYki1z42d^FF+!bT6@T4D()k(Q7yDW!8| z+5Mlz@9%nFuS*x<;W_8b+;h)8GbiS$wkk0J0|5jAAy!vY(uF`U!IzLkJY4W^9ERNz z_`r62r1b~_sZAtA*x-Qw-?3BE)q+3*I3bYG*AU2G@U75o2*gJK0@<~OKqNCD5L)+~ zFFMlT2e`Hxs!HG!{DCXBhJX)zcQq3)2!xOV{TE|mF&F`XaLlPIJ<|7^+sl0gH8((_ zmVNW`9g_#OvOcD0>e@HX=l_~1vFK^~`4^jbHTJ{!#FTvJC+bueyx3w5!fynr7Ut~w zWfPU~BI64E){ytbaUUu;K9gs^BsahPRiqJCOgj1B@Z>3L%E=Ymk|61cyW?hFPNq;k zEuN?s%hJVCX5iA6m+Y3;`^H95-0(Yiw)onH@nZRF=0mM+*T&eiu2jYov9Y;NdZzd3Bd&{9&`*#XP}WA`#>f z+1H2CmD=^#`@-1Lg&gjVx|y%%IWK%Te=<#rEa{AO+`NUxCX(>wCM|D-lubwx*io(c zFnD&$^Ozz>)bY_(GR7UeaAPHoQ)Dhl)CZY+;IwpfS>;(uLn{e`MN}O%&?D?eWW`Dx z&rmbBHlDcWbhDS|OcmO@M+!!{+pS8F+$<8@O~ja^xvzo+$+|wyW}4lo@$lvF#}77I z?J@ZGfGsP+%1^C<>5~clbn}K7t(H21{alA(T#(a4%IXj15G(sdV z035Zhv7=e?-x81v>#*1|uyE=9r#z;ZzOM7GF=?H-&R#}3zxnq~Zq5N&ap0yJw2Gk- zQXJq#oytvd!IH8YhG||AwZQhkF(f^Vd2HgwJ79;x zHJuOoUlFKxR{Jd|$h%M96?8U6Jeug>_HGY#DPKzodFr@cnYT@O7UnBFoh{~;c0BjFsM7*t71a=I#}KdUFei-@tG@5x!YL7-_SaA`p}4-G zf!>hM35C4g-rt{YzaC8CI$De6$29gUW0v;&wBp4tYuF)~=C#rpM$Heaa~$3DiQ_eE zth}6GMxKkkR><6P;iSM1I-4@O+>%4Ztgf!+Y>B`8Lw7d`FZiN$*~Z&jKb>!H>GbsU z4o&P%M;=u8t+l|L>T15P>qp@SE}Swy-}KsEo=!gTKwKVGZpr!`t|a%hWZ3bR*3^)a z%3fN}ZHYa67(Qbe$Xj!j84otFhJc^Uwg>vojW%pmr+Y6uw$HpoBK+Hq`WT&HRw_sb z;D&~V?d|PO_{rAMUej{P;%58Bl1AWyHv?M|Ug7vX2M31<*E)oK znFx2SF_Bf!k#g4s7Zt(kT5s&-pSsbB;Qg1awe~|aFXrm;8O2<`c6Q27uRFze=E($l zGeY+0e@z;not?4LnX56+wfWZ-$SBGzXA(1terRfhc<`{7)tBa()4r`Feu`zCZu<%JjI;X z>3w~X{&lK}%)HG<&TekEAVKFp9VHG%S61#wN=kkTK_TPj`SvkX?vi`Ie7QSOB2yGJ z+u%&gXW91V>Aly0Diw)Cmkuy6T?X`p;j{23) z@*128BNfC0PVbT2mVAFcSHG9%w}ual%capFg$9Z)KJEwB6-wSPDZOt#v%DmL8a%y_ zocqwWo=@xaS=e+$xPnqTdzgOol+)cRl_v|-L{>*`u z@h8^F*jIvBSXdbu8J*KrnLW~`iUsZFfq{WOI|CQ=PVJ}}tB~82l$2%6tvcINLekQ4 zNlD~Ncaz>{nkG!{{Fu7rlT9mk;G=seE{--$d*DTh3qoY=NE~?>E!Vl@y=nhoa(sFk z7oric7CWAIb$aTpvnAoa0#PU+BVm!vX*{wDa&c=vqsh^B99d26rGsbxiXpa~U7-Oa zT}3UxzqFs+dUPwa;?KiMhjj`GVj;+!hJ@Mn=cn~5{cmcw)Yy}o)SaA6@OY>xmxj-5 ztwtK0XFhKdLS?#y97jGf)S2^d2jwS~m!th>TT2H5fzP}-w1jirk{!Ma-$;1^LA)rT zDYCelsxb1otugQFF)?rZ_wQe_7$x`P4RwoA8JgHt5WHnu=J#AL6ztxYt^UXh6oljE z=H`NMlNV-~N_8&G%x~TQqH!S+hZsKoND+Wy7F((Nb{iwZ@dR4^9DNkg{Nb^6dIv~- z`Z2Jm%cU|cMWc4~`SEvOCfK|Gx;*P?17%moVq#+A@||QVkB&Ur&gYyVo~jtfF$$2* z{l!*tB3zHtZ5;?9al_=!cODF_L}s=QA=%|_LOwI3s^r7?#Dlp8Lf|R?$e#^YDfbl$ zZt*6v>h(A&js6{1Wl;t}xw2y2)jtra12b9D56AfLVu)omLzi>4VaUZZ`9X|NeBU#a zGacAs-sr~0$5mR_A7csytCI?axH}`cYV6)F73JK3AUhDpLviyDv^QgWZNC&k;7Y9e z2FgZ8v??kpx+Tia=1nd_oOY7S2j6pjm+?rhNf6-ksw`?6#?m}{=%FO6T`#mL6$b#3X41m2FWAdnDhQroKE?%Specg7*S%npb zF`cD}i{~#vs`Sh zt_RGgZ!opkGklA!=WFEaC-INJOk{s38Mc@6KYlhH<>61t1K_kVnDR#H?re*feZ|5gM-nm zuBEvzWDYz(zSA(|&7|}{eKBep`#uN>-@;*Gqy4wTZj>{o=aXx!(EFk>A2eK3dgv6r z6lV|D8AORcm6hRZmkK$~o&rknyIhU-VVU`7KvQhM=3-lPfhA?Ou|3B-3a2hEF7B<1 zvmLLbAkT8rij&HsMTCW4qlx>x38qz{=tgzd;=pRX^`JvhRaLd4NtQR@ROv3c^wpob z*?K2R0E&l8>1yoZ;Akc7up~8X=EPeU3tpt*U3Ut{q0>ih1_nNvF~6u7^Jb3e9*X45 zc`esF>5VL#2s3C&u|0}?f5?=-CBX!xaxh+fcFZ3~NiyK(neoaJEi<$%`z)BR)tdtZ zzeB`xwJjn&PdPt0Q6)>KZ0bd63~7s zA;vS;G2!7(g@R)9)SXlP{2|9?2f^N`t%fE4lGl2BEs1e)8##OL?$b}ac|C28X0wu{ zsYhW8JbgbaiO#CgI!@0BgLA8KohE&q!4^_)IYVm|WaH;F8kD@{Nlp;yjzqxQ&c_3M zdd<_%ZAbM#i&4Z_ulL3KZ5Kp;a$A;tG2h7ROx^inFvyh3dZyY!gD7;#$@6Cbs&iCE zwJOWD02*M{x0Z%LsMk^vO~ zx(5T|(2Z|)V|iB~X%lu_m`=&%q4%u}B&ai%=#JLNgX}KJ8bJy5V$F31*_fOtI!KkS zWryCU)2C3k7ZQ=2ob-aZ_h(`)hBo9p*07_ZqQ*ehJwHE>n|IX68=}G)JBb6l@ujs@ z=p5PL1q7Nvjl}BC*l8PJ66FgjFAm?n^&@?s0VFc`^!$9Swx3zUnMPPBsZ7(GGfpjN zC=~#_u!`pXebE9DT9s=D|AI~;F}+y1r!kWoHPj#vHdTr#YpjfXT@b0P`HPco$C!)_ zRVr@N+}6q)Qtt3t5sAwf`6%{?7_t|dE2#nPKgwSi41oyP@$g~DFh(gs;{JP|o)A>g zYR|U(I4IO(GV>U}byq#-+f>hETAYD1w4Hze@&4rjCFCwEH$9A98aU9DC1g5!p0VG0 zAPYFOay!?#hZL~YP=ITdZ{F}%Kv8_pUUrYs@LABT(C#W#4h540x$$IVk^Wq-QNqKr|p{4D`h&X@hW&1Nyr2oM#9iL+0Tfnp&Tkn6FTen_aCB-L-@ zxi2|A#b9>rCKyG8L8o({|2EvvcSz;m&L+C61AgOeyw%^{vvJZ11sWWQL{_faS6$RJ z%?`m(*KQCwxqJnIV<}34NN*ONnd{j8bs){5&dx($o{p{k25i~?^{dkJ;z0$!m9Sgy z)Y#p3f0R{zIT_Y69+{m5g8xmm=g8jP9$GmM47}MNhymh~S=@xofvzdz@qOEe7@)9; zMP14q8+jnck7Z_*Mhb~TbyANfY@TH_zdI}=pCTr-XycfaI8kp7I_jkr6ckM2CVIa^ zFLQl5=|2@Ulc!q1gT(;Pz3-jDIe#q`aQa_$>NQA%N2PMt_>e=y$!Mtyd&9{yGj^!E zI~ice(kJ;NvttaY(5v%#H!MirtMi{ZGmRkh*(qY;gcK&aoW;lPaf1@_mw~kqeJfP6 z%!9FMTzByjRXDed{hq1$9W1etBAp(qK#@|<{9(!d>16!L zX3B>~#KO+$X14Ujh}6MKrehw)J6VE)Gvt#z>CBnym|j~PE=&dk3-Wu?Eqa6orECoG zwpZtS+kgIi9UCKC@>`GRSpEr!U6t7%+rq*E5(=cB143K1NC(7lVQVYndK>TiUHuYsfTi zxe|!y`iJPUPfgo47`KWzs8pQB1yWC|TYXoIq1ITl2}9udh-X2Jx+zwAMRT0W7muYN ziXWl*jJ=wZKaTfoh)GH906pU2MmUK`gNy?L-9NgfzrP<8BA>O5zP~2dn0vmFy--G9 zdRyw{vtcW7AW8v%8KsZDQu=|)&?qQRjU7mmsEAvno5I>aBhxW4X_{$0Oj6tC*8V7S zVLo+F7{_S$|Vx zvfBE!c4B(k@CN}_k{bI|(WIg*dFaT1iv#HQx>G}D~ z%WGs?6i2<|du=O6M@P$1rBOlu{p=lM_yXx(%kE-nU7eRYUdW3Vl^<+aT^dw)xlhk# ztk#PXWhZ<{>$j?D+hN(cQoekHzwVvR(Jb?@1=mUcmx;nD|9Km<4|)%9kQWIka^46Y zb$0US1YJ(4fw>XR9Tk`MLdzy3%8ZckJ8wMi`hh0Mx4#XtFLY6fPd)JjHm7NX~nk3<)ae;sgsLqtd{3{37={$?Dj$_n3x+ibbuD>WTJ$7=#YC*u!ee zx7dKyAlfC+=@UA5ru=r&Rx(Sk`%4~9U0Z`p+Ud_Sb2^te5%+hb{`V(y2-QAUcZUdpE zXfX9d)U>FyoEvz+1F!>=)Jvl4>uZg)+tc50_&H}}=irbBKef$p9#W#)6kPd1$>%q! zXg%0;J+JEZ(N=y)-uW!Bq<^X~A1;nVbH;*QA7qT`9g4xt#Hh*fLHNN|bwNjfkE17O zbiK(J_t~Y|Z`sPD4hcEzy5({H=jRXD{QSJf_84o9gcmNbz29EL%;68cC%jJ0t*xzs z!1Qw}X3mcY!<=nAtXYX_$VsBpE2Tb^Ki@qG3k&18dLW9ixVR|pcX$U>oB;s=Ae-{9 z9QCt|KF8EI=-t@Zcncf-{{5pNi>9iX86z-it=E?JpJkX_6)Qb6vt=!FXnFa6Wo2D0 zUR#F0{J&%pP=2rQQRD0p0% znJNM4Od1gpA;ES_MHhbx6)sEo{p~`_g4j08}il)kpvUjK9huj}kcsLqXjP zcB^&f&|vxJI7)^g{w@_k)uowan%Ft19KyZNrO9>iZPRjaVDIvB@RbW%vHpg0a&fJC zwh*<;t-8~7S(DYY9TQlB4i>tlLQ1;+E8VKEoRC6`TVAt7Rk>tt+GtO^u?hI zefq%^6bs+89IbUXT+2(6Q=rxBt*3618;uFrNnHJjEd8K+sE69$-R&;ZE7e6UwfPH~ z^U)^UmTI)MlF?WJp-&rl{-;atiA?0E>=hA9@TJXkafV{S)45Sl@)*%2Ox>l4ts0|> zS2?;`MlqL{^X;sv7LC6b)G?rT>wt60q7YvDLpZI*BH!Nyj?*b)bT4rNx?8{aX7QI6 z5-gx4-?jT5WkG~Cl9DuYzme6eNI==3XG95fjF}+ses?6{_Rh}z?MvWky4$xS%gdWV zQCjOb%8b|)gQ>^wr3-;n*RwgCEuc2h&j1+eEdj^oeZJv_Pz3U!v zad983@G{ECXJ(r{*zyARTiWV_Kx6_=wK%#^WqCz~=3Si`|IP38(ubW`8px7z?&%t< z#6;P@_tt~$?CgN*v+~%ZUz6BW1welbuw~EI$!b9~ zb9ZTeaF!r~_yJw4%Y35^6pDu?&d^Avh@U@y#$BPc2PoO-7#O;*4q&7Z5IeU(`_()B z&#;m(189~QJx(0m>RC^e>tNS|wYT5qZ$G67zW!}h(;S@GA5mK?C@d;!3tZ|4N_wLg zdPYXkpqbUVbz%dIM90E1nss80ojP`P5kS?<>k6>+FwwtWe~1O?i~Tjzpt!0kKBfZ$ zTj%+IeF?js@ z7YBEvYZY*UV^lKjCpgNL=4J3VFnv&9SfD0D`nF`8#>-(T>ZKwiNE{MpAE%<{C+~3G zKv)OB5HTKl8LyYg(Hi0;L)E!xmgyGY!$)diI4{MGvo#Smh_f0X;;$Y(gMG0yO=j*fB8qUcV1m&%U zV5A15lgb~qRwh*F==0SP^3)IvGFMx~wzy@mI3u7@g>d8itO@0x~M z)BL5PCm%GBAtv?!|6VeeCsN=-h9M%pmt_EQGh3N%&LBwH7|H^}mto5zb-T8*bHiA4 znEmz{r_jBb;Zz<8!29DOf`uNuUEtiJaV==!egGU0E>fIQ`S@lnl`=f6Pt*J%qketD z#C3NYh56h{QuOd<8s4NOg`>x6_OU4jT|_NIefJ5*c2ndK2WJEA;cSo~x2(`YAa$_N z2K$!wcmPT2M?E|2Neg-WnccL!ce>Y#xXplhoFeV!OrMK^-m>fD2eT?ptr;7kd9-kh zhcg<_xJN_jHEyhGV(Tbt%zE+7kATiJh!xF{-V&g!*UqsB>oqrx$w6E0o(6Zp#lacG zvSPt*9XP%Di#Nr(pUp+OWi`RgPAEvx^R(a=#t=xxSD$7VbaW&?^J*^g$c57L{PW(; z5Rej7=e*QUX=Zlo-vXm)oTRUON?j7Tb@P@4;Gb3|qN$fHTPPs`VS^#L-tj+txn&_Y z(o^ZD4nD56mi#`pDkQ@;1y8&jeH!V_@d@KBJtp)3PscFBCOTzs5eku?wPN7u^HAPD z#)X9Pc%`p+rEa=Y-z@SraspONuPZ{(8ecHN5fZZ=B_9ERq%OIoq%nZ^?-4XkaQ^_D zNDY_hY$c&gqINaJ`onG<6M;|DY#a}zUvN5}K_5Y4-UU5}&2J@`s(G81M1BKAVpl^# z0K~N3ZZgjyx$Bx6AYN5M@lBGh(v`?w>+36ATAi8M=xzjyEL-DOo();8HCH#*pNMZD z)5x(|i3v2_h2VklU^uAA1c12X#T2ZG3~dl8c0toOwhq_>8Rz?HTW%FQP%FDRi7}{< z9e$IGKluVz9jEYAK%?w)XU|4HEz4=9wcwxy!vz=ux~GDo8r%6X>@8Xx-uVW>aW$M< zFH;$#dk1rrcF7C>`3!W;4@5?u6xnMz8KTV4+40U}W-h|c@Ch^RDK#n_=vnH1jz`g9 zz|FW9)8pRboh|Vj)Nho%{(}lN3hOZs;OV0uWXi61a|mntBAw>Ji7r0|^}qn7%PQ+^ zE&kb@Fn+7@J`Tk7bGGr!C+&J7i<>umtQF#~bO)WB+?xy$t+C(70;wLcikdQK{vQyX zq~F0V4t%gIo&8_O6WZqu7qyro4`GXLl)R6`ZlLOfmcuOX@W#Q9WKrcWUgjG}WrvzhwnOc{Xg+Q7M4gF@(qd+h{&sp$h77=knU zXC}JxNNyv7N!>A3vAj7dyUD$4GfUQ~pxXZ%MhC-ZJTknND0o@jZakc<-+dY4(#d!I zxmhTqi=hUAYrU6stg*p^2M#5GO_OTjLZ2QRtZAh>T8k6c=GBf5mC6^{Wo5$-3asL|#pR_H?;*Dij~*X0V-H zNYRI4y#6&0-M0TXdsZ8H;fY&yR#j+E^$&@-|6hqeWtC^w2Ve0Rf_1NoaFC?vb__$| z++27HlG2*Ua6#Eb%uR*;J8nQz4Z}OtBRsZ*6Ysl{PF;}0~nq=F{e2|&dKeJC)S#X)EjH3adAWkE`VvT{u z*ZDsj!c1Cn+OX5x5yLr%CvSoGO2I&jL@HwU9Sm_W#|`&lT5%|(rn^a%uR$zXYjuLe z>02W3e{+WBM+yHjFonKMq3c?Q5dKr9v~@?hn9u%8osBUeQplO(6m(5 zt1{_=U}J^9%gcCZM7xn)KS63U{vtdTyTjy@>piaHxA08?tQ^}AQ{*b0(gi+j3pY$eqwJW+4 z%?HbINWFQ7HV0iOF6;>?iZs_Ga||UIRpaOX(CixrmI82~GvwED+XzNcKV{HbiA8sC zMAL6NIQGbgFK8rcQf^-I7+jKB_;*af7&S==#PJQacxP|`h+)p)+z+N)`6jC2 Date: Tue, 27 Nov 2018 21:18:48 -0500 Subject: [PATCH 088/320] scale banner properly on init --- .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 7fb82c7432..92fea9cc54 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -496,6 +496,7 @@ t[#t + 1] = Name = "Banner", InitCommand = function(self) self:x(10):y(61):halign(0):valign(0) + self:scaletoclipped(capWideScale(get43size(384), 384), capWideScale(get43size(120), 120)):diffusealpha(1) end, MintyFreshCommand=function(self) if INPUTFILTER:IsBeingPressed("tab") then From 4509801a64c592eefa4446aebc282ad217ba61f2 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 27 Nov 2018 23:23:02 -0500 Subject: [PATCH 089/320] remove dlman broadcast on grabbing leaderboards (use callbacks instead) --- src/DownloadManager.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 9ba99f4447..520aaaf779 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1568,8 +1568,6 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) // json failed } - Message msg("ChartLeaderboardUpdate"); - if (!ref.IsNil() && ref.IsSet()) { Lua* L = LUA->Get(); ref.PushSelf(L); @@ -1587,13 +1585,6 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) } LUA->Release(L); } - // float ProbablyUnderratedness = - // mythicalmathymathsProbablyUnderratedness(chartkey); float coop = - // overratedness(chartkey); - // Renaming these 2 requires renaming them in lua wherever theyre used - // msg.SetParam("mmm", ProbablyUnderratedness); - // msg.SetParam("ixmixblixb", 2); - MESSAGEMAN->Broadcast(msg); }; SendRequest("/charts/" + chartkey + "/leaderboards", vector>(), From 272d516f7e3fbb82f2ecbc4925d27c420cfb8167 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 27 Nov 2018 23:23:29 -0500 Subject: [PATCH 090/320] update online scoreboard to use callbacks and add replay watch button --- .../ScreenSelectMusic decorations/score.lua | 10 +- .../BGAnimations/superscoreboard.lua | 92 +++++++++++++------ 2 files changed, 70 insertions(+), 32 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 9a942c268f..ebce33fc9b 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -71,11 +71,11 @@ local function updateLeaderBoardForCurrentChart() DLMAN:RequestChartLeaderBoardFromOnline( steps:GetChartKey(), function(leaderboard) + moped:playcommand("SetFromLeaderboard", leaderboard) end ) - moped:queuecommand("ChartLeaderboardUpdate") else - moped:queuecommand("Bort") + moped:queuecommand("SetFromLeaderboard", {}) end end end @@ -132,6 +132,10 @@ local ret = self:queuecommand("Set") updateLeaderBoardForCurrentChart() end, + ChangeStepsMessageCommand = function(self) + self:queuecommand("Set") + updateLeaderBoardForCurrentChart() + end, CollapseCommand = function(self) collapsed = true resetTabIndex() @@ -189,7 +193,7 @@ local ret = end, CurrentRateChangedMessageCommand = function(self) if ((getTabIndex() == 2 and nestedTab == 2) or collapsed) and DLMAN:GetCurrentRateFilter() then - moped:queuecommand("ChartLeaderboardUpdate") + moped:queuecommand("GetFilteredLeaderboard") end end } diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index 9c44191caa..d73ea5fde5 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -75,20 +75,23 @@ local o = InitCommand = function(self) cheese = self self:SetUpdateFunction(highlight) + self:SetUpdateFunctionInterval(0.05) end, BeginCommand = function(self) SCREENMAN:GetTopScreen():AddInputCallback(input) + self:playcommand("Update") end, - ChartLeaderboardUpdateMessageCommand = function(self) + GetFilteredLeaderboardCommand = function(self) if GAMESTATE:GetCurrentSong() then scoretable = DLMAN:GetChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), currentCountry) ind = 0 self:playcommand("Update") end end, - BortCommand = function(self) - scoretable = {} + SetFromLeaderboardCommand = function(self, lb) + scoretable = lb ind = 0 + self:playcommand("GetFilteredLeaderboard") -- we can move all the filter stuff to lua so we're not being dumb hurr hur -mina self:playcommand("Update") end, UpdateCommand = function(self) @@ -236,19 +239,21 @@ local o = Name = "RequestStatus", InitCommand = function(self) if collapsed then - self:xy(dwidth - 75, headeroff + 15):zoom(tzoom):halign(1) + self:xy(c1x, headeroff + 15):zoom(tzoom):halign(0) else - self:xy(dwidth / 3, headeroff + 25):zoom(tzoom):halign(1) + self:xy(c1x, headeroff + 25):zoom(tzoom):halign(0) end end, UpdateCommand = function(self) local numberofscores = #scoretable local online = DLMAN:IsLoggedIn() - if not online and #scoretable == 0 then + if not GAMESTATE:GetCurrentSong() then + self:settext("") + elseif not online and #scoretable == 0 then self:settext("Login to view scores") else if #scoretable == 0 then - self:settext("Retrieving scores...") + self:settext("Online scores not tracked...") else self:settext("") end @@ -275,7 +280,7 @@ local o = if isOver(self) then DLMAN:ToggleRateFilter() ind = 0 - self:GetParent():queuecommand("ChartLeaderboardUpdate") + self:GetParent():queuecommand("GetFilteredLeaderboard") end end }, @@ -303,7 +308,7 @@ local o = if isOver(self) then DLMAN:ToggleTopScoresOnlyFilter() ind = 0 - self:GetParent():queuecommand("ChartLeaderboardUpdate") + self:GetParent():queuecommand("GetFilteredLeaderboard") end end } @@ -320,11 +325,11 @@ local function makeScoreDisplay(i) self:visible(false) end end, - UpdateCommand = function(self) + UpdateCommand = function(self) hs = scoretable[(i + ind)] if hs and i <= numscores then - self:queuecommand("Display") self:visible(true) + self:playcommand("Display") else self:visible(false) end @@ -334,28 +339,14 @@ local function makeScoreDisplay(i) self:x(offx):zoomto(dwidth, pdh):halign(0) end, DisplayCommand = function(self) - if hs:HasReplayData() then - self:diffuse(color("#555555CC")) - else - self:diffuse(color("#111111CC")) - end + self:diffuse(color("#111111CC")) end, HighlightCommand = function(self) - if isOver(self) and collapsed then - self:diffusealpha(1) + if isOver(self) then + self:diffusealpha(0.8) else self:diffusealpha(0.6) end - end, - MouseLeftClickMessageCommand = function(self) - if isOver(self) and hs then - DLMAN:RequestOnlineScoreReplayData( - hs, - function() - SCREENMAN:GetTopScreen():PlayReplay(hs) - end - ) - end end }, LoadFont("Common normal") .. @@ -461,6 +452,45 @@ local function makeScoreDisplay(i) self:visible(true):addy(-row2yoff) end }, + LoadFont("Common normal") .. + { + Name = "Replay" .. i, + InitCommand = function(self) + if not collapsed then + self:x(capWideScale(c3x + 52, c3x) ):zoom(tzoom - 0.05):halign(1):valign(0):maxwidth(width / 2 / tzoom):addy(row2yoff):diffuse(getMainColor("enabled")) + end + end, + DisplayCommand = function(self) + DLMAN:RequestOnlineScoreReplayData(hs, + function(replay) + if #replay > 0 then + self:settext("Watch") + else + self:settext("") + end + end + ) + end, + HighlightCommand = function(self) + highlightIfOver(self) + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) and hs then + DLMAN:RequestOnlineScoreReplayData( + hs, + function() + SCREENMAN:GetTopScreen():PlayReplay(hs) + end + ) + end + end, + CollapseCommand = function(self) + self:visible(false) + end, + ExpandCommand = function(self) + self:visible(true):addy(-row2yoff) + end + }, LoadFont("Common normal") .. { --percent @@ -483,7 +513,11 @@ local function makeScoreDisplay(i) end end, DisplayCommand = function(self) - self:settext(hs:GetDate()) + if IsUsingWideScreen() then + self:settext(hs:GetDate()) + else + self:settext(hs:GetDate():sub(1, 10)) + end end, CollapseCommand = function(self) self:visible(false) From 01e7bd15598dd3838795f62665b437103cc3c7f4 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 27 Nov 2018 23:39:47 -0500 Subject: [PATCH 091/320] fix evalscreen mouseovers --- .../ScreenEvaluation decorations/scoreboard.lua | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua b/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua index ed9cb0a295..3a9a9ff210 100644 --- a/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua @@ -121,12 +121,9 @@ local function scoreitem(pn, index, scoreIndex, drawindex) Def.Quad { Name = "mouseOver", InitCommand = function(self) - self:xy(framex, framey + (drawindex * spacing) - 4):zoomto(frameWidth, 30):halign(0):valign(0):diffuse( + self:xy(framex, framey + (drawindex * spacing) - 4):zoomto(frameWidth*2, 30):halign(0):valign(0):diffuse( getMainColor("highlight") - ):diffusealpha(0.05) - end, - BeginCommand = function(self) - self:visible(false) + ):diffusealpha(0) end }, --ClearType lamps @@ -302,9 +299,9 @@ local function Update(self) end for i = 0, drawindex - 1 do if isOver(self:GetChild("scoreItem" .. tostring(i)):GetChild("mouseOver")) then - self:GetChild("scoreItem" .. tostring(i)):GetChild("mouseOver"):visible(true) + self:GetChild("scoreItem" .. tostring(i)):GetChild("mouseOver"):diffusealpha(0.2) else - self:GetChild("scoreItem" .. tostring(i)):GetChild("mouseOver"):visible(false) + self:GetChild("scoreItem" .. tostring(i)):GetChild("mouseOver"):diffusealpha(0) self:GetChild("scoreItem" .. tostring(i)):GetChild("grade"):visible(true) self:GetChild("scoreItem" .. tostring(i)):GetChild("judge"):visible(true) self:GetChild("scoreItem" .. tostring(i)):GetChild("date"):visible(false) From f12eb31aead4c0227efa919b9ced4d3bcd905fe0 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 00:08:56 -0500 Subject: [PATCH 092/320] make generichighlight slightly more generic --- .../ScreenSelectProfile overlay.lua | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua b/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua index 190eb14252..d81d2af8ba 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectProfile overlay.lua @@ -5,18 +5,23 @@ local function selectprofile(self) end end local function genericHighlight(self, highlight, base, clickaction) + local highlight = highlight or 0.6 + local base = base or 1 self:SetUpdateFunction(function(self) - self:RunCommandsOnChildren( - function(self) - if isOver(self) then - self:diffusealpha(highlight) - else - self:diffusealpha(base) + if self:IsVisible() then + self:RunCommandsOnChildren( + function(self) + if isOver(self) then + self:diffusealpha(highlight) + else + self:diffusealpha(base) + end end + ) end - ) - end) - self:SetUpdateRate(0.5) + end + ) + self:SetUpdateFunctionInterval(0.025) if clickaction then self:RunCommandsOnChildren( function(self) From 6d4a33191ac2904676cd6b9b3d48768cd7864331 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 00:47:25 -0500 Subject: [PATCH 093/320] changing rates in playlists probably doesnt need to invoke save --- src/SongManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 2a798e9556..7c42771336 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -2002,7 +2002,6 @@ class LunaChart : public Luna { p->rate += FArg(1); CLAMP(p->rate, 0.7f, 3.f); - PROFILEMAN->SaveProfile(PLAYER_1); return 1; } From d9b59e34d91fd6fe17cdb5ae0239439b30c5bbc6 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 00:48:07 -0500 Subject: [PATCH 094/320] fix/refactor/add to playlist mouseovers --- .../playlists.lua | 333 ++++++++---------- 1 file changed, 156 insertions(+), 177 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua index 897d795948..dd68b93a5a 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/playlists.lua @@ -1,3 +1,30 @@ +local function genericHighlight(self, highlight, base, clickaction) + local highlight = highlight or 0.6 + local base = base or 1 + self:SetUpdateFunction(function(self) + if self:IsVisible() then + self:RunCommandsOnChildren( + function(self) + if isOver(self) then + self:diffusealpha(highlight) + else + self:diffusealpha(base) + end + end + ) + end + end + ) + self:SetUpdateFunctionInterval(0.025) + if clickaction then + self:RunCommandsOnChildren( + function(self) + self:addcommand("LeftClickMessage", clickaction) + end + ) + end +end + local update = false local t = Def.ActorFrame { @@ -42,7 +69,6 @@ local rankingWidth = frameWidth - capWideScale(15, 50) local rankingX = capWideScale(30, 50) local rankingY = capWideScale(40, 40) local rankingTitleSpacing = (rankingWidth / (#ms.SkillSets)) -local buttondiffuse = 0 local whee local singleplaylistactive = false @@ -109,7 +135,7 @@ local function BroadcastIfActive(msg) end end -local function ButtonActive(self, scale) +local function ButtonActive(self) return isOver(self) and update end @@ -169,11 +195,9 @@ local function RateDisplayButton(i) Def.ActorFrame { Name = "RateDisplay", InitCommand = function(self) + genericHighlight(self) self:x(220) end, - ResizeCommand = function(self) - self:GetChild("Button"):zoomto(self:GetChild("Text"):GetWidth(), self:GetChild("Text"):GetHeight()) - end, LoadFont("Common Large") .. { Name = "Text", @@ -183,27 +207,20 @@ local function RateDisplayButton(i) "x" self:settext(ratestring) self:zoom(fontScale) - self:GetParent():queuecommand("Resize") - end - }, - Def.Quad { - Name = "Button", - InitCommand = function(self) - self:diffusealpha(buttondiffuse) - end, - MouseLeftClickMessageCommand = function(self) - if ButtonActive(self, fontScale) and singleplaylistactive then - chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:ChangeRate(0.1) - BroadcastIfActive("DisplaySinglePlaylist") - end - end, - MouseRightClickMessageCommand = function(self) - if ButtonActive(self, fontScale) and singleplaylistactive then - chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:ChangeRate(-0.1) - BroadcastIfActive("DisplaySinglePlaylist") + end, + MouseLeftClickMessageCommand = function(self) + if ButtonActive(self) and singleplaylistactive then + chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:ChangeRate(0.1) + BroadcastIfActive("DisplaySinglePlaylist") + end + end, + MouseRightClickMessageCommand = function(self) + if ButtonActive(self) and singleplaylistactive then + chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:ChangeRate(-0.1) + BroadcastIfActive("DisplaySinglePlaylist") + end end - end - } + } } return o end @@ -213,11 +230,9 @@ local function TitleDisplayButton(i) Def.ActorFrame { Name = "TitleDisplay", InitCommand = function(self) + genericHighlight(self) self:x(15) end, - ResizeCommand = function(self) - self:GetChild("Button"):zoomto(self:GetChild("Text"):GetWidth(), self:GetChild("Text"):GetHeight()) - end, LoadFont("Common Large") .. { Name = "Text", @@ -228,29 +243,22 @@ local function TitleDisplayButton(i) self:zoom(fontScale) self:maxwidth(480) self:settext(chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:GetSongTitle()) - self:GetParent():queuecommand("Resize") if chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:IsLoaded() then self:diffuse(getMainColor("positive")) else self:diffuse(byJudgment("TapNoteScore_Miss")) end + end, + MouseLeftClickMessageCommand = function(self) + if + ButtonActive(self) and chartlist[i + ((currentchartpage - 1) * chartsperplaylist)] and + chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:IsLoaded() and + singleplaylistactive + then + whee:SelectSong(songlist[i + ((currentchartpage - 1) * chartsperplaylist)]) + end end - }, - Def.Quad { - Name = "Button", - InitCommand = function(self) - self:diffusealpha(buttondiffuse):halign(0) - end, - MouseLeftClickMessageCommand = function(self) - if - ButtonActive(self, fontScale) and chartlist[i + ((currentchartpage - 1) * chartsperplaylist)] and - chartlist[i + ((currentchartpage - 1) * chartsperplaylist)]:IsLoaded() and - singleplaylistactive - then - whee:SelectSong(songlist[i + ((currentchartpage - 1) * chartsperplaylist)]) - end - end - } + } } return o end @@ -260,11 +268,9 @@ local function DeleteChartButton(i) Def.ActorFrame { Name = "DeleteButton", InitCommand = function(self) + genericHighlight(self) self:x(315) end, - ResizeCommand = function(self) - self:GetChild("Button"):zoomto(self:GetChild("Text"):GetWidth(), self:GetChild("Text"):GetHeight()) - end, LoadFont("Common Large") .. { Name = "Text", @@ -274,23 +280,16 @@ local function DeleteChartButton(i) DisplaySinglePlaylistLevel2Command = function(self) self:zoom(fontScale) self:settext("Del") - self:GetParent():queuecommand("Resize") self:diffuse(byJudgment("TapNoteScore_Miss")) + end, + MouseLeftClickMessageCommand = function(self) + if ButtonActive(self) and singleplaylistactive then + pl:DeleteChart(i + ((currentchartpage - 1) * chartsperplaylist)) + MESSAGEMAN:Broadcast("DisplayAll") + MESSAGEMAN:Broadcast("DisplaySinglePlaylist") + end end - }, - Def.Quad { - Name = "Button", - InitCommand = function(self) - self:diffusealpha(buttondiffuse):halign(0) - end, - MouseLeftClickMessageCommand = function(self) - if ButtonActive(self, fontScale) and singleplaylistactive then - pl:DeleteChart(i + ((currentchartpage - 1) * chartsperplaylist)) - MESSAGEMAN:Broadcast("DisplayAll") - MESSAGEMAN:Broadcast("DisplaySinglePlaylist") - end - end - } + } } return o end @@ -319,10 +318,12 @@ local function rankingLabel(i) self:GetChild("DeleteButton"):visible(true) self:GetChild("TitleDisplay"):visible(true) self:GetChild("RateDisplay"):visible(true) + self:GetChild("PackMouseOver"):visible(true) else self:GetChild("DeleteButton"):visible(false) self:GetChild("TitleDisplay"):visible(false) self:GetChild("RateDisplay"):visible(false) + self:GetChild("PackMouseOver"):visible(false) end else self:visible(true) @@ -340,16 +341,41 @@ local function rankingLabel(i) self:settext(((rankingPage - 1) * 25) + i + ((currentchartpage - 1) * chartsperplaylist) .. ".") end }, - LoadFont("Common Large") .. - { - -- pack mouseover for later + Def.ActorFrame { + Name = "PackMouseOver", InitCommand = function(self) - self:x(15):maxwidth(580) - self:halign(0):zoom(fontScale) + self:SetUpdateFunction(function(self) + if self:IsVisible() then + self:queuecommand("PackMouseover") + end + end) end, - DisplaySinglePlaylistLevel2MessageCommand = function(self) - --self:settext(songlist[i]:GetGroupName()) - end + Def.Quad { + InitCommand = function(self) + Name = "mouseover", + self:x(15):zoomto(180, 8):halign(0):diffusealpha(0) + end, + PackMouseoverMessageCommand = function(self) + if isOver(self) then + self:GetParent():queuecommand("DisplayPack") + end + end + }, + LoadFont("Common Large") .. { + Name = "text", + InitCommand = function(self) + self:xy(15, -10):maxwidth(580):halign(0):zoom(fontScale) + end, + DisplayPackCommand = function(self) + if songlist[i + ((currentchartpage - 1) * chartsperplaylist)] then + self:settext(songlist[i + ((currentchartpage - 1) * chartsperplaylist)]:GetGroupName()) + self:finishtweening() + self:diffusealpha(1) + self:linear(0.25) + self:diffusealpha(0) + end + end + } }, LoadFont("Common Large") .. { @@ -399,6 +425,7 @@ end local b2 = Def.ActorFrame { InitCommand = function(self) + genericHighlight(self) self:xy(215, rankingY) end, DisplayAllMessageCommand = function(self) @@ -414,19 +441,13 @@ b2[#b2 + 1] = { InitCommand = function(self) self:zoom(0.3):x(85):settext("Play As Course") + end, + MouseLeftClickMessageCommand = function(self) + if ButtonActive(self) and singleplaylistactive then + SCREENMAN:GetTopScreen():StartPlaylistAsCourse(pl:GetName()) + end end } -b2[#b2 + 1] = - Def.Quad { - InitCommand = function(self) - self:x(85):diffusealpha(buttondiffuse):zoomto(110, 20) - end, - MouseLeftClickMessageCommand = function(self) - if ButtonActive(self, 0.3) and singleplaylistactive then - SCREENMAN:GetTopScreen():StartPlaylistAsCourse(pl:GetName()) - end - end -} -- Back button b2[#b2 + 1] = @@ -434,39 +455,23 @@ b2[#b2 + 1] = { InitCommand = function(self) self:zoom(0.3):settext("Back") + end, + MouseLeftClickMessageCommand = function(self) + if ButtonActive(self) and singleplaylistactive then + MESSAGEMAN:Broadcast("DisplayAll") + end end } -b2[#b2 + 1] = - Def.Quad { - InitCommand = function(self) - self:diffusealpha(buttondiffuse):zoomto(110, 20) - end, - MouseLeftClickMessageCommand = function(self) - if ButtonActive(self, 0.3) and singleplaylistactive then - MESSAGEMAN:Broadcast("DisplayAll") - end - end -} + r[#r + 1] = b2 -- next/prev pages for individual playlists, i guess these could be merged with the allplaylists buttons for efficiency but meh r[#r + 1] = Def.ActorFrame { InitCommand = function(self) + genericHighlight(self) self:xy(frameX + 10, frameY + rankingY + 250) end, - Def.Quad { - InitCommand = function(self) - self:xy(300, -8):zoomto(40, 20):halign(0):valign(0):diffuse(getMainColor("frames")):diffusealpha(buttondiffuse) - end, - MouseLeftClickMessageCommand = function(self) - if isOver(self) and currentchartpage < numplaylistpages and singleplaylistactive then - currentchartpage = currentchartpage + 1 - MESSAGEMAN:Broadcast("DisplaySinglePlaylist") - MESSAGEMAN:Broadcast("DisplayPP") - end - end - }, LoadFont("Common Large") .. { InitCommand = function(self) @@ -478,19 +483,14 @@ r[#r + 1] = DisplaySinglePlaylistMessageCommand = function(self) self:visible(true) end - }, - Def.Quad { - InitCommand = function(self) - self:y(-8):zoomto(65, 20):halign(0):valign(0):diffuse(getMainColor("frames")):diffusealpha(buttondiffuse) - end, - MouseLeftClickMessageCommand = function(self) - if isOver(self) and currentchartpage > 1 and singleplaylistactive then - currentchartpage = currentchartpage - 1 - MESSAGEMAN:Broadcast("DisplaySinglePlaylist") - MESSAGEMAN:Broadcast("DisplayPP") + ,MouseLeftClickMessageCommand = function(self) + if isOver(self) and currentchartpage < numplaylistpages and singleplaylistactive then + currentchartpage = currentchartpage + 1 + MESSAGEMAN:Broadcast("DisplaySinglePlaylist") + MESSAGEMAN:Broadcast("DisplayPP") + end end - end - }, + }, LoadFont("Common Large") .. { InitCommand = function(self) @@ -501,6 +501,13 @@ r[#r + 1] = end, DisplaySinglePlaylistMessageCommand = function(self) self:visible(true) + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) and currentchartpage > 1 and singleplaylistactive then + currentchartpage = currentchartpage - 1 + MESSAGEMAN:Broadcast("DisplaySinglePlaylist") + MESSAGEMAN:Broadcast("DisplayPP") + end end }, LoadFont("Common Large") .. @@ -529,11 +536,9 @@ local function PlaylistTitleDisplayButton(i) local o = Def.ActorFrame { InitCommand = function(self) + genericHighlight(self) self:x(15) end, - ResizeCommand = function(self) - self:GetChild("Button"):zoomto(self:GetChild("Text"):GetWidth(), self:GetChild("Text"):GetHeight()) - end, LoadFont("Common Large") .. { Name = "Text", @@ -544,24 +549,17 @@ local function PlaylistTitleDisplayButton(i) self:zoom(fontScale) if allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)] then self:settext(allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)]:GetName()) - self:GetParent():queuecommand("Resize") + end + end, + MouseLeftClickMessageCommand = function(self) + if ButtonActive(self) and allplaylistsactive then + SONGMAN:SetActivePlaylist(allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)]:GetName()) + pl = allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)] + MESSAGEMAN:Broadcast("DisplaySinglePlaylist") end end - }, - Def.Quad { - Name = "Button", - InitCommand = function(self) - self:diffusealpha(buttondiffuse):halign(0) - end, - MouseLeftClickMessageCommand = function(self) - if ButtonActive(self, fontScale) and allplaylistsactive then - SONGMAN:SetActivePlaylist(allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)]:GetName()) - pl = allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)] - MESSAGEMAN:Broadcast("DisplaySinglePlaylist") - end - end + } } - } return o end @@ -569,11 +567,9 @@ local function DeletePlaylistButton(i) local o = Def.ActorFrame { InitCommand = function(self) + genericHighlight(self) self:x(315) end, - ResizeCommand = function(self) - self:GetChild("Button"):zoomto(self:GetChild("Text"):GetWidth(), self:GetChild("Text"):GetHeight()) - end, LoadFont("Common Large") .. { Name = "Text", @@ -584,23 +580,16 @@ local function DeletePlaylistButton(i) if allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)] then self:settext("Del") self:zoom(fontScale) - self:GetParent():queuecommand("Resize") self:diffuse(byJudgment("TapNoteScore_Miss")) end + end, + MouseLeftClickMessageCommand = function(self) + if ButtonActive(self) and allplaylistsactive then + SONGMAN:DeletePlaylist(allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)]:GetName()) + MESSAGEMAN:Broadcast("DisplayAll") + end end - }, - Def.Quad { - Name = "Button", - InitCommand = function(self) - self:diffusealpha(buttondiffuse):halign(0) - end, - MouseLeftClickMessageCommand = function(self) - if ButtonActive(self, fontScale) and allplaylistsactive then - SONGMAN:DeletePlaylist(allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)]:GetName()) - MESSAGEMAN:Broadcast("DisplayAll") - end - end - } + } } return o end @@ -631,7 +620,6 @@ local function PlaylistSelectLabel(i) end, AllDisplayMessageCommand = function(self) self:halign(0.5) - self:diffuse(getMainColor("positive")) self:settext(((rankingPage - 1) * 25) + i + ((currentplaylistpage - 1) * playlistsperpage) .. ".") end }, @@ -640,10 +628,10 @@ local function PlaylistSelectLabel(i) InitCommand = function(self) self:halign(0):zoom(fontScale) self:xy(15, row2Yoffset) + self:diffuse(getMainColor("positive")) end, AllDisplayMessageCommand = function(self) if allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)] then - self:diffuse(getMainColor("positive")) self:settextf( "Number of charts: %d", allplaylists[i + ((currentplaylistpage - 1) * playlistsperpage)]:GetNumCharts() @@ -656,10 +644,10 @@ local function PlaylistSelectLabel(i) InitCommand = function(self) self:halign(0):zoom(fontScale) self:xy(200, row2Yoffset) + self:diffuse(getMainColor("positive")) end, AllDisplayMessageCommand = function(self) self:settextf("Average Rating:") - self:diffuse(getMainColor("positive")) end }, LoadFont("Common Large") .. @@ -723,19 +711,9 @@ end r[#r + 1] = Def.ActorFrame { InitCommand = function(self) + genericHighlight(self) self:xy(frameX + 10, frameY + rankingY + 250) end, - Def.Quad { - InitCommand = function(self) - self:xy(300, -8):zoomto(40, 20):halign(0):valign(0):diffuse(getMainColor("frames")):diffusealpha(buttondiffuse) - end, - MouseLeftClickMessageCommand = function(self) - if isOver(self) and currentplaylistpage < numplaylistpages and allplaylistsactive then - currentplaylistpage = currentplaylistpage + 1 - MESSAGEMAN:Broadcast("DisplayAll") - end - end - }, LoadFont("Common Large") .. { InitCommand = function(self) @@ -746,19 +724,14 @@ r[#r + 1] = end, DisplayAllMessageCommand = function(self) self:visible(true) + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) and currentplaylistpage < numplaylistpages and allplaylistsactive then + currentplaylistpage = currentplaylistpage + 1 + MESSAGEMAN:Broadcast("DisplayAll") + end end }, - Def.Quad { - InitCommand = function(self) - self:y(-8):zoomto(65, 20):halign(0):valign(0):diffuse(getMainColor("frames")):diffusealpha(buttondiffuse) - end, - MouseLeftClickMessageCommand = function(self) - if isOver(self) and currentplaylistpage > 1 and allplaylistsactive then - currentplaylistpage = currentplaylistpage - 1 - MESSAGEMAN:Broadcast("DisplayAll") - end - end - }, LoadFont("Common Large") .. { InitCommand = function(self) @@ -769,6 +742,12 @@ r[#r + 1] = end, DisplayAllMessageCommand = function(self) self:visible(true) + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) and currentplaylistpage > 1 and allplaylistsactive then + currentplaylistpage = currentplaylistpage - 1 + MESSAGEMAN:Broadcast("DisplayAll") + end end }, LoadFont("Common Large") .. From 3c2c6344eb8a78732558a48c86031dac5c66ed43 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 01:15:50 -0500 Subject: [PATCH 095/320] replace accidentally removed codeblock for handling oneshot/permamirror also fixes a bug with chartpreview sound resetting unintentionally --- .../ScreenSelectMusic decorations/wifeTwirl.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 92fea9cc54..326dcdf839 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -23,7 +23,13 @@ local t = OnCommand = function(self) self:bouncebegin(0.2):xy(0, 0):diffusealpha(1) end, - CurrentSongChanged = function() + CurrentSongChangedMessageCommand = function() + -- This will disable mirror when switching songs if OneShotMirror is enabled or if permamirror is flagged on the chart (it is enabled if so in screengameplayunderlay/default) + if playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).OneShotMirror or profile:IsCurrentChartPermamirror() then + local modslevel = topscreen == "ScreenEditOptions" and "ModsLevel_Stage" or "ModsLevel_Preferred" + local playeroptions = GAMESTATE:GetPlayerState(PLAYER_1):GetPlayerOptions(modslevel) + playeroptions:Mirror(false) + end if getTabIndex() ~= 0 then boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone = true end From 31dc3723e3d00b7f9dbf15cadd4625618b3535a1 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 02:47:19 -0500 Subject: [PATCH 096/320] improve mpchat input handling --- .../BGAnimations/ScreenNetRoom underlay.lua | 3 +++ .../ScreenChatOverlay overlay.lua | 20 ++++++++++++------- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua index 919e2f233b..5553618d30 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua @@ -6,6 +6,9 @@ t[#t + 1] = self:xy(SCREEN_WIDTH, 0):halign(1):valign(0):zoomto(capWideScale(get43size(350), 350), SCREEN_HEIGHT):diffuse( color("#33333399") ) + end, + BeginCommand= function(self) + MESSAGEMAN:Broadcast("AddMPChatInput") end } diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index befddb9a7f..fb950153b5 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -65,7 +65,7 @@ local i = 0 chat.InitCommand = function(self) online = IsNetSMOnline() and IsSMOnlineLoggedIn(PLAYER_1) and NSMAN:IsETTP() end -chat.ScreenChangedMessageCommand = function(self) +chat.AddMPChatInputMessageCommand = function(self) local s = SCREENMAN:GetTopScreen() if not s then return @@ -98,19 +98,23 @@ chat.MultiplayerDisconnectionMessageCommand = function(self) SCREENMAN:set_input_redirected("PlayerNumber_P1", false) end +local chatbg chat[#chat + 1] = Def.Quad { Name = "Background", InitCommand = function(self) + chatbg = self self:diffuse(Colors.background) self:diffusealpha(transparency) self:stretchto(x, y, width + x, height * (lineNumber + inputLineNumber + tabHeight) + y) end } +local minbar chat[#chat + 1] = Def.Quad { Name = "Bar", InitCommand = function(self) + minbar = self self:diffuse(Colors.bar) self:diffusealpha(transparency) self:stretchto(x, y, width + x, height + y) @@ -271,10 +275,12 @@ for i = 0, maxTabs - 1 do } end +local inbg chatWindow[#chatWindow + 1] = Def.Quad { Name = "ChatBox", InitCommand = function(self) + inbg = self self:diffuse(Colors.input) self:diffusealpha(transparency) end, @@ -330,15 +336,11 @@ function input(event) end typing = false local mx, my = INPUTFILTER:GetMouseX(), INPUTFILTER:GetMouseY() - if mx >= x and mx <= x + width and my >= moveY + y and my <= moveY + y + height then + if isOver(minbar) then minimised = not minimised MESSAGEMAN:Broadcast("Minimise") update = true - elseif - mx >= x and mx <= width + x and my >= height * (lineNumber + tabHeight) + y + moveY + 4 and - my <= height * (lineNumber + inputLineNumber + tabHeight) + y + moveY and - not minimised - then + elseif isOver(inbg) and not minimised then typing = true update = true elseif mx >= x and mx <= x + width and my >= y + moveY and my <= y + height + moveY then @@ -410,6 +412,10 @@ function input(event) MESSAGEMAN:Broadcast("UpdateChatOverlay") end + -- always eat mouse inputs if its within the broader chatbox + if event.DeviceInput.button == "DeviceButton_left mouse button"and isOver(chatbg) then + return true + end return update or typing end From 256e2a3b6d202bc08019fcbbbde08f7481109876 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 02:51:57 -0500 Subject: [PATCH 097/320] remove stray sysmsgs --- .../BGAnimations/ScreenNetRoom decorations/roomsearch.lua | 2 -- .../BGAnimations/ScreenNetSelectMusic decorations/default.lua | 1 - 2 files changed, 3 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua index 0821d1e215..fb5fea2926 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua @@ -152,7 +152,6 @@ local t = SCREENMAN:GetTopScreen():AddInputCallback(searchInput) self:finishtweening() if NSMAN:IsETTP() then - ms.ok("Song search activated") self:visible(true) active = true whee:Move(0) @@ -166,7 +165,6 @@ local t = SetCommand = function(self) self:finishtweening() if getTabIndex() == (NSMAN:IsETTP() and 0 or 1) then - ms.ok("Song search activated") MESSAGEMAN:Broadcast("BeginningSearch") self:visible(true) active = true diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua index 5386ad53cb..59bee441e2 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua @@ -3,7 +3,6 @@ if NSMAN:IsETTP() then t[#t + 1] = Def.ActorFrame { LeftClickMessageCommand = function() - SCREENMAN:SystemMessage("asdasdasd") MESSAGEMAN:Broadcast("MouseLeftClick") end } From dd8d84dca361bf76179e9239235e126fd5be2d74 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 02:52:29 -0500 Subject: [PATCH 098/320] resize chat --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index fb950153b5..e3db969e95 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -1,7 +1,7 @@ local lastx, lasty = 0, 0 local width, height = SCREEN_WIDTH, SCREEN_HEIGHT * 0.035 -local lineNumber = 8 -local inputLineNumber = 3 +local lineNumber = 6 +local inputLineNumber = 2 local tabHeight = 1 local maxTabs = 10 local x, y = 0, SCREEN_HEIGHT - height * (lineNumber + inputLineNumber + tabHeight) From 15cab851b20fe4b8f6ecd570cdc0d9c453a3b191 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 03:23:28 -0500 Subject: [PATCH 099/320] add mousewheeling in chat --- .../ScreenChatOverlay overlay.lua | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index e3db969e95..5e3d5c239f 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -1,5 +1,6 @@ local lastx, lasty = 0, 0 local width, height = SCREEN_WIDTH, SCREEN_HEIGHT * 0.035 +local maxlines = 6 local lineNumber = 6 local inputLineNumber = 2 local tabHeight = 1 @@ -98,12 +99,12 @@ chat.MultiplayerDisconnectionMessageCommand = function(self) SCREENMAN:set_input_redirected("PlayerNumber_P1", false) end -local chatbg +local bg chat[#chat + 1] = Def.Quad { Name = "Background", InitCommand = function(self) - chatbg = self + bg = self self:diffuse(Colors.background) self:diffusealpha(transparency) self:stretchto(x, y, width + x, height * (lineNumber + inputLineNumber + tabHeight) + y) @@ -170,16 +171,17 @@ local chatWindow = end end } - +local chatbg chatWindow[#chatWindow + 1] = Def.Quad { Name = "ChatWindow", InitCommand = function(self) + chatbg = self self:diffuse(Colors.output) self:diffusealpha(transparency) end, UpdateChatOverlayMessageCommand = function(self) - self:stretchto(x, height * (1 + tabHeight) + y, width + x, height * (lineNumber + tabHeight) + y) + self:stretchto(x, height * (1 + tabHeight) + y, width + x, height * (maxlines + tabHeight) + y) curmsgh = 0 MESSAGEMAN:Broadcast("UpdateChatOverlayMsgs") end @@ -195,17 +197,17 @@ chatWindow[#chatWindow + 1] = self:zoom(scale) self:SetMaxLines(lineNumber, 1) self:wrapwidthpixels((width - 8) / scale) + self:xy(x + 4, y + height * (lineNumber + tabHeight) - 4) end, UpdateChatOverlayMsgsMessageCommand = function(self) local t = "" - for i = lineNumber - 1, 0, -1 do + for i = lineNumber - 1, lineNumber - maxlines, -1 do if messages[#messages - i] then t = t .. messages[#messages - i] .. "\n" end end self:settext(t) - self:SetMaxLines(lineNumber, 1) - self:xy(x + 4, y + height * (lineNumber + tabHeight) - 4) + end } @@ -285,7 +287,7 @@ chatWindow[#chatWindow + 1] = self:diffusealpha(transparency) end, UpdateChatOverlayMessageCommand = function(self) - self:stretchto(x, height * (lineNumber + 1) + y + 4, width + x, height * (lineNumber + 1 + inputLineNumber) + y) + self:stretchto(x, height * (maxlines + 1) + y + 4, width + x, height * (maxlines + 1 + inputLineNumber) + y) self:diffuse(typing and Colors.activeInput or Colors.input):diffusealpha(transparency) end } @@ -344,7 +346,7 @@ function input(event) typing = true update = true elseif mx >= x and mx <= x + width and my >= y + moveY and my <= y + height + moveY then - mousex, mousey = mx, my + mousex, mousey = mx, my -- no clue what this block of code is for lastx, lasty = x, y update = true elseif not minimised then @@ -408,14 +410,33 @@ function input(event) update = true end end + + if event.DeviceInput.button == "DeviceButton_mousewheel up" and event.type == "InputEventType_FirstPress" then + if isOver(chatbg) then + if lineNumber < #messages then + lineNumber = lineNumber + 1 + update = true + end + end + end + if event.DeviceInput.button == "DeviceButton_mousewheel down" and event.type == "InputEventType_FirstPress" then + if isOver(chatbg) then + if lineNumber > maxlines then + lineNumber = lineNumber - 1 + update = true + end + end + end + if update then MESSAGEMAN:Broadcast("UpdateChatOverlay") end -- always eat mouse inputs if its within the broader chatbox - if event.DeviceInput.button == "DeviceButton_left mouse button"and isOver(chatbg) then + if event.DeviceInput.button == "DeviceButton_left mouse button"and isOver(bg) then return true end + return update or typing end From 5dc5da301333b6fe3c82c39369af99f5564d7f98 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 03:40:52 -0500 Subject: [PATCH 100/320] always eat mousewheel input on the chat window --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 5e3d5c239f..a81debf04a 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -415,16 +415,16 @@ function input(event) if isOver(chatbg) then if lineNumber < #messages then lineNumber = lineNumber + 1 - update = true end + update = true end end if event.DeviceInput.button == "DeviceButton_mousewheel down" and event.type == "InputEventType_FirstPress" then if isOver(chatbg) then if lineNumber > maxlines then lineNumber = lineNumber - 1 - update = true end + update = true end end From 9f1bf36ef642a803d7366b93536e9aee2efd57d4 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 04:08:19 -0500 Subject: [PATCH 101/320] make tabs and search work in mp ( i think ) --- .../BGAnimations/ScreenSelectMusic decorations/songsearch.lua | 2 +- .../BGAnimations/ScreenSelectMusic decorations/tabs.lua | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua index 8bfeccc84d..49f7a6c15f 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua @@ -32,7 +32,7 @@ local function searchInput(event) local CtrlPressed = INPUTFILTER:IsBeingPressed("left ctrl") or INPUTFILTER:IsBeingPressed("right ctrl") if event.char and event.char:match('[%%%+%-%!%@%#%$%^%&%*%(%)%=%_%.%,%:%;%\'%"%>%<%?%/%~%|%w]') and - (not tonumber(event.char) or CtrlPressed == (SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic")) + (not tonumber(event.char) or CtrlPressed) then searchstring = searchstring .. event.char end diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua index 9ab29a380a..5e609dfd44 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua @@ -9,7 +9,8 @@ local function input(event) if numericinputactive == false then if not (INPUTFILTER:IsBeingPressed("left ctrl") or INPUTFILTER:IsBeingPressed("right ctrl") or - (SCREENMAN:GetTopScreen():GetName() ~= "ScreenSelectMusic")) + (SCREENMAN:GetTopScreen():GetName() ~= "ScreenSelectMusic" and + SCREENMAN:GetTopScreen():GetName() ~= "ScreenNetSelectMusic")) then if event.DeviceInput.button == "DeviceButton_0" then setTabIndex(9) @@ -31,6 +32,7 @@ end local t = Def.ActorFrame { BeginCommand = function(self) + MESSAGEMAN:Broadcast("AddMPChatInput") SCREENMAN:GetTopScreen():AddInputCallback(input) resetTabIndex() end, From 76c8cb09dff410f97eb24b7870a085bca0a83e37 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 04:08:51 -0500 Subject: [PATCH 102/320] remove custom smo mp garbage and use a proper mouseclick input callback --- .../default.lua | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua index 59bee441e2..193717c600 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua @@ -1,22 +1,34 @@ +local function input(event) + local top = SCREENMAN:GetTopScreen() + if event.DeviceInput.button == "DeviceButton_left mouse button" then + if event.type == "InputEventType_Release" then + if not SCREENMAN:get_input_redirected(PLAYER_1) then + if isOver(top:GetChild("Overlay"):GetChild("PlayerAvatar"):GetChild("Avatar" .. PLAYER_1):GetChild("Image")) then + SCREENMAN:AddNewScreenToTop("ScreenAvatarSwitch") + end + end + end + end + if event.DeviceInput.button == "DeviceButton_left mouse button" and event.type == "InputEventType_Release" then + MESSAGEMAN:Broadcast("MouseLeftClick") + elseif event.DeviceInput.button == "DeviceButton_right mouse button" and event.type == "InputEventType_Release" then + MESSAGEMAN:Broadcast("MouseRightClick") + end + return false +end + local t = Def.ActorFrame {} if NSMAN:IsETTP() then t[#t + 1] = - Def.ActorFrame { - LeftClickMessageCommand = function() - MESSAGEMAN:Broadcast("MouseLeftClick") - end + Def.ActorFrame { + BeginCommand = function(self) + MESSAGEMAN:Broadcast("AddMPChatInput") + SCREENMAN:GetTopScreen():AddInputCallback(input) + end, } t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/default") return t end -t[#t + 1] = LoadActor("../_chatbox") -t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/profile") -t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/msd") -t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/songsearch") -t[#t + 1] = LoadActor("tabs") -t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/score") -t[#t + 1] = LoadActor("dumbrate") -t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/filters") local g = Def.ActorFrame { From c81e4c486048521e703f4609f14eb846434af299 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 04:18:33 -0500 Subject: [PATCH 103/320] minimize chat with right click, add offset to tab names, recolor, resize + --- .../ScreenChatOverlay overlay.lua | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index a81debf04a..80e9ca10a1 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -1,8 +1,8 @@ local lastx, lasty = 0, 0 local width, height = SCREEN_WIDTH, SCREEN_HEIGHT * 0.035 -local maxlines = 6 -local lineNumber = 6 -local inputLineNumber = 2 +local maxlines = 5 +local lineNumber = 5 +local inputLineNumber = 1 local tabHeight = 1 local maxTabs = 10 local x, y = 0, SCREEN_HEIGHT - height * (lineNumber + inputLineNumber + tabHeight) @@ -12,14 +12,14 @@ local scale = 0.4 local minimised = false local typing = false local typingText = "" -local transparency = 0.5 +local transparency = 0.667 local curmsgh = 0 local closeTabSize = 10 local Colors = { - background = color("#7777FF"), + background = color("#333333"), input = color("#888888"), - activeInput = color("#BBBBFF"), - output = color("#888888"), + activeInput = color("#9977BB"), + output = color("#545454"), bar = color("#666666"), tab = color("#555555"), activeTab = color("#999999") @@ -239,7 +239,7 @@ for i = 0, maxTabs - 1 do self:maxwidth(tabWidth) self:zoom(scale) self:diffuse(color("#000000")) - self:xy(x + tabWidth * i, y + height * (1 + (tabHeight / 4))) + self:xy(x + tabWidth * i + 4, y + height * (1 + (tabHeight / 4))) end, UpdateChatOverlayMessageCommand = function(self) if not tabs[i + 1] then @@ -427,13 +427,21 @@ function input(event) update = true end end + + + -- right click over the chat to minimize + if event.DeviceInput.button == "DeviceButton_right mouse button" and event.type == "InputEventType_FirstPress" and isOver(bg) then + minimised = not minimised + MESSAGEMAN:Broadcast("Minimise") + return true + end if update then MESSAGEMAN:Broadcast("UpdateChatOverlay") end -- always eat mouse inputs if its within the broader chatbox - if event.DeviceInput.button == "DeviceButton_left mouse button"and isOver(bg) then + if event.DeviceInput.button == "DeviceButton_left mouse button" and isOver(bg) then return true end From 8da0bbdd609cb74aa3509d50437ec9121e647a0a Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 10:57:25 -0300 Subject: [PATCH 104/320] Replace c++ packlist with a lua one --- .../BGAnimations/packlistDisplay.lua | 8 +- Themes/_fallback/Scripts/09 PackList.lua | 103 ++++++++++++++++++ src/DownloadManager.cpp | 11 ++ 3 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 Themes/_fallback/Scripts/09 PackList.lua diff --git a/Themes/Til Death/BGAnimations/packlistDisplay.lua b/Themes/Til Death/BGAnimations/packlistDisplay.lua index feabc80327..cc7850f7df 100644 --- a/Themes/Til Death/BGAnimations/packlistDisplay.lua +++ b/Themes/Til Death/BGAnimations/packlistDisplay.lua @@ -41,7 +41,7 @@ local o = end, BeginCommand = function(self) self:SetUpdateFunction(highlight) - packlist = DLMAN:GetPacklist() + packlist = PackList:new() packlist:SetFromAll() self:queuecommand("PackTableRefresh") end, @@ -71,9 +71,11 @@ local o = ind = ind - numpacks self:queuecommand("Update") end, - Def.Quad {InitCommand = function(self) + Def.Quad { + InitCommand = function(self) self:zoomto(width, height - headeroff):halign(0):valign(0):diffuse(color("#888888")) - end}, + end + }, -- headers Def.Quad { InitCommand = function(self) diff --git a/Themes/_fallback/Scripts/09 PackList.lua b/Themes/_fallback/Scripts/09 PackList.lua new file mode 100644 index 0000000000..b1c3c3b385 --- /dev/null +++ b/Themes/_fallback/Scripts/09 PackList.lua @@ -0,0 +1,103 @@ +PackList = {} + +local getSizePropName = "GetSize" +local getAvgDiffPropName = "GetAvgDifficulty" +local getNamePropName = "GetName" + +function PackList:GetPackTable() + SCREENMAN:SystemMessage(tostring(#(self.packs))) + return self.packs +end +local foldr = function(func, val, tbl) + for i, v in pairs(tbl) do + val = func(val, v) + end + return val +end +function PackList:GetTotalSumByProp(propName) + return foldr( + function(sum, x) + return sum + x[propName](x) + end, + 0, + self.packs + ) +end +function PackList:GetTotalSize() + return self:GetTotalSumByProp(getSizePropName) +end +function PackList:GetAvgDiff() + return self:GetTotalSumByProp(getAvgDiffPropName) +end +function PackList:SetFromCoreBundle(bundleName) + local bundle = DLMAN:GetCoreBundle(bundleName) + self.packs = bundle + return self +end +function PackList:SortByProp(propName) + if self.lastsort == propName then + self.asc = not self.asc + end + self.lastsort = propName + local asc = self.asc + table.sort( + self.packs, + asc and function(a, b) + return a[propName](a) > b[propName](b) + end or function(a, b) + return a[propName](a) < b[propName](b) + end + ) + return self +end +function PackList:SortByName() + return self:SortByProp(getNamePropName) +end +function PackList:SortByDiff() + return self:SortByProp(getAvgDiffPropName) +end +function PackList:SortBySize() + return self:SortByProp(getSizePropName) +end +local function filter(func, tbl) + local newtbl = {} + for i, v in pairs(tbl) do + if func(v) then + newtbl[i] = v + end + end + return newtbl +end +function PackList:FilterAndSearch(name, avgMin, avgMax, sizeMin, sizeMax) + self.packs = + filter( + function(x) + local d = x[getAvgDiffPropName]:x() + local n = x[getNamePropName]:x() + local s = x[getSizePropName]:x() + return n == name and ((d > avgMin and d < avgMax) or d <= 0) and ((s > sizeMin and d < sizeMax) or s <= 0) + end, + self.packs + ) + return self +end +function PackList:SetFromAll() + self.packs = DLMAN:GetAllPacks() + return self +end +function PackList:new() + local packlist = {} + packlist.asc = true + packlist.lastsort = nil + packlist.packs = {} + setmetatable( + packlist, + { + __index = function(t, i) + return t.packs[i] or PackList[i] + end + } + ) + packlist:SetFromAll() + return packlist +end diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 9ba99f4447..7088d22e6d 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -2061,6 +2061,16 @@ class LunaDownloadManager : public Luna DLMAN->pl.PushSelf(L); return 1; } + static int GetAllPacks(T* p, lua_State* L) + { + vector& packs = DLMAN->downloadablePacks; + lua_createtable(L, packs.size(), 0); + for (unsigned i = 0; i < packs.size(); ++i) { + packs[i].PushSelf(L); + lua_rawseti(L, -2, i + 1); + } + return 1; + } static int GetDownloadingPacks(T* p, lua_State* L) { vector& packs = DLMAN->downloadablePacks; @@ -2410,6 +2420,7 @@ class LunaDownloadManager : public Luna ADD_METHOD(DownloadCoreBundle); ADD_METHOD(GetCoreBundle); ADD_METHOD(GetPacklist); + ADD_METHOD(GetAllPacks); ADD_METHOD(GetDownloadingPacks); ADD_METHOD(GetDownloads); ADD_METHOD(GetToken); From d6639aad989ce19e4a78f0ff203cf5338dec3149 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 11:21:05 -0300 Subject: [PATCH 105/320] Add lua functional mini library to fallback scripts --- Themes/_fallback/Scripts/01 Functional.lua | 176 +++++++++++++++++++++ Themes/_fallback/Scripts/09 PackList.lua | 16 -- 2 files changed, 176 insertions(+), 16 deletions(-) create mode 100644 Themes/_fallback/Scripts/01 Functional.lua diff --git a/Themes/_fallback/Scripts/01 Functional.lua b/Themes/_fallback/Scripts/01 Functional.lua new file mode 100644 index 0000000000..10f38a7d17 --- /dev/null +++ b/Themes/_fallback/Scripts/01 Functional.lua @@ -0,0 +1,176 @@ +-- Functional Library +-- +-- @file functional.lua +-- @author Shimomura Ikkei +-- @date 2005/05/18 +-- +-- @brief porting several convenience functional utilities form Haskell,Python etc.. + +-- map(function, table) +-- e.g: map(double, {1,2,3}) -> {2,4,6} +function map(func, tbl) + local newtbl = {} + for i, v in pairs(tbl) do + newtbl[i] = func(v) + end + return newtbl +end + +-- filter(function, table) +-- e.g: filter(is_even, {1,2,3,4}) -> {2,4} +function filter(func, tbl) + local newtbl = {} + for i, v in pairs(tbl) do + if func(v) then + newtbl[i] = v + end + end + return newtbl +end + +-- head(table) +-- e.g: head({1,2,3}) -> 1 +function head(tbl) + return tbl[1] +end + +-- tail(table) +-- e.g: tail({1,2,3}) -> {2,3} +-- +-- XXX This is a BAD and ugly implementation. +-- should return the address to next porinter, like in C (arr+1) +function tail(tbl) + if table.getn(tbl) < 1 then + return nil + else + local newtbl = {} + local tblsize = table.getn(tbl) + local i = 2 + while (i <= tblsize) do + table.insert(newtbl, i - 1, tbl[i]) + i = i + 1 + end + return newtbl + end +end + +-- foldr(function, default_value, table) +-- e.g: foldr(operator.mul, 1, {1,2,3,4,5}) -> 120 +function foldr(func, val, tbl) + for i, v in pairs(tbl) do + val = func(val, v) + end + return val +end + +-- reduce(function, table) +-- e.g: reduce(operator.add, {1,2,3,4}) -> 10 +function reduce(func, tbl) + return foldr(func, head(tbl), tail(tbl)) +end + +-- curry(f,g) +-- e.g: printf = curry(io.write, string.format) +-- -> function(...) return io.write(string.format(unpack(arg))) end +function curry(f, g) + return function(...) + return f(g(unpack(arg))) + end +end + +-- bind1(func, binding_value_for_1st) +-- bind2(func, binding_value_for_2nd) +-- @brief +-- Binding argument(s) and generate new function. +-- @see also STL's functional, Boost's Lambda, Combine, Bind. +-- @examples +-- local mul5 = bind1(operator.mul, 5) -- mul5(10) is 5 * 10 +-- local sub2 = bind2(operator.sub, 2) -- sub2(5) is 5 -2 +function bind1(func, val1) + return function(val2) + return func(val1, val2) + end +end +function bind2(func, val2) -- bind second argument. + return function(val1) + return func(val1, val2) + end +end + +-- is(checker_function, expected_value) +-- @brief +-- check function generator. return the function to return boolean, +-- if the condition was expected then true, else false. +-- @example +-- local is_table = is(type, "table") +-- local is_even = is(bind2(math.mod, 2), 1) +-- local is_odd = is(bind2(math.mod, 2), 0) +is = function(check, expected) + return function(...) + if (check(unpack(arg)) == expected) then + return true + else + return false + end + end +end + +-- operator table. +-- @see also python's operator module. +operator = { + mod = math.mod, + pow = math.pow, + add = function(n, m) + return n + m + end, + sub = function(n, m) + return n - m + end, + mul = function(n, m) + return n * m + end, + div = function(n, m) + return n / m + end, + gt = function(n, m) + return n > m + end, + lt = function(n, m) + return n < m + end, + eq = function(n, m) + return n == m + end, + le = function(n, m) + return n <= m + end, + ge = function(n, m) + return n >= m + end, + ne = function(n, m) + return n ~= m + end +} + +-- enumFromTo(from, to) +-- e.g: enumFromTo(1, 10) -> {1,2,3,4,5,6,7,8,9} +-- TODO How to lazy evaluate in Lua? (thinking with coroutine) +enumFromTo = function(from, to) + local newtbl = {} + local step = bind2(operator[(from < to) and "add" or "sub"], 1) + local val = from + while val <= to do + table.insert(newtbl, table.getn(newtbl) + 1, val) + val = step(val) + end + return newtbl +end + +-- make function to take variant arguments, replace of a table. +-- this does not mean expand the arguments of function took, +-- it expand the function's spec: function(tbl) -> function(...) +function expand_args(func) + return function(...) + return func(arg) + end +end diff --git a/Themes/_fallback/Scripts/09 PackList.lua b/Themes/_fallback/Scripts/09 PackList.lua index b1c3c3b385..d4e45ba61b 100644 --- a/Themes/_fallback/Scripts/09 PackList.lua +++ b/Themes/_fallback/Scripts/09 PackList.lua @@ -5,15 +5,8 @@ local getAvgDiffPropName = "GetAvgDifficulty" local getNamePropName = "GetName" function PackList:GetPackTable() - SCREENMAN:SystemMessage(tostring(#(self.packs))) return self.packs end -local foldr = function(func, val, tbl) - for i, v in pairs(tbl) do - val = func(val, v) - end - return val -end function PackList:GetTotalSumByProp(propName) return foldr( function(sum, x) @@ -59,15 +52,6 @@ end function PackList:SortBySize() return self:SortByProp(getSizePropName) end -local function filter(func, tbl) - local newtbl = {} - for i, v in pairs(tbl) do - if func(v) then - newtbl[i] = v - end - end - return newtbl -end function PackList:FilterAndSearch(name, avgMin, avgMax, sizeMin, sizeMax) self.packs = filter( From b9db0295ef5cdfa610a61a3f466863a326ed95bc Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 11:21:49 -0300 Subject: [PATCH 106/320] Remove forgotten debug print --- .../BGAnimations/ScreenNetSelectMusic decorations/default.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua index 5386ad53cb..59bee441e2 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua @@ -3,7 +3,6 @@ if NSMAN:IsETTP() then t[#t + 1] = Def.ActorFrame { LeftClickMessageCommand = function() - SCREENMAN:SystemMessage("asdasdasd") MESSAGEMAN:Broadcast("MouseLeftClick") end } From c7a792eab2f7cdbc4387787826a01af8576aa1ea Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 11:49:06 -0300 Subject: [PATCH 107/320] Create LICENCE --- LICENCE | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 LICENCE diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000000..16fa7692a3 --- /dev/null +++ b/LICENCE @@ -0,0 +1,19 @@ +Copyright (c) 2016-2019 Etterna . + +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. From cd5e1eb63839cf8a455edd505c9600a2343db371 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 10:58:44 -0300 Subject: [PATCH 108/320] Make ScreenNetSelectMusic inherit from ScreenSelectMusic --- Themes/_fallback/metrics.ini | 2 +- src/ScreenNetSelectMusic.cpp | 180 ++++++++++++----------------------- src/ScreenNetSelectMusic.h | 14 +-- 3 files changed, 62 insertions(+), 134 deletions(-) diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index ea525f433c..5d28e7117e 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -4307,7 +4307,7 @@ Users4Command=draworder,2;diffuse,color("1.0,0.5,0.5,1.0") [ScreenNetSelectMusic] Class="ScreenNetSelectMusic" -Fallback="ScreenNetSelectBase" +Fallback="ScreenSelectMusic" PrevScreen="ScreenNetRoom" NextScreen="ScreenNetStageInformation" DisconnectScreen="ScreenSelectMusic" diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index b94e07c3d8..15a256ff67 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -22,6 +22,7 @@ #include "RageUtil.h" #include "ScreenManager.h" #include "ScreenNetSelectMusic.h" +#include "ScreenNetSelectBase.h" #include "Song.h" #include "SongManager.h" #include "CodeDetector.h" @@ -30,6 +31,8 @@ #include "RageFileManager.h" #include "ScreenPrompt.h" +AutoScreenMessage(SM_AddToChat); +AutoScreenMessage(SM_FriendsUpdate); AutoScreenMessage(SM_NoSongs); AutoScreenMessage(SM_ChangeSong); AutoScreenMessage(SM_SMOnlinePack); @@ -51,34 +54,12 @@ static LocalizedString PERMANENTLY_DELETE("ScreenSelectMusic", void ScreenNetSelectMusic::Init() { - ScreenNetSelectBase::Init(); + ScreenSelectMusic::Init(); SAMPLE_MUSIC_PREVIEW_MODE.Load(m_sName, "SampleMusicPreviewMode"); MUSIC_WHEEL_TYPE.Load(m_sName, "MusicWheelType"); PLAYER_OPTIONS_SCREEN.Load(m_sName, "PlayerOptionsScreen"); - FOREACH_EnabledPlayer(p) - { - m_DC[p] = GAMESTATE->m_PreferredDifficulty[p]; - - m_StepsDisplays[p].SetName(ssprintf("StepsDisplayP%d", p + 1)); - m_StepsDisplays[p].Load("StepsDisplayNet", NULL); - LOAD_ALL_COMMANDS_AND_SET_XY(m_StepsDisplays[p]); - this->AddChild(&m_StepsDisplays[p]); - } - - m_MusicWheel.SetName("MusicWheel"); - m_MusicWheel.Load(MUSIC_WHEEL_TYPE); - LOAD_ALL_COMMANDS_AND_SET_XY(m_MusicWheel); - SONGMAN->MakeSongGroupsFromPlaylists(); - SONGMAN->SetFavoritedStatus( - PROFILEMAN->GetProfile(PLAYER_1)->FavoritedCharts); - SONGMAN->SetHasGoal(PROFILEMAN->GetProfile(PLAYER_1)->goalmap); - m_MusicWheel.BeginScreen(); - ON_COMMAND(m_MusicWheel); - this->AddChild(&m_MusicWheel); - this->MoveToHead(&m_MusicWheel); - // todo: handle me theme-side -aj FOREACH_EnabledPlayer(p) { @@ -172,7 +153,7 @@ ScreenNetSelectMusic::Input(const InputEventPlus& input) Song* to_reload = m_MusicWheel.GetSelectedSong(); if (to_reload != nullptr) { to_reload->ReloadFromSongDir(); - MusicChanged(); + this->AfterMusicChange(); handled = true; } } else if (c == 'F') { @@ -246,13 +227,19 @@ ScreenNetSelectMusic::Input(const InputEventPlus& input) } } } - return ScreenNetSelectBase::Input(input) || handled; + return ScreenSelectMusic::Input(input) || handled; } void ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) { - if (SM == SM_GoToPrevScreen) { + if (SM == SM_GoToNextScreen) + SOUND->StopMusic(); + else if (SM == SM_UsersUpdate) { + MESSAGEMAN->Broadcast("UsersUpdate"); + } else if (SM == SM_FriendsUpdate) { + MESSAGEMAN->Broadcast("FriendsUpdate"); + } else if (SM == SM_GoToPrevScreen) { NSMAN->LeaveRoom(); SCREENMAN->SetNewScreen(THEME->GetMetric(m_sName, "PrevScreen")); } else if (SM == SM_GoToNextScreen) { @@ -405,8 +392,10 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) // Update changes FOREACH_EnabledPlayer(p) m_ModIconRow[p].SetFromGameState(); } else if (SM == SM_SongChanged) { - GAMESTATE->m_pCurSong.Set(m_MusicWheel.GetSelectedSong()); - MusicChanged(); + if (m_MusicWheel.GetNumItems() > 0) { + GAMESTATE->m_pCurSong.Set(m_MusicWheel.GetSelectedSong()); + this->AfterMusicChange(); + } } else if (SM == ETTP_StartChart) { if (NSMAN->song != nullptr) { if (!m_MusicWheel.SelectSong(NSMAN->song)) { @@ -415,8 +404,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, 0.710f); m_MusicWheel.SelectSong(NSMAN->song); } - if (NSMAN->steps != nullptr) - m_DC[PLAYER_1] = NSMAN->steps->GetDifficulty(); if (NSMAN->rate > 0) { GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = NSMAN->rate / 1000.f; @@ -436,8 +423,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, 0.710f); m_MusicWheel.SelectSong(NSMAN->song); } - if (NSMAN->steps != nullptr) - m_DC[PLAYER_1] = NSMAN->steps->GetDifficulty(); if (NSMAN->rate > 0) { GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = NSMAN->rate / 1000.f; @@ -463,7 +448,7 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) done: // Must be at end, as so it is last resort for SMOnline packets. // If it doesn't know what to do, then it'll just remove them. - ScreenNetSelectBase::HandleScreenMessage(SM); + ScreenSelectMusic::HandleScreenMessage(SM); } void @@ -533,12 +518,10 @@ ScreenNetSelectMusic::MenuUp(const InputEventPlus& input) return true; } +/* bool ScreenNetSelectMusic::MenuDown(const InputEventPlus& input) { - /* Tricky: If we have a player on player 2, and there is only player 2, - * allow them to use player 1's controls to change their difficulty. */ - /* Why? Nothing else allows that. (-who?) */ // I agree, that's a stupid idea -aj // Funny story: If the arrow keys are mapped to Player 2, but the person @@ -593,6 +576,7 @@ ScreenNetSelectMusic::MenuDown(const InputEventPlus& input) GAMESTATE->m_PreferredDifficulty[pn].Set(m_DC[pn]); return true; } +*/ bool ScreenNetSelectMusic::MenuStart(const InputEventPlus& input) @@ -641,18 +625,7 @@ ScreenNetSelectMusic::MenuBack(const InputEventPlus& input) void ScreenNetSelectMusic::TweenOffScreen() { - ScreenNetSelectBase::TweenOffScreen(); - - OFF_COMMAND(m_MusicWheel); - - FOREACH_EnabledPlayer(pn) - { - OFF_COMMAND(m_StepsDisplays[pn]); - // OFF_COMMAND( m_DifficultyIcon[pn] ); - OFF_COMMAND(m_ModIconRow[pn]); - } - - OFF_COMMAND(m_MusicWheel); + ScreenSelectMusic::TweenOffScreen(); NSMAN->OffMusicSelect(); } @@ -666,8 +639,8 @@ ScreenNetSelectMusic::StartSelectedSong() { StepsType st = GAMESTATE->GetCurrentStyle(pn) ->m_StepsType; // StepsType_dance_single; - GAMESTATE->m_PreferredDifficulty[pn].Set(m_DC[pn]); - Steps* pSteps = SongUtil::GetStepsByDifficulty(pSong, st, m_DC[pn]); + Steps* pSteps = m_vpSteps[pn]; + GAMESTATE->m_PreferredDifficulty[pn].Set(pSteps->GetDifficulty()); GAMESTATE->m_pCurSteps[pn].Set(pSteps); } @@ -681,6 +654,7 @@ ScreenNetSelectMusic::StartSelectedSong() StartTransitioningScreen(SM_GoToNextScreen); } +/* void ScreenNetSelectMusic::UpdateDifficulties(PlayerNumber pn) { @@ -704,83 +678,16 @@ ScreenNetSelectMusic::UpdateDifficulties(PlayerNumber pn) m_StepsDisplays[pn].SetFromStepsTypeAndMeterAndDifficultyAndCourseType( StepsType_Invalid, 0, Difficulty_Beginner); } +*/ void ScreenNetSelectMusic::BeginScreen() { - ScreenNetSelectBase::BeginScreen(); Profile* prof = PROFILEMAN->GetProfile(PLAYER_1); SONGMAN->MakeSongGroupsFromPlaylists(); SONGMAN->SetFavoritedStatus(prof->FavoritedCharts); SONGMAN->SetHasGoal(prof->goalmap); -} -void -ScreenNetSelectMusic::MusicChanged() -{ - if (GAMESTATE->m_pCurSong == NULL) { - FOREACH_EnabledPlayer(pn) UpdateDifficulties(pn); - - SOUND->StopMusic(); - // todo: handle playing section music correctly. -aj - // SOUND->PlayMusic( m_sSectionMusicPath, NULL, true, 0, -1 ); - return; - } - - FOREACH_EnabledPlayer(pn) - { - m_DC[pn] = GAMESTATE->m_PreferredDifficulty[pn]; - StepsType st = GAMESTATE->GetCurrentStyle(pn)->m_StepsType; - vector MultiSteps; - MultiSteps = GAMESTATE->m_pCurSong->GetStepsByStepsType(st); - if (MultiSteps.size() == 0) - m_DC[pn] = NUM_Difficulty; - else { - int i; - Difficulty Target = Difficulty_Easy; - - bool dcs[NUM_Difficulty]; - - for (i = 0; i < NUM_Difficulty; ++i) - dcs[i] = false; - - for (i = 0; i < (int)MultiSteps.size(); ++i) - dcs[MultiSteps[i]->GetDifficulty()] = true; - - for (i = 0; i < NUM_Difficulty; ++i) - if (dcs[i]) { - Target = static_cast(i); - if (i >= m_DC[pn]) { - m_DC[pn] = static_cast(i); - break; - } - } - - if (i == NUM_Difficulty) - m_DC[pn] = Target; - } - UpdateDifficulties(pn); - } - - // Copied from ScreenSelectMusic - // TODO: Update me! -aj - SOUND->StopMusic(); - if (GAMESTATE->m_pCurSong->HasMusic()) { - // don't play the same sound over and over - if (SOUND->GetMusicPath().CompareNoCase( - GAMESTATE->m_pCurSong->GetMusicPath())) { - SOUND->StopMusic(); - Song* songPtr = GAMESTATE->m_pCurSong; - SOUND->PlayMusic(songPtr->GetPreviewMusicPath(), - &songPtr->m_SongTiming, - true, - songPtr->GetPreviewStartSeconds(), - songPtr->m_fMusicSampleLengthSeconds, - SAMPLE_MUSIC_FALLBACK_FADE_IN_SECONDS, - SAMPLE_MUSIC_FADE_OUT_SECONDS, - ALIGN_MUSIC_BEATS, - true); - } - } + ScreenSelectMusic::BeginScreen(); } void @@ -790,7 +697,7 @@ ScreenNetSelectMusic::Update(float fDeltaTime) m_bInitialSelect = true; SCREENMAN->PostMessageToTopScreen(SM_RefreshWheelLocation, 1.0f); } - ScreenNetSelectBase::Update(fDeltaTime); + ScreenSelectMusic::Update(fDeltaTime); } MusicWheel* @@ -821,15 +728,46 @@ class LunaScreenNetSelectMusic : public Luna lua_pushnumber(L, NSMAN->m_iSelectMode); return 1; } + static int GetUserQty(T* p, lua_State* L) + { + auto& users = NSMAN->m_PlayerNames; + lua_pushnumber(L, users.size()); + return 1; + } + static int GetUser(T* p, lua_State* L) + { + if (lua_isnil(L, 1)) + return 0; + auto& users = NSMAN->m_PlayerNames; + if (static_cast(IArg(1)) <= users.size() && IArg(1) >= 1) + lua_pushstring(L, users[IArg(1) - 1].c_str()); + else + lua_pushstring(L, ""); + return 1; + } + static int GetUserState(T* p, lua_State* L) + { + if (lua_isnil(L, 1)) + return 0; + auto& states = NSMAN->m_PlayerStatus; + if (static_cast(IArg(1)) <= states.size() && IArg(1) >= 1) + lua_pushnumber(L, states[IArg(1) - 1]); + else + lua_pushnumber(L, 0); + return 1; + } LunaScreenNetSelectMusic() { ADD_METHOD(GetMusicWheel); ADD_METHOD(SelectCurrent); ADD_METHOD(GetSelectionState); + ADD_METHOD(GetUser); + ADD_METHOD(GetUserQty); + ADD_METHOD(GetUserState); } }; -LUA_REGISTER_DERIVED_CLASS(ScreenNetSelectMusic, ScreenNetSelectBase) +LUA_REGISTER_DERIVED_CLASS(ScreenNetSelectMusic, ScreenSelectMusic) // lua end #endif diff --git a/src/ScreenNetSelectMusic.h b/src/ScreenNetSelectMusic.h index 11229a16c4..a9d99d3388 100644 --- a/src/ScreenNetSelectMusic.h +++ b/src/ScreenNetSelectMusic.h @@ -8,12 +8,12 @@ #include "DifficultyIcon.h" #include "ModIconRow.h" #include "MusicWheel.h" -#include "ScreenNetSelectBase.h" +#include "ScreenSelectMusic.h" #include "ScreenWithMenuElements.h" #include "Sprite.h" #include "StepsDisplay.h" -class ScreenNetSelectMusic : public ScreenNetSelectBase +class ScreenNetSelectMusic : public ScreenSelectMusic { public: void Init() override; @@ -37,7 +37,6 @@ class ScreenNetSelectMusic : public ScreenNetSelectBase bool MenuLeft(const InputEventPlus& input) override; bool MenuRight(const InputEventPlus& input) override; bool MenuUp(const InputEventPlus& input) override; - bool MenuDown(const InputEventPlus& input) override; bool LeftAndRightPressed(PlayerNumber pn); void Update(float fDeltaTime) override; @@ -45,8 +44,6 @@ class ScreenNetSelectMusic : public ScreenNetSelectBase Song* m_pSongAwaitingDeletionConfirmation; void OnConfirmSongDeletion(); - void MusicChanged(); - void TweenOffScreen() override; ThemeMetric SAMPLE_MUSIC_PREVIEW_MODE; @@ -62,13 +59,6 @@ class ScreenNetSelectMusic : public ScreenNetSelectBase ThemeMetric ALIGN_MUSIC_BEATS; private: - MusicWheel m_MusicWheel; - - StepsDisplay m_StepsDisplays[NUM_PLAYERS]; - Difficulty m_DC[NUM_PLAYERS]; - - void UpdateDifficulties(PlayerNumber pn); - RageSound m_soundChangeOpt; RageSound m_soundChangeSel; From 8d67f0393343fb0d09745184fa7d334e433eef56 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 11:55:43 -0300 Subject: [PATCH 109/320] Actually remove C++ packlist --- src/DownloadManager.cpp | 156 ---------------------------------------- src/DownloadManager.h | 13 ---- 2 files changed, 169 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index c92927169a..87b36726e0 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -2047,11 +2047,6 @@ class LunaDownloadManager : public Luna lua_pushstring(L, DLMAN->countryCode.c_str()); return 1; } - static int GetPacklist(T* p, lua_State* L) - { - DLMAN->pl.PushSelf(L); - return 1; - } static int GetAllPacks(T* p, lua_State* L) { vector& packs = DLMAN->downloadablePacks; @@ -2410,7 +2405,6 @@ class LunaDownloadManager : public Luna ADD_METHOD(GetUserCountryCode); ADD_METHOD(DownloadCoreBundle); ADD_METHOD(GetCoreBundle); - ADD_METHOD(GetPacklist); ADD_METHOD(GetAllPacks); ADD_METHOD(GetDownloadingPacks); ADD_METHOD(GetDownloads); @@ -2443,156 +2437,6 @@ class LunaDownloadManager : public Luna }; LUA_REGISTER_CLASS(DownloadManager) -class LunaPacklist : public Luna -{ - public: - static int GetPackTable(T* p, lua_State* L) - { - LuaHelpers::CreateTableFromArray(p->packs, L); - return 1; - } - static int SetFromCoreBundle(T* p, lua_State* L) - { - p->packs.clear(); - p->packs = DLMAN->GetCoreBundle(SArg(1)); - MESSAGEMAN->Broadcast("RefreshPacklist"); - return 0; - } - static int FilterAndSearch(T* p, lua_State* L) - { - if (lua_gettop(L) < 5) { - return luaL_error(L, - "GetFilteredAndSearchedPackList expects exactly " - "5 arguments(packname, lower diff, upper diff, " - "lower size, upper size)"); - } - string name = SArg(1); - double avgLower = max(luaL_checknumber(L, 2), 0.0); - double avgUpper = max(luaL_checknumber(L, 3), 0.0); - size_t sizeLower = static_cast(luaL_checknumber(L, 4)); - size_t sizeUpper = static_cast(luaL_checknumber(L, 5)); - - p->packs.clear(); - auto& packs = DLMAN->downloadablePacks; - for (unsigned i = 0; i < packs.size(); ++i) { - if (packs[i].avgDifficulty >= avgLower && - findStringIC(packs[i].name, name) && - (avgUpper <= 0 || packs[i].avgDifficulty < avgUpper) && - packs[i].size >= sizeLower && - (sizeUpper <= 0 || packs[i].size < sizeUpper)) - p->packs.push_back(&packs[i]); - } - MESSAGEMAN->Broadcast("RefreshPacklist"); - return 0; - } - static int GetTotalSize(T* p, lua_State* L) - { - size_t totalsize = 0; - for (auto n : p->packs) - totalsize += n->size; - lua_pushnumber(L, totalsize / 1024 / 1024); - return 1; - } - static int GetAvgDiff(T* p, lua_State* L) - { - float avgpackdiff = 0.f; - for (auto n : p->packs) - avgpackdiff += n->avgDifficulty; - if (!p->packs.empty()) - avgpackdiff /= p->packs.size(); - lua_pushnumber(L, avgpackdiff); - return 1; - } - // i guess these should be internal functions and lua just calls them huh - // -mina - static int SortByName(T* p, lua_State* L) - { - if (p->sortmode == 1) - if (p->asc) { - auto comp = [](DownloadablePack* a, DownloadablePack* b) { - return Rage::make_lower(a->name) > - Rage::make_lower(b->name); - }; // custom operators? - sort(p->packs.begin(), p->packs.end(), comp); - p->asc = false; - return 0; - } - auto comp = [](DownloadablePack* a, DownloadablePack* b) { - return Rage::make_lower(a->name) < Rage::make_lower(b->name); - }; - sort(p->packs.begin(), p->packs.end(), comp); - p->sortmode = 1; - p->asc = true; - MESSAGEMAN->Broadcast("RefreshPacklist"); - return 0; - } - static int SortByDiff(T* p, lua_State* L) - { - auto& packs = p->packs; - if (p->sortmode == 2) - if (p->asc) { - auto comp = [](DownloadablePack* a, DownloadablePack* b) { - return (a->avgDifficulty < b->avgDifficulty); - }; - sort(packs.begin(), packs.end(), comp); - p->asc = false; - return 0; - } - auto comp = [](DownloadablePack* a, DownloadablePack* b) { - return (a->avgDifficulty > b->avgDifficulty); - }; - sort(packs.begin(), packs.end(), comp); - p->sortmode = 2; - p->asc = true; - MESSAGEMAN->Broadcast("RefreshPacklist"); - return 0; - } - static int SortBySize(T* p, lua_State* L) - { - auto& packs = p->packs; - if (p->sortmode == 3) - if (p->asc) { - auto comp = [](DownloadablePack* a, DownloadablePack* b) { - return (a->size < b->size); - }; - sort(packs.begin(), packs.end(), comp); - p->asc = false; - return 0; - } - auto comp = [](DownloadablePack* a, DownloadablePack* b) { - return (a->size > b->size); - }; - sort(packs.begin(), packs.end(), comp); - p->sortmode = 3; - p->asc = true; - MESSAGEMAN->Broadcast("RefreshPacklist"); - return 0; - } - static int SetFromAll(T* p, lua_State* L) - { - auto& packs = DLMAN->downloadablePacks; - p->packs.clear(); - for (auto& n : packs) - p->packs.emplace_back(&n); - MESSAGEMAN->Broadcast("RefreshPacklist"); - return 0; - } - LunaPacklist() - { - ADD_METHOD(GetPackTable); - ADD_METHOD(GetTotalSize); - ADD_METHOD(GetAvgDiff); - ADD_METHOD(SetFromCoreBundle); - ADD_METHOD(SortByName); - ADD_METHOD(SortByDiff); - ADD_METHOD(SortBySize); - ADD_METHOD(FilterAndSearch); - ADD_METHOD(SetFromAll); - } -}; - -LUA_REGISTER_CLASS(Packlist) - class LunaDownloadablePack : public Luna { public: diff --git a/src/DownloadManager.h b/src/DownloadManager.h index c567632859..6dc1b4d613 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -89,18 +89,6 @@ class DownloadablePack void PushSelf(lua_State* L); }; -class Packlist -{ - public: - int sortmode = - 1; // 1=name 2=diff 3=size, init to name because that's the default- mina - bool asc = true; // default sort - - vector packs; - // Lua - void PushSelf(lua_State* L); -}; - class HTTPRequest { public: @@ -313,7 +301,6 @@ class DownloadManager const int maxPacksToDownloadAtOnce = 1; const float DownloadCooldownTime = 5.f; float timeSinceLastDownload = 0.f; - Packlist pl; // Lua void PushSelf(lua_State* L); From d15a661207a48989fe145a3d2825c56ef556beb0 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 05:51:12 -0500 Subject: [PATCH 110/320] remove replay fail prevention --- src/ScreenGameplay.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index d944bf218d..d47187fb24 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1562,11 +1562,9 @@ ScreenGameplay::Update(float fDeltaTime) } if (bAllFailed) { - if (!GamePreferences::m_AutoPlay == PC_REPLAY) { - m_pSoundMusic->StopPlaying(); - SCREENMAN->PostMessageToTopScreen(SM_NotesEnded, 0); - m_LyricDisplay.Stop(); - } + m_pSoundMusic->StopPlaying(); + SCREENMAN->PostMessageToTopScreen(SM_NotesEnded, 0); + m_LyricDisplay.Stop(); } // Update living players' alive time From 2931fc82e4209ab41f5bb66d3f8fcf1cecc3b8a2 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 10:52:15 -0500 Subject: [PATCH 111/320] REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE --- src/Player.cpp | 775 +++++++++++++++++++++++++++++++------- src/Player.h | 8 +- src/ScreenSelectMusic.cpp | 35 +- 3 files changed, 670 insertions(+), 148 deletions(-) diff --git a/src/Player.cpp b/src/Player.cpp index e4d834fcbd..8412002756 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -940,8 +940,8 @@ Player::Update(float fDeltaTime) if (PlayerAI::TapExistsAtOrBeforeThisRow(iSongRow)) { vector trrVector = PlayerAI::GetTapsAtOrBeforeRow(iSongRow); - for (TapReplayResult trr : trrVector) { - Step(trr.track, trr.row, now, false, false); + for (TapReplayResult& trr : trrVector) { + StepReplay(trr.track, trr.row, now, false, false); } } } @@ -2538,181 +2538,489 @@ Player::Step(int col, } void -Player::UpdateTapNotesMissedOlderThan(float fMissIfOlderThanSeconds) +Player::StepReplay(int col, + int row, + const std::chrono::steady_clock::time_point& tm, + bool bHeld, + bool bRelease, + float padStickSeconds) { - // LOG->Trace( "Steps::UpdateTapNotesMissedOlderThan(%f)", - // fMissIfOlderThanThisBeat ); - int iMissIfOlderThanThisRow; - const float fEarliestTime = - m_pPlayerState->m_Position.m_fMusicSeconds - fMissIfOlderThanSeconds; - { - TimingData::GetBeatArgs beat_info; - beat_info.elapsed_time = fEarliestTime; - m_Timing->GetBeatAndBPSFromElapsedTime(beat_info); + if (IsOniDead()) + return; - iMissIfOlderThanThisRow = BeatToNoteRow(beat_info.beat); - if (beat_info.freeze_out || beat_info.delay_out) { - /* If there is a freeze on iMissIfOlderThanThisIndex, include this - * index too. Otherwise we won't show misses for tap notes on - * freezes until the freeze finishes. */ - if (!beat_info.delay_out) - iMissIfOlderThanThisRow++; - } - } + // Do everything that depends on a timer here; + // set your breakpoints somewhere after this block. + std::chrono::duration stepDelta = + std::chrono::steady_clock::now() - tm; + float stepAgo = stepDelta.count() - padStickSeconds; - NoteData::all_tracks_iterator& iter = *m_pIterNeedsTapJudging; + const float fLastBeatUpdate = + m_pPlayerState->m_Position.m_LastBeatUpdate.Ago(); + const float fPositionSeconds = + m_pPlayerState->m_Position.m_fMusicSeconds - stepAgo; + const float fTimeSinceStep = stepAgo; - for (; !iter.IsAtEnd() && iter.Row() < iMissIfOlderThanThisRow; ++iter) { - TapNote& tn = *iter; + // idk if this is the correct value for input logs but we'll use them to + // test -mina ok this is 100% not the place to do this + // m_pPlayerStageStats->InputData.emplace_back(fPositionSeconds); - if (!NeedsTapJudging(tn)) - continue; + float fSongBeat = m_pPlayerState->m_Position.m_fSongBeat; - // Ignore all notes in WarpSegments or FakeSegments. - if (!m_Timing->IsJudgableAtRow(iter.Row())) - continue; + if (GAMESTATE->m_pCurSteps[m_pPlayerState->m_PlayerNumber]) + fSongBeat = m_Timing->GetBeatFromElapsedTime(fPositionSeconds); - if (tn.type == TapNoteType_Mine) { - tn.result.tns = TNS_AvoidMine; - /* The only real way to tell if a mine has been scored is if it has - * disappeared but this only works for hit mines so update the - * scores for avoided mines here. */ - if (m_pPrimaryScoreKeeper) - m_pPrimaryScoreKeeper->HandleTapScore(tn); - if (m_pSecondaryScoreKeeper) - m_pSecondaryScoreKeeper->HandleTapScore(tn); - } else { - tn.result.tns = TNS_Miss; - if (GAMESTATE->CountNotesSeparately()) { - SetJudgment(iter.Row(), iter.Track(), tn); - HandleTapRowScore(iter.Row()); + const int iSongRow = row == -1 ? BeatToNoteRow(fSongBeat) : row; + + if (col != -1 && !bRelease) { + // Update roll life + // Let's not check the whole array every time. + // Instead, only check 1 beat back. Even 1 is overkill. + // Just update the life here and let Update judge the roll. + const int iStartCheckingAt = max(0, iSongRow - BeatToNoteRow(1)); + NoteData::TrackMap::iterator begin, end; + m_NoteData.GetTapNoteRangeInclusive( + col, iStartCheckingAt, iSongRow + 1, begin, end); + for (; begin != end; ++begin) { + TapNote& tn = begin->second; + if (tn.type != TapNoteType_HoldHead) + continue; + + switch (tn.subType) { + DEFAULT_FAIL(tn.subType); + case TapNoteSubType_Hold: + continue; + case TapNoteSubType_Roll: + break; + } + + const int iRow = begin->first; + + HoldNoteScore hns = tn.HoldResult.hns; + if (hns != HNS_None) // if this HoldNote already has a result + continue; // we don't need to update the logic for this one + + // if they got a bad score or haven't stepped on the corresponding + // tap yet + const TapNoteScore tns = tn.result.tns; + bool bInitiatedNote = true; + if (REQUIRE_STEP_ON_HOLD_HEADS) + bInitiatedNote = tns != TNS_None && + tns != TNS_Miss; // did they step on the start? + const int iEndRow = iRow + tn.iDuration; + + if (bInitiatedNote && tn.HoldResult.fLife != 0) { + /* This hold note is not judged and we stepped on its head. + * Update iLastHeldRow. Do this even if we're a little beyond + * the end of the hold note, to make sure iLastHeldRow is + * clamped to iEndRow if the hold note is held all the way. */ + // LOG->Trace("setting iLastHeldRow to min of iSongRow (%i) and + // iEndRow (%i)",iSongRow,iEndRow); + tn.HoldResult.iLastHeldRow = min(iSongRow, iEndRow); + } + + // If the song beat is in the range of this hold: + if (iRow <= iSongRow && iRow <= iEndRow) { + if (bInitiatedNote) { + // Increase life + tn.HoldResult.fLife = 1; + + if (ROLL_BODY_INCREMENTS_COMBO && + m_pPlayerState->m_PlayerController != PC_AUTOPLAY) { + IncrementCombo(); + + bool bBright = + m_pPlayerStageStats && + m_pPlayerStageStats->m_iCurCombo > + (unsigned int)BRIGHT_GHOST_COMBO_THRESHOLD; + if (m_pNoteField) + m_pNoteField->DidHoldNote(col, HNS_Held, bBright); + } + } + break; } } } -} -void -Player::UpdateJudgedRows(float fDeltaTime) -{ - // Look into the future only as far as we need to - const int iEndRow = BeatToNoteRow(m_Timing->GetBeatFromElapsedTime( - m_pPlayerState->m_Position.m_fMusicSeconds + - GetMaxStepDistanceSeconds())); - bool bAllJudged = true; + // Check for step on a TapNote + /* XXX: This seems wrong. If a player steps twice quickly and two notes are + * close together in the same column then it is possible for the two notes + * to be graded out of order. + * Two possible fixes: + * 1. Adjust the fSongBeat (or the resulting note row) backward by + * iStepSearchRows and search forward two iStepSearchRows lengths, + * disallowing graded. This doesn't seem right because if a second note has + * passed, an earlier one should not be graded. + * 2. Clamp the distance searched backward to the previous row graded. + * Either option would fundamentally change the grading of two quick notes + * "jack hammers." Hmm. + */ - if (!GAMESTATE->CountNotesSeparately()) { - NoteData::all_tracks_iterator iter = *m_pIterUnjudgedRows; - int iLastSeenRow = -1; - for (; !iter.IsAtEnd() && iter.Row() <= iEndRow; ++iter) { - int iRow = iter.Row(); + int iStepSearchRows; + static const float StepSearchDistance = GetMaxStepDistanceSeconds(); + int skipstart = nerv[10]; // this is not robust need to come up with + // something better later - Mina - // Do not judge arrows in WarpSegments or FakeSegments - if (!m_Timing->IsJudgableAtRow(iRow)) - continue; + if (iSongRow < skipstart || iSongRow > static_cast(nerv.size()) - 10) { + iStepSearchRows = + max(BeatToNoteRow(m_Timing->GetBeatFromElapsedTime( + m_pPlayerState->m_Position.m_fMusicSeconds + + StepSearchDistance)) - + iSongRow, + iSongRow - BeatToNoteRow(m_Timing->GetBeatFromElapsedTime( + m_pPlayerState->m_Position.m_fMusicSeconds - + StepSearchDistance))) + + ROWS_PER_BEAT; + } else { + /* Buncha bullshit that speeds up searching for the rows that we're + concerned about judging taps within by avoiding the invocation of the + incredibly slow getbeatfromelapsedtime. Needs to be cleaned up a lot, + whole system does. Only in use if sequential assumption remains valid. - + Mina */ - if (iLastSeenRow != iRow) { - iLastSeenRow = iRow; + if (nerv[nervpos] < iSongRow && nervpos < nerv.size()) + nervpos += 1; - // crossed a nonempty row - if (!NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, - iRow)) { - bAllJudged = false; - continue; - } - if (bAllJudged) - *m_pIterUnjudgedRows = iter; - if (m_pJudgedRows->JudgeRow(iRow)) - continue; + size_t SearchIndexBehind = nervpos; + size_t SearchIndexAhead = nervpos; + float SearchBeginTime = m_Timing->WhereUAtBro(nerv[nervpos]); - const TapNote& lastTN = - NoteDataWithScoring::LastTapNoteWithResult(m_NoteData, iRow); + while (SearchIndexBehind > 1 && + SearchBeginTime - + m_Timing->WhereUAtBro(nerv[SearchIndexBehind - 1]) < + StepSearchDistance) + SearchIndexBehind -= 1; - if (lastTN.result.tns < TNS_Miss) - continue; + while (SearchIndexAhead > 1 && SearchIndexAhead + 1 > nerv.size() && + m_Timing->WhereUAtBro(nerv[SearchIndexAhead + 1]) - + SearchBeginTime < + StepSearchDistance) + SearchIndexAhead += 1; - SetJudgment( - iRow, - m_NoteData.GetFirstTrackWithTapOrHoldHead(iter.Row()), - lastTN); - HandleTapRowScore(iRow); - } - } + int MaxLookBehind = nerv[nervpos] - nerv[SearchIndexBehind]; + int MaxLookAhead = nerv[SearchIndexAhead] - nerv[nervpos]; + + if (nervpos > 0) + iStepSearchRows = + (max(MaxLookBehind, MaxLookAhead) + ROWS_PER_BEAT); } - // handle mines. - { - bAllJudged = true; - set setSounds; - NoteData::all_tracks_iterator iter = *m_pIterUnjudgedMineRows; // copy - int iLastSeenRow = -1; - for (; !iter.IsAtEnd() && iter.Row() <= iEndRow; ++iter) { - int iRow = iter.Row(); + // calculate TapNoteScore + TapNoteScore score = TNS_None; - // Do not worry about mines in WarpSegments or FakeSegments - if (!m_Timing->IsJudgableAtRow(iRow)) - continue; + int iRowOfOverlappingNoteOrRow = row; + if (row == -1) + iRowOfOverlappingNoteOrRow = GetClosestNote( + col, iSongRow, iStepSearchRows, iStepSearchRows, false); - TapNote& tn = *iter; + if (iRowOfOverlappingNoteOrRow != -1) { + // compute the score for this hit + float fNoteOffset = 0.f; + // we need this later if we are autosyncing + const float fStepBeat = NoteRowToBeat(iRowOfOverlappingNoteOrRow); + const float fStepSeconds = m_Timing->WhereUAtBro(fStepBeat); - if (iRow != iLastSeenRow) { - iLastSeenRow = iRow; - if (bAllJudged) - *m_pIterUnjudgedMineRows = iter; - } + if (row == -1) { + // We actually stepped on the note this long ago: + // fTimeSinceStep - bool bMineNotHidden = - tn.type == TapNoteType_Mine && !tn.result.bHidden; - if (!bMineNotHidden) - continue; + /* GAMESTATE->m_fMusicSeconds is the music time as of + * GAMESTATE->m_LastBeatUpdate. Figure out what the music time is as + * of now. */ + const float fCurrentMusicSeconds = + m_pPlayerState->m_Position.m_fMusicSeconds + + (fLastBeatUpdate * + GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate); - switch (tn.result.tns) { - DEFAULT_FAIL(tn.result.tns); - case TNS_None: - bAllJudged = false; - continue; - case TNS_AvoidMine: - SetMineJudgment(tn.result.tns, iter.Track()); - tn.result.bHidden = true; - continue; - case TNS_HitMine: - SetMineJudgment(tn.result.tns, iter.Track()); - break; + // ... which means it happened at this point in the music: + const float fMusicSeconds = + fCurrentMusicSeconds - + fTimeSinceStep * + GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate; + + // The offset from the actual step in seconds: + fNoteOffset = (fStepSeconds - fMusicSeconds) / + GAMESTATE->m_SongOptions.GetCurrent() + .m_fMusicRate; // account for music rate + /* + LOG->Trace("step was %.3f ago, music is off by %f: %f vs %f, step + was %f off", fTimeSinceStep, + GAMESTATE->m_LastBeatUpdate.Ago()/GAMESTATE->m_SongOptions.m_fMusicRate, + fStepSeconds, fMusicSeconds, fNoteOffset ); + */ + } + + NOTESKIN->SetLastSeenColor( + NoteTypeToString(GetNoteType(iRowOfOverlappingNoteOrRow))); + + const float fSecondsFromExact = fabsf(fNoteOffset); + + TapNote* pTN = nullptr; + NoteData::iterator iter = + m_NoteData.FindTapNote(col, GetClosestNote(col, iSongRow, MAX_NOTE_ROW, MAX_NOTE_ROW, true)); + + pTN = &iter->second; + + // We don't really have to care if we are releasing on a non-lift, + // right? This fixes a weird noteskin bug with tap explosions. + if (PREFSMAN->m_bFullTapExplosions && bRelease && + pTN->type != TapNoteType_Lift) + return; + + switch (m_pPlayerState->m_PlayerController) { + case PC_HUMAN: + case PC_CPU: + case PC_AUTOPLAY: + score = PlayerAI::GetTapNoteScore(m_pPlayerState); + + /* XXX: This doesn't make sense. + * Step should only be called in autoplay for hit notes. */ +#if 0 + // GetTapNoteScore always returns TNS_W1 in autoplay. + // If the step is far away, don't judge it. + if( m_pPlayerState->m_PlayerController == PC_AUTOPLAY && + fSecondsFromExact > GetWindowSeconds(TW_W5) ) + { + score = TNS_None; + break; } - if (m_pNoteField) - m_pNoteField->DidTapNote(iter.Track(), tn.result.tns, false); +#endif - if (tn.iKeysoundIndex >= 0 && - tn.iKeysoundIndex < static_cast(m_vKeysounds.size())) - setSounds.insert(&m_vKeysounds[tn.iKeysoundIndex]); - else if (g_bEnableMineSoundPlayback) - setSounds.insert(&m_soundMine); + // TRICKY: We're asking the AI to judge mines. Consider TNS_W4 + // and below as "mine was hit" and everything else as "mine was + // avoided" + if (pTN->type == TapNoteType_Mine) { + // The CPU hits a lot of mines. Only consider hitting the + // first mine for a row. We know we're the first mine if + // there are are no mines to the left of us. + for (int t = 0; t < col; t++) { + if (m_NoteData.GetTapNote(t, iRowOfOverlappingNoteOrRow) + .type == TapNoteType_Mine) // there's a mine to + // the left of us + return; // avoid + } - ChangeLife(tn.result.tns); + // The CPU hits a lot of mines. Make it less likely to hit + // mines that don't have a tap note on the same row. + bool bTapsOnRow = m_NoteData.IsThereATapOrHoldHeadAtRow( + iRowOfOverlappingNoteOrRow); + TapNoteScore get_to_avoid = bTapsOnRow ? TNS_W3 : TNS_W4; + + if (score >= get_to_avoid) + return; // avoided + + score = TNS_HitMine; + } + + if (score > TNS_W4) + score = TNS_W2; // sentinel + + /* AI will generate misses here. Don't handle a miss like a + * regular note because we want the judgment animation to appear + * delayed. Instead, return early if AI generated a miss, and + * let UpdateTapNotesMissedOlderThan() detect and handle the + * misses. */ + if (score == TNS_Miss) + return; + + // Put some small, random amount in fNoteOffset so that + // demonstration show a mix of late and early. - Chris + // (StepMania r15628) + // fNoteOffset = randomf( -0.1f, 0.1f ); + // Since themes may use the offset in a visual graph, the above + // behavior is not the best thing to do. Instead, random numbers + // should be generated based on the TapNoteScore, so that they + // can logically match up with the current timing windows. -aj + { + float fWindowW1 = GetWindowSeconds(TW_W1); + float fWindowW2 = GetWindowSeconds(TW_W2); + float fWindowW3 = GetWindowSeconds(TW_W3); + float fWindowW4 = GetWindowSeconds(TW_W4); + float fWindowW5 = GetWindowSeconds(TW_W5); + + // W1 is the top judgment, there is no overlap. + if (score == TNS_W1) + fNoteOffset = randomf(-fWindowW1, fWindowW1); + else { + // figure out overlap. + float fLowerBound = 0.0f; // negative upper limit + float fUpperBound = 0.0f; // positive lower limit + float fCompareWindow = 0.0f; // filled in here: + if (score == TNS_W2) { + fLowerBound = -fWindowW1; + fUpperBound = fWindowW1; + fCompareWindow = fWindowW2; + } else if (score == TNS_W3) { + fLowerBound = -fWindowW2; + fUpperBound = fWindowW2; + fCompareWindow = fWindowW3; + } else if (score == TNS_W4) { + fLowerBound = -fWindowW3; + fUpperBound = fWindowW3; + fCompareWindow = fWindowW4; + } else if (score == TNS_W5) { + fLowerBound = -fWindowW4; + fUpperBound = fWindowW4; + fCompareWindow = fWindowW5; + } + float f1 = randomf(-fCompareWindow, fLowerBound); + float f2 = randomf(fUpperBound, fCompareWindow); + + if (randomf() * 100 >= 50) + fNoteOffset = f1; + else + fNoteOffset = f2; + } + } + + break; + + case PC_REPLAY: + + if (bHeld) // a hack to make Rolls not do weird things like + // count as 0ms marvs. + { + score = TNS_None; + fNoteOffset = -1.f; + } else { + if (PlayerAI::GetReplayType() == 2) { + iRowOfOverlappingNoteOrRow = row; + } + fNoteOffset = PlayerAI::GetTapNoteOffsetForReplay( + pTN, iRowOfOverlappingNoteOrRow, col); + if (fNoteOffset == -2.f) // we hit a mine + { + score = TNS_HitMine; + PlayerAI::RemoveTapFromVectors( + iRowOfOverlappingNoteOrRow, col); + } else if (pTN->type == TapNoteType_Mine) // we are looking + // at a mine but + // missed it + { + return; + } else // every other case + { + if (pTN->IsNote() || pTN->type == TapNoteType_Lift) + score = PlayerAI::GetTapNoteScoreForReplay( + m_pPlayerState, fNoteOffset); + } + } + + break; + default: + FAIL_M(ssprintf("Invalid player controller type: %i", + m_pPlayerState->m_PlayerController)); + } + + if (m_pPlayerState->m_PlayerController == PC_HUMAN && score >= TNS_W3) + AdjustSync::HandleAutosync(fNoteOffset, fStepSeconds); + + // Do game-specific and mode-specific score mapping. + score = GAMESTATE->GetCurrentGame()->MapTapNoteScore(score); + if (score == TNS_W1 && !GAMESTATE->ShowW1()) + score = TNS_W2; + + if (score != TNS_None) { + pTN->result.tns = score; + pTN->result.fTapNoteOffset = -fNoteOffset; + } + + m_LastTapNoteScore = score; + if (pTN->result.tns != TNS_None) + AddNoteToReplayData(GAMESTATE->CountNotesSeparately() ? col : -1, + pTN, + iRowOfOverlappingNoteOrRow); + if (GAMESTATE->CountNotesSeparately()) { + if (pTN->type != TapNoteType_Mine) { + const bool bBlind = + (m_pPlayerState->m_PlayerOptions.GetCurrent().m_fBlind != 0); + // XXX: This is the wrong combo for shared players. + // STATSMAN->m_CurStageStats.m_Player[pn] might work, but could + // be wrong. + const bool bBright = + (m_pPlayerStageStats && + m_pPlayerStageStats->m_iCurCombo > + (unsigned int)BRIGHT_GHOST_COMBO_THRESHOLD) || + bBlind; + if (m_pNoteField != nullptr) + m_pNoteField->DidTapNote( + col, bBlind ? TNS_W1 : score, bBright); + if (score >= m_pPlayerState->m_PlayerOptions.GetCurrent() + .m_MinTNSToHideNotes || + bBlind) + HideNote(col, iRowOfOverlappingNoteOrRow); + + if (pTN->result.tns != TNS_None) { + if (pTN->type == TapNoteType_HoldHead && + m_pPlayerState->m_PlayerController == PC_REPLAY && + bHeld) { + // odd hack to make roll taps (Step() with bHeld true) + // not count as marvs + } else { + SetJudgment(iRowOfOverlappingNoteOrRow, col, *pTN); + HandleTapRowScore(iRowOfOverlappingNoteOrRow); + } + } + } + } else if (NoteDataWithScoring::IsRowCompletelyJudged( + m_NoteData, iRowOfOverlappingNoteOrRow)) { + FlashGhostRow(iRowOfOverlappingNoteOrRow); + } + } - if (m_pScoreDisplay) - m_pScoreDisplay->OnJudgment(tn.result.tns); - if (m_pSecondaryScoreDisplay) - m_pSecondaryScoreDisplay->OnJudgment(tn.result.tns); + if (score == TNS_None) + DoTapScoreNone(); - // Make sure hit mines affect the dance points. - if (m_pPrimaryScoreKeeper) - m_pPrimaryScoreKeeper->HandleTapScore(tn); - if (m_pSecondaryScoreKeeper) - m_pSecondaryScoreKeeper->HandleTapScore(tn); - tn.result.bHidden = true; + if (!bRelease) { + /* Search for keyed sounds separately. Play the nearest note. */ + /* XXX: This isn't quite right. As per the above XXX for + * iRowOfOverlappingNote, if iRowOfOverlappingNote is set to a previous + * note, the keysound could have changed and this would cause the wrong + * one to play, in essence playing two sounds in the opposite order. + * Maybe this should always perform the search. Still, even that doesn't + * seem quite right since it would then play the same (new) keysound + * twice which would sound wrong even though the notes were judged as + * being correct, above. Fixing the above problem would fix this one as + * well. */ + int iHeadRow; + if (iRowOfOverlappingNoteOrRow != -1 && score != TNS_None) { + // just pressing a note, use that row. + // in other words, iRowOfOverlappingNoteOrRow = + // iRowOfOverlappingNoteOrRow + } else if (m_NoteData.IsHoldNoteAtRow(col, iSongRow, &iHeadRow)) { + // stepping on a hold, use it! + iRowOfOverlappingNoteOrRow = iHeadRow; + } else { + // or else find the closest note. + iRowOfOverlappingNoteOrRow = + GetClosestNote(col, iSongRow, MAX_NOTE_ROW, MAX_NOTE_ROW, true); } - // If we hit the end of the loop, m_pIterUnjudgedMineRows needs to be - // updated. -Kyz - if ((iter.IsAtEnd() || iLastSeenRow == iEndRow) && bAllJudged) { - *m_pIterUnjudgedMineRows = iter; + if (iRowOfOverlappingNoteOrRow != -1) { + const TapNote& tn = + m_NoteData.GetTapNote(col, iRowOfOverlappingNoteOrRow); + PlayKeysound(tn, score); } + } + // XXX: - FOREACHS(RageSound*, setSounds, s) - { - // Only play one copy of each mine sound at a time per player. - (*s)->Stop(); - (*s)->Play(false); + if (!bRelease) { + if (m_pNoteField != nullptr) { // skip tapping in replay mode on misses + // to emulate... missing. + if (m_pPlayerState->m_PlayerController == PC_REPLAY) { + if (score != TNS_Miss) { + m_pNoteField->Step(col, score); + } + } else { + m_pNoteField->Step(col, score); + } } + Message msg("Step"); + msg.SetParam("PlayerNumber", m_pPlayerState->m_PlayerNumber); + msg.SetParam("MultiPlayer", m_pPlayerState->m_mp); + msg.SetParam("Column", col); + MESSAGEMAN->Broadcast(msg); + // Backwards compatibility + Message msg2(ssprintf("StepP%d", m_pPlayerState->m_PlayerNumber + 1)); + MESSAGEMAN->Broadcast(msg2); } } @@ -2913,6 +3221,185 @@ Player::CrossedRows(int iLastRowCrossed, m_iFirstUncrossedRow = iLastRowCrossed + 1; } +void +Player::UpdateTapNotesMissedOlderThan(float fMissIfOlderThanSeconds) +{ + // LOG->Trace( "Steps::UpdateTapNotesMissedOlderThan(%f)", + // fMissIfOlderThanThisBeat ); + int iMissIfOlderThanThisRow; + const float fEarliestTime = + m_pPlayerState->m_Position.m_fMusicSeconds - fMissIfOlderThanSeconds; + { + TimingData::GetBeatArgs beat_info; + beat_info.elapsed_time = fEarliestTime; + m_Timing->GetBeatAndBPSFromElapsedTime(beat_info); + + iMissIfOlderThanThisRow = BeatToNoteRow(beat_info.beat); + if (beat_info.freeze_out || beat_info.delay_out) { + /* If there is a freeze on iMissIfOlderThanThisIndex, include this + * index too. Otherwise we won't show misses for tap notes on + * freezes until the freeze finishes. */ + if (!beat_info.delay_out) + iMissIfOlderThanThisRow++; + } + } + + NoteData::all_tracks_iterator& iter = *m_pIterNeedsTapJudging; + + for (; !iter.IsAtEnd() && iter.Row() < iMissIfOlderThanThisRow; ++iter) { + TapNote& tn = *iter; + + if (!NeedsTapJudging(tn)) + continue; + + // Ignore all notes in WarpSegments or FakeSegments. + if (!m_Timing->IsJudgableAtRow(iter.Row())) + continue; + + if (tn.type == TapNoteType_Mine) { + tn.result.tns = TNS_AvoidMine; + /* The only real way to tell if a mine has been scored is if it has + * disappeared but this only works for hit mines so update the + * scores for avoided mines here. */ + if (m_pPrimaryScoreKeeper) + m_pPrimaryScoreKeeper->HandleTapScore(tn); + if (m_pSecondaryScoreKeeper) + m_pSecondaryScoreKeeper->HandleTapScore(tn); + } else { + tn.result.tns = TNS_Miss; + if (GAMESTATE->CountNotesSeparately()) { + SetJudgment(iter.Row(), iter.Track(), tn); + HandleTapRowScore(iter.Row()); + } + } + } +} + +void +Player::UpdateJudgedRows(float fDeltaTime) +{ + // Look into the future only as far as we need to + const int iEndRow = BeatToNoteRow(m_Timing->GetBeatFromElapsedTime( + m_pPlayerState->m_Position.m_fMusicSeconds + + GetMaxStepDistanceSeconds())); + bool bAllJudged = true; + + if (!GAMESTATE->CountNotesSeparately()) { + NoteData::all_tracks_iterator iter = *m_pIterUnjudgedRows; + int iLastSeenRow = -1; + for (; !iter.IsAtEnd() && iter.Row() <= iEndRow; ++iter) { + int iRow = iter.Row(); + + // Do not judge arrows in WarpSegments or FakeSegments + if (!m_Timing->IsJudgableAtRow(iRow)) + continue; + + if (iLastSeenRow != iRow) { + iLastSeenRow = iRow; + + // crossed a nonempty row + if (!NoteDataWithScoring::IsRowCompletelyJudged(m_NoteData, + iRow)) { + bAllJudged = false; + continue; + } + if (bAllJudged) + *m_pIterUnjudgedRows = iter; + if (m_pJudgedRows->JudgeRow(iRow)) + continue; + + const TapNote& lastTN = + NoteDataWithScoring::LastTapNoteWithResult(m_NoteData, iRow); + + if (lastTN.result.tns < TNS_Miss) + continue; + + SetJudgment( + iRow, + m_NoteData.GetFirstTrackWithTapOrHoldHead(iter.Row()), + lastTN); + HandleTapRowScore(iRow); + } + } + } + + // handle mines. + { + bAllJudged = true; + set setSounds; + NoteData::all_tracks_iterator iter = *m_pIterUnjudgedMineRows; // copy + int iLastSeenRow = -1; + for (; !iter.IsAtEnd() && iter.Row() <= iEndRow; ++iter) { + int iRow = iter.Row(); + + // Do not worry about mines in WarpSegments or FakeSegments + if (!m_Timing->IsJudgableAtRow(iRow)) + continue; + + TapNote& tn = *iter; + + if (iRow != iLastSeenRow) { + iLastSeenRow = iRow; + if (bAllJudged) + *m_pIterUnjudgedMineRows = iter; + } + + bool bMineNotHidden = + tn.type == TapNoteType_Mine && !tn.result.bHidden; + if (!bMineNotHidden) + continue; + + switch (tn.result.tns) { + DEFAULT_FAIL(tn.result.tns); + case TNS_None: + bAllJudged = false; + continue; + case TNS_AvoidMine: + SetMineJudgment(tn.result.tns, iter.Track()); + tn.result.bHidden = true; + continue; + case TNS_HitMine: + SetMineJudgment(tn.result.tns, iter.Track()); + break; + } + if (m_pNoteField) + m_pNoteField->DidTapNote(iter.Track(), tn.result.tns, false); + + if (tn.iKeysoundIndex >= 0 && + tn.iKeysoundIndex < static_cast(m_vKeysounds.size())) + setSounds.insert(&m_vKeysounds[tn.iKeysoundIndex]); + else if (g_bEnableMineSoundPlayback) + setSounds.insert(&m_soundMine); + + ChangeLife(tn.result.tns); + + if (m_pScoreDisplay) + m_pScoreDisplay->OnJudgment(tn.result.tns); + if (m_pSecondaryScoreDisplay) + m_pSecondaryScoreDisplay->OnJudgment(tn.result.tns); + + // Make sure hit mines affect the dance points. + if (m_pPrimaryScoreKeeper) + m_pPrimaryScoreKeeper->HandleTapScore(tn); + if (m_pSecondaryScoreKeeper) + m_pSecondaryScoreKeeper->HandleTapScore(tn); + tn.result.bHidden = true; + } + // If we hit the end of the loop, m_pIterUnjudgedMineRows needs to be + // updated. -Kyz + if ((iter.IsAtEnd() || iLastSeenRow == iEndRow) && bAllJudged) { + *m_pIterUnjudgedMineRows = iter; + } + + FOREACHS(RageSound*, setSounds, s) + { + // Only play one copy of each mine sound at a time per player. + (*s)->Stop(); + (*s)->Play(false); + } + } +} + void Player::HandleTapRowScore(unsigned row) { @@ -3230,8 +3717,6 @@ Player::SetJudgment(int iRow, TapNoteScore tns, float fTapNoteOffset) { - if (tns < 0 || tns > NUM_TapNoteScore) - tns = TNS_Miss; // dont know why or how this crashes -mina if (tns == TNS_Miss) AddNoteToReplayData( GAMESTATE->CountNotesSeparately() ? iTrack : -1, &tn, iRow); diff --git a/src/Player.h b/src/Player.h index 151139db74..1b0c9af649 100644 --- a/src/Player.h +++ b/src/Player.h @@ -1,4 +1,4 @@ -#ifndef PLAYER_H +#ifndef PLAYER_H #define PLAYER_H #include "ActorFrame.h" @@ -161,6 +161,12 @@ class Player : public ActorFrame int totalwifescore; protected: + void StepReplay(int col, + int row, + const std::chrono::steady_clock::time_point& tm, + bool bHeld, + bool bRelease, + float padStickSeconds = 0.0f); void UpdateTapNotesMissedOlderThan(float fMissIfOlderThanThisBeat); void UpdateJudgedRows(float fDeltaTime); void FlashGhostRow(int iRow); diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 1a568a5a2a..6dd074f473 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1704,11 +1704,11 @@ class LunaScreenSelectMusic : public Luna // from the existing, if the score was cc off then we need to fill in // extra rows for each tap in the chord -mina auto timestamps = hs->GetCopyOfSetOnlineReplayTimestampVector(); - + auto REEEEEEEEEEEEEE = hs->GetOffsetVector(); if (!timestamps.empty()) { GAMESTATE->SetProcessedTimingData( GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData()); - + auto* td = GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData(); vector ihatemylife; auto nd = GAMESTATE->m_pCurSteps[PLAYER_1]->GetNoteData(); auto nerv = nd.BuildAndGetNerv(); @@ -1720,8 +1720,39 @@ class LunaScreenSelectMusic : public Luna for (auto r : nerv) ihatemylife.emplace_back(r); } + auto REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = td->BuildAndGetEtaner(nerv); + vector REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; + for (auto t : timestamps) { + auto REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = + td->GetBeatFromElapsedTime(t * hs->GetMusicRate()); + auto REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE[0] - (timestamps[0] * hs->GetMusicRate()); + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE += + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; + auto + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = + BeatToNoteRow( + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE); + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.emplace_back( + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE); + } + int + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = + nerv[0] - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE[0]; + for (auto& REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE : + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE) + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE += + REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; GAMESTATE->SetProcessedTimingData(nullptr); hs->SetNoteRowVector(ihatemylife); + hs->SetNoteRowVector(REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE); + + for (size_t i = 0; i < ihatemylife.size(); ++i) + { + //LOG->Warn("REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE%i, %i", + // ihatemylife[i], + // REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE[i]); + } } PlayerAI::SetScoreData(hs); From 3e872eee4b28d531ab518e9944a470a5f9f9ef84 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 17:10:37 -0300 Subject: [PATCH 112/320] Fix invalid json --- src/DownloadManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index c92927169a..0f85175584 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1064,9 +1064,9 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) for (size_t i = 0; i < offsets.size(); i++) { replayString += "["; replayString += to_string(timestamps[i]) + ","; - replayString += to_string(1000.f * offsets[i]) + ","; + replayString += to_string(1000.f * offsets[i]); if (hs->GetReplayType() == 2) { - replayString += to_string(columns[i]) + ","; + replayString += "," + to_string(columns[i]) + ","; replayString += to_string(types[i]); } replayString += "],"; From 578d009fff77db6590c1bfc2fa9b2b15d2001fbb Mon Sep 17 00:00:00 2001 From: Nicolas Date: Wed, 28 Nov 2018 18:26:54 -0300 Subject: [PATCH 113/320] A lot of lua docs. A lot of it is taken from https://etternagame.github.io/Lua-For-Etterna/API/Lua.xml --- Themes/_fallback/docs/Actor.luadoc | 2073 +++++++++++------ .../_fallback/docs/ActorFrameTexture.luadoc | 51 + Themes/_fallback/docs/ActorMultiVertex.luadoc | 306 +++ Themes/_fallback/docs/DownloadManager.luadoc | 149 ++ Themes/_fallback/docs/ScreenManager.luadoc | 101 + Themes/_fallback/docs/SongManager.luadoc | 275 +++ Themes/_fallback/docs/Sprite.luadoc | 346 ++- 7 files changed, 2492 insertions(+), 809 deletions(-) create mode 100644 Themes/_fallback/docs/ActorFrameTexture.luadoc create mode 100644 Themes/_fallback/docs/ActorMultiVertex.luadoc create mode 100644 Themes/_fallback/docs/DownloadManager.luadoc create mode 100644 Themes/_fallback/docs/ScreenManager.luadoc create mode 100644 Themes/_fallback/docs/SongManager.luadoc diff --git a/Themes/_fallback/docs/Actor.luadoc b/Themes/_fallback/docs/Actor.luadoc index a3e2e5e1df..3b28323cd8 100644 --- a/Themes/_fallback/docs/Actor.luadoc +++ b/Themes/_fallback/docs/Actor.luadoc @@ -1,705 +1,1376 @@ --- Basic Actor class -- @classmod Actor +--[[ + This adds a wrapper state around the Actor, which is like wrapping the Actor in an ActorFrame, except that you can use it on any actor, and add or remove wrapper states in response to things that happen while the screen is being used. (wrapping an Actor in an ActorFrame normally requires setting it up before the screen starts)
+ The ActorFrame that is returned is the wrapper state, for convenience.
+ An Actor can have any number of wrapper states. Use GetWrapperState to access wrapper states for the actor. + @return ActorFrame +--]] +function Actor:AddWrapperState() +end ---- Get the name of this specific actor instance --- Usually set as Def.Actor{Name = "string"} --- @treturn Actor self -function Actor:name() end - ---- Inserts a linear tween of seconds time and then a 0 seconds empty tween --- to force the future tweens to happen after seconds seconds elapse --- @number seconds --- @treturn Actor self -function Actor:sleep(seconds) end - ---- Inserts a linear tween of seconds time --- @number seconds --- @treturn Actor self -function Actor:linear(seconds) end - ---- Inserts an accelerate tween of seconds time --- @number seconds --- @treturn Actor self -function Actor:accelerate(seconds) end - ---- Inserts a decelerate tween of seconds time --- @number seconds --- @treturn Actor self -function Actor:decelerate(seconds) end - ---- Inserts a spring tween of seconds time --- @number seconds --- @treturn Actor self -function Actor:spring(seconds) end - ---- Inserts a tween of tweenType with seconds duration --- @number seconds --- @treturn Actor self -function Actor:tween(seconds, tweenType) end - ---- Immediately cancels/stops all tweens left for this actor --- @treturn Actor self -function Actor:stoptweening() end - ---- Immediately finish all tweens left for this actor --- This reaches the final state of the tweens in succession --- @treturn Actor self -function Actor:finishtweening() end - ---- --- @number factor the ratio for the new tween speedup (Or slowdown) --- @treturn Actor self -function Actor:hurrytweening(factor) end - ---- --- @treturn Actor self -function Actor:GetTweenTimeLeft() end - ---- Set this actors horizontal position --- 0 is the left edge of the screen --- @number x The new horizontal position to set --- @treturn Actor self -function Actor:x(x) end - ---- Set this actors vertical position --- 0 is the top edge of the screen --- @number y The new vertical position to set --- @treturn Actor self -function Actor:y(y) end - ---- Set this actors normal position --- @number z The new position to set --- @treturn Actor self -function Actor:z(z) end - ---- Set this actors x and y position easily in one method --- Just for convenience --- @number x The new horizontal position to set --- @number y The new vertical position to set --- @treturn Actor self -function Actor:xy(x, y) end - ---- --- @treturn Actor self -function Actor:addx() end - ---- --- @treturn Actor self -function Actor:addy() end - ---- --- @treturn Actor self -function Actor:addz() end - ---- --- @treturn Actor self -function Actor:zoom() end - ---- --- @treturn Actor self -function Actor:zoomx() end - ---- --- @treturn Actor self -function Actor:zoomy() end - ---- --- @treturn Actor self -function Actor:zoomz() end - ---- --- @treturn Actor self -function Actor:zoomto() end - ---- --- @treturn Actor self -function Actor:zoomtowidth() end - ---- --- @treturn Actor self -function Actor:zoomtoheight() end - ---- --- @treturn Actor self -function Actor:setsize() end - ---- --- @treturn Actor self -function Actor:SetWidth() end - ---- --- @treturn Actor self -function Actor:SetHeight() end - ---- --- @treturn Actor self -function Actor:basealpha() end - ---- --- @treturn Actor self -function Actor:basezoom() end - ---- --- @treturn Actor self -function Actor:basezoomx() end - ---- --- @treturn Actor self -function Actor:basezoomy() end - ---- --- @treturn Actor self -function Actor:basezoomz() end - ---- --- @treturn Actor self -function Actor:stretchto() end - ---- --- @treturn Actor self -function Actor:cropleft() end - ---- --- @treturn Actor self -function Actor:croptop() end - ---- --- @treturn Actor self -function Actor:cropright() end - ---- --- @treturn Actor self -function Actor:cropbottom() end - ---- --- @treturn Actor self -function Actor:fadeleft() end - ---- --- @treturn Actor self -function Actor:fadetop() end - ---- --- @treturn Actor self -function Actor:faderight() end - ---- --- @treturn Actor self -function Actor:fadebottom() end - ---- --- @treturn Actor self -function Actor:diffuse() end - ---- --- @treturn Actor self -function Actor:diffuseupperleft() end - ---- --- @treturn Actor self -function Actor:diffuseupperright() end - ---- --- @treturn Actor self -function Actor:diffuselowerleft() end - ---- --- @treturn Actor self -function Actor:diffuselowerright() end - ---- --- @treturn Actor self -function Actor:diffuseleftedge() end - ---- --- @treturn Actor self -function Actor:diffuserightedge() end - ---- --- @treturn Actor self -function Actor:diffusetopedge() end - ---- --- @treturn Actor self -function Actor:diffusebottomedge() end - ---- --- @treturn Actor self -function Actor:diffusealpha() end - ---- --- @treturn Actor self -function Actor:diffusecolor() end - ---- --- @treturn Actor self -function Actor:glow() end - ---- --- @treturn Actor self -function Actor:aux() end - ---- --- @treturn Actor self -function Actor:getaux() end - ---- --- @treturn Actor self -function Actor:rotationx() end - ---- --- @treturn Actor self -function Actor:rotationy() end - ---- --- @treturn Actor self -function Actor:rotationz() end - ---- --- @treturn Actor self -function Actor:addrotationx() end - ---- --- @treturn Actor self -function Actor:addrotationy() end - ---- --- @treturn Actor self -function Actor:addrotationz() end - ---- --- @treturn Actor self -function Actor:getrotation() end - ---- --- @treturn Actor self -function Actor:baserotationx() end - ---- --- @treturn Actor self -function Actor:baserotationy() end - ---- --- @treturn Actor self -function Actor:baserotationz() end - ---- --- @treturn Actor self -function Actor:skewx() end - ---- --- @treturn Actor self -function Actor:skewy() end - ---- --- @treturn Actor self -function Actor:heading() end - ---- --- @treturn Actor self -function Actor:pitch() end - ---- --- @treturn Actor self -function Actor:roll() end - ---- --- @treturn Actor self -function Actor:shadowlength() end - ---- --- @treturn Actor self -function Actor:shadowlengthx() end - ---- --- @treturn Actor self -function Actor:shadowlengthy() end - ---- --- @treturn Actor self -function Actor:shadowcolor() end - ---- --- @treturn Actor self -function Actor:horizalign() end - ---- --- @treturn Actor self -function Actor:vertalign() end - ---- --- @treturn Actor self -function Actor:halign() end - ---- --- @treturn Actor self -function Actor:valign() end - ---- --- @treturn Actor self -function Actor:diffuseblink() end - ---- --- @treturn Actor self -function Actor:diffuseshift() end - ---- --- @treturn Actor self -function Actor:diffuseramp() end - ---- --- @treturn Actor self -function Actor:glowblink() end - ---- --- @treturn Actor self -function Actor:glowshift() end - ---- --- @treturn Actor self -function Actor:glowramp() end - ---- --- @treturn Actor self -function Actor:rainbow() end - ---- --- @treturn Actor self -function Actor:wag() end - ---- --- @treturn Actor self -function Actor:bounce() end - ---- --- @treturn Actor self -function Actor:bob() end - ---- --- @treturn Actor self -function Actor:pulse() end - ---- --- @treturn Actor self -function Actor:spin() end - ---- --- @treturn Actor self -function Actor:vibrate() end - ---- --- @treturn Actor self -function Actor:stopeffect() end - ---- --- @treturn Actor self -function Actor:effectcolor1() end - ---- --- @treturn Actor self -function Actor:effectcolor2() end - ---- --- @treturn Actor self -function Actor:effectperiod() end - ---- --- @treturn Actor self -function Actor:effecttiming() end - ---- --- @treturn Actor self -function Actor:effect_hold_at_full() end - ---- --- @treturn Actor self -function Actor:effectoffset() end - ---- --- @treturn Actor self -function Actor:effectclock() end - ---- --- @treturn Actor self -function Actor:effectmagnitude() end - ---- --- @treturn Actor self -function Actor:geteffectmagnitude() end - ADD_GET_SET_METHODS(tween_uses_effect_delta); - ---- --- @treturn Actor self -function Actor:scaletocover() end - ---- --- @treturn Actor self -function Actor:scaletofit() end - ---- --- @treturn Actor self -function Actor:animate() end - ---- --- @treturn Actor self -function Actor:play() end - ---- --- @treturn Actor self -function Actor:pause() end - ---- --- @treturn Actor self -function Actor:setstate() end - ---- --- @treturn Actor self -function Actor:GetNumStates() end - ---- --- @treturn Actor self -function Actor:texturetranslate() end - ---- --- @treturn Actor self -function Actor:texturewrapping() end - ---- --- @treturn Actor self -function Actor:SetTextureFiltering() end - ---- --- @treturn Actor self -function Actor:blend() end - ---- --- @treturn Actor self -function Actor:zbuffer() end - ---- --- @treturn Actor self -function Actor:ztest() end - ---- --- @treturn Actor self -function Actor:ztestmode() end - ---- --- @treturn Actor self -function Actor:zwrite() end - ---- --- @treturn Actor self -function Actor:zbias() end - ---- --- @treturn Actor self -function Actor:clearzbuffer() end - ---- --- @treturn Actor self -function Actor:backfacecull() end - ---- --- @treturn Actor self -function Actor:cullmode() end - ---- --- @treturn Actor self -function Actor:visible() end - ---- --- @treturn Actor self -function Actor:hibernate() end - ---- --- @treturn Actor self -function Actor:draworder() end - ---- --- @treturn Actor self -function Actor:playcommand() end - ---- --- @treturn Actor self -function Actor:queuecommand() end - ---- --- @treturn Actor self -function Actor:queuemessage() end - ---- --- @treturn Actor self -function Actor:addcommand() end - ---- --- @treturn Actor self -function Actor:GetCommand() end - ---- --- @treturn Actor self -function Actor:RunCommandsRecursively() end - ---- Get X position (horizontal) --- 0 is leftmost --- @treturn number the horizontal x position. -function Actor:GetX() end - - ---- Get Y position (vertical) --- 0 is topmost --- @treturn number the vertical y position. -function Actor:GetY() end - - ---- Get Z position --- @treturn number the z position. -function Actor:GetZ() end - ---- --- @treturn Actor self -function Actor:GetDestX() end - ---- --- @treturn Actor self -function Actor:GetDestY() end - ---- --- @treturn Actor self -function Actor:GetDestZ() end - ---- --- @treturn Actor self -function Actor:GetWidth() end - ---- --- @treturn Actor self -function Actor:GetHeight() end - ---- --- @treturn Actor self -function Actor:GetZoomedWidth() end - ---- --- @treturn Actor self -function Actor:GetZoomedHeight() end - ---- --- @treturn Actor self -function Actor:GetZoom() end - ---- --- @treturn Actor self -function Actor:GetZoomX() end - ---- --- @treturn Actor self -function Actor:GetZoomY() end - ---- --- @treturn Actor self -function Actor:GetZoomZ() end - ---- --- @treturn Actor self -function Actor:GetRotationX() end - ---- --- @treturn Actor self -function Actor:GetRotationY() end - ---- --- @treturn Actor self -function Actor:GetRotationZ() end - ---- --- @treturn Actor self -function Actor:GetBaseZoomX() end - ---- --- @treturn Actor self -function Actor:GetBaseZoomY() end - ---- --- @treturn Actor self -function Actor:GetBaseZoomZ() end - ---- --- @treturn Actor self -function Actor:GetSecsIntoEffect() end - ---- --- @treturn Actor self -function Actor:GetEffectDelta() end - ---- --- @treturn Actor self -function Actor:GetDiffuse() end - ---- --- @treturn Actor self -function Actor:GetDiffuseAlpha() end - ---- --- @treturn Actor self -function Actor:GetGlow() end - ---- --- @treturn Actor self -function Actor:GetVisible() end - ---- --- @treturn Actor self -function Actor:GetHAlign() end - ---- --- @treturn Actor self -function Actor:GetVAlign() end - - ---- --- @treturn Actor self -function Actor:GetName() end - ---- --- @treturn Actor self -function Actor:GetParent() end - ---- --- @treturn Actor self -function Actor:GetFakeParent() end - ---- --- @treturn Actor self -function Actor:SetFakeParent() end - ---- --- @treturn Actor self -function Actor:AddWrapperState() end - ---- --- @treturn Actor self -function Actor:RemoveWrapperState() end - ---- --- @treturn Actor self -function Actor:GetNumWrapperStates() end - ---- --- @treturn Actor self -function Actor:GetWrapperState() end - - ---- --- @treturn Actor self -function Actor:Draw() end - - ---- --- @treturn Actor self -function Actor:SaveXY() end - ---- --- @treturn Actor self -function Actor:LoadXY() end \ No newline at end of file +--[[ + Returns the number of wrapper states the actor has. + @return ActorFrame +--]] +function Actor:GetNumWrapperStates() +end + +--[[ + Returns the wrapper state at index i. Think of wrapper states with a higher index as being "further out". Actor is inside Wrapper 1, Wrapper 1 is inside Wrapper 2, Wrapper 2 is inside Wrapper 3, and so on. + @return ActorFrame +--]] +function Actor:GetWrapperState(i) +end + +--[[ + Removes the wrapper state at index i. + @return +--]] +function Actor:RemoveWrapperState(int, i) +end + +--[[ + Returns the Actor's parent, or nil if it doesn't have one. + @return Actor +--]] +function Actor:GetParent() +end + +--[[ + Returns the Actor's fake parent, or nil if it doesn't have one. + @return Actor +--]] +function Actor:GetFakeParent() +end + +--[[ + Sets the Actor's fake parent to p, or clears it if p is nil. + @return +--]] +function Actor:SetFakeParent(Actor, p) +end + +--[[ + Returns the Actor's visibility. + @return bool +--]] +function Actor:GetVisible() +end + +--[[ + Returns the Actor's x position. + @return float +--]] +function Actor:GetX() +end + +--[[ + Returns the Actor's y position. + @return float +--]] +function Actor:GetY() +end + +--[[ + Returns the Actor's z position. + @return float +--]] +function Actor:GetZ() +end + +--[[ + Returns what the Actor's x position will be when it reaches its destination tween state. + @return float +--]] +function Actor:GetDestX() +end + +--[[ + Returns what the Actor's y position will be when it reaches its destination tween state. + @return float +--]] +function Actor:GetDestY() +end + +--[[ + Returns what the Actor's z position will be when it reaches its destination tween state. + @return float +--]] +function Actor:GetDestZ() +end + +--[[ + Returns the Actor's zoom. + @return float +--]] +function Actor:GetZoom() +end + +--[[ + Returns the Actor's X zoom. + @return float +--]] +function Actor:GetZoomX() +end + +--[[ + Returns the Actor's Y zoom. + @return float +--]] +function Actor:GetZoomY() +end + +--[[ + Returns the Actor's Z zoom. + @return float +--]] +function Actor:GetZoomZ() +end + +--[[ + Sets Texture Filtering for an Actor to b. + @return void +--]] +function Actor:SetTextureFiltering(bool, b) +end + +--[[ + Plays the commands that follow at an accelerated rate (fRate * fRate), where fRate is in seconds. + @return void +--]] +function Actor:accelerate(float, fRate) +end + +--[[ + Adds a command to the Actor. + @return void +--]] +function Actor:addcommand(string, sName, ActorCommand, cmd) +end + +--[[ + Adds rot to the Actor's current x rotation. + @return void +--]] +function Actor:addrotationx(float, rot) +end + +--[[ + Adds rot to the Actor's current y rotation. + @return void +--]] +function Actor:addrotationy(float, rot) +end + +--[[ + Adds rot to the Actor's current z rotation. + @return void +--]] +function Actor:addrotationz(float, rot) +end + +--[[ + Adds xPos to the Actor's current x position. + @return void +--]] +function Actor:addx(float, xPos) +end + +--[[ + Adds yPos to the Actor's current y position. + @return void +--]] +function Actor:addy(float, yPos) +end + +--[[ + Adds zPos to the Actor's current z position. + @return void +--]] +function Actor:addz(float, zPos) +end + +--[[ + Sets the alignment of an Actor, where h and v are in the range 0..1. + @return void +--]] +function Actor:align(h, v) +end + +--[[ + Sets whether or not the Actor should animate. + @return void +--]] +function Actor:animate(bool, b) +end + +--[[ + Sets the Actor's aux value. (This can be a solution for coupling data with an Actor.) + @return void +--]] +function Actor:aux(float, fAux) +end + +--[[ + If true, cull the Actor's back faces. See also: . + @return void +--]] +function Actor:backfacecull(bool, b) +end + +--[[ + Sets the Actor's base alpha to fAlpha, where fAlpha is in the range 0..1. + @return void +--]] +function Actor:basealpha(float, fAlpha) +end + +--[[ + Sets the Actor's base X rotation to rot. + @return void +--]] +function Actor:baserotationx(float, rot) +end + +--[[ + Sets the Actor's base Y rotation to rot. + @return void +--]] +function Actor:baserotationy(float, rot) +end + +--[[ + Sets the Actor's base Z rotation to rot. + @return void +--]] +function Actor:baserotationz(float, rot) +end + +--[[ + Sets the Actor's base zoom to zoom. + @return void +--]] +function Actor:basezoom(float, zoom) +end + +--[[ + Sets the Actor's base X zoom to zoom. + @return void +--]] +function Actor:basezoomx(float, zoom) +end + +--[[ + Sets the Actor's base Y zoom to zoom. + @return void +--]] +function Actor:basezoomy(float, zoom) +end + +--[[ + Sets the Actor's base Z zoom to zoom. + @return void +--]] +function Actor:basezoomz(float, zoom) +end + +--[[ + Sets the Actor to use the specified blend mode. + @return void +--]] +function Actor:blend(BlendMode, mode) +end + +--[[ + Makes the Actor bob up and down. Can use to define different bobbing behavior. + @return void +--]] +function Actor:bob() +end + +--[[ + Makes the Actor bounce, similar to bob but with one point acting as the ground. Can use to define different bouncing behavior (with effectmagnitude values relating to x, y, and z movement). + @return void +--]] +function Actor:bounce() +end + +--- +function Actor:bounce(time) +end + +--- +function Actor:bouncebegin(time) +end + +--- +function Actor:bounceend(time) +end + +--- Centers an Actor on the screen. (equivalent to x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y) +function Actor:Center(time) +end + +--- Centers an Actor on the X axis. (equivalent to x,SCREEN_CENTER_X) +function Actor:CenterX(time) +end + +--- Centers an Actor on the y axis. (equivalent to y,SCREEN_CENTER_Y) +function Actor:CenterY(time) +end + +--[[ + Determines if the z-buffer should be cleared or not. + @return void +--]] +function Actor:clearzbuffer(bool, bClear) +end + +--[[ + Combines multiple interpolators for complex tweens. tweens + can either be a string like "linear,0.25,accelerate,0.75" or + a table with tween information { {Type="linear", Percent=0.25, Bezier=nil}, {Type="accelerate", Percent=0.75, Bezier=nil} } + @tparam number length + @tparam string tweens + @return void +--]] +function Actor:compound(length, tweens) +end + +--[[ + Crops percent of the Actor from the bottom, where percent is in the range 0..1. + @return void +--]] +function Actor:cropbottom(float, percent) +end + +--[[ + Crops percent of the Actor from the left, where percent is in the range 0..1. + @return void +--]] +function Actor:cropleft(float, percent) +end + +--[[ + Crops percent of the Actor from the right, where percent is in the range 0..1. + @return void +--]] +function Actor:cropright(float, percent) +end + +--[[ + Crops percent of the Actor from the top, where percent is in the range 0..1. + @return void +--]] +function Actor:croptop(float, percent) +end + +--[[ + Sets the Actor's cull mode to mode. + @return void +--]] +function Actor:cullmode(CullMode, mode) +end + +--[[ + Plays the commands that follow at an decelerated rate (1 - (1-fRate) * (1-fRate)), where fRate is in seconds. + @return void +--]] +function Actor:decelerate(float, fRate) +end + +--[[ + Set the Actor's diffuse color to c. + @return void +--]] +function Actor:diffuse(color, c) +end + +--[[ + Sets the Actor's alpha level to fAlpha, where fAlpha is in the range 0..1. + @return void +--]] +function Actor:diffusealpha(float, fAlpha) +end + +--[[ + Makes the Actor switch between two colors immediately. See Themerdocs/effect_colors.txt for an example. + @return void +--]] +function Actor:diffuseblink() +end + +--[[ + Sets the Actor's bottom edge color to c. + @return void +--]] +function Actor:diffusebottomedge() +end + +--[[ + Set the Actor's diffuse color to c, ignoring any alpha value in c. + @return void +--]] +function Actor:diffusecolor(color, c) +end + +--[[ + Sets the Actor's left edge color to c. + @return void +--]] +function Actor:diffuseleftedge(color, c) +end + +--[[ + Sets the Actor's lower left corner color to c. + @return void +--]] +function Actor:diffuselowerleft(color, c) +end + +--[[ + Sets the Actor's lower right corner color to c. + @return void +--]] +function Actor:diffuselowerright(color, c) +end + +--[[ + Makes the Actor switch between two colors, jumping back to the first after reaching the second. See Themerdocs/effect_colors.txt for an example. + @return void +--]] +function Actor:diffuseramp() +end + +--[[ + Sets the Actor's right edge color to c. + @return void +--]] +function Actor:diffuserightedge(color, c) +end + +--[[ + Makes the Actor shift between two colors smoothly. See Themerdocs/effect_colors.txt for an example. + @return void +--]] +function Actor:diffuseshift() +end + +--[[ + Sets the Actor's top edge color to c. + @return void +--]] +function Actor:diffusetopedge(color, c) +end + +--[[ + Sets the Actor's upper left corner color to c. + @return void +--]] +function Actor:diffuseupperleft(color, c) +end + +--[[ + Sets the Actor's upper right corner color to c. + @return void +--]] +function Actor:diffuseupperright(color, c) +end + +--[[ + Tells the Actor to draw itself. + @return void +--]] +function Actor:Draw() +end + +--[[ + Sets the Actor's draworder to iOrder, where larger values display first. + @return void +--]] +function Actor:draworder(int, iOrder) +end + +--[[ + Set the Actor's effect clock to s. + @return void +--]] +function Actor:drop(time) +end + +--[[ + Set the Actor's effect clock to s. + @return void +--]] +function Actor:ease(time, ease) +end + +--[[ + Set the Actor's effect clock to s. + @return void +--]] +function Actor:effectclock(string, s) +end + +--[[ + Sets the first effect color to c. + @return void +--]] +function Actor:effectcolor1(color, c) +end + +--[[ + Sets the second effect color to c. + @return void +--]] +function Actor:effectcolor2(color, c) +end + +--[[ + Set the Actor's effect magnitude in each direction to the given values. + @return void +--]] +function Actor:effectmagnitude(float, fX, float, fY, float, fZ) +end + +--[[ + Set the Actor's effect offset to fTime. The offset is added to the time into the effect before calculating percent_through_effect. + @return void +--]] +function Actor:effectoffset(float, fTime) +end + +--[[ + Set the Actor's effect period to fTime. + @return void +--]] +function Actor:effectperiod(float, fTime) +end + +--[[ + Set the Actor's effect timing.
+ hold_at_zero is before hold_at_full in the argument list for compatibility. A future version will probably swap them because it makes more sense to have hold_at_full come before hold_at_zero.
+ All effect timings must be greater than or equal to zero, at least one of them must be greater than zero.
+ The effect timing controls how long it takes an effect to cycle and how long it spends in each phase.
+ Depending on the effect clock, the actor's time into effect is updated every frame. That time is then translated into a percent_through_effect using the parameters to this function.
+
+ ramp_to_half is the amount of time for percent_through_effect to reach 0.5.
+ hold_at_half is the amount of time percent_through_effect will stay at 0.5.
+ ramp_to_full is the amount of time percent_through_effect will take to go from 0.5 to 1.0.
+ hold_at_full is the amount of time percent_through_effect will stay at 1.0.
+ After reaching the end of hold_at_full, percent_through_effect stays at 0 until hold_at_zero is over.
+
+ The different effects use percent_through_effect in different ways. Some use it to calculate percent_between_colors with this sine wave: sin((percent_through_effect + 0.25f) * 2 * PI ) / 2 + 0.5f
+ Some effects check the internal bool blink_on. blink_on is true if percent_through_effect is greater than 0.5 and false if percent_through_effect is less than or equal to 0.5.
+ Check the effect functions for individual explanations: diffuseblink, diffuseshift, glowblink, glowshift, glowramp, rainbow, wag, bounce, bob, pulse, spin, vibrate. + @return void +--]] +function Actor:effecttiming( + float, + ramp_to_half, + float, + hold_at_half, + float, + ramp_to_full, + float, + hold_at_zero, + float, + hold_at_full) +end + +--[[ + Set the hold_at_full part of the effect timing while leaving the others unchanged. + @return void +--]] +function Actor:effect_hold_at_full(float, hold_at_full) +end + +--[[ + Fades percent of the Actor from the bottom where percent is in the range 0..1. + @return void +--]] +function Actor:fadebottom(float, percent) +end + +--[[ + Fades percent of the Actor from the left where percent is in the range 0..1. + @return void +--]] +function Actor:fadeleft(float, percent) +end + +--[[ + Fades percent of the Actor from the right where percent is in the range 0..1. + @return void +--]] +function Actor:faderight(float, percent) +end + +--[[ + Fades percent of the Actor from the top where percent is in the range 0..1. + @return void +--]] +function Actor:fadetop(float, percent) +end + +--[[ + Finishes up an Actor's tween immediately. + @return void +--]] +function Actor:finishtweening() +end + +--[[ + Stretches an Actor to fill the entire screen. + @return void +--]] +function Actor:FullScreen() +end + +--[[ + Returns the Actor's aux value. + @return float +--]] +function Actor:getaux() +end + +--[[ + Returns the Actor's base X zoom value. + @return float +--]] +function Actor:GetBaseZoomX() +end + +--[[ + Returns the Actor's base Y zoom value. + @return float +--]] +function Actor:GetBaseZoomY() +end + +--[[ + Returns the Actor's base Z zoom value. + @return float +--]] +function Actor:GetBaseZoomZ() +end + +--[[ + Returns true if the Actor has a command named sCmdName. + @return bool +--]] +function Actor:GetCommand(string, sCmdName) +end + +--[[ + Returns the Actor's current diffuse color. + @return color +--]] +function Actor:GetDiffuse() +end + +--[[ + Returns the Actor's current diffusealpha. + @return float +--]] +function Actor:GetDiffuseAlpha() +end + +--[[ + Returns the Actor's current effect delta. + @return float +--]] +function Actor:GetEffectDelta() +end + +--[[ + Returns the Actor's current effect magnitude as three floats (not one; I hate Lua.xsd). + @return float +--]] +function Actor:geteffectmagnitude() +end + +--[[ + Returns the Actor's current glow color. + @return color +--]] +function Actor:GetGlow() +end + +--[[ + Returns the Actor's horizontal alignment as a number in the range 0..1. + @return float +--]] +function Actor:GetHAlign() +end + +--[[ + Returns the Actor's name. + @return string +--]] +function Actor:GetName() +end + +--[[ + Returns the number of states the Actor has. + @return int +--]] +function Actor:GetNumStates() +end + +--[[ + Returns the Actor's current height. + @return float +--]] +function Actor:GetHeight() +end + +--[[ + Returns the Actor's current X rotation. + @return float +--]] +function Actor:GetRotationX() +end + +--[[ + Returns the Actor's current Y rotation. + @return float +--]] +function Actor:GetRotationY() +end + +--[[ + Returns the Actor's current Z rotation. + @return float +--]] +function Actor:GetRotationZ() +end + +--[[ + Returns the number of seconds into the currently running effect (e.g. diffuseshift, bob). + @return float +--]] +function Actor:GetSecsIntoEffect() +end + +--[[ + Returns how much time is remaining for the current tween. + @return float +--]] +function Actor:GetTweenTimeLeft() +end + +--[[ + Returns the Actor's vertical alignment as a number in the range 0..1. + @return float +--]] +function Actor:GetVAlign() +end + +--[[ + Returns the Actor's current width. + @return float +--]] +function Actor:GetWidth() +end + +--[[ + Returns the zoomed height of an Actor. + @return float +--]] +function Actor:GetZoomedHeight() +end + +--[[ + Returns the zoomed width of an Actor. + @return float +--]] +function Actor:GetZoomedWidth() +end + +--[[ + Returns true if this actor is currently set to use the effect delta for tweening. + @return bool +--]] +function Actor:get_tween_uses_effect_delta() +end + +--[[ + Sets the Actor's glow color. + @return void +--]] +function Actor:glow(color, c) +end + +--[[ + Makes the Actor glow between two colors immediately. See Themerdocs/effect_colors.txt for an example. + @return void +--]] +function Actor:glowblink() +end + +--[[ + Makes the Actor glow between two colors smoothly, jumping back to the first at the end. See Themerdocs/effect_colors.txt for an example. + @return void +--]] +function Actor:glowramp() +end + +--[[ + Makes the Actor glow between two colors smoothly. See Themerdocs/effect_colors.txt for an example. + @return void +--]] +function Actor:glowshift() +end + +--[[ + Set the fractional horizontal alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is left aligned while an alignment of 1 is right aligned. See for the common case. + @return void +--]] +function Actor:halign(float, fAlign) +end + +--[[ + Sets the heading of this Actor to fHeading. + @return void +--]] +function Actor:heading(float, fHeading) +end + +--[[ + Hides the Actor for the specified amount of time. + @return void +--]] +function Actor:hibernate(float, fTime) +end + +--[[ + Compatibility alias for the hidden command, which was removed in sm-ssc. Use instead. + @tparam boolean b + @return void +--]] +function Actor:hidden(b) +end + +--[[ + Compatibility alias for the hidden command, which was removed in sm-ssc. Use `visible` instead. + @tparam boolean b + @return void +--]] +function Actor:hide_if(b) +end + +--[[ + Set the horizontal alignment of the Actor according to align. See for fractional alignment. + @return void +--]] +function Actor:horizalign(HorizAlign, align) +end + +--[[ + Hurries up an Actor's tweening by factor. + @return void +--]] +function Actor:hurrytweening(float, factor) +end + +--[[ + Plays the commands that follow at a normal rate, where fRate is in seconds. + @return void +--]] +function Actor:linear(float, fRate) +end + +--[[ + Plays the lyric command for the specified side ("Back" or "Front"). + @tparam string side + @return void +--]] +function Actor:linear(side) +end + +--[[ + Sets the Actor's name to sName. + @return void +--]] +function Actor:name(string, sName) +end + +--[[ + Stops the Actor's movement. (Usually used for Sprites or Models.) + @return void +--]] +function Actor:pause() +end + +--[[ + Sets the pitch of this Actor to fPitch. + @return void +--]] +function Actor:pitch(float, fPitch) +end + +--[[ + Starts the Actor's movement. (Usually used for Sprites or Models.) + @return void +--]] +function Actor:play() +end + +--[[ + Plays a command named sCommandName. params is passed to the command as an argument if it is a table. + @return void +--]] +function Actor:playcommand(string, sCommandName, table, params) +end + +--[[ + Sets the visibility of the Actor based on p being a human player. + @return void +--]] +function Actor:playcommand(playerNumber) +end + +--[[ + Makes the Actor grow and shrink. Can use to define different pulsing behavior. + @return void +--]] +function Actor:pulse() +end + +--[[ + Queues a command named sCommandName to be played. + @return void +--]] +function Actor:queuecommand(string, sCommandName) +end + +--[[ + Basically creates a command named !sMessageName (Note the ! at the beginning. The source code says this: "Hack: use "!" as a marker to broadcast a command, instead of playing a command, so we don't have to add yet another element to every tween state for this rarely-used command.") + @return void +--]] +function Actor:queuemessage(string, sMessageName) +end + +--[[ + Makes the Actor change colors continually using colors of the rainbow. Each channel follows a cosine wave, red starts at 0, green starts at 2pi/3, and blue starts at 4pi/3. + @return void +--]] +function Actor:rainbow() +end + +--[[ + Sets the roll of this Actor to fRoll. + @return void +--]] +function Actor:roll(float, fRoll) +end + +--[[ + Set the Actor's rotation on the X axis to fAlign. + @return void +--]] +function Actor:rotationx(float, fRotation) +end + +--[[ + Set the Actor's rotation on the Y axis to fAlign. + @return void +--]] +function Actor:rotationy(float, fRotation) +end + +--[[ + Set the Actor's rotation on the Z axis to fAlign. + @return void +--]] +function Actor:rotationz(float, fRotation) +end + +--[[ + Set the Actor's rotation on the Z axis to fAlign. + @return void +--]] +function Actor:rotationz(float, fRotation) +end + +--[[ + Set the Actor's rotation on the Z axis to fAlign. + @return void +--]] +function Actor:rotationz(float, fRotation) +end + +--[[ + An alternative version of `scale_or_crop_background` + @return void +--]] +function Actor:scale_or_crop_alternative(float, fRotation) +end + +--[[ + + @return void +--]] +function Actor:scale_or_crop_background(float, fRotation) +end + +--[[ + Scales the Actor to cover a rectangle defined by the four float arguments. + @return void +--]] +function Actor:scaletocover(float, fLeft, float, fTop, float, fRight, float, fBottom) +end + +--[[ + Scales the Actor to fit inside a rectangle defined by the four float arguments. + @return void +--]] +function Actor:scaletofit(float, fLeft, float, fTop, float, fRight, float, fBottom) +end + +--[[ + Sets the height of the Actor. + @return void +--]] +function Actor:SetHeight(float, height) +end + +--[[ + Sets the size of the Actor. + @return void +--]] +function Actor:setsize(width, height) +end + +--[[ + Alias for setsize. + @return void +--]] +function Actor:SetSize(width, height) +end + +--[[ + Sets a multi-framed Actor's state to iNewState. + @return void +--]] +function Actor:setstate(int, iNewState) +end + +--[[ + Sets the width of the Actor. + @return void +--]] +function Actor:SetWidth(float, width) +end + +--[[ + Use this to make the actor use the effect clock to tween instead of using the global frame delta. + @return +--]] +function Actor:set_tween_uses_effect_delta(bool) +end + +--[[ + Sets the shadow's color to c. + @return void +--]] +function Actor:shadowcolor(color, c) +end + +--[[ + Sets the Actor's shadow length to fLength. + @return void +--]] +function Actor:shadowlength(float, fLength) +end + +--[[ + Sets the Actor's horizontal shadow length to fLength. + @return void +--]] +function Actor:shadowlengthx(float, fLength) +end + +--[[ + Sets the Actor's vertical shadow length to fLength. + @return void +--]] +function Actor:shadowlengthy(float, fLength) +end + +--[[ + Skews the Actor on the x axis by fAmount. + @return void +--]] +function Actor:skewx(float, fAmount) +end + +--[[ + Skews the Actor on the y axis by fAmount. + @return void +--]] +function Actor:skewy(float, fAmount) +end + +--[[ + Waits fSeconds before executing the next command. + @return void +--]] +function Actor:sleep(float, fSeconds) +end + +--[[ + + @return void +--]] +function Actor:smooth(time) +end + +--[[ + Tells the Actor to spin. Can use to define different spinning behavior. + @return void +--]] +function Actor:spin() +end + +--[[ + Stops any effect the Actor has. + @return void +--]] +function Actor:stopeffect() +end + +--[[ + Stops any tweening. + @return void +--]] +function Actor:stoptweening() +end + +--[[ + Stretches the Actor to a rectangle of a specific size. + @return void +--]] +function Actor:stretchto(float, x1, float, y1, float, x2, float, y2) +end + +--[[ + Translates the texture of the actor by x and y. + @return void +--]] +function Actor:texturetranslate(float, x, float, y) +end + +--[[ + Determines if the Actor should use texture wrapping or not. + @return void +--]] +function Actor:texturewrapping(bool, bWrap) +end + +--[[ + Uses type to determine the tween to use. The type must be one of the TweenType enum values. If the type is note TweenType_Bezier, the params table is ignored. If the type is TweenType_Bezier, then the params table must have 4 or 8 numbers. 4 numbers in the params creates a 1 dimensional bezier curve, 8 numbers creates a 2 dimensional bezier curve.
+ It's usually more convenient to use Actor:linear, Actor:accelerate, and so on, rather than using Actor:tween directly. + @return void +--]] +function Actor:tween(time, tweentype, params) +end + +--[[ + Set the fractional vertical alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is top aligned while an alignment of 1 is bottom aligned. See for the common case. + @return void +--]] +function Actor:valign(float, fAlign) +end + +--[[ + Set the vertical alignment of the Actor according to align. See for fractional alignment. + @return void +--]] +function Actor:vertalign(VertAlign, align) +end + +--[[ + Makes the Actor vibrate violently. Can use to define different vibration behavior. + @return void +--]] +function Actor:vibrate() +end + +--[[ + Sets an Actor's visibility to b. + @return void +--]] +function Actor:visible(bool, b) +end + +--[[ + Makes the Actor wag. Use to define different wag behavior. + @return void +--]] +function Actor:wag() +end + +--[[ + Set the x position of the Actor to xPos. + @return void +--]] +function Actor:x(float, xPos) +end + +--[[ + Set the y position of the Actor to yPos. + @return void +--]] +function Actor:y(float, yPos) +end + +--[[ + Set the z position of the Actor to zPos. + @return void +--]] +function Actor:z(float, zPos) +end + +--[[ + Sets the z bias to fBias. + @return void +--]] +function Actor:zbias(float, fBias) +end + +--[[ + Enables/disables z-buffer depending on bUse. + @return void +--]] +function Actor:zbuffer(bool, bUse) +end + +--[[ + Zooms the Actor to zoom scale. + @return void +--]] +function Actor:zoom(float, zoom) +end + +--[[ + Zooms the Actor on both the X and Y axis using zoomX and zoomY. + @return void +--]] +function Actor:zoomto(float, zoomX, float, zoomY) +end + +--[[ + Zooms the Actor to zoom height. See also: . + @return void +--]] +function Actor:zoomtoheight(float, zoom) +end + +--[[ + Zooms the Actor to zoom width. See also: . + @return void +--]] +function Actor:zoomtowidth(float, zoom) +end + +--[[ + Zooms the Actor to zoom scale on the X axis. + @return void +--]] +function Actor:zoomx(float, zoom) +end + +--[[ + Zooms the Actor to zoom scale on the Y axis. + @return void +--]] +function Actor:zoomy(float, zoom) +end + +--[[ + Zooms the Actor to zoom scale on the Z axis. + @return void +--]] +function Actor:zoomz(float, zoom) +end + +--[[ + Sets the z testing mode to write on pass if true, turns it off if false + @return void +--]] +function Actor:ztest(bool, bTest) +end + +--[[ + Sets the z testing mode to testMode. + @return void +--]] +function Actor:ztestmode(ZTestMode, testMode) +end + +--[[ + Sets z writing to true or false based on bWrite. + @return void +--]] +function Actor:zwrite(bool, bWrite) +end + +--[[ + Plays the commands that follow using a bezier curve to determine the rate. The curve must have 4 or 8 elements. This is a convenience wrapper around calling Actor:tween with TweenType_Bezier. + @return void +--]] +function Actor:bezier(time, curve) +end + +--[[ + Stretches an Actor to cover the screen. (equivalent to stretchto,0,0,SCREEN_WIDTH,SCREEN_HEIGHT) + @return void +--]] +function Actor:FullScreen() +end + +--[[ + Sets and Actor as a mask destination. + @return void +--]] +function Actor:MaskDest() +end + +--[[ + Sets an Actor as a mask source. (Also clears zbuffer; other mask sources need to not clear the zbuffer) + @return void +--]] +function Actor:MaskSource() +end + +--[[ + Make graphics their true size at any resolution. + @return void +--]] +function Actor:Real(f) +end + +--[[ + Scale things back up after they have already been scaled down. + @return void +--]] +function Actor:RealInverse(f) +end + +--[[ + A customized version of pulse that is more appealing for on-beat effects. + @return void +--]] +function Actor:thump(fEffectPeriod) +end + +--[[ + Sets the x and y location of the Actor in one command. + @return void +--]] +function Actor:xy(float, actorX, float, actorY) +end diff --git a/Themes/_fallback/docs/ActorFrameTexture.luadoc b/Themes/_fallback/docs/ActorFrameTexture.luadoc new file mode 100644 index 0000000000..2c77f0625b --- /dev/null +++ b/Themes/_fallback/docs/ActorFrameTexture.luadoc @@ -0,0 +1,51 @@ +--- ActorFrameTexture (Inherits ActorFrame) +-- @classmod ActorFrameTexture + +--[[-- + Creates the ActorFrameTexture. + @return void +--]] +function ActorFrameTexture:Create() +end + +--[[-- + Enables/disables the Alpha Buffer. + @return void +--]] +function ActorFrameTexture:EnableAlphaBuffer(bool, bEnable) +end + +--[[-- + Enables/disables the Depth Buffer. + @return void +--]] +function ActorFrameTexture:EnableDepthBuffer(bool, bEnable) +end + +--[[-- + Enables/disables + @return void +--]] +function ActorFrameTexture:EnableFloat(bool, bEnable) +end + +--[[-- + Enables/disables the Preserve Texture option. + @return void +--]] +function ActorFrameTexture:EnablePreserveTexture(bool, bEnable) +end + +--[[-- + Returns the texture. + @return RageTexture +--]] +function ActorFrameTexture:GetTexture() +end + +--[[-- + Sets the Texture's name to sName. + @return void +--]] +function ActorFrameTexture:SetTextureName(string, sName) +end diff --git a/Themes/_fallback/docs/ActorMultiVertex.luadoc b/Themes/_fallback/docs/ActorMultiVertex.luadoc new file mode 100644 index 0000000000..eeca14db66 --- /dev/null +++ b/Themes/_fallback/docs/ActorMultiVertex.luadoc @@ -0,0 +1,306 @@ +--- ActorMultiVertex (Inherits `Actor`) +-- @classmod ActorMultiVertex + +--[[-- + The list of quad states is used to determine which animation state is used for each quad. The offset is added to the AMV's current state, and the resulting state is used. + @return +--]] +function ActorMultiVertex:AddQuadState(offset) +end + +--[[-- + Adds an animation state to the ActorMultiVertex. The state_data table must be like this:
+ {{left, top, right, bottom}, delay}
+ left, top, right, and bottom are pixel coordinates, starting at 0. If delay is 0 or negative, the state will last forever. + @return +--]] +function ActorMultiVertex:AddState(table, state_data) +end + +--[[-- + Forces the AMV to update the texture coordinates on all its quads, even if the current state has not changed. + @return +--]] +function ActorMultiVertex:ForceStateUpdate() +end + +--[[-- + Returns whether the AMV uses the animation state. + @return bool +--]] +function ActorMultiVertex:GetUseAnimationState() +end + +--[[-- + Sets whether the AMV uses the animation state.
+ This works best when using DrawMode_Quads.
+ AMV's can have animated textures like sprites. Each state tells the AMV what part of the texture to use, and how long the state lasts.
+ Use AddState to add a state onto the end, or SetStateProperties to set all the states at once, or SetState to set a single state.
+ Each quad has its own offset that is added to the current state. Use AddQuadState to add to the list of quad states, or SetQuadState to set an existing quad state. + @tparam boolean use + @return void +--]] +function ActorMultiVertex:SetUseAnimationState(use) +end + +--[[-- + Returns the number of states the AMV has. + @return int +--]] +function ActorMultiVertex:GetNumStates() +end + +--[[-- + Returns the number of quad states in the destination tween state for the AMV. + @return int +--]] +function ActorMultiVertex:GetNumQuadStates() +end + +--[[-- + Returns the id of the current state. + @return int +--]] +function ActorMultiVertex:GetState() +end + +--[[-- + Gets whether the AMV should call the decode function for its texture during updates. + @return bool +--]] +function ActorMultiVertex:GetDecodeMovie() +end + +--[[-- + Sets whether the AMV should call the decode function for its texture during updates. + @return +--]] +function ActorMultiVertex:SetDecodeMovie(bool, decode) +end + +--[[-- + Sets vertex number index with the properties provided. The tables of properties are each optional and can be provided in any order. + @tparam number index + @tparam table { table pos, table color, table textcoords } + @return void +--]] +function ActorMultiVertex:SetVertex(index, table) +end + +--[[-- + Sets multiple vertices at once. The elements of vertices should themselves be tables, of the form provided to SetVertex. If vertices is the first argument it will start from vertex 1. If an integer is provided before vertices it will start from that vertex. It will add vertices as necessary. + Example: self:SetVertices( { { { x1, y1, z1 } , { r1,g1,b1,a1 } , { tcx1,tcy1 } }; { { x2, y2, z2 } , { r2,g2,b2,a2 } , { tcx2,tcy2 } } } ) + @return void +--]] +function ActorMultiVertex:SetVertices(first, vertices) +end + +--[[-- + Sets all the drawn verts of the ActorMultiVertex by evaluating the splines.
+ ("all the drawn verts" means all the verts between FirstToDraw and NumToDraw, the verts that are set to draw in the current tween state.)
+ The parts of the ActorMultiVertex are evenly spaced along the spline in terms of t value.
+ The exact behavior depends on the draw mode.
+ DrawMode_Quads uses all 4 splines, one for each corner.
+ DrawMode_QuadStrip and DrawMode_Strip use 2 splines, one for each edge of the strip.
+ DrawMode_Fan uses one spline, for the edge verts of the fan. The first vert is not touched because it is the center.
+ DrawMode_Triangles uses 3 splines, one for each corner.
+ DrawMode_SymmetricQuadStrip uses 3 splines, one on each edge and one in the center.
+ DrawMode_LineStrip uses 1 spline.
+ @return +--]] +function ActorMultiVertex:SetVertsFromSplines() +end + +--[[-- + Returns the requested spline. Spline indices range from 1 to 4.
+ ActorMultiVertex splines are not inside the tween state, and will not change the verts until you call SetVertsFromSplines. + @return CubicSplineN +--]] +function ActorMultiVertex:GetSpline(i) +end + +--[[-- + Sets the number of vertices. + @return void +--]] +function ActorMultiVertex:SetNumVertices(num) +end + +--[[-- + Returns the number of vertices + @return void +--]] +function ActorMultiVertex:GetNumVertices(void) +end + +--[[-- + Sets the draw state variables to the values in the table.
+ Mode must be a DrawMode.
+ First is the index of the first vertex to draw.
+ Num is the number of vertices to draw. -1 for Num means draw all verts after First.
+ Any value not in the table defaults to the already set value.
+ Examples:
+ -- Sets all three parts of the draw state.
+ self:SetDrawState{Mode="DrawMode_Quads", First= 1, Num= -1}
+ -- Set only the draw mode. First and Num remain unchanged from previous.
+ self:SetDrawState{Mode="DrawMode_Quads"}
+ -- Set the first and number to draw. Draw mode remains unchanged.
+ self:SetDrawState{First= 3, Num= 4}
+ @tparam table table { Mode= mode, First= first, Num= num } + @return void +--]] +function ActorMultiVertex:SetDrawState(table) +end + +--[[-- + Sets the current state. + @return void +--]] +function ActorMultiVertex:SetState(int) +end + +--[[-- + Returns the offset of the requested quad state. + @return int +--]] +function ActorMultiVertex:GetQuadState(void) +end + +--[[-- + Sets the offset of the requested quad state. + @return void +--]] +function ActorMultiVertex:SetQuadState(id, offset) +end + +--[[-- + Returns a table containing the data for the requested state. + @return table +--]] +function ActorMultiVertex:GetStateData(id) +end + +--[[-- + Sets the requested state to the data in state_data. Similar to AddState, but SetStateData only works on states that have already been added. + @return void +--]] +function ActorMultiVertex:SetStateData(id, table) +end + +--[[-- + Each element of the table must be a state_data and is used to construct one state. The table as a whole is the entire list of all states for the AMV. + @tparam table table {state_data, ...} + @return void +--]] +function ActorMultiVertex:SetStateProperties(table) +end + +--[[-- + Removes the requested state from the state list. +--]] +function ActorMultiVertex:RemoveState(id) +end + +--[[-- + Removes the requested quad state from the quad state list. + @return table +--]] +function ActorMultiVertex:RemoveQuadState(id) +end + +--[[-- + Sets the delay for every state to delay. (seconds) +--]] +function ActorMultiVertex:SetAllStateDelays(delay) +end + +--[[-- + Sets how far into its animation the AMV is. + @return table +--]] +function ActorMultiVertex:SetSecondsIntoAnimation(seconds) +end + +--[[-- + Get the DrawMode of the destination tween state. + @return DrawMode +--]] +function ActorMultiVertex:GetDestDrawMode(void) +end + +--[[-- + Get the FirstToDraw of the destination tween state. + @return int +--]] +function ActorMultiVertex:GetDestFirstToDraw(void) +end + +--[[-- + Get the NumToDraw of the destination tween state. + @return int +--]] +function ActorMultiVertex:GetDestNumToDraw(void) +end + +--[[-- + Get the DrawMode of the current tween state. + @return DrawMode +--]] +function ActorMultiVertex:GetCurrDrawMode(void) +end + +--[[-- + Get the FirstToDraw of the current tween state. + @return int +--]] +function ActorMultiVertex:GetCurrFirstToDraw(void) +end + +--[[-- + Get the NumToDraw of the current tween state. + @return int +--]] +function ActorMultiVertex:GetCurrNumToDraw(void) +end + +--[[-- + Returns the ActorMultiVertex's texture. + @return RageTexture +--]] +function ActorMultiVertex:GetTexture() +end + +--[[-- + Sets the EffectMode of the ActorMultiVertex. + @return void +--]] +function ActorMultiVertex:SetEffectMode(EffectMode, em) +end + +--[[-- + Sets the TextureMode of the ActorMultiVertex. + @return void +--]] +function ActorMultiVertex:SetTextureMode(TextureMode, tm) +end + +--[[-- + Sets the width of the line for DrawMode_LineStrip. + @return void +--]] +function ActorMultiVertex:SetLineWidth(float, width) +end + +--[[-- + Sets the texture to texture + @return void +--]] +function ActorMultiVertex:SetTexture(RageTexture, texture) +end + +--[[-- + Sets the texture at from the file path path. + @return void +--]] +function ActorMultiVertex:LoadTexture(string, path) +end diff --git a/Themes/_fallback/docs/DownloadManager.luadoc b/Themes/_fallback/docs/DownloadManager.luadoc new file mode 100644 index 0000000000..082a113657 --- /dev/null +++ b/Themes/_fallback/docs/DownloadManager.luadoc @@ -0,0 +1,149 @@ +--- DownloadManager singleton +-- @classmod DownloadManager + +--[[-- + Returns the packlist (Which is requested at startup automatically). + @return PackList +--]] +function DownloadManager:GetPacklist() +end + +--[[-- + Returns an indexed table of the currently downloading downloadable packs. + @return {DownloadablePack} +--]] +function DownloadManager:GetDownloadingPacks() +end + +--[[-- + Returns the currently logged in user's username (Or an empty string if not logged in) + @return string +--]] +function DownloadManager:GetUsername() +end + +--[[-- + Returns the currently logged in user's online rank for the provided skillset + @return PackList +--]] +function DownloadManager:GetSkillsetRank(string) +end + +--[[-- + Returns the currently logged in user's online MSD rating for the provided skillset + @return PackList +--]] +function DownloadManager:GetSkillsetRating() +end + +--[[-- + Returns an indexed table with all the currently downloading download tables. + @return {Download} +--]] +function DownloadManager:GetDownloads() +end + +--[[-- + Returns a boolean that indicates if the player is currently logged in to the API server + @return bool +--]] +function DownloadManager:IsLoggedIn() +end + +--[[-- + Begins an asynchronous attempt to login with the provided username (First parameter) and password (Second one) + @return void +--]] +function DownloadManager:Login(string, string) +end + +--[[-- + Begins an asynchronous attempt to login with the provided auth Token + @return void +--]] +function DownloadManager:LoginWithToken(string) +end + +--[[-- + Ends the current session (If it exists) + @return void +--]] +function DownloadManager:Logout() +end + +--[[-- + Returns the string for the latest version (According to the API server) + @return string +--]] +function DownloadManager:GetLastVersion() +end + +--[[-- + Returns the Nth (First parameter) top online score for the given skillset (Second param) + The lua tables for Online Profile Scores are defined here: https://github.com/etternagame/etterna/blob/develop/src/DownloadManager.cpp#L1645-L1659 + TODO: Properly document online profile cores + @return OnlineProfileScore +--]] +function DownloadManager:GetTopSkillsetScore(float, string) +end + +--[[-- + Returns the amount of leaderboard scores for the given chart + @return float +--]] +function DownloadManager:GetTopChartScoreCount(string) +end + +--[[-- + Returns the Nth (Second parameter) top online score for the given skillset (First param) + The lua tables for Online Chart Leaderboard Scores are defined here: https://github.com/etternagame/etterna/blob/develop/src/DownloadManager.cpp#L1686-L1727 + TODO: Properly document online chart leaderboard scores + @return ChartLeaderboardScore +--]] +function DownloadManager:GetTopChartScore(string, float) +end + +--[[-- + Returns the packs in the core bundle in an indexed table. + Additionally, the table has key TotalSize and AveragePackDifficulty + with the appropiate values in it for ease of use. + @return {DownloadablePack} +--]] +function DownloadManager:GetCoreBundle(string) +end + +--[[-- + Queues all the packs in the bundle named after the first parameter for download. + @return void +--]] +function DownloadManager:DownloadCoreBundle(string) +end + +--[[-- + Returns the current Authenthication Token used for the server API. + It is recommended that themes store this to automatically relogin and not the username/password for security reasons. + @return string +--]] +function DownloadManager:GetToken() +end + +--[[-- + Recieves a chartkey, and returns the online leaderboard for that chart. + @return {HighScore} +--]] +function DownloadManager:RequestChartLeaderBoard(string) +end + +--[[-- + RetuSets rate filtering to the boolean passed for the chart leaderboards + @return void +--]] +function DownloadManager:ToggleRateFilter(bool) +end + +--[[-- + Returns true if rate filtering is enabled for the chart leaderboards + @return bool +--]] +function DownloadManager:GetCurrentRateFilter() +end diff --git a/Themes/_fallback/docs/ScreenManager.luadoc b/Themes/_fallback/docs/ScreenManager.luadoc new file mode 100644 index 0000000000..988fbf2529 --- /dev/null +++ b/Themes/_fallback/docs/ScreenManager.luadoc @@ -0,0 +1,101 @@ +--- ScreenManager singleton +-- @classmod ScreenManager + +--[[-- + Adds a screen at the top of the screen stack. (sMessage is an optional ScreenMessage posted once the new screen is finished.) + @return void +--]] +function ScreenManager:AddNewScreenToTop(string, sScreenName, string, sMessage) +end + +--[[-- + Gets the screen at the top of the screen stack. + @return Screen +--]] +function ScreenManager:GetTopScreen() +end + +--[[-- + Returns whether the input for the player has been redirected away from the normal screen input function. Input that has been redirected is only sent to lua input callbacks. + @return bool +--]] +function ScreenManager:get_input_redirected(PlayerNumber, pn) +end + +--[[-- + Plays the invalid sound. + @return +--]] +function ScreenManager:PlayInvalidSound() +end + +--[[-- + Plays the start sound. + @return +--]] +function ScreenManager:PlayStartSound() +end + +--[[-- + Plays the coin sound. + @return +--]] +function ScreenManager:PlayCoinSound() +end + +--[[-- + Plays the cancel sound. + @return +--]] +function ScreenManager:PlayCancelSound() +end + +--[[-- + Plays the screenshot sound. + @return +--]] +function ScreenManager:PlayScreenshotSound() +end + +--[[-- + Reloads any loaded overlay screens. + @return void +--]] +function ScreenManager:ReloadOverlayScreens() +end + +--[[-- + Returns true if screen class s exists. + @return bool +--]] +function ScreenManager:ScreenClassExists(string, s) +end + +--[[-- + Returns true if screen s is prepared. + @return bool +--]] +function ScreenManager:ScreenIsPrepped(string, s) +end + +--[[-- + Sets the next screen to s. + @return void +--]] +function ScreenManager:SetNewScreen(string, s) +end + +--[[-- + Sets whether the input for the player has been redirected away from the normal screen input function. Input that has been redirected is only sent to lua input callbacks.
+ This can be useful when putting a custom menu on a screen, and you want to disable the built in actors while the menu is open. Then you handle input through an input callback until the player closes the menu. + @return bool +--]] +function ScreenManager:set_input_redirected(PlayerNumber, pn, bool, redir) +end + +--[[-- + Broadcasts a system message. + @return void +--]] +function ScreenManager:SystemMessage(string, s) +end diff --git a/Themes/_fallback/docs/SongManager.luadoc b/Themes/_fallback/docs/SongManager.luadoc new file mode 100644 index 0000000000..c4a59162d4 --- /dev/null +++ b/Themes/_fallback/docs/SongManager.luadoc @@ -0,0 +1,275 @@ +--- SongManager singleton +-- @classmod SongManager + +--[[-- + Returns true if the specified course group exists. + @return bool +--]] +function SongManager:DoesCourseGroupExist(string, sGroup) +end + +--[[-- + Returns true if the specified song group exists. + @return bool +--]] +function SongManager:DoesSongGroupExist(string, sGroup) +end + +--[[-- + Returns a Course if one matching sCourse is found. + @return Course +--]] +function SongManager:FindCourse(string, sCourse) +end + +--[[-- + Returns a Song if one matching sSong is found. + @return Song +--]] +function SongManager:FindSong(string, sSong) +end + +--[[-- + Returns an array of all the installed courses. + @return {Course} +--]] +function SongManager:GetAllCourses(bool, bIncludeAutogen) +end + +--[[-- + Returns an array of all the installed songs. + @return {Song} +--]] +function SongManager:GetAllSongs() +end + +--[[-- + Returns the course color of Course c. + @return color +--]] +function SongManager:GetCourseColor(Course, c) +end + +--[[-- + Returns the path to the specified course group's banner. + @return string +--]] +function SongManager:GetCourseGroupBannerPath(string, sGroup) +end + +--[[-- + Returns a table containing all of the course group names. + @return {string} +--]] +function SongManager:GetCourseGroupNames() +end + +--[[-- + Returns a table with all of the courses in the specified group. + @return {Course} +--]] +function SongManager:GetCoursesInGroup(string, sGroup, bool, bIncludeAutogen) +end + +--[[-- + Returns the extra stage info (Song, Steps) for the specified Style s. (If bExtra2 is true, it will use the second Extra Stage data instead of the first. Again, Lua.xsd sucks) + @return various +--]] +function SongManager:GetExtraStageInfo(bool, bExtra2, Style, s) +end + +--[[-- + Returns the number of courses loaded via Additional folders. + @return int +--]] +function SongManager:GetNumAdditionalCourses() +end + +--[[-- + Returns the number of songs loaded via Additional folders. + @return int +--]] +function SongManager:GetNumAdditionalSongs() +end + +--[[-- + Returns the number of course groups. + @return int +--]] +function SongManager:GetNumCourseGroups() +end + +--[[-- + Returns the number of courses. + @return int +--]] +function SongManager:GetNumCourses() +end + +--[[-- + Returns the number of selectable and unlocked songs. + @return int +--]] +function SongManager:GetNumSelectableAndUnlockedSongs() +end + +--[[-- + Returns the number of song groups. + @return int +--]] +function SongManager:GetNumSongGroups() +end + +--[[-- + Returns the number of songs. + @return int +--]] +function SongManager:GetNumSongs() +end + +--[[-- + Returns the number of locked songs, regardless of reason for locking. + @return int +--]] +function SongManager:GetNumLockedSongs() +end + +--[[-- + Returns the number of unlocked songs. + @return int +--]] +function SongManager:GetNumUnlockedSongs() +end + +--[[-- + Returns a table of popular courses for the specified CourseType. + @return {Course} +--]] +function SongManager:GetPopularCourses(CourseType, ct) +end + +--[[-- + Returns a table of popular songs. + @return {Song} +--]] +function SongManager:GetPopularSongs() +end + +--[[-- + Returns a table of courses as they'd appear in preferred sort. + @return {Course} +--]] +function SongManager:GetPreferredSortCourses(CourseType, ct, bool, bIncludeAutogen) +end + +--[[-- + Returns a table of songs as they'd appear in preferred sort. + @return {Song} +--]] +function SongManager:GetPreferredSortSongs() +end + +--[[-- + Returns a random course. + @return Course +--]] +function SongManager:GetRandomCourse() +end + +--[[-- + Returns a random song. + @return Song +--]] +function SongManager:GetRandomSong() +end + +--[[-- + Returns the song color of Song s. + @return color +--]] +function SongManager:GetSongColor(Song, s) +end + +--[[-- + Returns a Song given a set of Steps st. + @return Song +--]] +function SongManager:GetSongFromSteps(Steps, st) +end + +--[[-- + Returns the path to the specified song group's banner. + @return string +--]] +function SongManager:GetSongGroupBannerPath(string, sGroup) +end + +--[[-- + Returns the song group color of sGroupName. + @return color +--]] +function SongManager:GetSongGroupColor(string, sGroupName) +end + +--[[-- + Returns a table containing all of the song group names. + @return {string} +--]] +function SongManager:GetSongGroupNames() +end + +--[[-- + Returns the rank (popularity) of Song s. + @return int +--]] +function SongManager:GetSongRank(Song, s) +end + +--[[-- + Returns a table containing all of the songs in group sGroupName. + @return {Song} +--]] +function SongManager:GetSongsInGroup(string, sGroupName) +end + +--[[-- + Returns the shortened group name (based on entries in Translations.xml). + @return string +--]] +function SongManager:ShortenGroupName(string, sGroupName) +end + +--[[-- + Loads preferred courses from {theme}/Other/SongManager sListName.txt. + @return void +--]] +function SongManager:SetPreferredCourses(string, sListName) +end + +--[[-- + Loads preferred songs from {theme}/Other/SongManager sListName.txt. + @return void +--]] +function SongManager:SetPreferredSongs(string, sListName) +end + +--[[-- + Returns the preferred sort section name for the specified Song. + @return string +--]] +function SongManager:SongToPreferredSortSectionName(Song, s) +end + +--[[-- + Returns true if the specified course was loaded from AdditionalCourses. + @return bool +--]] +function SongManager:WasLoadedFromAdditionalCourses(Course, c) +end + +--[[-- + Returns true if the specified song was loaded from AdditionalSongs. + @return bool +--]] +function SongManager:WasLoadedFromAdditionalSongs(Song, s) +end diff --git a/Themes/_fallback/docs/Sprite.luadoc b/Themes/_fallback/docs/Sprite.luadoc index fba534fcc7..78f3ef705d 100644 --- a/Themes/_fallback/docs/Sprite.luadoc +++ b/Themes/_fallback/docs/Sprite.luadoc @@ -1,112 +1,242 @@ --- Sprite -- @classmod Sprite +--[[-- Returns the length of the animation in seconds. + @return float +--]] +function Sprite:GetAnimationLengthSeconds() +end - ---- --- @treturn Sprite self -function Sprite:Load() end - ---- --- @treturn Sprite self -function Sprite:LoadBanner() end - ---- --- @treturn Sprite self -function Sprite:LoadBackground() end - ---- --- @treturn Sprite self -function Sprite:LoadFromCached() end - ---- --- @treturn Sprite self -function Sprite:customtexturerect() end - ---- --- @treturn Sprite self -function Sprite:SetCustomImageRect() end - ---- --- @treturn Sprite self -function Sprite:SetCustomPosCoords() end - ---- --- @treturn Sprite self -function Sprite:StopUsingCustomPosCoords() end - ---- --- @treturn Sprite self -function Sprite:texcoordvelocity() end - ---- --- @treturn Sprite self -function Sprite:get_use_effect_clock_for_texcoords() end - ---- --- @treturn Sprite self -function Sprite:set_use_effect_clock_for_texcoords() end - ---- --- @treturn Sprite self -function Sprite:scaletoclipped() end - ---- --- @treturn Sprite self -function Sprite:CropTo() end - ---- --- @treturn Sprite self -function Sprite:stretchtexcoords() end - ---- --- @treturn Sprite self -function Sprite:addimagecoords() end - ---- --- @treturn Sprite self -function Sprite:setstate() end - ---- --- @treturn Sprite self -function Sprite:GetState() end - ---- --- @treturn Sprite self -function Sprite:SetStateProperties() end - ---- --- @treturn Sprite self -function Sprite:GetAnimationLengthSeconds() end - ---- --- @treturn Sprite self -function Sprite:SetSecondsIntoAnimation() end - ---- --- @treturn Sprite self -function Sprite:SetTexture() end - ---- --- @treturn Sprite self -function Sprite:GetTexture() end - ---- --- @treturn Sprite self -function Sprite:SetEffectMode() end - ---- --- @treturn Sprite self -function Sprite:GetNumStates() end - ---- --- @treturn Sprite self -function Sprite:SetAllStateDelays() end - ---- --- @treturn Sprite self -function Sprite:GetDecodeMovie() end - ---- --- @treturn Sprite self -function Sprite:SetDecodeMovie() end \ No newline at end of file +--[[-- Gets whether the Sprite should call the decode function for its texture during updates. + @return bool +--]] +function Sprite:GetDecodeMovie() +end + +--[[-- Return the number of states this Sprite has. + @return int +--]] +function Sprite:GetNumStates() +end + +--[[-- Returns the Sprite's current state (frame number in a multi-frame sprite). + @return int +--]] +function Sprite:GetState() +end + +--[[-- Returns the Sprite's texture. + @return RageTexture +--]] +function Sprite:GetTexture() +end + +--[[-- Returns a Frames table consisting of iNumFrames frames lasting for a total of fSeconds seconds. This function is not a member function and should be used as Frames = Sprite.LinearFrames( 5, 2.6 ). + @return Frames +--]] +function Sprite:LinearFrames() +end + +--[[-- If sPath is nil, then unload the texture. Otherwise, load the texture at path sPath. + @return void +--]] +function Sprite:Load(string, sPath) +end + +--[[-- Load the song background texture at sPath. + @return void +--]] +function Sprite:LoadBackground(string, sPath) +end + +--[[-- Load the song banner texture at sPath. + @return void +--]] +function Sprite:LoadBanner(string, sPath) +end + +--[[-- Loads the image of type sType from the cache based on sPath. + Internal types: "Banner", "Background", "CDTitle", "Jacket", "CDImage" and "Disc". + @return void +--]] +function Sprite:LoadFromCached(string, sType, string, sPath) +end + +--[[-- Loads the background from the current Song or the first Trail entry. + @return void +--]] +function Sprite:LoadFromCurrentSongBackground() +end + +--[[-- Load the texture for `Song` background. + @tparam Song song + @return void +--]] +function Sprite:LoadFromSongBackground(song) +end + +--[[-- Load the texture for `Song` banner. + @tparam Song song + @return void +--]] +function Sprite:LoadFromSongBanner(song) +end + +--[[-- Sets the custom image rectangle. (Works in image pixel space.) + @return void +--]] +function Sprite:SetCustomImageRect(float, fLeft, float, fTop, float, fRight, float, fBottom) +end + +--[[-- Sets custom offsets for the corners of the Sprite. Coordinates are paired, + corner order is upper left, lower left, lower right, upper right. + @return void +--]] +function Sprite:SetCustomPosCoords( + float, + ulx, + float, + uly, + float, + llx, + float, + lly, + float, + lrx, + float, + lry, + float, + urx, + float, + ury) +end + +--[[-- Turns off the custom pos coords for the sprite. + @return void +--]] +function Sprite:StopUsingCustomPosCoords() +end + +--[[-- Sets whether the Sprite should call the decode function for its texture during updates. + @return +--]] +function Sprite:SetDecodeMovie(bool, decode) +end + +--[[-- Set the to mode. + @return void +--]] +function Sprite:SetEffectMode(EffectMode, mode) +end + +--[[-- Sets the number of seconds into the animation to fSeconds. + @return void +--]] +function Sprite:SetSecondsIntoAnimation(float, fSeconds) +end + +--[[-- Sets the properties of the states of the sprite. The properties table is identical to the "Frames" table that can be put in the sprite when calling Def.Sprite.
+ Example:
+ {{Frame= 0, Delay= .016, {0, 0}, {.25, .25}},
+ {Frame= 1, Delay= .016, {0, 0}, {.25, .25}},
+ {Frame= 2, Delay= .016, {0, 0}, {.25, .25}},
+ {Frame= 3, Delay= .016, {0, 0}, {.25, .25}},
+ }
+ Frame is optional, defaulting to 0.
+ Delay is optional, defaulting to 0.
+ The two tables are optional upper left and lower right corners of the fraction of the frame to use. The example makes the sprite only use the upper left corner of each frame.
+ Simpler example:
+ {{Frame= 0, Delay= .016}, {Frame= 1, Delay= .016}, {Frame= 2, Delay= .016}, {Frame= 3, Delay= .016}}
+ This example makes the sprite use the whole of each frame. + @return void +--]] +function Sprite:SetStateProperties(table) +end + +--[[-- Set the texture to texture. + @return void +--]] +function Sprite:SetTexture(RageTexture, texture) +end + +--[[-- + @return void +--]] +function Sprite:addimagecoords(float, fX, float, fY) +end + +--[[-- Allows the themer to set a custom texture rectangle that effects the way the texture is drawn. + @return void +--]] +function Sprite:customtexturerect(float, fLeft, float, fTop, float, fRight, float, fBottom) +end + +--[[-- Returns true if the sprite is using the effect clock for texcoordvelocity. + @return bool +--]] +function Sprite:get_use_effect_clock_for_texcoords() +end + +--[[-- Call loop on the `RageTexture` + @return bool +--]] +function Sprite:loop(bLoop) +end + +--[[-- Call position on the `RageTexture` + @return bool +--]] +function Sprite:position(fPos) +end + +--[[-- Call rate on the `RageTexture` + @return bool +--]] +function Sprite:rate(fRate) +end + +--[[-- Scale the Sprite to width fWidth and height fHeight clipping if the dimensions do not match. + @return void +--]] +function Sprite:scaletoclipped(float, fWidth, float, fHeight) +end + +--[[-- Set the Sprite's state to iNewState. + @return void +--]] +function Sprite:setstate(iNewState) +end + +--[[-- If use is true, then the sprite will use the effect clock for texcoordvelocity. + @return +--]] +function Sprite:set_use_effect_clock_for_texcoords(bool, use) +end + +--[[-- + @return void +--]] +function Sprite:stretchtexcoords(float, fX, float, fY) +end + +--[[-- Set the texture coordinate velocity which controls how the Sprite changes as it animates. A velocity of 1 makes the texture scroll all the way once per second. + @return void +--]] +function Sprite:texcoordvelocity(float, fVelX, float, fVelY) +end + +--[[-- Crops the Sprite to fWidthxfHeight. + @return void +--]] +function Sprite:CropTo(float, fWidth, float, fHeight) +end + +--- Alias for CropTo +function Sprite:cropto(float, fWidth, float, fHeight) +end + +--[[-- Sets all the state delays to fRate. Useful for Sprites that need to change by BPM (e.g. Tran from DDR 5th Mix, the cube from DS EuroMix 2). + @return void +--]] +function Sprite:SetAllStateDelays(float, fRate) +end From 55ed90bee8fdb113b1ecf53063afbcfc3ab8a81d Mon Sep 17 00:00:00 2001 From: poco0317 Date: Wed, 28 Nov 2018 16:48:31 -0600 Subject: [PATCH 114/320] Fix broken eval screen when watching replay for file without scores --- .../BGAnimations/ScreenEvaluation decorations/scoreboard.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua b/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua index 3a9a9ff210..96adee720c 100644 --- a/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenEvaluation decorations/scoreboard.lua @@ -44,6 +44,9 @@ if GAMESTATE:IsPlayerEnabled(player) then origTable = getScoresByKey(player) score = STATSMAN:GetCurStageStats():GetPlayerStageStats(player):GetHighScore() rtTable = getRateTable(origTable) + if rtTable == nil then + return + end hsTable = rtTable[getRate(score)] or {score} scoreIndex = getHighScoreIndex(hsTable, score) end From 79dd2d13e483faf91bbb7e32232b9977b481b27f Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Wed, 28 Nov 2018 20:10:14 -0300 Subject: [PATCH 115/320] Fill m_sSongFileName for .osu files This fixes multiplayer and possibly some other issues --- src/NotesLoaderOSU.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/NotesLoaderOSU.cpp b/src/NotesLoaderOSU.cpp index c7d23a432f..23f8254249 100644 --- a/src/NotesLoaderOSU.cpp +++ b/src/NotesLoaderOSU.cpp @@ -112,6 +112,7 @@ OsuLoader::SetMetadata(map> parsedData, Song& out) { // set metadata values auto& metadata = parsedData["Metadata"]; + out.m_sSongFileName = metadata["Title"]; out.m_sMainTitle = metadata["Title"]; out.m_sSubTitle = metadata["Version"]; out.m_sArtist = metadata["Artist"]; From e6092c4a1b6f32dc822c335c3ce74a2785996d0a Mon Sep 17 00:00:00 2001 From: poco0317 Date: Wed, 28 Nov 2018 17:48:17 -0600 Subject: [PATCH 116/320] Clarify REEEEEE block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ┬──┬◡ノ(° -°ノ) --- src/ScreenSelectMusic.cpp | 56 +++++++++++++++------------------------ 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 6dd074f473..d8b773b378 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1709,9 +1709,10 @@ class LunaScreenSelectMusic : public Luna GAMESTATE->SetProcessedTimingData( GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData()); auto* td = GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData(); - vector ihatemylife; + // vector ihatemylife; auto nd = GAMESTATE->m_pCurSteps[PLAYER_1]->GetNoteData(); - auto nerv = nd.BuildAndGetNerv(); + auto nerv = nd.BuildAndGetNerv(); + /* functionally dead code, may be removed -poco if (!hs->GetChordCohesion()) { for (auto r : nerv) for (int i = 0; i < nd.GetNumTapNotesInRow(r); ++i) @@ -1719,40 +1720,25 @@ class LunaScreenSelectMusic : public Luna } else { for (auto r : nerv) ihatemylife.emplace_back(r); - } - auto REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = td->BuildAndGetEtaner(nerv); - vector REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; - for (auto t : timestamps) { - auto REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = - td->GetBeatFromElapsedTime(t * hs->GetMusicRate()); - auto REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE[0] - (timestamps[0] * hs->GetMusicRate()); - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE += - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; - auto - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = - BeatToNoteRow( - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE); - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.emplace_back( - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE); - } - int - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE = - nerv[0] - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE[0]; - for (auto& REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE : - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE) - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE += - REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE; + } + */ + auto sdifs = td->BuildAndGetEtaner(nerv); + vector noterows; + for (auto t : timestamps) { + auto timestamptobeat = + td->GetBeatFromElapsedTime(t * hs->GetMusicRate()); + auto somenumberscaledbyoffsets = + sdifs[0] - (timestamps[0] * hs->GetMusicRate()); + timestamptobeat += somenumberscaledbyoffsets; + auto noterowfrombeat = BeatToNoteRow(timestamptobeat); + noterows.emplace_back(noterowfrombeat); + } + int noterowoffsetter = nerv[0] - noterows[0]; + for (auto& noterowwithoffset : noterows) + noterowwithoffset += noterowoffsetter; GAMESTATE->SetProcessedTimingData(nullptr); - hs->SetNoteRowVector(ihatemylife); - hs->SetNoteRowVector(REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE); - - for (size_t i = 0; i < ihatemylife.size(); ++i) - { - //LOG->Warn("REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE%i, %i", - // ihatemylife[i], - // REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE[i]); - } + //hs->SetNoteRowVector(ihatemylife); + hs->SetNoteRowVector(noterows); } PlayerAI::SetScoreData(hs); From f54d91fd09cb9d49b92394c893e50e2fcd0b4b56 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Wed, 28 Nov 2018 17:50:58 -0600 Subject: [PATCH 117/320] Fix 180ms bads counting as bads instead of misses in replays --- src/ScreenSelectMusic.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index d8b773b378..7022bef692 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1738,7 +1738,15 @@ class LunaScreenSelectMusic : public Luna noterowwithoffset += noterowoffsetter; GAMESTATE->SetProcessedTimingData(nullptr); //hs->SetNoteRowVector(ihatemylife); - hs->SetNoteRowVector(noterows); + hs->SetNoteRowVector(noterows); + + // Since we keep misses on EO as 180ms, we need to convert them back. + auto offsets = hs->GetCopyOfOffsetVector(); + for (auto& offset : offsets) { + if (fabs(offset) >= .18f) + offset = -1.1f; // This is a miss to the replay reader. + } + hs->SetOffsetVector(offsets); } PlayerAI::SetScoreData(hs); From 5da2462f52e2bc5f85eeb7d8d458984558c67004 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Wed, 28 Nov 2018 17:51:35 -0600 Subject: [PATCH 118/320] Improve bad logic for negative noterows in replay data for early first hits, the note still flies past the receptors but it gets scored --- src/PlayerAI.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index d03c27c265..e2b757790f 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -344,17 +344,17 @@ PlayerAI::GetTapsAtOrBeforeRow(int noteRow) // 2 is a replay with column data if (pScoreData->GetReplayType() == 2) { - auto rowIt = m_ReplayExactTapMap.lower_bound(0); + auto rowIt = m_ReplayExactTapMap.lower_bound(-100); int row = rowIt->first; - for (; row <= noteRow && row != -1;) { + for (; row <= noteRow && row != -100;) { vector toMerge = GetTapsToTapForRow(row); output.insert(output.end(), toMerge.begin(), toMerge.end()); row = GetNextRowNoOffsets(row); } } else { - auto rowIt = m_ReplayTapMap.lower_bound(0); + auto rowIt = m_ReplayTapMap.lower_bound(-100); int row = rowIt->first; - for (; row <= noteRow && row != -1;) { + for (; row <= noteRow && row != -100;) { vector toMerge = GetTapsToTapForRow(row); output.insert(output.end(), toMerge.begin(), toMerge.end()); row = GetNextRowNoOffsets(row); @@ -398,7 +398,7 @@ PlayerAI::GetNextRowNoOffsets(int currentRow) auto thing = m_ReplayExactTapMap.lower_bound(currentRow + 1); if (thing == m_ReplayExactTapMap.end()) { - return -1; + return -100; } else { return thing->first; } @@ -406,7 +406,7 @@ PlayerAI::GetNextRowNoOffsets(int currentRow) auto thing = m_ReplayTapMap.lower_bound(currentRow + 1); if (thing == m_ReplayTapMap.end()) { - return -1; + return -100; } else { return thing->first; } From 3c3a5dbef56f5979f2f900241e460dca24782d64 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 21:25:27 -0500 Subject: [PATCH 119/320] dont let cache load ungrouped songs --- src/SongManager.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 5e181973f6..9dd55077a1 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -162,7 +162,6 @@ SongManager::DifferentialReloadDir(string dir) GetDirListing(dir + "*", folders, true); StripCvsAndSvn(folders); StripMacResourceForks(folders); - SortRStringArray(folders); vector groups; Group unknownGroup("Unknown Group"); @@ -179,7 +178,6 @@ SongManager::DifferentialReloadDir(string dir) GetDirListing(dir + folder + "/*", songdirs, true, true); StripCvsAndSvn(songdirs); StripMacResourceForks(songdirs); - SortRStringArray(songdirs); Group group(folder); for (auto& song : songdirs) { group.songs.emplace_back(SongDir(song)); @@ -285,6 +283,10 @@ split(vector& v, size_t elementsPerThread) void SongManager::FinalizeSong(Song* pNewSong, const RString& dir) { + // never load stray songs from the cache -mina + if (pNewSong->m_sGroupName == "Songs" || + pNewSong->m_sGroupName == "AdditionalSongs") + return; SONGMAN->AddSongToList(pNewSong); SONGMAN->AddKeyedPointers(pNewSong); SONGMAN->m_mapSongGroupIndex[pNewSong->m_sGroupName].emplace_back(pNewSong); @@ -765,7 +767,6 @@ SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) GetDirListing(sDir + "*", songFolders, true); StripCvsAndSvn(songFolders); StripMacResourceForks(songFolders); - SortRStringArray(songFolders); int songCount = 0; if (ld != nullptr) { ld->SetIndeterminate(false); @@ -777,6 +778,10 @@ SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) int foldersChecked = 0; int onePercent = std::max(static_cast(songFolders.size() / 100), 1); for (const auto& folder : songFolders) { + // inefficiency here when loading from cache, the check to see if we've + // already loaded a song is 40 lines down and run after issongdir, + // ideally we wouldnt need to run issongdir on anything we already know + // is a group or anything we already know is a song -mina if (IsSongDir(sDir + folder)) { auto s = SongDir(sDir + folder); unknownGroup.songs.emplace_back(s); @@ -786,7 +791,6 @@ SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) GetDirListing(sDir + folder + "/*", songPaths, true, true); StripCvsAndSvn(songPaths); StripMacResourceForks(songPaths); - SortRStringArray(songPaths); for (auto& song : songPaths) { group.songs.emplace_back(SongDir(song)); } @@ -830,7 +834,7 @@ SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) SongPointerVector& index_entry = SONGMAN->m_mapSongGroupIndex[sGroupName]; RString group_base_name = sGroupName; - for (auto sSongDirName : arraySongDirs) { + for (auto& sSongDirName : arraySongDirs) { RString hur = sSongDirName.path + "/"; hur.MakeLower(); if (SONGMAN->m_SongsByDir.count(hur)) From 3ea88b29e3bca35fc8810c1069ef6d35f4315bbd Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Wed, 28 Nov 2018 23:32:20 -0300 Subject: [PATCH 120/320] Fix the filter helper function --- Themes/_fallback/Scripts/01 Functional.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/_fallback/Scripts/01 Functional.lua b/Themes/_fallback/Scripts/01 Functional.lua index 10f38a7d17..eb75fe67c2 100644 --- a/Themes/_fallback/Scripts/01 Functional.lua +++ b/Themes/_fallback/Scripts/01 Functional.lua @@ -22,7 +22,7 @@ function filter(func, tbl) local newtbl = {} for i, v in pairs(tbl) do if func(v) then - newtbl[i] = v + newtbl[#newtbl+1] = v end end return newtbl From 9f51065d9ba066bdda0edbcd69ebf8d7d7910683 Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Wed, 28 Nov 2018 23:38:35 -0300 Subject: [PATCH 121/320] Fix searching and filtering on the Lua Packlist --- .../ScreenPackDownloader underlay.lua | 2 -- .../BGAnimations/packlistDisplay.lua | 3 +- Themes/_fallback/Scripts/09 PackList.lua | 33 +++++++++++++++---- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenPackDownloader underlay.lua b/Themes/Til Death/BGAnimations/ScreenPackDownloader underlay.lua index 62fda7f542..8e58e09a0e 100644 --- a/Themes/Til Death/BGAnimations/ScreenPackDownloader underlay.lua +++ b/Themes/Til Death/BGAnimations/ScreenPackDownloader underlay.lua @@ -3,7 +3,6 @@ local filters = {"", "0", "0", "0", "0", "0", "0"} local curInput = "" local inputting = 0 --1=name 2=lowerdiff 3=upperdiff 4=lowersize 5=uppersize 0=none -local packlist local function getFilter(index) return filters[index] @@ -165,7 +164,6 @@ local o = InitCommand = function(self) self:xy(0, 0):halign(0.5):valign(0) self:GetChild("PacklistDisplay"):xy(SCREEN_WIDTH / 2.5 - offx, offy * 2 + 14) - packlist = DLMAN:GetPacklist() self:SetUpdateFunction(highlight) end, BeginCommand = function(self) diff --git a/Themes/Til Death/BGAnimations/packlistDisplay.lua b/Themes/Til Death/BGAnimations/packlistDisplay.lua index cc7850f7df..3f8488d1f0 100644 --- a/Themes/Til Death/BGAnimations/packlistDisplay.lua +++ b/Themes/Til Death/BGAnimations/packlistDisplay.lua @@ -31,7 +31,7 @@ local function highlightIfOver(self) end end -local packlist +packlist = {} local packtable local o = Def.ActorFrame { @@ -42,7 +42,6 @@ local o = BeginCommand = function(self) self:SetUpdateFunction(highlight) packlist = PackList:new() - packlist:SetFromAll() self:queuecommand("PackTableRefresh") end, PackTableRefreshCommand = function(self) diff --git a/Themes/_fallback/Scripts/09 PackList.lua b/Themes/_fallback/Scripts/09 PackList.lua index d4e45ba61b..4e00133c2a 100644 --- a/Themes/_fallback/Scripts/09 PackList.lua +++ b/Themes/_fallback/Scripts/09 PackList.lua @@ -53,20 +53,39 @@ function PackList:SortBySize() return self:SortByProp(getSizePropName) end function PackList:FilterAndSearch(name, avgMin, avgMax, sizeMin, sizeMax) - self.packs = + self.packs = filter( function(x) - local d = x[getAvgDiffPropName]:x() - local n = x[getNamePropName]:x() - local s = x[getSizePropName]:x() - return n == name and ((d > avgMin and d < avgMax) or d <= 0) and ((s > sizeMin and d < sizeMax) or s <= 0) + local d = x[getAvgDiffPropName](x) + local n = x[getNamePropName](x) + local s = x[getSizePropName](x) + local valid = string.lower(n):sub(1, #name) == string.lower(name) + if d > 0 then + if avgMin > 0 then + valid = valid and d > avgMin + end + if avgMax > 0 then + valid = valid and d < avgMax + end + end + if s > 0 then + if sizeMin > 0 then + valid = valid and s > sizeMin + end + if sizeMax > 0 then + valid = valid and s < sizeMax + end + end + return valid end, - self.packs + self.allPacks ) return self end function PackList:SetFromAll() - self.packs = DLMAN:GetAllPacks() + local allPacks = DLMAN:GetAllPacks() + self.allPacks = allPacks + self.packs = DeepCopy(allPacks) return self end function PackList:new() From b3fd361bc8c88df6278db1076f298c539a70cfef Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 21:45:23 -0500 Subject: [PATCH 122/320] use find instead of sub/== for pack searches --- Themes/_fallback/Scripts/09 PackList.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/_fallback/Scripts/09 PackList.lua b/Themes/_fallback/Scripts/09 PackList.lua index 4e00133c2a..896148234e 100644 --- a/Themes/_fallback/Scripts/09 PackList.lua +++ b/Themes/_fallback/Scripts/09 PackList.lua @@ -59,7 +59,7 @@ function PackList:FilterAndSearch(name, avgMin, avgMax, sizeMin, sizeMax) local d = x[getAvgDiffPropName](x) local n = x[getNamePropName](x) local s = x[getSizePropName](x) - local valid = string.lower(n):sub(1, #name) == string.lower(name) + local valid = string.find(string.lower(n), string.lower(name)) if d > 0 then if avgMin > 0 then valid = valid and d > avgMin From 3d654caf97e4e531de879a82c423e3f6b7dffc31 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Wed, 28 Nov 2018 21:31:36 -0600 Subject: [PATCH 123/320] Fix "missing" sound files due to ScreenNetSelectMusic inheritance change --- Themes/_fallback/Sounds/ScreenNetSelectMusic change opt.redir | 1 + Themes/_fallback/Sounds/ScreenNetSelectMusic change sel.redir | 1 + 2 files changed, 2 insertions(+) create mode 100644 Themes/_fallback/Sounds/ScreenNetSelectMusic change opt.redir create mode 100644 Themes/_fallback/Sounds/ScreenNetSelectMusic change sel.redir diff --git a/Themes/_fallback/Sounds/ScreenNetSelectMusic change opt.redir b/Themes/_fallback/Sounds/ScreenNetSelectMusic change opt.redir new file mode 100644 index 0000000000..5c93a18f43 --- /dev/null +++ b/Themes/_fallback/Sounds/ScreenNetSelectMusic change opt.redir @@ -0,0 +1 @@ +Common value diff --git a/Themes/_fallback/Sounds/ScreenNetSelectMusic change sel.redir b/Themes/_fallback/Sounds/ScreenNetSelectMusic change sel.redir new file mode 100644 index 0000000000..5c93a18f43 --- /dev/null +++ b/Themes/_fallback/Sounds/ScreenNetSelectMusic change sel.redir @@ -0,0 +1 @@ +Common value From 16232b4bdec5d94a3d1891acd419b414030b2fc8 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 22:23:50 -0500 Subject: [PATCH 124/320] hide chatoverlay on init --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 80e9ca10a1..bba08c0a6c 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -65,6 +65,7 @@ end local i = 0 chat.InitCommand = function(self) online = IsNetSMOnline() and IsSMOnlineLoggedIn(PLAYER_1) and NSMAN:IsETTP() + self:visible(false); end chat.AddMPChatInputMessageCommand = function(self) local s = SCREENMAN:GetTopScreen() From 19bbc4b29e944cf2a1ebce44853f5772c733ab2c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 22:29:27 -0500 Subject: [PATCH 125/320] he who borps the loudest dorps the farthest --- .../ScreenSelectMusic decorations/wifeTwirl.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 326dcdf839..794e8208b9 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -54,6 +54,7 @@ local t = MESSAGEMAN:Broadcast("ChartPreviewOn") if boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone then song:Borp() + boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone = false end heyiwasusingthat = false end @@ -140,7 +141,10 @@ local function toggleNoteField() else mcbootlarder:visible(true) mcbootlarder:GetChild("NoteField"):visible(true) - song:Borp() + if boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone then + song:Borp() + boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone = false + end MESSAGEMAN:Broadcast("ChartPreviewOn") end end From 460f3a19f4e3667cee660b7f4afbda412b7f2adb Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Thu, 29 Nov 2018 01:13:44 -0300 Subject: [PATCH 126/320] Use the new packlist for the select bundle screen --- .../BGAnimations/ScreenBundleSelect underlay.lua | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenBundleSelect underlay.lua b/Themes/Til Death/BGAnimations/ScreenBundleSelect underlay.lua index 45b75e936f..8fa4372eec 100644 --- a/Themes/Til Death/BGAnimations/ScreenBundleSelect underlay.lua +++ b/Themes/Til Death/BGAnimations/ScreenBundleSelect underlay.lua @@ -68,7 +68,7 @@ local packgap = 4 local packspacing = packh + packgap local offx = 10 local offy = 40 -local packlist +local packtable local ind = 0 local o = @@ -76,7 +76,7 @@ local o = InitCommand = function(self) self:xy(offx + width / 2, 0):halign(0.5):valign(0) self:GetChild("PacklistDisplay"):xy(SCREEN_WIDTH / 2.5 - offx - (offx + width / 2), offy * 2 + 14):visible(false) --- uuuu messy... basically cancel out the x coord of the parent - packlist = DLMAN:GetPacklist() + packlist = PackList:new() self:SetUpdateFunction(highlight) end, BeginCommand = function(self) @@ -126,7 +126,7 @@ local o = self:xy(width / 2 + offx, offy * 2):zoom(tzoom + 0.1):halign(0):maxwidth(width / 2 / tzoom) end, PackTableRefreshCommand = function(self) - self:settextf("Average Difficulty: %0.2f", packlist:GetAvgDiff()):diffuse(byMSD(packlist:GetAvgDiff())) + self:settextf("Average Difficulty: %0.2f", packtable.AveragePackDifficulty):diffuse(byMSD(packtable.AveragePackDifficulty)) end }, LoadFont("Common normal") .. @@ -136,7 +136,7 @@ local o = self:xy(width * 2 + width / 2 - 150, offy * 2):zoom(tzoom + 0.1):halign(1):maxwidth(width / 2 / tzoom) end, PackTableRefreshCommand = function(self) - self:settextf("Total Size: %i(MB)", packlist:GetTotalSize()):diffuse(byFileSize(packlist:GetTotalSize())) + self:settextf("Total Size: %i(MB)", packtable.TotalSize):diffuse(byFileSize(packtable.TotalSize)) end }, LoadFont("Common normal") .. @@ -212,6 +212,7 @@ local function makedoots(i) MouseLeftClickMessageCommand = function(self) if isOver(self) then packlist:SetFromCoreBundle(minidoots[i]:lower()) + packtable = packlist:GetPackTable() self:GetParent():GetParent():queuecommand("PackTableRefresh") -- perhaps it would be best if the packlist broadcast instead - mina self:GetParent():GetParent():visible(true):GetChild("PacklistDisplay"):visible(true) ind = i From 5ba071e766aee1f0e84bcc2ac5a6cbcedeab1c0a Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Wed, 28 Nov 2018 23:41:40 -0500 Subject: [PATCH 127/320] purge all smo interface code and properly fallback to ssm with netselect --- .../ScreenNetRoom overlay/default.lua | 1 - .../currentsort.lua | 59 -- .../currenttime.lua | 38 - .../ScreenNetSelectBase overlay/default.lua | 59 -- .../wifesearchbar.lua | 265 ------- .../ScreenNetSelectMusic decorations.lua | 10 + .../default.lua | 190 ----- .../dumbrate.lua | 177 ----- .../onlinebpm.lua | 42 -- .../radaronline.lua | 145 ---- .../ScreenNetSelectMusic decorations/tabs.lua | 152 ---- .../wifeonline.lua | 697 ------------------ .../ScreenNetSelectMusic decorations/yolo.lua | 205 ------ .../ScreenNetSelectMusic overlay.lua | 3 + .../ScreenSelectMusic overlay/default.lua | 13 - Themes/Til Death/BGAnimations/_PlayerInfo.lua | 6 + Themes/Til Death/BGAnimations/_userlist.lua | 2 +- 17 files changed, 20 insertions(+), 2044 deletions(-) delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currentsort.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currenttime.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/default.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/wifesearchbar.lua create mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/dumbrate.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/onlinebpm.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/radaronline.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/tabs.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/wifeonline.lua delete mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/yolo.lua create mode 100644 Themes/Til Death/BGAnimations/ScreenNetSelectMusic overlay.lua diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua index 82545875d7..1fba2ead08 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua @@ -22,7 +22,6 @@ local t = Def.ActorFrame { OnCommand = function(self) SCREENMAN:GetTopScreen():AddInputCallback(input) - SCREENMAN:GetTopScreen():UsersVisible(false) end } diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currentsort.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currentsort.lua deleted file mode 100644 index 4fbed1be01..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currentsort.lua +++ /dev/null @@ -1,59 +0,0 @@ -local t = Def.ActorFrame {} - -local frameWidth = 280 -local frameHeight = 20 -local frameX = SCREEN_WIDTH - 5 -local frameY = 15 - -local sortTable = { - SortOrder_Preferred = "Preferred", - SortOrder_Group = "Group", - SortOrder_Title = "Title", - SortOrder_BPM = "BPM", - SortOrder_Popularity = "Popular", - SortOrder_TopGrades = "Grade", - SortOrder_Artist = "Artist", - SortOrder_Genre = "Genre", - SortOrder_ModeMenu = "Mode Menu", - SortOrder_Length = "Song Length", - SortOrder_Recent = "Recently Played", - SortOrder_Favorites = "Favorites" -} - -t[#t + 1] = - Def.Quad { - Name = "CurrentSort", - InitCommand = function(self) - self:xy(frameX, frameY):halign(1):zoomto(frameWidth, frameHeight):diffuse(getMainColor("frames")) - end -} - -t[#t + 1] = - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX, frameY + 5):halign(1):zoom(0.55):maxwidth((frameWidth - 40) / 0.35) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - local sort = GAMESTATE:GetSortOrder() - local song = GAMESTATE:GetCurrentSong() - if sort == nil then - self:settext("Sort: ") - elseif sort == "SortOrder_Group" and song ~= nil then - self:settext(song:GetGroupName()) - else - self:settext("Sort: " .. sortTable[sort]) - end - end, - SortOrderChangedMessageCommand = function(self) - self:queuecommand("Set"):diffuse(getMainColor("positive")) - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end - } - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currenttime.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currenttime.lua deleted file mode 100644 index 381b6ab67c..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/currenttime.lua +++ /dev/null @@ -1,38 +0,0 @@ -local t = Def.ActorFrame {} - -t[#t + 1] = - LoadFont("Common Normal") .. - { - Name = "currentTime", - InitCommand = function(self) - self:xy(SCREEN_WIDTH - 5, SCREEN_BOTTOM - 5):halign(1):valign(1):zoom(0.45) - end - } - -t[#t + 1] = - LoadFont("Common Normal") .. - { - Name = "SessionTime", - InitCommand = function(self) - self:xy(SCREEN_CENTER_X, SCREEN_BOTTOM - 5):halign(0.5):valign(1):zoom(0.45) - end - } - -local function Update(self) - local year = Year() - local month = MonthOfYear() + 1 - local day = DayOfMonth() - local hour = Hour() - local minute = Minute() - local second = Second() - self:GetChild("currentTime"):settextf("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second) - - local sessiontime = GAMESTATE:GetSessionTime() - self:GetChild("SessionTime"):settextf("Session Time: " .. SecondsToHHMMSS(sessiontime)) - self:diffuse(getMainColor("positive")) -end - -t.InitCommand = function(self) - self:SetUpdateFunction(Update) -end -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/default.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/default.lua deleted file mode 100644 index 5b59bb9975..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/default.lua +++ /dev/null @@ -1,59 +0,0 @@ --- forcibly set the game style to single so we dont crash when loading songs -GAMESTATE:SetCurrentStyle("single") -GAMESTATE:SetCurrentPlayMode("PlayMode_Regular") - ---Input event for mouse clicks -local function input(event) - local top = SCREENMAN:GetTopScreen() - if event.DeviceInput.button == "DeviceButton_left mouse button" then - if event.type == "InputEventType_Release" then - if GAMESTATE:IsPlayerEnabled(PLAYER_1) then - if isOver(top:GetChild("Overlay"):GetChild("PlayerAvatar"):GetChild("Avatar" .. PLAYER_1):GetChild("Image")) then - SCREENMAN:AddNewScreenToTop("ScreenAvatarSwitch") - end - end - if GAMESTATE:IsPlayerEnabled(PLAYER_2) then - if isOver(top:GetChild("Overlay"):GetChild("PlayerAvatar"):GetChild("Avatar" .. PLAYER_2):GetChild("Image")) then - SCREENMAN:AddNewScreenToTop("ScreenAvatarSwitch") - end - end - end - end - return false -end - -local t = - Def.ActorFrame { - OnCommand = function(self) - SCREENMAN:GetTopScreen():AddInputCallback(input) - SCREENMAN:GetTopScreen():UsersVisible(false) - end -} - -t[#t + 1] = - Def.Actor { - CodeMessageCommand = function(self, params) - if params.Name == "AvatarShow" then - SCREENMAN:AddNewScreenToTop("ScreenAvatarSwitch") - end - end -} -t[#t + 1] = LoadActor("../_frame") -t[#t + 1] = LoadActor("../_PlayerInfo") -t[#t + 1] = LoadActor("currentsort") -t[#t + 1] = LoadActor("currenttime") -t[#t + 1] = - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(5, 32):halign(0):valign(1):zoom(0.55):diffuse(getMainColor("positive")):maxwidth(SCREEN_WIDTH / 2 - 10):settext( - "Room: " .. (NSMAN:GetCurrentRoomName() or "") - ) - end - } -t[#t + 1] = LoadActor("../_cursor") -t[#t + 1] = LoadActor("../_mouseselect") -t[#t + 1] = LoadActor("../_halppls") -t[#t + 1] = LoadActor("../_userlist") - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/wifesearchbar.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/wifesearchbar.lua deleted file mode 100644 index 7984c3e99f..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectBase overlay/wifesearchbar.lua +++ /dev/null @@ -1,265 +0,0 @@ --- Search functionalities --- to be used in ScreenNetSelectMusic and/or ScreenSelectMusic --- Now uses Til Death's search system - -local searchstring = "" -local englishes = { - "a", - "b", - "c", - "d", - "e", - "f", - "g", - "h", - "i", - "j", - "k", - "l", - "m", - "n", - "o", - "p", - "q", - "r", - "s", - "t", - "u", - "v", - "w", - "x", - "y", - "z" -} -local frameX = 10 -local frameY = 180 + capWideScale(get43size(120), 120) -local active = false -local whee -local mouseClickHandled = false - -local function searchInput(event) - if event.type ~= "InputEventType_Release" and active == true then - if event.button == "Back" then - searchstring = "" - whee:SongSearch(searchstring) - resetTabIndex(0) - MESSAGEMAN:Broadcast("TabChanged") - elseif event.button == "Start" then - resetTabIndex(0) - MESSAGEMAN:Broadcast("TabChanged") - elseif event.DeviceInput.button == "DeviceButton_space" then -- add space to the string - searchstring = searchstring .. " " - elseif event.DeviceInput.button == "DeviceButton_backspace" then - searchstring = searchstring:sub(1, -2) -- remove the last element of the string - elseif event.DeviceInput.button == "DeviceButton_delete" then - searchstring = "" - elseif event.DeviceInput.button == "DeviceButton_=" then - searchstring = searchstring .. "=" - else - for i = 1, #englishes do -- add standard characters to string - if event.DeviceInput.button == "DeviceButton_" .. englishes[i] then - searchstring = searchstring .. englishes[i] - end - end - end - MESSAGEMAN:Broadcast("UpdateString") - whee:SongSearch(searchstring) - end -end - -local function DeterminePressed(self, element) - local region_x = self:GetX() + element:GetX() - local region_y = self:GetY() + element:GetY() - local region_width = element:GetZoomedWidth() - local region_height = element:GetZoomedHeight() - - local mouse_x = INPUTFILTER:GetMouseX() - local mouse_y = INPUTFILTER:GetMouseY() - - if - region_x - region_width / 2 <= mouse_x and region_x + region_width / 2 >= mouse_x and - region_y - region_height / 2 <= mouse_y and - region_y + region_height / 2 >= mouse_y - then - return true - else - return false - end -end - -local function UpdateSearchBar(self) - if self == nil then - return - end - if active then - ms.ok("Song search activated") - self:visible(true) - GAMESTATE:GetPlayerState(PLAYER_1):DisableChatboxInput() - SCREENMAN:set_input_redirected(PLAYER_1, true) - MESSAGEMAN:Broadcast("RefreshSearchResults") - else - self:visible(false) - self:queuecommand("Off") - GAMESTATE:GetPlayerState(PLAYER_1):EnableChatboxInput() - SCREENMAN:set_input_redirected(PLAYER_1, false) - end -end - -local t = Def.ActorFrame {} - -t[#t + 1] = - Def.ActorFrame { - LeftClickMessageCommand = function(self, params) - local c = self:GetChildren() - if DeterminePressed(self, c.searchButton) then - if mouseClickHandled == false then - if active == false then - ms.ok("Song search activated") - local c = self:GetChildren() - active = true - GAMESTATE:GetPlayerState(PLAYER_1):DisableChatboxInput() - SCREENMAN:set_input_redirected(PLAYER_1, true) - MESSAGEMAN:Broadcast("RefreshSearchResults") - else - local c = self:GetChildren() - self:finishtweening() - self:queuecommand("Off") - active = false - GAMESTATE:GetPlayerState(PLAYER_1):EnableChatboxInput() - SCREENMAN:set_input_redirected(PLAYER_1, false) - end - mouseClickHandled = true - end - end - return true - end, - LoadActor(THEME:GetPathG("", "SearchBar/searchButton")) .. - { - Name = "searchButton", - InitCommand = function(self) - self:xy((SCREEN_WIDTH / 2) + 50, SCREEN_TOP + 15):setsize(24, 24) - end - } -} - -t[#t + 1] = - Def.ActorFrame { - Name = "SearchBar", - BeginCommand = function(self) - UpdateSearchBar(self) - self:SetUpdateFunction(UpdateSearchBar) - self:SetUpdateRate(1 / 30) - end, - OnCommand = function(self) - local topScreen = SCREENMAN:GetTopScreen() - --whee = topScreen:GetMusicWheel() --Idk why this gives an error - whee = topScreen:GetChild("MusicWheel") - topScreen:AddInputCallback(searchInput) - self:visible(false) - end, - TabChangedMessageCommand = function(self) - if active == false then - ms.ok("Song search activated") - local c = self:GetChildren() - active = true - GAMESTATE:GetPlayerState(PLAYER_1):DisableChatboxInput() - SCREENMAN:set_input_redirected(PLAYER_1, true) - MESSAGEMAN:Broadcast("RefreshSearchResults") - else - local c = self:GetChildren() - self:finishtweening() - self:queuecommand("Off") - active = false - GAMESTATE:GetPlayerState(PLAYER_1):EnableChatboxInput() - SCREENMAN:set_input_redirected(PLAYER_1, false) - end - mouseClickHandled = false - end, - Def.Quad { - InitCommand = function(self) - self:xy(frameX + 20, frameY - 210):zoomto(400, 300):halign(0):valign(0):diffuse(color("#333333CC")) - end - }, - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX + 250 - capWideScale(get43size(120), 30), frameY - 90):zoom(0.7):halign(0.5):maxwidth(470) - end, - SetCommand = function(self) - if active then - self:settext("Search Active:") - self:diffuse(getGradeColor("Grade_Tier03")) - else - self:settext("Search Complete:") - self:diffuse(byJudgment("TapNoteScore_Miss")) - end - end, - UpdateStringMessageCommand = function(self) - self:queuecommand("Set") - end - }, - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX + 250 - capWideScale(get43size(120), 30), frameY - 50):zoom(0.7):halign(0.5):maxwidth(470):settext( - searchstring - ) - end, - SetCommand = function(self) - self:settext(searchstring) - end, - UpdateStringMessageCommand = function(self) - self:queuecommand("Set") - end - }, - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX + 20, frameY - 200):zoom(0.4):halign(0) - end, - SetCommand = function(self) - self:settext("Start to lock search results.") - end, - UpdateStringMessageCommand = function(self) - self:queuecommand("Set") - end - }, - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX + 20, frameY - 175):zoom(0.4):halign(0):settext("Back to cancel search.") - end, - SetCommand = function(self) - self:settext("Back to cancel search.") - end, - UpdateStringMessageCommand = function(self) - self:queuecommand("Set") - end - }, - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX + 20, frameY - 150):zoom(0.4):halign(0):settext("Delete resets search query.") - end, - SetCommand = function(self) - self:settext("Delete resets search query.") - end, - UpdateStringMessageCommand = function(self) - self:queuecommand("Set") - end - }, - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(frameX + 20, frameY + 70):zoom(0.5):halign(0):settext("Currently supports standard english alphabet only.") - end, - SetCommand = function(self) - self:settext("Currently supports standard english alphabet only.") - end, - UpdateStringMessageCommand = function(self) - self:queuecommand("Set") - end - } -} - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua new file mode 100644 index 0000000000..623bf6b35e --- /dev/null +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua @@ -0,0 +1,10 @@ +local t = LoadActor("ScreenSelectMusic decorations/default") + t[#t + 1] = + Def.ActorFrame { + BeginCommand = function(self) + MESSAGEMAN:Broadcast("AddMPChatInput") + SCREENMAN:GetTopScreen():AddInputCallback(input)-- not sure if we need this or fallback handles it -mina + end + } + +return t \ No newline at end of file diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua deleted file mode 100644 index 192de366de..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/default.lua +++ /dev/null @@ -1,190 +0,0 @@ -local function input(event) - local top = SCREENMAN:GetTopScreen() - if event.DeviceInput.button == "DeviceButton_left mouse button" then - if event.type == "InputEventType_Release" then - if not SCREENMAN:get_input_redirected(PLAYER_1) then - if isOver(top:GetChild("Overlay"):GetChild("PlayerAvatar"):GetChild("Avatar" .. PLAYER_1):GetChild("Image")) then - SCREENMAN:AddNewScreenToTop("ScreenAvatarSwitch") - end - end - end - end - if event.DeviceInput.button == "DeviceButton_left mouse button" and event.type == "InputEventType_Release" then - MESSAGEMAN:Broadcast("MouseLeftClick") - elseif event.DeviceInput.button == "DeviceButton_right mouse button" and event.type == "InputEventType_Release" then - MESSAGEMAN:Broadcast("MouseRightClick") - end - return false -end - -local t = Def.ActorFrame {} -if NSMAN:IsETTP() then - t[#t + 1] = - Def.ActorFrame { - BeginCommand = function(self) - MESSAGEMAN:Broadcast("AddMPChatInput") - SCREENMAN:GetTopScreen():AddInputCallback(input) - end - } - t[#t + 1] = LoadActor("../ScreenSelectMusic decorations/default") - return t -end - -local g = - Def.ActorFrame { - TabChangedMessageCommand = function(self) - local top = SCREENMAN:GetTopScreen() - if getTabIndex() == 0 then - self:visible(true) - top:ChatboxVisible(true) - top:ChatboxInput(true) - else - self:visible(false) - top:ChatboxVisible(false) - top:ChatboxInput(false) - end - end -} - -g[#g + 1] = - Def.Banner { - InitCommand = function(self) - self:x(10):y(60):halign(0):valign(0) - end, - SetMessageCommand = function(self) - local top = SCREENMAN:GetTopScreen() - if top:GetName() == "ScreenSelectMusic" or top:GetName() == "ScreenNetSelectMusic" then - local song = GAMESTATE:GetCurrentSong() - local group = top:GetMusicWheel():GetSelectedSection() - if song then - self:LoadFromSong(song) - elseif group then - self:LoadFromSongGroup(group) - end - end - self:scaletoclipped(capWideScale(get43size(384), 384), capWideScale(get43size(120), 120)) - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand = function(self) - self:queuecommand("Set") - end -} -g[#g + 1] = - Def.Quad { - InitCommand = function(self) - self:xy(10, 60 + capWideScale(get43size(120), 120) - capWideScale(get43size(10), 10)):zoomto( - capWideScale(get43size(384), 384), - capWideScale(get43size(20), 20) - ):halign(0):diffuse(color("#000000")):diffusealpha(0.7) - end -} -g[#g + 1] = - LoadFont("Common Normal") .. - { - Name = "songTitle", - InitCommand = function(self) - self:xy(15, 60 + capWideScale(get43size(120), 120) - capWideScale(get43size(10), 10)):visible(true):halign(0):zoom( - capWideScale(get43size(0.45), 0.45) - ):maxwidth(capWideScale(get43size(340), 340) / capWideScale(get43size(0.45), 0.45)) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - local song = GAMESTATE:GetCurrentSong() - if song ~= nil then - self:settext(song:GetDisplayMainTitle() .. " // " .. song:GetDisplayArtist()) - else - self:settext("") - end - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end - } - -g[#g + 1] = LoadActor("wifeonline") -g[#g + 1] = LoadActor("onlinebpm") -g[#g + 1] = LoadActor("radaronline") - -g[#g + 1] = - Def.ActorFrame { - Name = "StepsDisplay", - InitCommand = function(self) - self:xy(stepsdisplayx, 70):valign(0) - end, - OffCommand = function(self) - self:visible(false) - end, - OnCommand = function(self) - self:visible(true) - end, - TabChangedMessageCommand = function(self) - self:finishtweening() - if getTabIndex() < 3 and GAMESTATE:GetCurrentSong() then - self:playcommand("On") - else - self:playcommand("Off") - end - end, - CurrentSongChangedMessageCommand = function(self) - local song = GAMESTATE:GetCurrentSong() - if song and getTabIndex() < 3 then - self:playcommand("On") - elseif not song then - self:playcommand("Off") - end - end, - PlayingSampleMusicMessageCommand = function(self) - local leaderboardEnabled = - playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() - if leaderboardEnabled and GAMESTATE:GetCurrentSteps(PLAYER_1) then - local chartkey = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() - DLMAN:RequestChartLeaderBoardFromOnline( - chartkey, - function(leaderboard) - end - ) - end - end, - ChartPreviewOnMessageCommand = function(self) - self:addx(capWideScale(12, 0)):addy(capWideScale(18, 0)) - end, - ChartPreviewOffMessageCommand = function(self) - self:addx(capWideScale(-12, 0)):addy(capWideScale(-18, 0)) - end, - Def.StepsDisplayList { - Name = "StepsDisplayListRow", - CursorP1 = Def.ActorFrame { - InitCommand = function(self) - self:player(PLAYER_1) - end, - Def.Quad { - InitCommand = function(self) - self:x(54):zoomto(6, 20):halign(1):valign(0.5) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - self:zoomy(20) - end - } - }, - CursorP2 = Def.ActorFrame {}, - CursorP1Frame = Def.Actor { - ChangeCommand = function(self) - self:stoptweening():decelerate(0.05) - end - }, - CursorP2Frame = Def.Actor {} - } -} -t[#t + 1] = g - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/dumbrate.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/dumbrate.lua deleted file mode 100644 index 409310d7c9..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/dumbrate.lua +++ /dev/null @@ -1,177 +0,0 @@ ---A dumb way of getting the rate to update online. -Misterkister - ---Local vars -local update = false -local steps -local song -local frameX = 10 -local frameY = 45 -local frameWidth = capWideScale(320, 400) -local frameHeight = 350 -local fontScale = 0.4 -local distY = 15 -local offsetX = 10 -local offsetY = 20 -local pn = GAMESTATE:GetEnabledPlayers()[1] -local greatest = 0 -local steps -local meter = {} -local curateX = frameX + frameWidth + 5 -local curateY = frameY + offsetY + 140 -meter[1] = 0.00 - ---4:3 ratio. -Misterkister -if not IsUsingWideScreen() == true then - curateX = frameX + frameWidth - 40 - curateY = frameY + offsetY - 20 -end - ---Hacky way of fixing these ratios outside of 16:9 and 4:3. -Misterkister - ---16:10 ratio. -Misterkister -if round(GetScreenAspectRatio(), 5) == 1.6 then - curateX = frameX + frameWidth - 8 -end - ---5:4 ratio. -Misterkister -if round(GetScreenAspectRatio(), 5) == 1.25 then - curateX = frameX + frameWidth - 80 -end - ---8:3 ratio targeted. -Misterkister -if round(GetScreenAspectRatio(), 5) > 1.77778 then - curateX = frameX + frameWidth + 425 -end - ---Actor Frame -local t = - Def.ActorFrame { - BeginCommand = function(self) - self:queuecommand("Set"):visible(false) - end, - OffCommand = function(self) - self:bouncebegin(0.2):xy(-500, 0):diffusealpha(0) - end, - OnCommand = function(self) - self:bouncebegin(0.2):xy(0, 0):diffusealpha(1) - end, - SetCommand = function(self) - self:finishtweening() - if getTabIndex() == 0 then - self:queuecommand("On") - self:visible(true) - song = GAMESTATE:GetCurrentSong() - steps = GAMESTATE:GetCurrentSteps(PLAYER_1) - - --Find max MSD value, store MSD values in meter[] - greatest = 0 - if song and steps then - for i = 1, #ms.SkillSets do - meter[i + 1] = steps:GetMSD(getCurRateValue(), i) - if meter[i + 1] > meter[greatest + 1] then - greatest = i - end - end - end - - MESSAGEMAN:Broadcast("UpdateMSDInfo") - update = true - else - self:queuecommand("Off") - update = false - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - TabChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - PlayerJoinedMessageCommand = function(self) - self:queuecommand("Set") - end -} - ---Skillset label function -local function littlebits(i) - local t = - Def.ActorFrame { - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX + 35, frameY + 120 + 22 * i):halign(0):valign(0):zoom(0.5):maxwidth(110 / 0.6) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - --skillset name - if song and steps then - self:settext(ms.SkillSets[i] .. ":") - else - self:settext("") - end - --highlight - if greatest == i then - self:diffuse(getMainColor("positive")) - else - self:diffuse(getMainColor("negative")) - end - end, - UpdateMSDInfoCommand = function(self) - self:queuecommand("Set") - end - }, - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX + 225, frameY + 120 + 22 * i):halign(1):valign(0):zoom(0.5):maxwidth(110 / 0.6) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and steps then - self:settextf("%05.2f", meter[i + 1]) - self:diffuse(byMSD(meter[i + 1])) - else - self:settext("") - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - UpdateMSDInfoCommand = function(self) - self:queuecommand("Set") - end - } - } - return t -end - --- Music Rate Display -t[#t + 1] = - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(curateX, curateY):visible(true):halign(0):zoom(0.35):maxwidth( - capWideScale(get43size(360), 360) / capWideScale(get43size(0.45), 0.45) - ) - end, - SetCommand = function(self) - self:settext(getCurRateDisplayString()) - end, - CodeMessageCommand = function(self, params) - local rate = getCurRateValue() - ChangeMusicRate(rate, params) - self:settext(getCurRateDisplayString()) - end, - RateChangedMessageCommand = function(self, params) - self:settext(getCurRateDisplayString()) - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("set") - end - } - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/onlinebpm.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/onlinebpm.lua deleted file mode 100644 index e539c1de3b..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/onlinebpm.lua +++ /dev/null @@ -1,42 +0,0 @@ ---Merge two files "somethingelseBPMLabel" and "netplayBPMDisplay" into one file. -Misterkister - -local bpmx = SCREEN_CENTER_X + 10 -local bpmy = SCREEN_CENTER_Y + 35 -local displayx = SCREEN_CENTER_X + 45 -local displayy = SCREEN_CENTER_Y + 35 - -if round(GetScreenAspectRatio(), 5) == 1.25 then - bpmx = SCREEN_CENTER_X - displayx = SCREEN_CENTER_X + 35 -end - -local t = Def.ActorFrame {} - -t[#t + 1] = - LoadFont("Common Normal") .. - { - Text = "BPM", - InitCommand = function(self) - self:x(bpmx):y(bpmy):zoom(0.50) - end - } - -t[#t + 1] = - Def.BPMDisplay { - File = THEME:GetPathF("BPMDisplay", "bpm"), - Name = "BPMDisplay", - InitCommand = function(self) - self:x(displayx):y(displayy):zoom(0.50) - end, - SetCommand = function(self) - self:SetFromGameState() - end, - CurrentSongChangedMessageCommand = function(self) - self:playcommand("Set") - end, - CurrentCourseChangedMessageCommand = function(self) - self:playcommand("Set") - end -} - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/radaronline.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/radaronline.lua deleted file mode 100644 index 3bfab5ae75..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/radaronline.lua +++ /dev/null @@ -1,145 +0,0 @@ ---Similar to dummy.lua and I'm just commenting again because I don't know what I am exactly doing. -Misterkister - -local update = false -local t = - Def.ActorFrame { - BeginCommand = function(self) - self:queuecommand("Set"):visible(false) - end, - OffCommand = function(self) - self:bouncebegin(0.2):xy(-500, 0):diffusealpha(0) -- visible(false() - end, - OnCommand = function(self) - self:bouncebegin(0.2):xy(0, 0):diffusealpha(1) - end, - SetCommand = function(self) - self:finishtweening() - if getTabIndex() == 0 then - self:queuecommand("On") - self:visible(true) - update = true - else - self:queuecommand("Off") - update = false - end - end, - TabChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - PlayerJoinedMessageCommand = function(self) - self:queuecommand("Set") - end -} - -local frameX = 10 -local frameY = 45 -local frameWidth = capWideScale(320, 400) -local frameHeight = 350 -local fontScale = 0.4 -local distY = 15 -local offsetX = 10 -local offsetY = 20 -local pn = GAMESTATE:GetEnabledPlayers()[1] - -local cdtitleX = frameX + 440 -local cdtitleY = frameY + 225 - -if not IsUsingWideScreen() == true then - cdtitleX = frameX + 440 - 105 - cdtitleY = frameY + 225 -end - -local stepstuffX = frameX + frameWidth - offsetX - 300 -local stepstuffY = frameY + offsetY - 23 - -if not IsUsingWideScreen() == true then - stepstuffX = frameX + frameWidth - offsetX + 30 - stepstuffY = frameY + offsetY - 13 + 110 -end - -local radarValues = { - {"RadarCategory_Notes", "Notes"}, - {"RadarCategory_TapsAndHolds", "Taps"}, - {"RadarCategory_Jumps", "Jumps"}, - {"RadarCategory_Hands", "Hands"}, - {"RadarCategory_Holds", "Holds"}, - {"RadarCategory_Rolls", "Rolls"}, - {"RadarCategory_Mines", "Mines"} -} - -local radarX = frameX + offsetX + 450 -local stuffstuffstuffX = frameX + offsetX + 400 - -if not IsUsingWideScreen() == true then - radarX = frameX + offsetX + 450 - 120 - stuffstuffstuffX = frameX + offsetX + 400 - 105 -end - ---Hacky way of fixing these ratios outside of 16:9 and 4:3. -Misterkister - ---16:10 ratio. -Misterkister -if round(GetScreenAspectRatio(), 5) == 1.6 then - radarX = frameX + offsetX + 450 - 45 - stuffstuffstuffX = frameX + offsetX + 400 - 40 -end - ---5:4 ratio. -Misterkister -if round(GetScreenAspectRatio(), 5) == 1.25 then - radarX = frameX + offsetX + 310 - stuffstuffstuffX = frameX + offsetX + 270 -end - ---8:3 ratio targeted. -Misterkister -if round(GetScreenAspectRatio(), 5) > 1.77778 then - radarX = SCREEN_CENTER_X + 50 - stuffstuffstuffX = SCREEN_CENTER_X -end - -for k, v in ipairs(radarValues) do - t[#t + 1] = - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(stuffstuffstuffX, frameY + offsetY + 230 + (15 * (k - 1))):zoom(0.4):halign(0):maxwidth( - (frameWidth - offsetX * 2 - 150) / 0.4 - ) - end, - OnCommand = function(self) - self:settext(v[2] .. ": ") - end - } - t[#t + 1] = - LoadFont("Common Normal") .. - { - Name = "RadarValue" .. v[1], - InitCommand = function(self) - self:xy(radarX, frameY + offsetY + 230 + (15 * (k - 1))):zoom(0.4):halign(0):maxwidth( - (frameWidth - offsetX * 2 - 150) / 0.4 - ) - end, - SetCommand = function(self) - local song = GAMESTATE:GetCurrentSong() - local steps = GAMESTATE:GetCurrentSteps(pn) - local count = 0 - if song ~= nil and steps ~= nil and update then - count = steps:GetRadarValues(pn):GetValue(v[1]) - self:settext(count) - self:diffuse(color("#FFFFFF")) - else - self:settext(0) - self:diffuse(getMainColor("disabled")) - end - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand = function(self) - self:queuecommand("Set") - end - } -end - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/tabs.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/tabs.lua deleted file mode 100644 index 84835ca735..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/tabs.lua +++ /dev/null @@ -1,152 +0,0 @@ -local active = true - -local CtrlPressed = false -local function input(event) - if event.type ~= "InputEventType_Release" and active then - for i = 1, 6 do - if event.DeviceInput.button == "DeviceButton_" .. i and CtrlPressed == true then - setTabIndex(i - 1) - MESSAGEMAN:Broadcast("TabChanged") - end - end - if event.DeviceInput.button == "DeviceButton_left mouse button" then - MESSAGEMAN:Broadcast("MouseLeftClick") - elseif event.DeviceInput.button == "DeviceButton_right mouse button" then - MESSAGEMAN:Broadcast("MouseRightClick") - end - end - if event.DeviceInput.button == "DeviceButton_left ctrl" then - if event.type == "InputEventType_Release" then - CtrlPressed = false - else - CtrlPressed = true - end - end - if event.DeviceInput.button == "DeviceButton_right ctrl" then - if event.type == "InputEventType_Release" then - CtrlPressed = false - else - CtrlPressed = true - end - end - return false -end - -local t = - Def.ActorFrame { - OnCommand = function(self) - SCREENMAN:GetTopScreen():AddInputCallback(input) - end, - BeginCommand = function(self) - resetTabIndex() - end, - PlayerJoinedMessageCommand = function(self) - resetTabIndex() - end, - BeginningSearchMessageCommand = function(self) - active = true - end, - EndingSearchMessageCommand = function(self) - active = true - end -} - --- Just for debug ---[[ -t[#t+1] = LoadFont("Common Normal") .. { - InitCommand=function(self) - self:xy(300,300):halign(0):zoom(2):diffuse(getMainColor(2)) - end; - BeginCommand=function(self) - self:queuecommand("Set") - end; - SetCommand=function(self) - self:settext(getTabIndex()) - end; - CodeMessageCommand=function(self) - self:queuecommand("Set") - end; -}; ---]] ---====================================================================================== - -local tabNames = {"General", "MSD", "Score", "Search", "Profile", "Filters"} -- this probably should be in tabmanager. - -local frameWidth = (SCREEN_WIDTH * (403 / 854)) / (#tabNames - 1) -local frameX = frameWidth / 2 -local frameY = SCREEN_HEIGHT - 70 - -function tabs(index) - local t = - Def.ActorFrame { - Name = "Tab" .. index, - InitCommand = function(self) - self:xy(frameX + ((index - 1) * frameWidth), frameY) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - self:finishtweening() - self:linear(0.1) - --show tab if it's the currently selected one - if getTabIndex() == index - 1 then - self:y(frameY) - self:diffusealpha(1) - else -- otherwise "Hide" them - self:y(frameY) - self:diffusealpha(0.65) - end - end, - TabChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - PlayerJoinedMessageCommand = function(self) - self:queuecommand("Set") - end - } - - t[#t + 1] = - Def.Quad { - Name = "TabBG", - InitCommand = function(self) - self:y(2):valign(0):zoomto(frameWidth, 20):diffusecolor(getMainColor("frames")):diffusealpha(0.85) - end, - MouseLeftClickMessageCommand = function(self) - if isOver(self) then - setTabIndex(index - 1) - MESSAGEMAN:Broadcast("TabChanged") - end - end - } - - t[#t + 1] = - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:y(5):valign(0):zoom(0.45):diffuse(getMainColor("positive")) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - self:settext(tabNames[index]) - if isTabEnabled(index) then - self:diffuse(getMainColor("positive")) - else - self:diffuse(color("#666666")) - end - end, - PlayerJoinedMessageCommand = function(self) - self:queuecommand("Set") - end - } - return t -end - ---Make tabs -for i = 1, #tabNames do - t[#t + 1] = tabs(i) -end - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/wifeonline.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/wifeonline.lua deleted file mode 100644 index 51ec2a1b7a..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/wifeonline.lua +++ /dev/null @@ -1,697 +0,0 @@ -local profile = PROFILEMAN:GetProfile(PLAYER_1) -local frameX = 10 -local frameY = 250 + capWideScale(get43size(120), 90) -local frameWidth = capWideScale(get43size(455), 455) -local scoreType = themeConfig:get_data().global.DefaultScoreType -local score -local song -local steps -local alreadybroadcasted -local alreadybroadcasted - -local update = false -local t = - Def.ActorFrame { - BeginCommand = function(self) - steps = nil - song = nil - score = nil - self:finishtweening() - if getTabIndex() == 0 then - self:queuecommand("On") - update = true - else - self:queuecommand("Off") - update = false - end - end, - OffCommand = function(self) - self:bouncebegin(0.2):xy(-500, 0):diffusealpha(0) - end, - OnCommand = function(self) - self:bouncebegin(0.2):xy(0, 0):diffusealpha(1) - end, - SetCommand = function(self) - self:finishtweening() - if getTabIndex() == 0 then - self:queuecommand("On") - update = true - else - self:queuecommand("Off") - update = false - end - end, - TabChangedMessageCommand = function(self) - self:queuecommand("Set") - end -} - --- Temporary update control tower; it would be nice if the basic song/step change commands were thorough and explicit and non-redundant -t[#t + 1] = - Def.Actor { - SetCommand = function(self) - if song and not alreadybroadcasted then -- if this is true it means we've just exited a pack's songlist into the packlist - song = GAMESTATE:GetCurrentSong() -- also apprently true if we're tabbing around within a songlist and then stop... - MESSAGEMAN:Broadcast("UpdateChart") -- ms.ok(whee:GetSelectedSection( )) -- use this later to detect pack changes - MESSAGEMAN:Broadcast("RefreshChartInfo") - else - alreadybroadcasted = false - end - end, - CurrentStepsP1ChangedMessageCommand = function(self) - song = GAMESTATE:GetCurrentSong() - MESSAGEMAN:Broadcast("UpdateChart") - alreadybroadcasted = true - end, - CurrentSongChangedMessageCommand = function(self) - if playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).OneShotMirror then -- This will disable mirror when switching songs if OneShotMirror is enabled - local modslevel = topscreen == "ScreenEditOptions" and "ModsLevel_Stage" or "ModsLevel_Preferred" - local playeroptions = GAMESTATE:GetPlayerState(PLAYER_1):GetPlayerOptions(modslevel) - playeroptions:Mirror(false) - end - self:queuecommand("Set") - end -} - -local function GetBestScoreByFilter(perc, CurRate) - local rtTable = getRateTable() - if not rtTable then - return nil - end - - local rates = tableKeys(rtTable) - local scores, score - - if CurRate then - local tmp = getCurRateString() - if tmp == "1x" then - tmp = "1.0x" - end - rates = {tmp} - if not rtTable[rates[1]] then - return nil - end - end - - table.sort(rates) - for i = #rates, 1, -1 do - scores = rtTable[rates[i]] - local bestscore = 0 - local index - - for ii = 1, #scores do - score = scores[ii] - if score:ConvertDpToWife() > bestscore then - index = ii - bestscore = score:ConvertDpToWife() - end - end - - if index and scores[index]:GetWifeScore() == 0 and GetPercentDP(scores[index]) > perc * 100 then - return scores[index] - end - - if bestscore > perc then - return scores[index] - end - end -end - -local function GetDisplayScore() - local score - score = GetBestScoreByFilter(0, true) - - if not score then - score = GetBestScoreByFilter(0.9, false) - end - if not score then - score = GetBestScoreByFilter(0.5, false) - end - if not score then - score = GetBestScoreByFilter(0, false) - end - return score -end - -t[#t + 1] = - Def.Actor { - SetCommand = function(self) - if song then - steps = GAMESTATE:GetCurrentSteps(PLAYER_1) - score = GetDisplayScore() - MESSAGEMAN:Broadcast("RefreshChartInfo") - end - end, - UpdateChartMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentRateChangedMessageCommand = function() - score = GetDisplayScore() - end -} - ---All these 4:3 ratio and 16:9 widescreen ratio stuff goes here. -Misterkister ----------------------------------------------------------------------------------------- -local wifeY = frameY - 170 -local wifeX = frameX + 25 -local wifescoretypeX = frameX + 150 -local wifescoretypeY = frameY + 40 -local secondarytypeX = frameX + 130 -local secondarytypeY = frameY + 63 -local secondaryscoretypeX = frameX + 173 -local secondaryscoretypeY = frameY + 63 -local rateX = frameX + 55 -local rateY = frameY + 58 -local datescoreX = frameX + 185 -local datescoreY = frameY + 59 -local maxcomboX = frameX + 185 -local maxcomboY = frameY + 49 -local difficultyX = frameX + 58 -local difficultyY = frameY -local negativebpmX = frameX + 10 -local negativebpmY = frameY - 120 -local infoboxx = 310 -local infoboxy = 200 -local infoboxbar = 3 -local infoboxwidth = 65 -local infoboxheight = 200 -local lengthx = capWideScale(get43size(374), 420) + 60 -local lengthy = capWideScale(get43size(360), 275) -local cdtitlemaxwidth = 75 -local cdtitlemaxheight = 30 -local curateX = 18 -local curateY = SCREEN_BOTTOM - 225 -local cdtitleX = capWideScale(get43size(374), 394) + 60 -local cdtitleY = capWideScale(get43size(290), 270) - ---16:9 ratio. -if IsUsingWideScreen() == true then - wifeY = frameY - 290 - wifeX = frameX + 25 - wifescoretypeX = frameX + 95 - wifescoretypeY = frameY - 290 - secondarytypeX = frameX + 180 - secondarytypeY = frameY - 290 - secondaryscoretypeX = frameX + 245 - secondaryscoretypeY = frameY - 290 - rateX = frameX + 125 - rateY = frameY - 295 - datescoreX = frameX + 170 - datescoreY = frameY - 150 - maxcomboY = frameY - 150 - maxcomboX = frameX + 300 - difficultyY = frameY - 115 - difficultyX = frameX + 440 - negativebpmY = frameY - 150 - --radarX = frameX+400 - - infoboxx = capWideScale(get43size(374), 405) - infoboxy = capWideScale(get43size(360), 215) - infoboxbar = 8 - infoboxwidth = 95 - infoboxheight = 195 - lengthx = capWideScale(get43size(374), 375) - lengthy = capWideScale(get43size(360), 170) - cdtitlemaxwidth = 75 - cdtitlemaxheight = 30 - curateX = 425 - curateY = SCREEN_CENTER_Y - 35 -end - ---4:3 ratio. -if not IsUsingWideScreen() == true then - wifeY = frameY - 170 - wifeX = frameX + 25 - wifescoretypeX = frameX + 95 - wifescoretypeY = frameY - 170 - secondarytypeX = frameX + 25 - secondarytypeY = frameY - 150 - secondaryscoretypeX = frameX + 95 - secondaryscoretypeY = frameY - 150 - rateX = frameX + 145 - rateY = frameY - 175 - datescoreX = frameX + 130 - datescoreY = frameY - 150 - maxcomboY = frameY - 175 - maxcomboX = frameX + 210 - difficultyY = frameY - 95 - difficultyX = frameX + 330 - negativebpmY = frameY - 290 - --radarX = frameX+400 - - infoboxx = 310 - infoboxy = 220 - infoboxbar = 3 - infoboxwidth = 65 - infoboxheight = 175 - lengthx = 290 - lengthy = 142 - cdtitlemaxwidth = 50 - cdtitlemaxheight = 60 - curateX = SCREEN_CENTER_X - 20 - curateY = SCREEN_CENTER_Y - 72 -end - ---Hacky way of fixing these ratios outside of 16:9 and 4:3. I'm not doing 3:4 or 1:1 ratio support unless there's good reasons to do those. -Misterkister - ---16:10 ratio. -Misterkister -if round(GetScreenAspectRatio(), 5) == 1.6 then - infoboxx = 368 - infoboxy = 215 - difficultyX = frameX + 400 - cdtitleY = capWideScale(get43size(350), 270) - infoboxwidth = 85 - lengthy = capWideScale(get43size(185), 170) -end - ---5:4 ratio. -Misterkister -if round(GetScreenAspectRatio(), 5) == 1.25 then - infoboxx = 285 - infoboxwidth = 58 - difficultyX = frameX + 305 - cdtitleY = capWideScale(get43size(290), 270) - cdtitleX = capWideScale(get43size(344), 394) + 60 - maxcomboX = frameX + 180 - maxcomboY = frameY - 182 -end - ---8:3 ratio targeted. -Misterkister -if round(GetScreenAspectRatio(), 5) > 1.77778 then - infoboxx = SCREEN_CENTER_X - 15 - infoboxy = SCREEN_CENTER_Y - 90 - infoboxwidth = 100 - cdtitleY = SCREEN_CENTER_Y - 25 - cdtitleX = SCREEN_CENTER_X + 25 - infoboxheight = 250 - difficultyX = SCREEN_CENTER_X + 30 - wifeX = SCREEN_CENTER_X - 140 - wifeY = SCREEN_CENTER_Y - 188 - wifescoretypeX = SCREEN_CENTER_X - 50 - wifescoretypeY = SCREEN_CENTER_Y - 188 - secondarytypeX = SCREEN_CENTER_X - 140 - secondarytypeY = SCREEN_CENTER_Y - 158 - secondaryscoretypeX = SCREEN_CENTER_X - 50 - secondaryscoretypeY = SCREEN_CENTER_Y - 158 - lengthx = SCREEN_CENTER_X - 255 - lengthy = SCREEN_CENTER_Y - 70 - maxcomboX = SCREEN_CENTER_X - 160 - maxcomboY = SCREEN_CENTER_Y - 140 - datescoreX = SCREEN_CENTER_X - 160 - datescoreY = SCREEN_CENTER_Y - 120 - rateX = SCREEN_CENTER_X - 145 - rateY = SCREEN_CENTER_Y - 100 -end - -t[#t + 1] = - Def.Quad { - InitCommand = function(self) - self:xy(infoboxx, infoboxy):zoomto(infoboxwidth, infoboxheight):halign(0):valign(0):diffuse(color("#333333CC")):diffusealpha( - 0.66 - ) - end -} -t[#t + 1] = - Def.Quad { - InitCommand = function(self) - self:xy(infoboxx, infoboxy):zoomto(infoboxbar, infoboxheight):halign(0):valign(0):diffuse(getMainColor("highlight")):diffusealpha( - 0.5 - ) - end -} - -t[#t + 1] = - Def.ActorFrame { - -- **score related stuff** These need to be updated with rate changed commands - -- Primary percent score - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(wifeX, wifeY):zoom(0.3):halign(0.5):maxwidth(175):valign(1) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and score then - if score:GetWifeScore() == 0 then - self:settextf("%05.2f%%", notShit.floor(GetPercentDP(score) * 100) / 100) - self:diffuse(getGradeColor(score:GetGrade())) - else - self:settextf("%05.2f%%", notShit.floor(score:GetWifeScore() * 10000) / 100) - self:diffuse(getGradeColor(score:GetWifeGrade())) - end - else - self:settext("") - end - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand = function(self) - self:queuecommand("Set") - end - }, - -- Primary ScoreType - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(wifescoretypeX, wifescoretypeY):zoom(0.3):halign(1):valign(1) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and score then - if score:GetWifeScore() == 0 then - self:settext("DP*") - else - self:settext(scoringToText(scoreType)) - end - else - self:settext("") - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand = function(self) - self:queuecommand("Set") - end - }, - -- Secondary percent score - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(secondarytypeX, secondarytypeY):zoom(0.6):halign(0.5):maxwidth(125):valign(1) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and score then - if score:GetWifeScore() == 0 then - self:settextf("NA") - self:diffuse(getGradeColor("Grade_Failed")) - else - self:settextf("%05.2f%%", GetPercentDP(score)) - self:diffuse(getGradeColor(score:GetGrade())) - end - else - self:settext("") - end - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end - }, - -- Secondary ScoreType - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(secondaryscoretypeX, secondaryscoretypeY):zoom(0.4):halign(1):valign(1) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and score then - if score:GetWifeScore() == 0 then - self:settext("Wife") - else - self:settext("DP") - end - else - self:settext("") - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end - }, - -- Rate for the displayed score - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(rateX, rateY):zoom(0.5):halign(0.5) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and score then - local rate = getRate(score) - if getCurRateString() ~= rate then - self:settext("(" .. rate .. ")") - else - self:settext(rate) - end - else - self:settext("") - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end - }, - -- Date score achieved on - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(datescoreX, datescoreY):zoom(0.4):halign(0) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and score then - self:settext(score:GetDate()) - else - self:settext("") - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end - }, - -- MaxCombo - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(maxcomboX, maxcomboY):zoom(0.4):halign(0) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and score then - self:settextf("Max Combo: %d", score:GetMaxCombo()) - else - self:settext("") - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end - } - -- **End score related stuff** -} - --- Difficulty value ("meter"), need to change this later -t[#t + 1] = - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(difficultyX, difficultyY):halign(0.5):zoom(0.4):maxwidth(110 / 0.6) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song then - local meter = GAMESTATE:GetCurrentSteps(PLAYER_1):GetMSD(getCurRateValue(), 1) - --If meter is showing 0 because it's a solo or a double chart, then don't show the numbers. -Misterkister - if meter == 0 then - self:settext("") - else - self:settextf("%05.2f", meter) - self:diffuse(byMSD(meter)) - end - else - self:settext("") - end - if song and steps:GetTimingData():HasWarps() then - self:settext("") - end - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand = function(self) - self:queuecommand("Set") - end - } - -t[#t + 1] = - Def.Sprite { - InitCommand = function(self) - self:xy(cdtitleX, cdtitleY):halign(0.5):valign(1) - end, - SetCommand = function(self) - self:finishtweening() - if GAMESTATE:GetCurrentSong() then - local song = GAMESTATE:GetCurrentSong() - if song then - if song:HasCDTitle() then - self:visible(true) - self:Load(song:GetCDTitlePath()) - else - self:visible(false) - end - else - self:visible(false) - end - local height = self:GetHeight() - local width = self:GetWidth() - - if height >= cdtitlemaxheight and width >= cdtitlemaxwidth then - if height * (cdtitlemaxwidth / cdtitlemaxheight) >= width then - self:zoom(cdtitlemaxheight / height) - else - self:zoom(cdtitlemaxwidth / width) - end - elseif height >= cdtitlemaxheight then - self:zoom(cdtitlemaxheight / height) - elseif width >= cdtitlemaxwidth then - self:zoom(cdtitlemaxwidth / width) - else - self:zoom(1) - end - else - self:visible(false) - end - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end -} - -t[#t + 1] = - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(negativebpmX, negativebpmY):halign(0):zoom(0.25) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song and steps:GetTimingData():HasWarps() then - self:settext("Negative BPMs Detected") - self:diffuse(color("#e61e25")) - else - self:settext("") - end - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end - } - ---test actor -t[#t + 1] = - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(frameX, frameY - 120):halign(0):zoom(0.4, maxwidth, 125) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - self:settext("") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end - } - --- Song duration -t[#t + 1] = - LoadFont("Common Large") .. - { - InitCommand = function(self) - self:xy(lengthx, lengthy):visible(true):halign(1):zoom(capWideScale(get43size(0.4), 0.4)):maxwidth( - capWideScale(get43size(360), 360) / capWideScale(get43size(0.45), 0.45) - ) - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - SetCommand = function(self) - if song then - local playabletime = GetPlayableTime() - self:settext(SecondsToMMSS(playabletime)) - self:diffuse(byMusicLength(playabletime)) - else - self:settext("") - end - end, - CurrentRateChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - RefreshChartInfoMessageCommand = function(self) - self:queuecommand("Set") - end - } -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/yolo.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/yolo.lua deleted file mode 100644 index 6909553e7b..0000000000 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations/yolo.lua +++ /dev/null @@ -1,205 +0,0 @@ ---Similar to dummy.lua and I'm just commenting again because I don't know what I am exactly doing. -Misterkister - -local update = false -local t = - Def.ActorFrame { - BeginCommand = function(self) - self:queuecommand("Set"):visible(false) - end, - OffCommand = function(self) - self:bouncebegin(0.2):xy(-500, 0):diffusealpha(0) - end, - OnCommand = function(self) - self:bouncebegin(0.2):xy(0, 0):diffusealpha(1) - end, - SetCommand = function(self) - self:finishtweening() - if getTabIndex() == 0 then - self:queuecommand("On") - self:visible(true) - update = true - else - self:queuecommand("Off") - update = false - end - end, - TabChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - PlayerJoinedMessageCommand = function(self) - self:queuecommand("Set") - end -} - -local frameX = 10 -local frameY = 45 -local frameWidth = capWideScale(320, 400) -local frameHeight = 350 -local fontScale = 0.4 -local distY = 15 -local offsetX = 10 -local offsetY = 20 -local pn = GAMESTATE:GetEnabledPlayers()[1] - -local cdtitleX = frameX + 440 -local cdtitleY = frameY + 225 - -if not IsUsingWideScreen() == true then - cdtitleX = frameX + 440 - 105 - cdtitleY = frameY + 225 -end - -t[#t + 1] = - Def.Sprite { - InitCommand = function(self) - self:xy(cdtitleX, cdtitleY + 10):zoomy(0):valign(1) - end, - Name = "CDTitle", - SetCommand = function(self) - if update then - local song = GAMESTATE:GetCurrentSong() - if song then - if song:HasCDTitle() then - self:visible(true) - self:Load(song:GetCDTitlePath()) - else - self:visible(false) - end - else - self:visible(false) - end - local height = self:GetHeight() - local width = self:GetWidth() - - if height >= 80 and width >= 100 then - if height * (100 / 80) >= width then - self:zoom(80 / height) - else - self:zoom(100 / width) - end - elseif height >= 80 then - self:zoom(80 / height) - elseif width >= 100 then - self:zoom(100 / width) - else - self:zoom(1) - end - self:diffusealpha(1) - end - end, - BeginCommand = function(self) - self:queuecommand("Set") - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end -} - -local stepstuffX = frameX + frameWidth - offsetX - 300 -local stepstuffY = frameY + offsetY - 23 - -if not IsUsingWideScreen() == true then - stepstuffX = frameX + frameWidth - offsetX + 30 - stepstuffY = frameY + offsetY - 13 + 110 -end - -t[#t + 1] = - LoadFont("Common Normal") .. - { - Name = "StepsAndMeter", - InitCommand = function(self) - self:xy(stepstuffX, stepstuffY):zoom(0.4):halign(1) - end, - SetCommand = function(self) - local steps = GAMESTATE:GetCurrentSteps(pn) - local song = GAMESTATE:GetCurrentSong() - local notecount = 0 - local length = 1 - if steps ~= nil and song ~= nil and update then - length = song:GetStepsSeconds() - notecount = steps:GetRadarValues(pn):GetValue("RadarCategory_Notes") - self:settext(string.format("%0.2f Average NPS", notecount / length)) - self:diffuse(Saturation(getDifficultyColor(GetCustomDifficulty(steps:GetStepsType(), steps:GetDifficulty())), 0.3)) - else - self:settext("0.00 Average NPS") - end - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand = function(self) - self:queuecommand("Set") - end - } - -local radarValues = { - {"RadarCategory_Notes", "Notes"}, - {"RadarCategory_TapsAndHolds", "Taps"}, - {"RadarCategory_Jumps", "Jumps"}, - {"RadarCategory_Hands", "Hands"}, - {"RadarCategory_Holds", "Holds"}, - {"RadarCategory_Rolls", "Rolls"}, - {"RadarCategory_Mines", "Mines"}, - {"RadarCategory_Lifts", "Lifts"}, - {"RadarCategory_Fakes", "Fakes"} -} - -local radarX = frameX + offsetX + 450 -local stuffstuffstuffX = frameX + offsetX + 400 - -if not IsUsingWideScreen() == true then - radarX = frameX + offsetX + 450 - 120 - stuffstuffstuffX = frameX + offsetX + 400 - 110 -end - -for k, v in ipairs(radarValues) do - t[#t + 1] = - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(stuffstuffstuffX, frameY + offsetY + 230 + (15 * (k - 1))):zoom(0.4):halign(0):maxwidth( - (frameWidth - offsetX * 2 - 150) / 0.4 - ) - end, - OnCommand = function(self) - self:settext(v[2] .. ": ") - end - } - t[#t + 1] = - LoadFont("Common Normal") .. - { - Name = "RadarValue" .. v[1], - InitCommand = function(self) - self:xy(radarX, frameY + offsetY + 230 + (15 * (k - 1))):zoom(0.4):halign(0):maxwidth( - (frameWidth - offsetX * 2 - 150) / 0.4 - ) - end, - SetCommand = function(self) - local song = GAMESTATE:GetCurrentSong() - local steps = GAMESTATE:GetCurrentSteps(pn) - local count = 0 - if song ~= nil and steps ~= nil and update then - count = steps:GetRadarValues(pn):GetValue(v[1]) - self:settext(count) - self:diffuse(color("#FFFFFF")) - else - self:settext(0) - self:diffuse(getMainColor("disabled")) - end - end, - CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand = function(self) - self:queuecommand("Set") - end - } -end - -return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic overlay.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic overlay.lua new file mode 100644 index 0000000000..7ad27cd03b --- /dev/null +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic overlay.lua @@ -0,0 +1,3 @@ +local t = LoadActor("ScreenSelectMusic overlay/default") +t[#t+1] = LoadActor("_userlist") +return t \ No newline at end of file diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua index 36ddf0d4c6..c016bf51fe 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua @@ -1,14 +1,4 @@ local function input(event) - local top = SCREENMAN:GetTopScreen() - if event.DeviceInput.button == "DeviceButton_left mouse button" then - if event.type == "InputEventType_Release" then - if not SCREENMAN:get_input_redirected(PLAYER_1) then - if isOver(top:GetChild("Overlay"):GetChild("PlayerAvatar"):GetChild("Avatar" .. PLAYER_1):GetChild("Image")) then - SCREENMAN:AddNewScreenToTop("ScreenAvatarSwitch") - end - end - end - end if event.DeviceInput.button == "DeviceButton_left mouse button" and event.type == "InputEventType_Release" then MESSAGEMAN:Broadcast("MouseLeftClick") elseif event.DeviceInput.button == "DeviceButton_right mouse button" and event.type == "InputEventType_Release" then @@ -22,9 +12,6 @@ local t = BeginCommand = function(self) local s = SCREENMAN:GetTopScreen() s:AddInputCallback(input) - if s:GetName() == "ScreenNetSelectMusic" then - s:UsersVisible(false) - end end } diff --git a/Themes/Til Death/BGAnimations/_PlayerInfo.lua b/Themes/Til Death/BGAnimations/_PlayerInfo.lua index e7361a3e25..74e1425720 100644 --- a/Themes/Til Death/BGAnimations/_PlayerInfo.lua +++ b/Themes/Til Death/BGAnimations/_PlayerInfo.lua @@ -74,6 +74,12 @@ t[#t + 1] = self:finishtweening() self:Load(getAvatarPath(PLAYER_1)) self:zoomto(50, 50) + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) and not SCREENMAN:get_input_redirected(PLAYER_1) then + local top = SCREENMAN:GetTopScreen() + SCREENMAN:AddNewScreenToTop("ScreenAvatarSwitch") + end end }, LoadFont("Common Normal") .. diff --git a/Themes/Til Death/BGAnimations/_userlist.lua b/Themes/Til Death/BGAnimations/_userlist.lua index 8832405a68..16fd5d25bd 100644 --- a/Themes/Til Death/BGAnimations/_userlist.lua +++ b/Themes/Til Death/BGAnimations/_userlist.lua @@ -1,4 +1,4 @@ -local usersZoom = 0.35 +local usersZoom = 0.45 local usersWidth = 50 local usersWidthSmall = 25 local usersWidthZoom = 50 * (1 / usersZoom) From e97af08af50146c5e66b7c1d178241e9d1638454 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 01:29:00 -0500 Subject: [PATCH 128/320] improve multi branching for til death --- Themes/Til Death/Scripts/02 Branches.lua | 10 ++++++++-- Themes/Til Death/metrics.ini | 3 +++ src/ScreenNetworkOptions.cpp | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/Themes/Til Death/Scripts/02 Branches.lua b/Themes/Til Death/Scripts/02 Branches.lua index b454579502..aed00d7011 100644 --- a/Themes/Til Death/Scripts/02 Branches.lua +++ b/Themes/Til Death/Scripts/02 Branches.lua @@ -13,6 +13,9 @@ function SMOnlineScreen() return "ScreenSMOnlineLogin" end end + if not IsSMOnlineLoggedIn(pn) then + return "ScreenSMOnlineLogin" + end return "ScreenNetRoom" end @@ -133,8 +136,8 @@ Branch = { if not IsSMOnlineLoggedIn(PLAYER_1) then return "ScreenNetSelectProfile" else - return "ScreenNetRoom" - end + return "ScreenNetRoom" -- cant do this, we need to select a local profile even + end -- if logged into smo -mina else return "ScreenNetworkOptions" end @@ -291,6 +294,9 @@ Branch = { if PROFILEMAN:GetProfile(1):GetDisplayName() == "" then -- this is suuuuper hacky and will mess with people using "" as display names, but they're idiots anyway -mina return "ScreenTitleMenu" end + if IsSMOnlineLoggedIn(PLAYER_1) then + return "ScreenNetSelectMusic" + end return "ScreenSelectMusic" end } diff --git a/Themes/Til Death/metrics.ini b/Themes/Til Death/metrics.ini index 89db219dee..371e7ad3f0 100644 --- a/Themes/Til Death/metrics.ini +++ b/Themes/Til Death/metrics.ini @@ -832,6 +832,9 @@ LineHelpMenu="lua,HelpMenu()" LineNPSWindow="lua,NPSWindow()" LineMeasureLines="lua,MeasureLines()" +[ScreenNetworkOptions] +NextScreen=Branch.MultiScreen() + [ScreenThemeColorChange] Fallback="ScreenTextEntry" diff --git a/src/ScreenNetworkOptions.cpp b/src/ScreenNetworkOptions.cpp index ffe05dbe15..2b8389692e 100644 --- a/src/ScreenNetworkOptions.cpp +++ b/src/ScreenNetworkOptions.cpp @@ -171,7 +171,7 @@ ScreenNetworkOptions::ExportOptions(int /* iRow */, void ScreenNetworkOptions::UpdateConnectStatus() { - SCREENMAN->SetNewScreen(m_sName); + SCREENMAN->SetNewScreen(THEME->GetMetric(m_sName, "NextScreen")); } #endif From 700d5512ecca1ad156ab8e32a9679db78dfde23a Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 01:29:18 -0500 Subject: [PATCH 129/320] unbreak previewseek for multi rooms --- Themes/Til Death/BGAnimations/_chartpreview.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/_chartpreview.lua b/Themes/Til Death/BGAnimations/_chartpreview.lua index 8c0b7419fe..f8152af28f 100644 --- a/Themes/Til Death/BGAnimations/_chartpreview.lua +++ b/Themes/Til Death/BGAnimations/_chartpreview.lua @@ -10,7 +10,8 @@ local yeet local cd local function UpdatePreviewPos(self) - if noteField and yeet and SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" then + if noteField and yeet and SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" or + noteField and yeet and SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then local pos = SCREENMAN:GetTopScreen():GetPreviewNoteFieldMusicPosition() / musicratio self:GetChild("Pos"):zoomto(math.min(pos,wodth), hidth) self:queuecommand("Highlight") From 5d880bc4a1f8f7e6cd0c5f8ea80ccea8030c5ff4 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Thu, 29 Nov 2018 00:42:03 -0600 Subject: [PATCH 130/320] Make the color picker allow arrow key input --- Themes/Til Death/metrics.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Themes/Til Death/metrics.ini b/Themes/Til Death/metrics.ini index 371e7ad3f0..153c5c6196 100644 --- a/Themes/Til Death/metrics.ini +++ b/Themes/Til Death/metrics.ini @@ -309,10 +309,10 @@ Fallback="ScreenWithMenuElements" PrevScreen="ScreenTitleMenu" CodeNames="ColorUp,ColorDown,ColorLeft,ColorRight,ColorCancel,ColorStart" -CodeColorUp="Up" -CodeColorDown="Down" -CodeColorLeft="Left" -CodeColorRight="Right" +CodeColorUp="MenuUp" +CodeColorDown="MenuDown" +CodeColorLeft="MenuLeft" +CodeColorRight="MenuRight" CodeColorCancel="Back" CodeColorStart="Start" From ea54daf2554c00afbc5312d3c8327e8cac54d870 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 02:12:35 -0500 Subject: [PATCH 131/320] refactor mousescroll a bit and fix multi use when songs are selected --- .../BGAnimations/_mousewheelscroll.lua | 44 ++++++++----------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua index 62691e6a98..272fd09cac 100644 --- a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua +++ b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua @@ -4,37 +4,31 @@ local pressingtab = false local top local function scrollInput(event) - if top:GetSelectionState() == 2 then - return + if top:GetName() == "ScreenSelectmusic" then + if top:GetSelectionState() == 2 then + return + end elseif event.DeviceInput.button == "DeviceButton_tab" then if event.type == "InputEventType_FirstPress" then pressingtab = true elseif event.type == "InputEventType_Release" then pressingtab = false end - elseif - event.DeviceInput.button == "DeviceButton_mousewheel up" and event.type == "InputEventType_FirstPress" and - top:GetSelectionState() ~= 2 - then - moving = true - if pressingtab == true then - whee:Move(-2) - elseif whee:IsSettled() then - whee:Move(-1) - else - whee:Move(-1) - end - elseif - event.DeviceInput.button == "DeviceButton_mousewheel down" and event.type == "InputEventType_FirstPress" and - top:GetSelectionState() ~= 2 - then - moving = true - if pressingtab == true then - whee:Move(2) - elseif whee:IsSettled() then - whee:Move(1) - else - whee:Move(1) + elseif event.type == "InputEventType_FirstPress" then + if event.DeviceInput.button == "DeviceButton_mousewheel up" then + moving = true + if pressingtab == true and not whee:IsSettled() then + whee:Move(2) + else + whee:Move(1) + end + elseif event.DeviceInput.button == "DeviceButton_mousewheel down" then + moving = true + if pressingtab == true and not whee:IsSettled() then + whee:Move(2) + else + whee:Move(1) + end end elseif moving == true then whee:Move(0) From 64a911040f4c42828ee94efbc6d4f6ead3b87fd3 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 02:34:16 -0500 Subject: [PATCH 132/320] copypastagoof --- Themes/Til Death/BGAnimations/_mousewheelscroll.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua index 272fd09cac..56c33ebdc6 100644 --- a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua +++ b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua @@ -18,9 +18,9 @@ local function scrollInput(event) if event.DeviceInput.button == "DeviceButton_mousewheel up" then moving = true if pressingtab == true and not whee:IsSettled() then - whee:Move(2) + whee:Move(-2) else - whee:Move(1) + whee:Move(-1) end elseif event.DeviceInput.button == "DeviceButton_mousewheel down" then moving = true From 6803d0a0c4e2391f012c50a01d784c01225fa19c Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 05:04:56 -0300 Subject: [PATCH 133/320] Remove SMOProtocol --- src/NetworkSyncManager.cpp | 833 ----------------------------------- src/NetworkSyncManager.h | 61 --- src/ScreenGameplay.cpp | 11 +- src/ScreenGameplay.h | 6 - src/ScreenNetRoom.cpp | 4 - src/ScreenNetSelectBase.cpp | 1 - src/ScreenNetSelectMusic.cpp | 6 +- src/ScreenSMOnlineLogin.cpp | 35 -- src/ScreenSelectMusic.cpp | 50 ++- 9 files changed, 32 insertions(+), 975 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 746c9db4c9..f7648177a2 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -214,7 +214,6 @@ AutoScreenMessage(SM_ChangeSong); AutoScreenMessage(SM_GotEval); AutoScreenMessage(SM_UsersUpdate); AutoScreenMessage(SM_FriendsUpdate); -AutoScreenMessage(SM_SMOnlinePack); AutoScreenMessage(ETTP_Disconnect); AutoScreenMessage(ETTP_LoginResponse); @@ -232,15 +231,6 @@ static LocalizedString CONNECTION_SUCCESSFUL("NetworkSyncManager", static LocalizedString CONNECTION_FAILED("NetworkSyncManager", "Connection failed."); -SMOProtocol::SMOProtocol() -{ - NetPlayerClient = new EzSockets; - NetPlayerClient->blocking = false; - BroadcastReception = new EzSockets; - BroadcastReception->create(IPPROTO_UDP); - BroadcastReception->bind(8765); - BroadcastReception->blocking = false; -} static LocalizedString INITIALIZING_CLIENT_NETWORK( "NetworkSyncManager", "Initializing Client Network..."); @@ -265,18 +255,6 @@ NetworkSyncManager::NetworkSyncManager(LoadingWindow* ld) } } -SMOProtocol::~SMOProtocol() -{ - if (NetPlayerClient) { - NetPlayerClient->close(); - SAFE_DELETE(NetPlayerClient); - } - - if (BroadcastReception != nullptr) { - BroadcastReception->close(); - SAFE_DELETE(BroadcastReception); - } -} NetworkSyncManager::~NetworkSyncManager() {} void @@ -328,49 +306,6 @@ NetworkSyncManager::OffEval() curProtocol->OffEval(); } -void -SMOProtocol::OffEval() -{ - ReportNSSOnOff(4); -} -void -SMOProtocol::OnEval() -{ - ReportNSSOnOff(5); -} -void -SMOProtocol::OnMusicSelect() -{ - ReportNSSOnOff(1); - ReportPlayerOptions(); -} -void -SMOProtocol::OffMusicSelect() -{ - ReportNSSOnOff(0); -} -void -SMOProtocol::OffRoomSelect() -{ - ReportNSSOnOff(6); -} -void -SMOProtocol::OnRoomSelect() -{ - ReportNSSOnOff(7); -} -void -SMOProtocol::OnOptions() -{ - ReportNSSOnOff(3); -} -void -SMOProtocol::OffOptions() -{ - ReportNSSOnOff(1); - ReportPlayerOptions(); -} - void ETTProtocol::OffEval() { @@ -416,14 +351,6 @@ ETTProtocol::OffOptions() state = 0; } -void -SMOProtocol::close() -{ - serverVersion = 0; - serverName = ""; - NetPlayerClient->close(); -} - void ETTProtocol::close() { @@ -462,7 +389,6 @@ NetworkSyncManager::CloseConnection() m_sArtist = ""; difficulty = Difficulty_Invalid; meter = -1; - SMOP.close(); ETTP.close(); curProtocol = nullptr; MESSAGEMAN->Broadcast("MultiplayerDisconnection"); @@ -505,10 +431,6 @@ NetworkSyncManager::PostStartUp(const RString& ServerIP) if (ETTP.Connect(this, iPort, sAddress)) curProtocol = &ETTP; - else - - if (SMOP.Connect(this, iPort, sAddress)) - curProtocol = &SMOP; if (curProtocol == nullptr) return; g_sLastServer.Set(ServerIP); @@ -1046,68 +968,6 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) newMessages.clear(); } -bool -SMOProtocol::TryConnect(unsigned short port, RString address) -{ - NetPlayerClient->create(); // Initialize Socket - return NetPlayerClient->connect(address, port); -} - -bool -SMOProtocol::Connect(NetworkSyncManager* n, - unsigned short port, - RString address) -{ - if (!EzSockets::CanConnect(address, port) || !TryConnect(port, address)) { - n->m_startupStatus = 2; - LOG->Warn("SMOProtocol failed to connect"); - return false; - } - - // If network play is desired and the connection works, - // halt until we know what server version we're dealing with - - m_packet.ClearPacket(); - m_packet.Write1(NSCHello); // Hello Packet - m_packet.Write1(NETPROTOCOLVERSION); - m_packet.WriteNT(RString(string(PRODUCT_FAMILY) + product_version)); - - /* Block until response is received. - * Move mode to blocking in order to give CPU back to the system, - * and not wait. - */ - bool dontExit = true; - NetPlayerClient->blocking = true; - - // The following packet must get through, so we block for it. - // If we are serving, we do not block for this. - NetPlayerClient->SendPack(reinterpret_cast(m_packet.Data), - m_packet.Position); - m_packet.ClearPacket(); - while (dontExit) { - m_packet.ClearPacket(); - if (NetPlayerClient->ReadPack(reinterpret_cast(&m_packet), - NETMAXBUFFERSIZE) < 1) - dontExit = - false; // Also allow exit if there is a problem on the socket - if (m_packet.Read1() == NSServerOffset + NSCHello) - dontExit = false; - // Only allow passing on handshake; otherwise scoreboard updates and - // such will confuse us. - } - - NetPlayerClient->blocking = false; - serverVersion = m_packet.Read1(); - if (serverVersion >= 128) - n->isSMOnline = true; - serverName = m_packet.ReadNT(); - m_iSalt = m_packet.Read4(); - RString sMessage = - ssprintf(CONNECTION_SUCCESSFUL.GetValue(), serverName.c_str()); - SCREENMAN->SystemMessage(sMessage); - return true; -} - void NetworkSyncManager::StartUp() { @@ -1125,15 +985,6 @@ NetworkSyncManager::ReportNSSOnOff(int i) if (curProtocol != nullptr) curProtocol->ReportNSSOnOff(i); } -void -SMOProtocol::ReportNSSOnOff(int i) -{ - m_packet.ClearPacket(); - m_packet.Write1(NSCSMS); - m_packet.Write1((uint8_t)i); - NetPlayerClient->SendPack(reinterpret_cast(m_packet.Data), - m_packet.Position); -} RString NetworkSyncManager::GetServerName() @@ -1141,109 +992,6 @@ NetworkSyncManager::GetServerName() return curProtocol != nullptr ? curProtocol->serverName : ""; } -void -SMOProtocol::DealWithSMOnlinePack(PacketFunctions& SMOnlinePacket, - ScreenNetSelectMusic* s) -{ - if (SMOnlinePacket.Read1() == 1) { - switch (SMOnlinePacket.Read1()) { - case 0: // Room title Change - { - RString titleSub; - titleSub = SMOnlinePacket.ReadNT() + "\n"; - titleSub += SMOnlinePacket.ReadNT(); - if (SMOnlinePacket.Read1() != 1) { - RString SMOnlineSelectScreen = THEME->GetMetric( - "ScreenNetSelectMusic", "RoomSelectScreen"); - SCREENMAN->SetNewScreen(SMOnlineSelectScreen); - } - } - } - } -} - -int -SMOProtocol::DealWithSMOnlinePack(PacketFunctions& SMOnlinePacket, - ScreenSMOnlineLogin* s, - RString& response) -{ - int ResponseCode = SMOnlinePacket.Read1(); - if (ResponseCode == 0) { - int Status = SMOnlinePacket.Read1(); - if (Status == 0) { - NSMAN->loggedIn = true; - SCREENMAN->SetNewScreen( - THEME->GetMetric("ScreenSMOnlineLogin", "NextScreen")); - return 2; - } else { - response = SMOnlinePacket.ReadNT(); - return 3; - } - } - return 4; -} - -void -SMOProtocol::DealWithSMOnlinePack(PacketFunctions& SMOnlinePacket, - ScreenNetRoom* s) -{ - switch (SMOnlinePacket.Read1()) { - case 1: - switch (SMOnlinePacket.Read1()) { - case 0: // Room title Change - { - RString title, subtitle; - title = SMOnlinePacket.ReadNT(); - subtitle = SMOnlinePacket.ReadNT(); - - Message msg(MessageIDToString(Message_UpdateScreenHeader)); - msg.SetParam("Header", title); - msg.SetParam("Subheader", subtitle); - MESSAGEMAN->Broadcast(msg); - - if (SMOnlinePacket.Read1() != 0) { - RString SMOnlineSelectScreen = THEME->GetMetric( - "ScreenNetRoom", "MusicSelectScreen"); - SCREENMAN->SetNewScreen(SMOnlineSelectScreen); - } - } break; - case 1: // Rooms list change - { - int numRooms = SMOnlinePacket.Read1(); - (NSMAN->m_Rooms).clear(); - for (int i = 0; i < numRooms; ++i) { - RoomData tmpRoomData; - tmpRoomData.SetName(SMOnlinePacket.ReadNT()); - tmpRoomData.SetDescription(SMOnlinePacket.ReadNT()); - (NSMAN->m_Rooms).push_back(tmpRoomData); - } - // Abide by protocol and read room status - for (int i = 0; i < numRooms; ++i) - (NSMAN->m_Rooms)[i].SetState(SMOnlinePacket.Read1()); - - for (int i = 0; i < numRooms; ++i) - (NSMAN->m_Rooms)[i].SetFlags(SMOnlinePacket.Read1()); - - s->UpdateRoomsList(); - } break; - } - break; - case 3: - RoomInfo info; - info.songTitle = SMOnlinePacket.ReadNT(); - info.songSubTitle = SMOnlinePacket.ReadNT(); - info.songArtist = SMOnlinePacket.ReadNT(); - info.numPlayers = SMOnlinePacket.Read1(); - info.maxPlayers = SMOnlinePacket.Read1(); - info.players.resize(info.numPlayers); - for (int i = 0; i < info.numPlayers; ++i) - info.players[i] = SMOnlinePacket.ReadNT(); - - s->m_roomInfo.SetRoomInfo(info); - break; - } -} - void NetworkSyncManager::Logout() { @@ -1358,23 +1106,6 @@ ETTProtocol::Login(RString user, RString pass) SCREENMAN->SendMessageToTopScreen(ETTP_LoginResponse); }; } -void -SMOProtocol::Login(RString user, RString pass) -{ - RString HashedName = NSMAN->MD5Hex(pass); - int authMethod = 0; - if (m_iSalt != 0) { - authMethod = 1; - HashedName = NSMAN->MD5Hex(HashedName + ssprintf("%d", m_iSalt)); - } - SMOnlinePacket.ClearPacket(); - SMOnlinePacket.Write1((uint8_t)0); // Login command - SMOnlinePacket.Write1((uint8_t)0); // Player - SMOnlinePacket.Write1((uint8_t)authMethod); // MD5 hash style - SMOnlinePacket.WriteNT(user); - SMOnlinePacket.WriteNT(HashedName); - SendSMOnline(); -} void NetworkSyncManager::ReportScore(int playerID, @@ -1389,56 +1120,6 @@ NetworkSyncManager::ReportScore(int playerID, this, playerID, step, score, combo, offset, numNotes); } void -SMOProtocol::ReportScore(NetworkSyncManager* n, - int playerID, - int step, - int score, - int combo, - float offset, - int numNotes) -{ - if (!n->useSMserver) // Make sure that we are using the network - return; - - LOG->Trace("Player ID %i combo = %i", playerID, combo); - m_packet.ClearPacket(); - - m_packet.Write1(NSCGSU); - step = n->TranslateStepType(step); - uint8_t ctr = (uint8_t)(playerID * 16 + step - (SMOST_HITMINE - 1)); - m_packet.Write1(ctr); - - ctr = uint8_t(STATSMAN->m_CurStageStats.m_player[playerID].GetGrade() * 16 + - numNotes); - - if (STATSMAN->m_CurStageStats.m_player[playerID].m_bFailed) - ctr = - uint8_t(112); // Code for failed (failed constant seems not to work) - - m_packet.Write1(ctr); - m_packet.Write4(score); - m_packet.Write2((uint16_t)combo); - m_packet.Write2((uint16_t)n->m_playerLife); - - // Offset Info - // Note: if a 0 is sent, then disregard data. - - // ASSUMED: No step will be more than 16 seconds off center. - // If this assumption is false, read 16 seconds in either direction. - auto iOffset = int((offset + 16.384) * 2000.0f); - if (iOffset > 65535) - iOffset = 65535; - if (iOffset < 1) - iOffset = 1; - - // Report 0 if hold, or miss (don't forget mines should report) - if (step == SMOST_HITMINE || step > SMOST_W1) - iOffset = 0; - m_packet.Write2((uint16_t)iOffset); - NetPlayerClient->SendPack(reinterpret_cast(m_packet.Data), - m_packet.Position); -} -void NetworkSyncManager::ReportHighScore(HighScore* hs, PlayerStageStats& pss) { if (curProtocol != nullptr) @@ -1529,58 +1210,6 @@ NetworkSyncManager::ReportScore(int playerID, if (curProtocol != nullptr) curProtocol->ReportScore(this, playerID, step, score, combo, offset); } -void -SMOProtocol::ReportScore(NetworkSyncManager* n, - int playerID, - int step, - int score, - int combo, - float offset) -{ - if (!n->useSMserver) // Make sure that we are using the network - return; - - LOG->Trace("Player ID %i combo = %i", playerID, combo); - m_packet.ClearPacket(); - - m_packet.Write1(NSCGSU); - step = n->TranslateStepType(step); - uint8_t ctr = (uint8_t)(playerID * 16 + step - (SMOST_HITMINE - 1)); - m_packet.Write1(ctr); - - ctr = uint8_t(STATSMAN->m_CurStageStats.m_player[playerID].GetGrade() * 16); - - if (STATSMAN->m_CurStageStats.m_player[playerID].m_bFailed) - ctr = - uint8_t(112); // Code for failed (failed constant seems not to work) - - m_packet.Write1(ctr); - m_packet.Write4(score); - m_packet.Write2((uint16_t)combo); - m_packet.Write2((uint16_t)n->m_playerLife); - - // Offset Info - // Note: if a 0 is sent, then disregard data. - - // ASSUMED: No step will be more than 16 seconds off center. - // If this assumption is false, read 16 seconds in either direction. - auto iOffset = int((offset + 16.384) * 2000.0f); - - if (iOffset > 65535) - iOffset = 65535; - if (iOffset < 1) - iOffset = 1; - - // Report 0 if hold, or miss (don't forget mines should report) - if (step == SMOST_HITMINE || step > SMOST_W1) - iOffset = 0; - - m_packet.Write2((uint16_t)iOffset); - - NetPlayerClient->SendPack(reinterpret_cast(m_packet.Data), - m_packet.Position); -} - void NetworkSyncManager::ReportSongOver() { @@ -1597,41 +1226,12 @@ ETTProtocol::ReportSongOver(NetworkSyncManager* n) gameOver["id"] = msgId++; Send(gameOver); } -void -SMOProtocol::ReportSongOver(NetworkSyncManager* n) -{ - if (!n->useSMserver) // Make sure that we are using the network - return; - m_packet.ClearPacket(); - - m_packet.Write1(NSCGON); - - NetPlayerClient->SendPack(reinterpret_cast(&m_packet.Data), - m_packet.Position); - return; -} - void NetworkSyncManager::ReportStyle() { if (curProtocol != nullptr) curProtocol->ReportStyle(this); } -void -SMOProtocol::ReportStyle(NetworkSyncManager* n) -{ - LOG->Trace(R"(Sending "Style" to server)"); - - if (!n->useSMserver) - return; - m_packet.ClearPacket(); - m_packet.Write1(NSCSU); - m_packet.Write1((int8_t)GAMESTATE->GetNumPlayersEnabled()); - m_packet.Write1((uint8_t)PLAYER_1); - m_packet.WriteNT(GAMESTATE->GetPlayerDisplayName(PLAYER_1)); - NetPlayerClient->SendPack(reinterpret_cast(&m_packet.Data), - m_packet.Position); -} void NetworkSyncManager::StartRequest(short position) @@ -1641,125 +1241,6 @@ NetworkSyncManager::StartRequest(short position) if (curProtocol != nullptr) curProtocol->StartRequest(this, position); } -void -SMOProtocol::StartRequest(NetworkSyncManager* n, short position) -{ - if (!n->useSMserver) - return; - if (GAMESTATE->m_bDemonstrationOrJukebox) - return; - LOG->Trace("Requesting Start from Server."); - - m_packet.ClearPacket(); - m_packet.Write1(NSCGSR); - unsigned char ctr = 0; - - Steps* tSteps; - tSteps = GAMESTATE->m_pCurSteps[PLAYER_1]; - if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_1)) - ctr = uint8_t(ctr + tSteps->GetMeter() * 16); - - tSteps = GAMESTATE->m_pCurSteps[PLAYER_2]; - if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_2)) - ctr = uint8_t(ctr + tSteps->GetMeter()); - - m_packet.Write1(ctr); - ctr = 0; - - tSteps = GAMESTATE->m_pCurSteps[PLAYER_1]; - if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_1)) - ctr = uint8_t(ctr + (int)tSteps->GetDifficulty() * 16); - - tSteps = GAMESTATE->m_pCurSteps[PLAYER_2]; - if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_2)) - ctr = uint8_t(ctr + (int)tSteps->GetDifficulty()); - - m_packet.Write1(ctr); - // Notify server if this is for sync or not. - ctr = char(position * 16); - m_packet.Write1(ctr); - - if (GAMESTATE->m_pCurSong != NULL) { - m_packet.WriteNT(GAMESTATE->m_pCurSong->m_sMainTitle); - m_packet.WriteNT(GAMESTATE->m_pCurSong->m_sSubTitle); - m_packet.WriteNT(GAMESTATE->m_pCurSong->m_sArtist); - } else { - m_packet.WriteNT(""); - m_packet.WriteNT(""); - m_packet.WriteNT(""); - } - - m_packet.WriteNT(RString()); - - // Send Player (and song) Options - m_packet.WriteNT(GAMESTATE->m_SongOptions.GetCurrent().GetString()); - - int players = 0; - FOREACH_PlayerNumber(p) - { - ++players; - m_packet.WriteNT(GAMESTATE->m_pPlayerState[p] - ->m_PlayerOptions.GetCurrent() - .GetString()); - } - for (int i = 0; i < 2 - players; ++i) - m_packet.WriteNT(""); // Write a NULL if no player - - // Send chartkey - if (serverVersion >= 129) { - tSteps = GAMESTATE->m_pCurSteps[PLAYER_1]; - if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_1)) { - m_packet.WriteNT(tSteps->GetChartKey()); - } else { - m_packet.WriteNT(""); - } - - tSteps = GAMESTATE->m_pCurSteps[PLAYER_2]; - if (tSteps != NULL && GAMESTATE->IsPlayerEnabled(PLAYER_2)) { - m_packet.WriteNT(tSteps->GetChartKey()); - } else { - m_packet.WriteNT(""); - } - - int rate = - (int)(GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate * 100); - m_packet.Write1(rate); - m_packet.WriteNT(GAMESTATE->m_pCurSong->GetFileHash()); - } - - // Block until go is recieved. - // Switch to blocking mode (this is the only - // way I know how to get precievably instantanious results - - bool dontExit = true; - - NetPlayerClient->blocking = true; - - // The following packet HAS to get through, so we turn blocking on for it as - // well Don't block if we are serving - NetPlayerClient->SendPack(reinterpret_cast(&m_packet.Data), - m_packet.Position); - - LOG->Trace("Waiting for RECV"); - - m_packet.ClearPacket(); - - while (dontExit) { - m_packet.ClearPacket(); - if (NetPlayerClient->ReadPack(reinterpret_cast(&m_packet), - NETMAXBUFFERSIZE) < 1) - dontExit = - false; // Also allow exit if there is a problem on the socket - // Only do if we are not the server, otherwise the sync - // gets hosed up due to non blocking mode. - - if (m_packet.Read1() == (NSServerOffset + NSCGSR)) - dontExit = false; - // Only allow passing on Start request; otherwise scoreboard updates - // and such will confuse us. - } - NetPlayerClient->blocking = false; -} void NetworkSyncManager::DisplayStartupStatus() @@ -1790,245 +1271,9 @@ NetworkSyncManager::Update(float fDeltaTime) if (curProtocol != nullptr) curProtocol->Update(this, fDeltaTime); } -void -SMOProtocol::Update(NetworkSyncManager* n, float fDeltaTime) -{ - if (n->useSMserver) - ProcessInput(n); - else - return; - PacketFunctions BroadIn; - if (BroadcastReception->ReadPack(reinterpret_cast(&BroadIn.Data), - 1020) != 0) { - NetServerInfo ThisServer; - BroadIn.Position = 0; - if (BroadIn.Read1() == 141) // SMLS_Info? - { - ThisServer.Name = BroadIn.ReadNT(); - int port = BroadIn.Read2(); - BroadIn.Read2(); // Num players connected. - uint32_t addy = - EzSockets::LongFromAddrIn(BroadcastReception->fromAddr); - ThisServer.Address = ssprintf("%u.%u.%u.%u:%d", - (addy << 0) >> 24, - (addy << 8) >> 24, - (addy << 16) >> 24, - (addy << 24) >> 24, - port); - - // It's fairly safe to assume that users will not be on networks - // with more than 30 or 40 servers. Until this point, maps would - // be slower than vectors. So I am going to use a vector to store - // all of the servers. - // - // In this situation, I will traverse the vector to find the element - // that contains the corresponding server. - - unsigned int i; - for (i = 0; i < n->m_vAllLANServers.size(); i++) { - if (n->m_vAllLANServers[i].Address == ThisServer.Address) { - n->m_vAllLANServers[i].Name = ThisServer.Name; - break; - } - } - if (i >= n->m_vAllLANServers.size()) - n->m_vAllLANServers.push_back(ThisServer); - } - } -} static LocalizedString CONNECTION_DROPPED("NetworkSyncManager", "Connection to server dropped."); -void -SMOProtocol::ProcessInput(NetworkSyncManager* n) -{ - // If we're disconnected, just exit - if ((NetPlayerClient->state != NetPlayerClient->skCONNECTED) || - NetPlayerClient->IsError()) { - SCREENMAN->SystemMessageNoAnimate(CONNECTION_DROPPED); - n->useSMserver = false; - n->isSMOnline = false; - n->loggedIn = false; - NetPlayerClient->close(); - MESSAGEMAN->Broadcast("MultiplayerDisconnection"); - return; - } - - // load new data into buffer - NetPlayerClient->update(); - m_packet.ClearPacket(); - - int packetSize; - while ((packetSize = NetPlayerClient->ReadPack( - reinterpret_cast(&m_packet), NETMAXBUFFERSIZE)) > 0) { - m_packet.size = packetSize; - int command = m_packet.Read1(); - // Check to make sure command is valid from server - if (command < NSServerOffset) { - LOG->Trace("CMD (below 128) Invalid> %d", command); - break; - } - - command = command - NSServerOffset; - - switch (command) { - case NSCPing: // Ping packet responce - m_packet.ClearPacket(); - m_packet.Write1(NSCPingR); - NetPlayerClient->SendPack( - reinterpret_cast(m_packet.Data), m_packet.Position); - break; - case NSCPingR: // These are in response to when/if we send packet - // 0's - case NSCHello: // This is already taken care of by the blocking code - // earlier - case NSCGSR: // This is taken care of by the blocking start code - break; - case NSCGON: { - int PlayersInPack = m_packet.Read1(); - n->m_EvalPlayerData.resize(PlayersInPack); - for (int i = 0; i < PlayersInPack; ++i) - n->m_EvalPlayerData[i].name = m_packet.Read1(); - for (int i = 0; i < PlayersInPack; ++i) - n->m_EvalPlayerData[i].score = m_packet.Read4(); - for (int i = 0; i < PlayersInPack; ++i) - n->m_EvalPlayerData[i].grade = m_packet.Read1(); - for (int i = 0; i < PlayersInPack; ++i) - n->m_EvalPlayerData[i].difficulty = - (Difficulty)m_packet.Read1(); - for (int j = 0; j < NETNUMTAPSCORES; ++j) - for (int i = 0; i < PlayersInPack; ++i) - n->m_EvalPlayerData[i].tapScores[j] = m_packet.Read2(); - for (int i = 0; i < PlayersInPack; ++i) - n->m_EvalPlayerData[i].playerOptions = m_packet.ReadNT(); - SCREENMAN->SendMessageToTopScreen(SM_GotEval); - } break; - case NSCGSU: // Scoreboard Update - { // Ease scope - int ColumnNumber = m_packet.Read1(); - int NumberPlayers = m_packet.Read1(); - RString ColumnData; - - switch (ColumnNumber) { - case NSSB_NAMES: - ColumnData = "Names\n"; - for (int i = 0; i < NumberPlayers; ++i) - ColumnData += - n->m_PlayerNames[m_packet.Read1()] + "\n"; - break; - case NSSB_COMBO: - ColumnData = "Combo\n"; - for (int i = 0; i < NumberPlayers; ++i) - ColumnData += ssprintf("%d\n", m_packet.Read2()); - break; - case NSSB_GRADE: - ColumnData = "Grade\n"; - for (int i = 0; i < NumberPlayers; i++) - ColumnData += - GradeToLocalizedString(Grade(m_packet.Read1())) + - "\n"; - break; - } - n->m_Scoreboard[ColumnNumber] = ColumnData; - n->m_scoreboardchange[ColumnNumber] = true; - /* - Message msg("ScoreboardUpdate"); - msg.SetParam( "NumPlayers", NumberPlayers ); - MESSAGEMAN->Broadcast( msg ); - */ - } break; - case NSCSU: // System message from server - { - RString SysMSG = m_packet.ReadNT(); - SCREENMAN->SystemMessage(SysMSG); - } break; - case NSCCM: // Chat message from server - { - n->m_sChatText += m_packet.ReadNT() + " \n "; - // 10000 chars backlog should be more than enough - n->m_sChatText = n->m_sChatText.Right(10000); - SCREENMAN->SendMessageToTopScreen(SM_AddToChat); - } break; - case NSCRSG: // Select Song/Play song - { - n->m_EvalPlayerData.clear(); - n->m_iSelectMode = m_packet.Read1(); - n->m_sMainTitle = m_packet.ReadNT(); - n->m_sArtist = m_packet.ReadNT(); - n->m_sSubTitle = m_packet.ReadNT(); - // Read songhash - if (serverVersion >= 129) { - n->m_sFileHash = m_packet.ReadNT(); - } - SCREENMAN->SendMessageToTopScreen(SM_ChangeSong); - SCREENMAN->SendMessageToTopScreen(SM_ChangeSong); - } break; - case NSCUUL: { - /*int ServerMaxPlayers=*/m_packet.Read1(); - int PlayersInThisPacket = m_packet.Read1(); - n->m_ActivePlayer.clear(); - n->m_PlayerStatus.clear(); - n->m_PlayerNames.clear(); - n->m_ActivePlayers = 0; - for (int i = 0; i < PlayersInThisPacket; ++i) { - int PStatus = m_packet.Read1(); - if (PStatus > 0) { - n->m_ActivePlayers++; - n->m_ActivePlayer.push_back(i); - } - n->m_PlayerStatus.push_back(PStatus); - n->m_PlayerNames.push_back(m_packet.ReadNT()); - } - SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); - } break; - case NSCSMS: { - RString StyleName, GameName; - GameName = m_packet.ReadNT(); - StyleName = m_packet.ReadNT(); - - GAMESTATE->SetCurGame(GAMEMAN->StringToGame(GameName)); - GAMESTATE->SetCurrentStyle(GAMEMAN->GameAndStringToStyle( - GAMESTATE->m_pCurGame, StyleName), - PLAYER_INVALID); - - SCREENMAN->SetNewScreen( - "ScreenNetSelectMusic"); // Should this be metric'd out? - } break; - case NSCSMOnline: { - SMOnlinePacket.size = packetSize - 1; - SMOnlinePacket.Position = 0; - memcpy( - SMOnlinePacket.Data, (m_packet.Data + 1), packetSize - 1); - LOG->Trace("Received SMOnline Command: %d, size:%d", - command, - packetSize - 1); - SCREENMAN->SendMessageToTopScreen(SM_SMOnlinePack); - } break; - case NSCAttack: { - PlayerNumber iPlayerNumber = (PlayerNumber)m_packet.Read1(); - - if (GAMESTATE->IsPlayerEnabled(iPlayerNumber)) // There was an - // attack here, - // now there isnt - { - } - m_packet.ClearPacket(); - } break; - case FLU: { - int PlayersInThisPacket = m_packet.Read1(); - n->fl_PlayerNames.clear(); - n->fl_PlayerStates.clear(); - for (int i = 0; i < PlayersInThisPacket; ++i) { - int PStatus = m_packet.Read1(); - n->fl_PlayerStates.push_back(PStatus); - n->fl_PlayerNames.push_back(m_packet.ReadNT()); - } - SCREENMAN->SendMessageToTopScreen(SM_FriendsUpdate); - } break; - } - m_packet.ClearPacket(); - } -} bool NetworkSyncManager::ChangedScoreboard(int Column) @@ -2045,27 +1290,6 @@ NetworkSyncManager::SendChat(const RString& message, string tab, int type) if (curProtocol != nullptr) curProtocol->SendChat(message, tab, type); } -void -SMOProtocol::SendChat(const RString& message, string tab, int type) -{ - m_packet.ClearPacket(); - m_packet.Write1(NSCCM); - m_packet.WriteNT(message); - NetPlayerClient->SendPack(reinterpret_cast(&m_packet.Data), - m_packet.Position); -} - -void -SMOProtocol::ReportPlayerOptions() -{ - ModsGroup& opts = - GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions; - m_packet.ClearPacket(); - m_packet.Write1(NSCUPOpts); - m_packet.WriteNT(opts.GetCurrent().GetString()); - NetPlayerClient->SendPack(reinterpret_cast(&m_packet.Data), - m_packet.Position); -} int NetworkSyncManager::GetServerVersion() @@ -2131,63 +1355,6 @@ ETTProtocol::SelectUserSong(NetworkSyncManager* n, Song* song) Send(selectChart); } } -void -SMOProtocol::SelectUserSong(NetworkSyncManager* n, Song* song) -{ - m_packet.ClearPacket(); - m_packet.Write1(NSCRSG); - m_packet.Write1((uint8_t)n->m_iSelectMode); - m_packet.WriteNT(n->m_sMainTitle); - m_packet.WriteNT(n->m_sArtist); - m_packet.WriteNT(n->m_sSubTitle); - // Send songhash - if (serverVersion >= 129) { - m_packet.WriteNT(GAMESTATE->m_pCurSong->GetFileHash()); - } - NetPlayerClient->SendPack(reinterpret_cast(&m_packet.Data), - m_packet.Position); -} - -void -SMOProtocol::SendSMOnline() -{ - m_packet.Position = SMOnlinePacket.Position + 1; - memcpy((m_packet.Data + 1), SMOnlinePacket.Data, SMOnlinePacket.Position); - m_packet.Data[0] = NSCSMOnline; - NetPlayerClient->SendPack(reinterpret_cast(&m_packet.Data), - m_packet.Position); -} -void -SMOProtocol::CreateNewRoom(RString name, RString desc, RString password) -{ - SMOnlinePacket.ClearPacket(); - SMOnlinePacket.Write1((uint8_t)2); // Create room command - SMOnlinePacket.Write1(1); // Type game room - SMOnlinePacket.WriteNT(name); - SMOnlinePacket.WriteNT(desc); - if (!password.empty()) - SMOnlinePacket.WriteNT(password); - SendSMOnline(); -} -void -SMOProtocol::EnterRoom(RString name, RString password) -{ - SMOnlinePacket.ClearPacket(); - SMOnlinePacket.Write1(1); - SMOnlinePacket.Write1(1); // Type (enter a room) - SMOnlinePacket.WriteNT(name); - if (!password.empty()) - SMOnlinePacket.WriteNT(password); - SendSMOnline(); -} -void -SMOProtocol::RequestRoomInfo(RString name) -{ - SMOnlinePacket.ClearPacket(); - SMOnlinePacket.Write1((uint8_t)3); // Request Room Info - SMOnlinePacket.WriteNT(name); - SendSMOnline(); -} void NetworkSyncManager::EnterRoom(RString name, RString password) diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index 843c0a9fee..2c2d5f23a6 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -227,66 +227,6 @@ class NetProtocol virtual void OnEval(){}; virtual void OffEval(){}; }; -class SMOProtocol : public NetProtocol -{ // Built on raw tcp - EzSockets* NetPlayerClient; - EzSockets* BroadcastReception; - PacketFunctions m_packet; - int m_iSalt; - bool TryConnect(unsigned short port, RString address); - void SendSMOnline(); - - public: - PacketFunctions SMOnlinePacket; - SMOProtocol(); - ~SMOProtocol(); - bool Connect(NetworkSyncManager* n, - unsigned short port, - RString address) override; // Connect and say hello - void close() override; - void Update(NetworkSyncManager* n, float fDeltaTime) override; - void SelectUserSong(NetworkSyncManager* n, Song* song) override; - void CreateNewRoom(RString name, RString desc, RString password) override; - void EnterRoom(RString name, RString password) override; - void RequestRoomInfo(RString name) override; - void ReportPlayerOptions(); - void SendChat(const RString& message, string tab, int type) override; - void ReportNSSOnOff(int i) override; - void ReportScore(NetworkSyncManager* n, - int playerID, - int step, - int score, - int combo, - float offset, - int numNotes) override; - void ReportScore(NetworkSyncManager* n, - int playerID, - int step, - int score, - int combo, - float offset) override; - void ReportSongOver(NetworkSyncManager* n) override; - void ReportStyle(NetworkSyncManager* n) override; - void StartRequest(NetworkSyncManager* n, short position) override; - void ProcessInput(NetworkSyncManager* n); - void Login(RString user, RString pass) override; - void OnMusicSelect() override; - void OffMusicSelect() override; - void OnRoomSelect() override; - void OffRoomSelect() override; - void OnOptions() override; - void OffOptions() override; - void OnEval() override; - void OffEval() override; - - static void DealWithSMOnlinePack(PacketFunctions& SMOnlinePacket, - ScreenNetSelectMusic* s); - static void DealWithSMOnlinePack(PacketFunctions& SMOnlinePacket, - ScreenNetRoom* s); - static int DealWithSMOnlinePack(PacketFunctions& SMOnlinePacket, - ScreenSMOnlineLogin* s, - RString& response); -}; class ETTProtocol : public NetProtocol { // Websockets using uwebsockets sending json @@ -355,7 +295,6 @@ class NetworkSyncManager public: NetworkSyncManager(LoadingWindow* ld = NULL); ~NetworkSyncManager(); - SMOProtocol SMOP; ETTProtocol ETTP; NetProtocol* curProtocol{ nullptr }; // If "useSMserver" then send score to server diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index d47187fb24..2e1ed06ef3 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -301,7 +301,6 @@ ScreenGameplay::ScreenGameplay() { m_pSongBackground = NULL; m_pSongForeground = NULL; - m_bForceNoNetwork = !GAMESTATE->m_bInNetGameplay; m_delaying_ready_announce = false; GAMESTATE->m_AdjustTokensBySongCostForFinalStageCheck = false; #if !defined(WITHOUT_NETWORKING) @@ -575,7 +574,7 @@ ScreenGameplay::Init() // we need to wait, so that there is no Dead On Start issues. // if you wait too long at the second checkpoint, you will // appear dead when you begin your game. - if (!m_bForceNoNetwork) + if (GAMESTATE->m_bPlayingMulti) NSMAN->StartRequest(0); // Add individual life meter @@ -618,7 +617,7 @@ ScreenGameplay::Init() #if !defined(WITHOUT_NETWORKING) // Only used in SMLAN/SMOnline: - if (!m_bForceNoNetwork && NSMAN->useSMserver && + if (GAMESTATE->m_bPlayingMulti && NSMAN->useSMserver && GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StyleType != StyleType_OnePlayerTwoSides) { m_bShowScoreboard = PREFSMAN->m_bEnableScoreboard.Get(); @@ -892,7 +891,7 @@ ScreenGameplay::~ScreenGameplay() m_GameplayAssist.StopPlaying(); - if (!m_bForceNoNetwork) + if (GAMESTATE->m_bPlayingMulti) NSMAN->ReportSongOver(); #if !defined(WITHOUT_NETWORKING) DLMAN->UpdateDLSpeed(false); @@ -1338,7 +1337,7 @@ ScreenGameplay::BeginScreen() SOUND->PlayOnceFromAnnouncer("gameplay intro"); // crowd cheer // Get the transitions rolling - if (!m_bForceNoNetwork && NSMAN->useSMserver) { + if (GAMESTATE->m_bPlayingMulti && NSMAN->useSMserver) { // If we're using networking, we must not have any delay. If we do, // this can cause inconsistency on different computers and // different themes. @@ -1785,7 +1784,7 @@ ScreenGameplay::Update(float fDeltaTime) PlayTicks(); SendCrossedMessages(); - if (!m_bForceNoNetwork && NSMAN->useSMserver) { + if (GAMESTATE->m_bPlayingMulti && NSMAN->useSMserver) { FOREACH_EnabledPlayerNumberInfo(m_vPlayerInfo, pi) if (pi->m_pLifeMeter) NSMAN->m_playerLife = int(pi->m_pLifeMeter->GetLife() * 10000); diff --git a/src/ScreenGameplay.h b/src/ScreenGameplay.h index a479f1d8d1..fb3fb3361e 100644 --- a/src/ScreenGameplay.h +++ b/src/ScreenGameplay.h @@ -325,12 +325,6 @@ class ScreenGameplay : public ScreenWithMenuElements // announcer sound needs to be delayed. See HandleScreenMessage for more. // -Kyz bool m_delaying_ready_announce; - - // HACK: We have no idea whether we're actually using SMOnline or not. - // No, seriously, NOWHERE is it stored what room we're in or whether we're - // in a room at all. Apparently we just hope the server is keeping track. - // All we can do is guess based on what subclass we are. - bool m_bForceNoNetwork; }; vector::iterator diff --git a/src/ScreenNetRoom.cpp b/src/ScreenNetRoom.cpp index 883def53d3..93347fa1d5 100644 --- a/src/ScreenNetRoom.cpp +++ b/src/ScreenNetRoom.cpp @@ -11,7 +11,6 @@ #include "ThemeManager.h" #include "WheelItemBase.h" -AutoScreenMessage(SM_SMOnlinePack); AutoScreenMessage(SM_BackFromRoomName); AutoScreenMessage(SM_BackFromRoomDesc); AutoScreenMessage(SM_BackFromRoomPass); @@ -90,9 +89,6 @@ ScreenNetRoom::HandleScreenMessage(const ScreenMessage SM) if (!ScreenTextEntry::s_bCancelledLast) { NSMAN->EnterRoom(m_sLastPickedRoom, ScreenTextEntry::s_sLastAnswer); } - } else if (SM == SM_SMOnlinePack) { - SMOProtocol::DealWithSMOnlinePack( - static_cast(NSMAN->curProtocol)->SMOnlinePacket, this); } else if (SM == ETTP_RoomsChange) { UpdateRoomsList(); } else if (SM == SM_BackFromRoomName) { diff --git a/src/ScreenNetSelectBase.cpp b/src/ScreenNetSelectBase.cpp index 59f93a14fc..d9ff65e198 100644 --- a/src/ScreenNetSelectBase.cpp +++ b/src/ScreenNetSelectBase.cpp @@ -26,7 +26,6 @@ AutoScreenMessage(SM_AddToChat); AutoScreenMessage(SM_UsersUpdate); AutoScreenMessage(SM_FriendsUpdate); -AutoScreenMessage(SM_SMOnlinePack); REGISTER_SCREEN_CLASS(ScreenNetSelectBase); diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index 15a256ff67..2948deb1d1 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -35,7 +35,6 @@ AutoScreenMessage(SM_AddToChat); AutoScreenMessage(SM_FriendsUpdate); AutoScreenMessage(SM_NoSongs); AutoScreenMessage(SM_ChangeSong); -AutoScreenMessage(SM_SMOnlinePack); AutoScreenMessage(SM_SetWheelSong); AutoScreenMessage(SM_RefreshWheelLocation); AutoScreenMessage(SM_SongChanged); @@ -55,7 +54,7 @@ void ScreenNetSelectMusic::Init() { ScreenSelectMusic::Init(); - + GAMESTATE->m_bPlayingMulti = true; SAMPLE_MUSIC_PREVIEW_MODE.Load(m_sName, "SampleMusicPreviewMode"); MUSIC_WHEEL_TYPE.Load(m_sName, "MusicWheelType"); PLAYER_OPTIONS_SCREEN.Load(m_sName, "PlayerOptionsScreen"); @@ -433,9 +432,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) m_MusicWheel.Move(1); m_MusicWheel.Select(); } - } else if (SM == SM_SMOnlinePack) { - SMOProtocol::DealWithSMOnlinePack( - static_cast(NSMAN->curProtocol)->SMOnlinePacket, this); } else if (SM == SM_ConfirmDeleteSong) { if (ScreenPrompt::s_LastAnswer == ANSWER_YES) { OnConfirmSongDeletion(); diff --git a/src/ScreenSMOnlineLogin.cpp b/src/ScreenSMOnlineLogin.cpp index f0041a1c8c..489a620407 100644 --- a/src/ScreenSMOnlineLogin.cpp +++ b/src/ScreenSMOnlineLogin.cpp @@ -17,7 +17,6 @@ REGISTER_SCREEN_CLASS(ScreenSMOnlineLogin); -AutoScreenMessage(SM_SMOnlinePack); AutoScreenMessage(SM_PasswordDone); AutoScreenMessage(SM_UsernameDone); AutoScreenMessage(SM_NoProfilesDefined); @@ -165,40 +164,6 @@ ScreenSMOnlineLogin::HandleScreenMessage(const ScreenMessage SM) NULL); } } - } else if (SM == SM_SMOnlinePack) { - LOG->Trace("[ScreenSMOnlineLogin::HandleScreenMessage] SMOnlinePack"); - if (!GAMESTATE->IsPlayerEnabled(static_cast(m_iPlayer))) { - LuaHelpers::ReportScriptErrorFmt("Invalid player number: %i", - m_iPlayer); - return; - } - // This can cause problems in certain situations -aj - sLoginQuestion = - YOU_ARE_LOGGING_ON_AS.GetValue() + "\n" + - GAMESTATE->GetPlayerDisplayName((PlayerNumber)m_iPlayer) + "\n" + - ENTER_YOUR_PASSWORD.GetValue(); - RString Response; - switch (SMOProtocol::DealWithSMOnlinePack( - static_cast(NSMAN->curProtocol)->SMOnlinePacket, - this, - Response)) { - case 0: - SCREENMAN->SetNewScreen( - THEME->GetMetric(m_sName, "NextScreen")); - m_iPlayer = 0; - break; - case 1: - ScreenTextEntry::Password( - SM_PasswordDone, sLoginQuestion, NULL); - break; - case 2: - m_iPlayer = 0; - break; - case 3: - ScreenTextEntry::Password( - SM_PasswordDone, Response + "\n\n" + sLoginQuestion, NULL); - break; - } } else if (SM == SM_GoToNextScreen) { LOG->Trace("[ScreenSMOnlineLogin::HandleScreenMessage] GoToNextScreen"); vector v; diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 7022bef692..61117015cd 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -80,6 +80,7 @@ REGISTER_SCREEN_CLASS(ScreenSelectMusic); void ScreenSelectMusic::Init() { + GAMESTATE->m_bPlayingMulti = false; g_ScreenStartedLoadingAt.Touch(); if (PREFSMAN->m_sTestInitialScreen.Get() == m_sName) { GAMESTATE->m_PlayMode.Set(PLAY_MODE_REGULAR); @@ -1711,7 +1712,7 @@ class LunaScreenSelectMusic : public Luna auto* td = GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData(); // vector ihatemylife; auto nd = GAMESTATE->m_pCurSteps[PLAYER_1]->GetNoteData(); - auto nerv = nd.BuildAndGetNerv(); + auto nerv = nd.BuildAndGetNerv(); /* functionally dead code, may be removed -poco if (!hs->GetChordCohesion()) { for (auto r : nerv) @@ -1720,32 +1721,33 @@ class LunaScreenSelectMusic : public Luna } else { for (auto r : nerv) ihatemylife.emplace_back(r); - } + } */ - auto sdifs = td->BuildAndGetEtaner(nerv); - vector noterows; - for (auto t : timestamps) { - auto timestamptobeat = - td->GetBeatFromElapsedTime(t * hs->GetMusicRate()); - auto somenumberscaledbyoffsets = - sdifs[0] - (timestamps[0] * hs->GetMusicRate()); - timestamptobeat += somenumberscaledbyoffsets; - auto noterowfrombeat = BeatToNoteRow(timestamptobeat); - noterows.emplace_back(noterowfrombeat); - } - int noterowoffsetter = nerv[0] - noterows[0]; - for (auto& noterowwithoffset : noterows) + auto sdifs = td->BuildAndGetEtaner(nerv); + vector noterows; + for (auto t : timestamps) { + auto timestamptobeat = + td->GetBeatFromElapsedTime(t * hs->GetMusicRate()); + auto somenumberscaledbyoffsets = + sdifs[0] - (timestamps[0] * hs->GetMusicRate()); + timestamptobeat += somenumberscaledbyoffsets; + auto noterowfrombeat = BeatToNoteRow(timestamptobeat); + noterows.emplace_back(noterowfrombeat); + } + int noterowoffsetter = nerv[0] - noterows[0]; + for (auto& noterowwithoffset : noterows) noterowwithoffset += noterowoffsetter; GAMESTATE->SetProcessedTimingData(nullptr); - //hs->SetNoteRowVector(ihatemylife); - hs->SetNoteRowVector(noterows); - - // Since we keep misses on EO as 180ms, we need to convert them back. - auto offsets = hs->GetCopyOfOffsetVector(); - for (auto& offset : offsets) { - if (fabs(offset) >= .18f) - offset = -1.1f; // This is a miss to the replay reader. - } + // hs->SetNoteRowVector(ihatemylife); + hs->SetNoteRowVector(noterows); + + // Since we keep misses on EO as 180ms, we need to convert them + // back. + auto offsets = hs->GetCopyOfOffsetVector(); + for (auto& offset : offsets) { + if (fabs(offset) >= .18f) + offset = -1.1f; // This is a miss to the replay reader. + } hs->SetOffsetVector(offsets); } From d0af8d68c8e2cc817f15f01f52641842469a3bac Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 05:29:40 -0300 Subject: [PATCH 134/320] Finish removing smop --- src/GameState.h | 1 + src/ScreenGameplaySyncMachine.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/GameState.h b/src/GameState.h index f1d95b068c..1d1400dbbf 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -102,6 +102,7 @@ class GameState BroadcastOnChange m_PlayMode; // many screens display different info depending on this value + bool m_bPlayingMulti = false; bool m_bMultiplayer; int m_iNumMultiplayerNoteFields; bool DifficultiesLocked() const; diff --git a/src/ScreenGameplaySyncMachine.cpp b/src/ScreenGameplaySyncMachine.cpp index 15a6757833..ae52a5085c 100644 --- a/src/ScreenGameplaySyncMachine.cpp +++ b/src/ScreenGameplaySyncMachine.cpp @@ -17,9 +17,9 @@ REGISTER_SCREEN_CLASS(ScreenGameplaySyncMachine); void ScreenGameplaySyncMachine::Init() { - m_bForceNoNetwork = true; + GAMESTATE->m_bPlayingMulti = false; // The server crashes if syncing is attempted while connected to SMO. -Kyz - NSMAN->CloseConnection(); + NSMAN->ReportSongOver(); GAMESTATE->m_PlayMode.Set(PLAY_MODE_REGULAR); GAMESTATE->SetCurrentStyle( From da6e59a9d5ca28774fa07a5d4d10a01128136f5f Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 05:30:09 -0300 Subject: [PATCH 135/320] Rename xml uploaded servers node, add noterows to score uploads --- src/DownloadManager.cpp | 36 +++++++++++++++++++++++++++++------- src/DownloadManager.h | 4 +++- src/HighScore.cpp | 4 ++-- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 5ab95c572b..ca185cc1cd 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -966,6 +966,7 @@ DownloadManager::UploadScoreWithReplayData(HighScore* hs) vector offsets = hs->GetOffsetVector(); vector columns = hs->GetTrackVector(); vector types = hs->GetTapNoteTypeVector(); + vector rows = hs->GetNoteRowVector(); if (offsets.size() > 0) { replayString = "["; vector& timestamps = hs->timeStamps; @@ -974,7 +975,8 @@ DownloadManager::UploadScoreWithReplayData(HighScore* hs) replayString += to_string(timestamps[i]) + ","; replayString += to_string(1000.f * offsets[i]) + ","; replayString += to_string(columns[i]) + ","; - replayString += to_string(types[i]); + replayString += to_string(types[i]) + ","; + replayString += to_string(rows[i]); replayString += "],"; } replayString = @@ -1035,7 +1037,8 @@ DownloadManager::UploadScoreWithReplayData(HighScore* hs) return; } void // not tested exhaustively -mina -DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) +DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, + function callback) { if (!LoggedIn()) return; @@ -1054,6 +1057,7 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) vector offsets = hs->GetOffsetVector(); vector columns = hs->GetTrackVector(); vector types = hs->GetTapNoteTypeVector(); + auto& rows = hs->GetNoteRowVector(); if (offsets.size() > 0) { replayString = "["; @@ -1067,7 +1071,8 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) replayString += to_string(1000.f * offsets[i]); if (hs->GetReplayType() == 2) { replayString += "," + to_string(columns[i]) + ","; - replayString += to_string(types[i]); + replayString += to_string(types[i]) + ","; + replayString += to_string(rows[i]); } replayString += "],"; } @@ -1081,7 +1086,7 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) curlHandle, form, lastPtr, "replay_data", replayString); SetCURLPostToURL(curlHandle, url); curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); - auto done = [this, hs](HTTPRequest& req, CURLMsg*) { + auto done = [this, hs, callback](HTTPRequest& req, CURLMsg*) { long response_code; curl_easy_getinfo(req.handle, CURLINFO_RESPONSE_CODE, &response_code); json j; @@ -1123,6 +1128,7 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk) } } catch (exception e) { } + callback(); }; HTTPRequest* req = new HTTPRequest(curlHandle, done); SetCURLResultsString(curlHandle, &(req->result)); @@ -1865,14 +1871,30 @@ DownloadManager::UploadScores() if (!LoggedIn()) return false; auto scores = SCOREMAN->GetAllPBPtrs(); + deque toUpload; for (auto& vec : scores) { for (auto& scorePtr : vec) { - if (!scorePtr->IsUploadedToServer(serverURL.Get())) { - UploadScore(scorePtr); - scorePtr->AddUploadedServer(serverURL.Get()); + auto ts = scorePtr->GetTopScore(); + if ((ts == 1 || ts == 2) && + !scorePtr->IsUploadedToServer(serverURL.Get())) { + toUpload.emplace_back(scorePtr); } } } + function lambda; + lambda = [toUpload, lambda]() mutable { + auto& it = toUpload.begin(); + if (it != toUpload.end()) { + toUpload.pop_front(); + auto& hs = (*it); + DLMAN->UploadScoreWithReplayDataFromDisk( + hs->GetChartKey(), [hs, toUpload, lambda]() { + hs->AddUploadedServer(serverURL.Get()); + lambda(); + }); + } + }; + lambda(); return true; } diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 6dc1b4d613..f687927e74 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -246,7 +246,9 @@ class DownloadManager bool EncodeSpaces(string& str); void UploadScoreWithReplayData(HighScore* hs); - void UploadScoreWithReplayDataFromDisk(string sk); + void UploadScoreWithReplayDataFromDisk( + string sk, + function callback = function()); void UploadScore(HighScore* hs); bool ShouldUploadScores(); diff --git a/src/HighScore.cpp b/src/HighScore.cpp index e3ef15436c..2f63de7de1 100644 --- a/src/HighScore.cpp +++ b/src/HighScore.cpp @@ -320,7 +320,7 @@ HighScoreImpl::CreateNode() const pNode->AppendChild("NoChordCohesion", bNoChordCohesion); pNode->AppendChild("EtternaValid", bEtternaValid); if (!uploaded.empty()) { - XNode* pServerNode = pNode->AppendChild("Servers"); + XNode* pServerNode = pNode->AppendChild("Servs"); for (auto server : uploaded) pServerNode->AppendChild("server", server); } @@ -395,7 +395,7 @@ HighScoreImpl::CreateEttNode() const pNode->AppendChild("DateTime", dateTime.GetString()); pNode->AppendChild("TopScore", TopScore); if (!uploaded.empty()) { - XNode* pServerNode = pNode->AppendChild("Servers"); + XNode* pServerNode = pNode->AppendChild("Servs"); for (auto server : uploaded) pServerNode->AppendChild("server", server); } From bb1ccef29b63bd5cdb82f9d4262052df5ed0de81 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 05:30:28 -0300 Subject: [PATCH 136/320] lua doc thing --- Themes/_fallback/docs/Actor.luadoc | 397 +++++++++++++++-------------- 1 file changed, 203 insertions(+), 194 deletions(-) diff --git a/Themes/_fallback/docs/Actor.luadoc b/Themes/_fallback/docs/Actor.luadoc index 3b28323cd8..905dfd4da6 100644 --- a/Themes/_fallback/docs/Actor.luadoc +++ b/Themes/_fallback/docs/Actor.luadoc @@ -1,7 +1,7 @@ --- Basic Actor class -- @classmod Actor ---[[ +--[[-- This adds a wrapper state around the Actor, which is like wrapping the Actor in an ActorFrame, except that you can use it on any actor, and add or remove wrapper states in response to things that happen while the screen is being used. (wrapping an Actor in an ActorFrame normally requires setting it up before the screen starts)
The ActorFrame that is returned is the wrapper state, for convenience.
An Actor can have any number of wrapper states. Use GetWrapperState to access wrapper states for the actor. @@ -10,325 +10,334 @@ function Actor:AddWrapperState() end ---[[ +--[[-- Returns the number of wrapper states the actor has. @return ActorFrame --]] function Actor:GetNumWrapperStates() end ---[[ +--[[-- Returns the wrapper state at index i. Think of wrapper states with a higher index as being "further out". Actor is inside Wrapper 1, Wrapper 1 is inside Wrapper 2, Wrapper 2 is inside Wrapper 3, and so on. @return ActorFrame --]] function Actor:GetWrapperState(i) end ---[[ +--[[-- Removes the wrapper state at index i. @return --]] function Actor:RemoveWrapperState(int, i) end ---[[ +--[[-- Returns the Actor's parent, or nil if it doesn't have one. @return Actor --]] function Actor:GetParent() end ---[[ +--[[-- Returns the Actor's fake parent, or nil if it doesn't have one. @return Actor --]] function Actor:GetFakeParent() end ---[[ +--[[-- Sets the Actor's fake parent to p, or clears it if p is nil. @return --]] function Actor:SetFakeParent(Actor, p) end ---[[ +--[[-- Returns the Actor's visibility. @return bool --]] function Actor:GetVisible() end ---[[ +--[[-- Returns the Actor's x position. @return float --]] function Actor:GetX() end ---[[ +--[[-- Returns the Actor's y position. @return float --]] function Actor:GetY() end ---[[ +--[[-- Returns the Actor's z position. @return float --]] function Actor:GetZ() end ---[[ +--[[-- Returns what the Actor's x position will be when it reaches its destination tween state. @return float --]] function Actor:GetDestX() end ---[[ +--[[-- Returns what the Actor's y position will be when it reaches its destination tween state. @return float --]] function Actor:GetDestY() end ---[[ +--[[-- Returns what the Actor's z position will be when it reaches its destination tween state. @return float --]] function Actor:GetDestZ() end ---[[ +--[[-- Returns the Actor's zoom. @return float --]] function Actor:GetZoom() end ---[[ +--[[-- Returns the Actor's X zoom. @return float --]] function Actor:GetZoomX() end ---[[ +--[[-- Returns the Actor's Y zoom. @return float --]] function Actor:GetZoomY() end ---[[ +--[[-- Returns the Actor's Z zoom. @return float --]] function Actor:GetZoomZ() end ---[[ +--[[-- Sets Texture Filtering for an Actor to b. @return void --]] function Actor:SetTextureFiltering(bool, b) end ---[[ +--[[-- Plays the commands that follow at an accelerated rate (fRate * fRate), where fRate is in seconds. @return void --]] function Actor:accelerate(float, fRate) end ---[[ +--[[-- Adds a command to the Actor. @return void --]] function Actor:addcommand(string, sName, ActorCommand, cmd) end ---[[ +--[[-- Adds rot to the Actor's current x rotation. @return void --]] function Actor:addrotationx(float, rot) end ---[[ +--[[-- Adds rot to the Actor's current y rotation. @return void --]] function Actor:addrotationy(float, rot) end ---[[ +--[[-- Adds rot to the Actor's current z rotation. @return void --]] function Actor:addrotationz(float, rot) end ---[[ +--[[-- Adds xPos to the Actor's current x position. @return void --]] function Actor:addx(float, xPos) end ---[[ +--[[-- Adds yPos to the Actor's current y position. @return void --]] function Actor:addy(float, yPos) end ---[[ +--[[-- Adds zPos to the Actor's current z position. @return void --]] function Actor:addz(float, zPos) end ---[[ +--[[-- Sets the alignment of an Actor, where h and v are in the range 0..1. @return void --]] function Actor:align(h, v) end ---[[ +--[[-- Sets whether or not the Actor should animate. @return void --]] function Actor:animate(bool, b) end ---[[ +--[[-- Sets the Actor's aux value. (This can be a solution for coupling data with an Actor.) @return void --]] function Actor:aux(float, fAux) end ---[[ +--[[-- If true, cull the Actor's back faces. See also: . @return void --]] function Actor:backfacecull(bool, b) end ---[[ +--[[-- Sets the Actor's base alpha to fAlpha, where fAlpha is in the range 0..1. @return void --]] function Actor:basealpha(float, fAlpha) end ---[[ +--[[-- Sets the Actor's base X rotation to rot. @return void --]] function Actor:baserotationx(float, rot) end ---[[ +--[[-- Sets the Actor's base Y rotation to rot. @return void --]] function Actor:baserotationy(float, rot) end ---[[ +--[[-- Sets the Actor's base Z rotation to rot. @return void --]] function Actor:baserotationz(float, rot) end ---[[ +--[[-- Sets the Actor's base zoom to zoom. @return void --]] function Actor:basezoom(float, zoom) end ---[[ +--[[-- Sets the Actor's base X zoom to zoom. @return void --]] function Actor:basezoomx(float, zoom) end ---[[ +--[[-- Sets the Actor's base Y zoom to zoom. @return void --]] function Actor:basezoomy(float, zoom) end ---[[ +--[[-- Sets the Actor's base Z zoom to zoom. @return void --]] function Actor:basezoomz(float, zoom) end ---[[ +--[[-- Sets the Actor to use the specified blend mode. @return void --]] function Actor:blend(BlendMode, mode) end ---[[ +--[[-- Makes the Actor bob up and down. Can use to define different bobbing behavior. @return void --]] function Actor:bob() end ---[[ +--[[-- Makes the Actor bounce, similar to bob but with one point acting as the ground. Can use to define different bouncing behavior (with effectmagnitude values relating to x, y, and z movement). @return void --]] function Actor:bounce() end ---- +--[[-- + --]] function Actor:bounce(time) end ---- +--[[-- + --]] function Actor:bouncebegin(time) end ---- +--[[-- + --]] function Actor:bounceend(time) end ---- Centers an Actor on the screen. (equivalent to x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y) +--[[-- + Centers an Actor on the screen. (equivalent to x,SCREEN_CENTER_X;y,SCREEN_CENTER_Y) + --]] function Actor:Center(time) end ---- Centers an Actor on the X axis. (equivalent to x,SCREEN_CENTER_X) +--[[-- + Centers an Actor on the X axis. (equivalent to x,SCREEN_CENTER_X) + --]] function Actor:CenterX(time) end ---- Centers an Actor on the y axis. (equivalent to y,SCREEN_CENTER_Y) +--[[-- + Centers an Actor on the y axis. (equivalent to y,SCREEN_CENTER_Y) + --]] function Actor:CenterY(time) end ---[[ +--[[-- Determines if the z-buffer should be cleared or not. @return void --]] function Actor:clearzbuffer(bool, bClear) end ---[[ +--[[-- Combines multiple interpolators for complex tweens. tweens can either be a string like "linear,0.25,accelerate,0.75" or a table with tween information { {Type="linear", Percent=0.25, Bezier=nil}, {Type="accelerate", Percent=0.75, Bezier=nil} } @@ -339,217 +348,217 @@ end function Actor:compound(length, tweens) end ---[[ +--[[-- Crops percent of the Actor from the bottom, where percent is in the range 0..1. @return void --]] function Actor:cropbottom(float, percent) end ---[[ +--[[-- Crops percent of the Actor from the left, where percent is in the range 0..1. @return void --]] function Actor:cropleft(float, percent) end ---[[ +--[[-- Crops percent of the Actor from the right, where percent is in the range 0..1. @return void --]] function Actor:cropright(float, percent) end ---[[ +--[[-- Crops percent of the Actor from the top, where percent is in the range 0..1. @return void --]] function Actor:croptop(float, percent) end ---[[ +--[[-- Sets the Actor's cull mode to mode. @return void --]] function Actor:cullmode(CullMode, mode) end ---[[ +--[[-- Plays the commands that follow at an decelerated rate (1 - (1-fRate) * (1-fRate)), where fRate is in seconds. @return void --]] function Actor:decelerate(float, fRate) end ---[[ +--[[-- Set the Actor's diffuse color to c. @return void --]] function Actor:diffuse(color, c) end ---[[ +--[[-- Sets the Actor's alpha level to fAlpha, where fAlpha is in the range 0..1. @return void --]] function Actor:diffusealpha(float, fAlpha) end ---[[ +--[[-- Makes the Actor switch between two colors immediately. See Themerdocs/effect_colors.txt for an example. @return void --]] function Actor:diffuseblink() end ---[[ +--[[-- Sets the Actor's bottom edge color to c. @return void --]] function Actor:diffusebottomedge() end ---[[ +--[[-- Set the Actor's diffuse color to c, ignoring any alpha value in c. @return void --]] function Actor:diffusecolor(color, c) end ---[[ +--[[-- Sets the Actor's left edge color to c. @return void --]] function Actor:diffuseleftedge(color, c) end ---[[ +--[[-- Sets the Actor's lower left corner color to c. @return void --]] function Actor:diffuselowerleft(color, c) end ---[[ +--[[-- Sets the Actor's lower right corner color to c. @return void --]] function Actor:diffuselowerright(color, c) end ---[[ +--[[-- Makes the Actor switch between two colors, jumping back to the first after reaching the second. See Themerdocs/effect_colors.txt for an example. @return void --]] function Actor:diffuseramp() end ---[[ +--[[-- Sets the Actor's right edge color to c. @return void --]] function Actor:diffuserightedge(color, c) end ---[[ +--[[-- Makes the Actor shift between two colors smoothly. See Themerdocs/effect_colors.txt for an example. @return void --]] function Actor:diffuseshift() end ---[[ +--[[-- Sets the Actor's top edge color to c. @return void --]] function Actor:diffusetopedge(color, c) end ---[[ +--[[-- Sets the Actor's upper left corner color to c. @return void --]] function Actor:diffuseupperleft(color, c) end ---[[ +--[[-- Sets the Actor's upper right corner color to c. @return void --]] function Actor:diffuseupperright(color, c) end ---[[ +--[[-- Tells the Actor to draw itself. @return void --]] function Actor:Draw() end ---[[ +--[[-- Sets the Actor's draworder to iOrder, where larger values display first. @return void --]] function Actor:draworder(int, iOrder) end ---[[ +--[[-- Set the Actor's effect clock to s. @return void --]] function Actor:drop(time) end ---[[ +--[[-- Set the Actor's effect clock to s. @return void --]] function Actor:ease(time, ease) end ---[[ +--[[-- Set the Actor's effect clock to s. @return void --]] function Actor:effectclock(string, s) end ---[[ +--[[-- Sets the first effect color to c. @return void --]] function Actor:effectcolor1(color, c) end ---[[ +--[[-- Sets the second effect color to c. @return void --]] function Actor:effectcolor2(color, c) end ---[[ +--[[-- Set the Actor's effect magnitude in each direction to the given values. @return void --]] function Actor:effectmagnitude(float, fX, float, fY, float, fZ) end ---[[ +--[[-- Set the Actor's effect offset to fTime. The offset is added to the time into the effect before calculating percent_through_effect. @return void --]] function Actor:effectoffset(float, fTime) end ---[[ +--[[-- Set the Actor's effect period to fTime. @return void --]] function Actor:effectperiod(float, fTime) end ---[[ +--[[-- Set the Actor's effect timing.
hold_at_zero is before hold_at_full in the argument list for compatibility. A future version will probably swap them because it makes more sense to have hold_at_full come before hold_at_zero.
All effect timings must be greater than or equal to zero, at least one of them must be greater than zero.
@@ -580,273 +589,273 @@ function Actor:effecttiming( hold_at_full) end ---[[ +--[[-- Set the hold_at_full part of the effect timing while leaving the others unchanged. @return void --]] function Actor:effect_hold_at_full(float, hold_at_full) end ---[[ +--[[-- Fades percent of the Actor from the bottom where percent is in the range 0..1. @return void --]] function Actor:fadebottom(float, percent) end ---[[ +--[[-- Fades percent of the Actor from the left where percent is in the range 0..1. @return void --]] function Actor:fadeleft(float, percent) end ---[[ +--[[-- Fades percent of the Actor from the right where percent is in the range 0..1. @return void --]] function Actor:faderight(float, percent) end ---[[ +--[[-- Fades percent of the Actor from the top where percent is in the range 0..1. @return void --]] function Actor:fadetop(float, percent) end ---[[ +--[[-- Finishes up an Actor's tween immediately. @return void --]] function Actor:finishtweening() end ---[[ +--[[-- Stretches an Actor to fill the entire screen. @return void --]] function Actor:FullScreen() end ---[[ +--[[-- Returns the Actor's aux value. @return float --]] function Actor:getaux() end ---[[ +--[[-- Returns the Actor's base X zoom value. @return float --]] function Actor:GetBaseZoomX() end ---[[ +--[[-- Returns the Actor's base Y zoom value. @return float --]] function Actor:GetBaseZoomY() end ---[[ +--[[-- Returns the Actor's base Z zoom value. @return float --]] function Actor:GetBaseZoomZ() end ---[[ +--[[-- Returns true if the Actor has a command named sCmdName. @return bool --]] function Actor:GetCommand(string, sCmdName) end ---[[ +--[[-- Returns the Actor's current diffuse color. @return color --]] function Actor:GetDiffuse() end ---[[ +--[[-- Returns the Actor's current diffusealpha. @return float --]] function Actor:GetDiffuseAlpha() end ---[[ +--[[-- Returns the Actor's current effect delta. @return float --]] function Actor:GetEffectDelta() end ---[[ +--[[-- Returns the Actor's current effect magnitude as three floats (not one; I hate Lua.xsd). @return float --]] function Actor:geteffectmagnitude() end ---[[ +--[[-- Returns the Actor's current glow color. @return color --]] function Actor:GetGlow() end ---[[ +--[[-- Returns the Actor's horizontal alignment as a number in the range 0..1. @return float --]] function Actor:GetHAlign() end ---[[ +--[[-- Returns the Actor's name. @return string --]] function Actor:GetName() end ---[[ +--[[-- Returns the number of states the Actor has. @return int --]] function Actor:GetNumStates() end ---[[ +--[[-- Returns the Actor's current height. @return float --]] function Actor:GetHeight() end ---[[ +--[[-- Returns the Actor's current X rotation. @return float --]] function Actor:GetRotationX() end ---[[ +--[[-- Returns the Actor's current Y rotation. @return float --]] function Actor:GetRotationY() end ---[[ +--[[-- Returns the Actor's current Z rotation. @return float --]] function Actor:GetRotationZ() end ---[[ +--[[-- Returns the number of seconds into the currently running effect (e.g. diffuseshift, bob). @return float --]] function Actor:GetSecsIntoEffect() end ---[[ +--[[-- Returns how much time is remaining for the current tween. @return float --]] function Actor:GetTweenTimeLeft() end ---[[ +--[[-- Returns the Actor's vertical alignment as a number in the range 0..1. @return float --]] function Actor:GetVAlign() end ---[[ +--[[-- Returns the Actor's current width. @return float --]] function Actor:GetWidth() end ---[[ +--[[-- Returns the zoomed height of an Actor. @return float --]] function Actor:GetZoomedHeight() end ---[[ +--[[-- Returns the zoomed width of an Actor. @return float --]] function Actor:GetZoomedWidth() end ---[[ +--[[-- Returns true if this actor is currently set to use the effect delta for tweening. @return bool --]] function Actor:get_tween_uses_effect_delta() end ---[[ +--[[-- Sets the Actor's glow color. @return void --]] function Actor:glow(color, c) end ---[[ +--[[-- Makes the Actor glow between two colors immediately. See Themerdocs/effect_colors.txt for an example. @return void --]] function Actor:glowblink() end ---[[ +--[[-- Makes the Actor glow between two colors smoothly, jumping back to the first at the end. See Themerdocs/effect_colors.txt for an example. @return void --]] function Actor:glowramp() end ---[[ +--[[-- Makes the Actor glow between two colors smoothly. See Themerdocs/effect_colors.txt for an example. @return void --]] function Actor:glowshift() end ---[[ +--[[-- Set the fractional horizontal alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is left aligned while an alignment of 1 is right aligned. See for the common case. @return void --]] function Actor:halign(float, fAlign) end ---[[ +--[[-- Sets the heading of this Actor to fHeading. @return void --]] function Actor:heading(float, fHeading) end ---[[ +--[[-- Hides the Actor for the specified amount of time. @return void --]] function Actor:hibernate(float, fTime) end ---[[ +--[[-- Compatibility alias for the hidden command, which was removed in sm-ssc. Use instead. @tparam boolean b @return void @@ -854,7 +863,7 @@ end function Actor:hidden(b) end ---[[ +--[[-- Compatibility alias for the hidden command, which was removed in sm-ssc. Use `visible` instead. @tparam boolean b @return void @@ -862,28 +871,28 @@ end function Actor:hide_if(b) end ---[[ +--[[-- Set the horizontal alignment of the Actor according to align. See for fractional alignment. @return void --]] function Actor:horizalign(HorizAlign, align) end ---[[ +--[[-- Hurries up an Actor's tweening by factor. @return void --]] function Actor:hurrytweening(float, factor) end ---[[ +--[[-- Plays the commands that follow at a normal rate, where fRate is in seconds. @return void --]] function Actor:linear(float, fRate) end ---[[ +--[[-- Plays the lyric command for the specified side ("Back" or "Front"). @tparam string side @return void @@ -891,287 +900,287 @@ end function Actor:linear(side) end ---[[ +--[[-- Sets the Actor's name to sName. @return void --]] function Actor:name(string, sName) end ---[[ +--[[-- Stops the Actor's movement. (Usually used for Sprites or Models.) @return void --]] function Actor:pause() end ---[[ +--[[-- Sets the pitch of this Actor to fPitch. @return void --]] function Actor:pitch(float, fPitch) end ---[[ +--[[-- Starts the Actor's movement. (Usually used for Sprites or Models.) @return void --]] function Actor:play() end ---[[ +--[[-- Plays a command named sCommandName. params is passed to the command as an argument if it is a table. @return void --]] function Actor:playcommand(string, sCommandName, table, params) end ---[[ +--[[-- Sets the visibility of the Actor based on p being a human player. @return void --]] function Actor:playcommand(playerNumber) end ---[[ +--[[-- Makes the Actor grow and shrink. Can use to define different pulsing behavior. @return void --]] function Actor:pulse() end ---[[ +--[[-- Queues a command named sCommandName to be played. @return void --]] function Actor:queuecommand(string, sCommandName) end ---[[ +--[[-- Basically creates a command named !sMessageName (Note the ! at the beginning. The source code says this: "Hack: use "!" as a marker to broadcast a command, instead of playing a command, so we don't have to add yet another element to every tween state for this rarely-used command.") @return void --]] function Actor:queuemessage(string, sMessageName) end ---[[ +--[[-- Makes the Actor change colors continually using colors of the rainbow. Each channel follows a cosine wave, red starts at 0, green starts at 2pi/3, and blue starts at 4pi/3. @return void --]] function Actor:rainbow() end ---[[ +--[[-- Sets the roll of this Actor to fRoll. @return void --]] function Actor:roll(float, fRoll) end ---[[ +--[[-- Set the Actor's rotation on the X axis to fAlign. @return void --]] function Actor:rotationx(float, fRotation) end ---[[ +--[[-- Set the Actor's rotation on the Y axis to fAlign. @return void --]] function Actor:rotationy(float, fRotation) end ---[[ +--[[-- Set the Actor's rotation on the Z axis to fAlign. @return void --]] function Actor:rotationz(float, fRotation) end ---[[ +--[[-- Set the Actor's rotation on the Z axis to fAlign. @return void --]] function Actor:rotationz(float, fRotation) end ---[[ +--[[-- Set the Actor's rotation on the Z axis to fAlign. @return void --]] function Actor:rotationz(float, fRotation) end ---[[ +--[[-- An alternative version of `scale_or_crop_background` @return void --]] function Actor:scale_or_crop_alternative(float, fRotation) end ---[[ +--[[-- @return void --]] function Actor:scale_or_crop_background(float, fRotation) end ---[[ +--[[-- Scales the Actor to cover a rectangle defined by the four float arguments. @return void --]] function Actor:scaletocover(float, fLeft, float, fTop, float, fRight, float, fBottom) end ---[[ +--[[-- Scales the Actor to fit inside a rectangle defined by the four float arguments. @return void --]] function Actor:scaletofit(float, fLeft, float, fTop, float, fRight, float, fBottom) end ---[[ +--[[-- Sets the height of the Actor. @return void --]] function Actor:SetHeight(float, height) end ---[[ +--[[-- Sets the size of the Actor. @return void --]] function Actor:setsize(width, height) end ---[[ +--[[-- Alias for setsize. @return void --]] function Actor:SetSize(width, height) end ---[[ +--[[-- Sets a multi-framed Actor's state to iNewState. @return void --]] function Actor:setstate(int, iNewState) end ---[[ +--[[-- Sets the width of the Actor. @return void --]] function Actor:SetWidth(float, width) end ---[[ +--[[-- Use this to make the actor use the effect clock to tween instead of using the global frame delta. @return --]] function Actor:set_tween_uses_effect_delta(bool) end ---[[ +--[[-- Sets the shadow's color to c. @return void --]] function Actor:shadowcolor(color, c) end ---[[ +--[[-- Sets the Actor's shadow length to fLength. @return void --]] function Actor:shadowlength(float, fLength) end ---[[ +--[[-- Sets the Actor's horizontal shadow length to fLength. @return void --]] function Actor:shadowlengthx(float, fLength) end ---[[ +--[[-- Sets the Actor's vertical shadow length to fLength. @return void --]] function Actor:shadowlengthy(float, fLength) end ---[[ +--[[-- Skews the Actor on the x axis by fAmount. @return void --]] function Actor:skewx(float, fAmount) end ---[[ +--[[-- Skews the Actor on the y axis by fAmount. @return void --]] function Actor:skewy(float, fAmount) end ---[[ +--[[-- Waits fSeconds before executing the next command. @return void --]] function Actor:sleep(float, fSeconds) end ---[[ +--[[-- @return void --]] function Actor:smooth(time) end ---[[ +--[[-- Tells the Actor to spin. Can use to define different spinning behavior. @return void --]] function Actor:spin() end ---[[ +--[[-- Stops any effect the Actor has. @return void --]] function Actor:stopeffect() end ---[[ +--[[-- Stops any tweening. @return void --]] function Actor:stoptweening() end ---[[ +--[[-- Stretches the Actor to a rectangle of a specific size. @return void --]] function Actor:stretchto(float, x1, float, y1, float, x2, float, y2) end ---[[ +--[[-- Translates the texture of the actor by x and y. @return void --]] function Actor:texturetranslate(float, x, float, y) end ---[[ +--[[-- Determines if the Actor should use texture wrapping or not. @return void --]] function Actor:texturewrapping(bool, bWrap) end ---[[ +--[[-- Uses type to determine the tween to use. The type must be one of the TweenType enum values. If the type is note TweenType_Bezier, the params table is ignored. If the type is TweenType_Bezier, then the params table must have 4 or 8 numbers. 4 numbers in the params creates a 1 dimensional bezier curve, 8 numbers creates a 2 dimensional bezier curve.
It's usually more convenient to use Actor:linear, Actor:accelerate, and so on, rather than using Actor:tween directly. @return void @@ -1179,196 +1188,196 @@ end function Actor:tween(time, tweentype, params) end ---[[ +--[[-- Set the fractional vertical alignment of the Actor according to fAlign which should be a float in the range 0..1. An alignment of 0 is top aligned while an alignment of 1 is bottom aligned. See for the common case. @return void --]] function Actor:valign(float, fAlign) end ---[[ +--[[-- Set the vertical alignment of the Actor according to align. See for fractional alignment. @return void --]] function Actor:vertalign(VertAlign, align) end ---[[ +--[[-- Makes the Actor vibrate violently. Can use to define different vibration behavior. @return void --]] function Actor:vibrate() end ---[[ +--[[-- Sets an Actor's visibility to b. @return void --]] function Actor:visible(bool, b) end ---[[ +--[[-- Makes the Actor wag. Use to define different wag behavior. @return void --]] function Actor:wag() end ---[[ +--[[-- Set the x position of the Actor to xPos. @return void --]] function Actor:x(float, xPos) end ---[[ +--[[-- Set the y position of the Actor to yPos. @return void --]] function Actor:y(float, yPos) end ---[[ +--[[-- Set the z position of the Actor to zPos. @return void --]] function Actor:z(float, zPos) end ---[[ +--[[-- Sets the z bias to fBias. @return void --]] function Actor:zbias(float, fBias) end ---[[ +--[[-- Enables/disables z-buffer depending on bUse. @return void --]] function Actor:zbuffer(bool, bUse) end ---[[ +--[[-- Zooms the Actor to zoom scale. @return void --]] function Actor:zoom(float, zoom) end ---[[ +--[[-- Zooms the Actor on both the X and Y axis using zoomX and zoomY. @return void --]] function Actor:zoomto(float, zoomX, float, zoomY) end ---[[ +--[[-- Zooms the Actor to zoom height. See also: . @return void --]] function Actor:zoomtoheight(float, zoom) end ---[[ +--[[-- Zooms the Actor to zoom width. See also: . @return void --]] function Actor:zoomtowidth(float, zoom) end ---[[ +--[[-- Zooms the Actor to zoom scale on the X axis. @return void --]] function Actor:zoomx(float, zoom) end ---[[ +--[[-- Zooms the Actor to zoom scale on the Y axis. @return void --]] function Actor:zoomy(float, zoom) end ---[[ +--[[-- Zooms the Actor to zoom scale on the Z axis. @return void --]] function Actor:zoomz(float, zoom) end ---[[ +--[[-- Sets the z testing mode to write on pass if true, turns it off if false @return void --]] function Actor:ztest(bool, bTest) end ---[[ +--[[-- Sets the z testing mode to testMode. @return void --]] function Actor:ztestmode(ZTestMode, testMode) end ---[[ +--[[-- Sets z writing to true or false based on bWrite. @return void --]] function Actor:zwrite(bool, bWrite) end ---[[ +--[[-- Plays the commands that follow using a bezier curve to determine the rate. The curve must have 4 or 8 elements. This is a convenience wrapper around calling Actor:tween with TweenType_Bezier. @return void --]] function Actor:bezier(time, curve) end ---[[ +--[[-- Stretches an Actor to cover the screen. (equivalent to stretchto,0,0,SCREEN_WIDTH,SCREEN_HEIGHT) @return void --]] function Actor:FullScreen() end ---[[ +--[[-- Sets and Actor as a mask destination. @return void --]] function Actor:MaskDest() end ---[[ +--[[-- Sets an Actor as a mask source. (Also clears zbuffer; other mask sources need to not clear the zbuffer) @return void --]] function Actor:MaskSource() end ---[[ +--[[-- Make graphics their true size at any resolution. @return void --]] function Actor:Real(f) end ---[[ +--[[-- Scale things back up after they have already been scaled down. @return void --]] function Actor:RealInverse(f) end ---[[ +--[[-- A customized version of pulse that is more appealing for on-beat effects. @return void --]] function Actor:thump(fEffectPeriod) end ---[[ +--[[-- Sets the x and y location of the Actor in one command. @return void --]] From a4b3c9f03bf95b64e96211e3a43e93025ea1d09b Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 05:39:49 -0300 Subject: [PATCH 137/320] Fix compile with gcc/clang --- src/DownloadManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index ca185cc1cd..19279c9300 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1426,8 +1426,8 @@ DownloadManager::RequestReplayData(string scoreid, static_cast(note[3].get())); } auto& lbd = DLMAN->chartLeaderboards[chartkey]; - auto it = - find_if(lbd.begin(), lbd.end(), [userid, username](auto& a) { + auto it = find_if( + lbd.begin(), lbd.end(), [userid, username](OnlineScore& a) { return a.userid == userid && a.username == username; }); if (it != lbd.end()) { From c9d69ea0e0f66952b1ef32cd1c9cddfb6cf82eca Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 05:53:41 -0300 Subject: [PATCH 138/320] Actually fix compile with gcc/clang --- src/Actor.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index aeb3b7b3e8..dcfef0489a 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -959,9 +959,10 @@ Actor::UpdateInternal(float delta_time) } } // Doing this in place did weird things - std::remove_if(delayedFunctions.begin(), - delayedFunctions.end(), - [](auto& x) { return x.second <= 0; }); + std::remove_if( + delayedFunctions.begin(), + delayedFunctions.end(), + [](pair, float>& x) { return x.second <= 0; }); for (auto it = this->delayedPeriodicFunctions.begin(); it != this->delayedPeriodicFunctions.end(); ++it) { @@ -1754,8 +1755,11 @@ class LunaActor : public Luna { int r = IArg(1); auto& l = p->delayedPeriodicFunctions; - auto it = find_if( - l.begin(), l.end(), [r](auto& x) { return std::get<3>(x) == r; }); + auto it = find_if(l.begin(), + l.end(), + [r](tuple, float, float, int>& x) { + return std::get<3>(x) == r; + }); if (it != l.end()) { luaL_unref(L, LUA_REGISTRYINDEX, r); l.erase(it); From 87ba78bc7d925daa255916dfd4788db24f4e2ce4 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 07:12:22 -0300 Subject: [PATCH 139/320] Actually actually fix gcc/clang --- src/DownloadManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 19279c9300..6a53f6cd56 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1883,7 +1883,7 @@ DownloadManager::UploadScores() } function lambda; lambda = [toUpload, lambda]() mutable { - auto& it = toUpload.begin(); + auto it = toUpload.begin(); if (it != toUpload.end()) { toUpload.pop_front(); auto& hs = (*it); From 84408cf9c570a87cfd887e3e900fbd2676da76c4 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 07:12:45 -0300 Subject: [PATCH 140/320] ETTP gameplay updates --- src/NetworkSyncManager.cpp | 54 +++++++++++++++++++++++++++++++++++--- src/NetworkSyncManager.h | 11 ++++++++ src/ScreenGameplay.cpp | 9 +++++++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index f7648177a2..1460b45678 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -782,6 +782,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) } break; case ettps_selectchart: { + n->gameplayLeaderboard.clear(); auto ch = (*payload).at("chart"); FindJsonChart(n, ch); json j; @@ -795,6 +796,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) Send(j); } break; case ettps_startchart: { + n->gameplayLeaderboard.clear(); n->m_EvalPlayerData.clear(); auto ch = (*payload).at("chart"); FindJsonChart(n, ch); @@ -821,9 +823,17 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) msg.SetParam("type", type); MESSAGEMAN->Broadcast(msg); } break; - case ettps_gameplayleaderboard: - - break; + case ettps_gameplayleaderboard: { + auto& scores = (*payload)["scores"]; + for (json::iterator it = scores.begin(); it != scores.end(); + ++it) { + float wife = (*it)["wife"]; + string user = (*it)["user"].get(); + n->gameplayLeaderboard[user].wife = wife; + } + Message msg("GameplayUpdate"); + MESSAGEMAN->Broadcast(msg); + } break; case ettps_createroomresponse: { bool created = (*payload)["created"]; inRoom = created; @@ -1028,6 +1038,18 @@ ETTProtocol::SendChat(const RString& message, string tab, int type) Send(chatMsg); } void +ETTProtocol::SendGameplayUpdate(float wife) +{ + if (ws == nullptr) + return; + json j; + j["type"] = ettClientMessageMap[ettpc_gameplayupdate]; + auto& payload = j["payload"]; + payload["wife"] = wife; + j["id"] = msgId++; + Send(j); +} +void ETTProtocol::CreateNewRoom(RString name, RString desc, RString password) { if (ws == nullptr) @@ -1291,6 +1313,13 @@ NetworkSyncManager::SendChat(const RString& message, string tab, int type) curProtocol->SendChat(message, tab, type); } +void +NetworkSyncManager::SendGameplayUpdate(float wife) +{ + if (curProtocol != nullptr) + curProtocol->SendGameplayUpdate(wife); +} + int NetworkSyncManager::GetServerVersion() { @@ -1653,6 +1682,18 @@ NetworkSyncManager::GetCurrentSMBuild(LoadingWindow* ld) } #endif +void +NetworkSyncManager::PushGameplayLeaderboard(lua_State* L) +{ + lua_newtable(L); + for (auto& pair : gameplayLeaderboard) { + lua_newtable(L); + lua_pushnumber(L, pair.second.wife); + lua_setfield(L, -2, "wife"); + lua_setfield(L, -2, pair.first.c_str()); + } + return; +} void ChartRequest::PushSelf(lua_State* L) { @@ -1710,6 +1751,12 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) lua_pushboolean(L, p->IsETTP()); return 1; } + static int GetGameplayLeaderboard(T* p, lua_State* L) + { + auto& lbd = NSMAN->gameplayLeaderboard; + NSMAN->PushGameplayLeaderboard(L); + return 1; + } static int GetChartRequests(T* p, lua_State* L) { auto& reqs = p->requests; @@ -1762,6 +1809,7 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) } LunaNetworkSyncManager() { + ADD_METHOD(GetGameplayLeaderboard); ADD_METHOD(GetChatMsg); ADD_METHOD(SendChatMsg); ADD_METHOD(Login); diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index 2c2d5f23a6..a3a14b334a 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -150,6 +150,11 @@ class ChartRequest class EzSockets; class StepManiaLanServer; +class GameplayScore +{ + public: + float wife; +}; class PacketFunctions { @@ -226,6 +231,7 @@ class NetProtocol virtual void OffOptions(){}; virtual void OnEval(){}; virtual void OffEval(){}; + virtual void SendGameplayUpdate(float wife){}; }; class ETTProtocol : public NetProtocol @@ -264,6 +270,7 @@ class ETTProtocol : public NetProtocol void OffOptions() override; void OnEval() override; void OffEval() override; + void SendGameplayUpdate(float wife) override; void ReportHighScore(HighScore* hs, PlayerStageStats& pss) override; void Send(const char* msg); void Send(json msg); @@ -368,6 +375,8 @@ class NetworkSyncManager // since function was last called. RString m_Scoreboard[NUM_NSScoreBoardColumn]; + void SendGameplayUpdate(float wife); + // Used for chatting void SendChat(const RString& message, string tab = "", @@ -382,6 +391,8 @@ class NetworkSyncManager string chartkey; Song* song{ nullptr }; Steps* steps{ nullptr }; + map gameplayLeaderboard; + void PushGameplayLeaderboard(lua_State* L); Difficulty difficulty; int meter; int rate; diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 2e1ed06ef3..aa9f447a38 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1360,6 +1360,15 @@ ScreenGameplay::BeginScreen() } else { StartPlayingSong(MIN_SECONDS_TO_STEP, MIN_SECONDS_TO_MUSIC); } + if (GAMESTATE->m_bPlayingMulti) { + this->SetInterval( + [this]() { + NSMAN->SendGameplayUpdate( + this->GetPlayerInfo(PLAYER_1)->m_pPlayer->curwifescore); + }, + 1, + -1); + } } bool From 7d536c572b554f090153b7be8df3bcba18429bc9 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 07:16:01 -0300 Subject: [PATCH 141/320] Actually rename score upload xml tag --- src/HighScore.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HighScore.cpp b/src/HighScore.cpp index 2f63de7de1..717554c2e3 100644 --- a/src/HighScore.cpp +++ b/src/HighScore.cpp @@ -447,7 +447,7 @@ HighScoreImpl::LoadFromEttNode(const XNode* pNode) pNode->GetChildValue("JudgeScale", fJudgeScale); pNode->GetChildValue("NoChordCohesion", bNoChordCohesion); pNode->GetChildValue("EtternaValid", bEtternaValid); - const XNode* pUploadedServers = pNode->GetChild("Servers"); + const XNode* pUploadedServers = pNode->GetChild("Servs"); if (pUploadedServers != nullptr) { FOREACH_CONST_Child(pUploadedServers, p) { From 08fb18d35d38470af3beb95a1feacac1784569d3 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 07:54:15 -0300 Subject: [PATCH 142/320] Use scorekey instead of chartkey --- src/DownloadManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 6a53f6cd56..d4e3b0605c 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1888,7 +1888,7 @@ DownloadManager::UploadScores() toUpload.pop_front(); auto& hs = (*it); DLMAN->UploadScoreWithReplayDataFromDisk( - hs->GetChartKey(), [hs, toUpload, lambda]() { + hs->GetScoreKey(), [hs, toUpload, lambda]() { hs->AddUploadedServer(serverURL.Get()); lambda(); }); From 478c9cc72b91d884e83148365e59d2e5edd4d716 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 08:10:40 -0300 Subject: [PATCH 143/320] Fix bad function callf --- src/DownloadManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index d4e3b0605c..6afbfa7522 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1128,7 +1128,8 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, } } catch (exception e) { } - callback(); + if (callback) + callback(); }; HTTPRequest* req = new HTTPRequest(curlHandle, done); SetCURLResultsString(curlHandle, &(req->result)); From 293cb1e007a7753673163913ecc34aa99cd3ff20 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 02:41:08 -0500 Subject: [PATCH 144/320] eat all right clicks over chat but only toggle minimize on firstpress --- .../_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index bba08c0a6c..e07c90f001 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -431,9 +431,11 @@ function input(event) -- right click over the chat to minimize - if event.DeviceInput.button == "DeviceButton_right mouse button" and event.type == "InputEventType_FirstPress" and isOver(bg) then - minimised = not minimised - MESSAGEMAN:Broadcast("Minimise") + if event.DeviceInput.button == "DeviceButton_right mouse button" and isOver(bg) then + if event.type == "InputEventType_FirstPress" then + minimised = not minimised + MESSAGEMAN:Broadcast("Minimise") + end return true end From da66a8186f6c87e48183abf77136e528abfd5864 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 03:52:57 -0500 Subject: [PATCH 145/320] efficiency twerks to songgroup checking --- src/SongManager.cpp | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/src/SongManager.cpp b/src/SongManager.cpp index 9dd55077a1..fcec3a253d 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -37,14 +37,7 @@ #include "arch/LoadingWindow/LoadingWindow.h" #include "ScreenManager.h" -struct SongDir -{ - RString path; - SongDir(RString path) - : path(path) - { - } -}; +typedef RString SongDir; struct Group { RString name; @@ -206,13 +199,13 @@ SongManager::DifferentialReloadDir(string dir) RString group_base_name = Basename(group.name); for (auto& songDir : songDirs) { // skip any dir we've already loaded -mina - RString hur = songDir.path + "/"; + RString hur = songDir + "/"; hur.MakeLower(); if (m_SongsByDir.count(hur)) continue; Song* pNewSong = new Song; - if (!pNewSong->LoadFromSongDir(songDir.path)) { + if (!pNewSong->LoadFromSongDir(songDir)) { delete pNewSong; continue; } @@ -771,33 +764,23 @@ SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) if (ld != nullptr) { ld->SetIndeterminate(false); ld->SetTotalWork(songFolders.size()); - ld->SetText("Checking song folders"); + ld->SetText("Checking song folders..."); } vector groups; auto unknownGroup = Group(RString("Unknown Group")); int foldersChecked = 0; int onePercent = std::max(static_cast(songFolders.size() / 100), 1); for (const auto& folder : songFolders) { - // inefficiency here when loading from cache, the check to see if we've - // already loaded a song is 40 lines down and run after issongdir, - // ideally we wouldnt need to run issongdir on anything we already know - // is a group or anything we already know is a song -mina - if (IsSongDir(sDir + folder)) { - auto s = SongDir(sDir + folder); - unknownGroup.songs.emplace_back(s); + auto burp = sDir + folder; + if (IsSongDir(burp)) { + unknownGroup.songs.emplace_back(burp); } else { - vector songPaths; auto group = Group(folder); - GetDirListing(sDir + folder + "/*", songPaths, true, true); - StripCvsAndSvn(songPaths); - StripMacResourceForks(songPaths); - for (auto& song : songPaths) { - group.songs.emplace_back(SongDir(song)); - } + GetDirListing(sDir + folder + "/*", group.songs, true, true); + StripCvsAndSvn(group.songs); + StripMacResourceForks(group.songs); songCount += group.songs.size(); groups.emplace_back(group); - if (ld != nullptr && foldersChecked % onePercent == 0) - ld->SetProgress(++foldersChecked); } } if (!unknownGroup.songs.empty()) @@ -835,12 +818,12 @@ SongManager::LoadStepManiaSongDir(RString sDir, LoadingWindow* ld) SONGMAN->m_mapSongGroupIndex[sGroupName]; RString group_base_name = sGroupName; for (auto& sSongDirName : arraySongDirs) { - RString hur = sSongDirName.path + "/"; + RString hur = sSongDirName + "/"; hur.MakeLower(); if (SONGMAN->m_SongsByDir.count(hur)) continue; Song* pNewSong = new Song; - if (!pNewSong->LoadFromSongDir(sSongDirName.path)) { + if (!pNewSong->LoadFromSongDir(sSongDirName)) { delete pNewSong; continue; } From a231159410710d33667ec2ad8933170260e9e29e Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 06:28:07 -0500 Subject: [PATCH 146/320] hooverphonic --- .../BGAnimations/_mousewheelscroll.lua | 2 +- .../_fallback/Graphics/ScrollBar TickThumb.lua | 18 ++++++++++++++---- src/WheelBase.cpp | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua index 56c33ebdc6..57ce82e0d4 100644 --- a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua +++ b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua @@ -42,7 +42,7 @@ local function scrollInput(event) local mouseX = INPUTFILTER:GetMouseX() local mouseY = INPUTFILTER:GetMouseY() - if mouseX > capWideScale(370, 500) and mouseX < SCREEN_WIDTH then + if mouseX > capWideScale(370, 500) and mouseX < SCREEN_WIDTH - 32 then if event.DeviceInput.button == "DeviceButton_left mouse button" and event.type == "InputEventType_FirstPress" then local n = 0 local m = 1 diff --git a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua index f8e1dc22bd..34fcb5b308 100644 --- a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua +++ b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua @@ -1,12 +1,22 @@ local t = Def.ActorFrame {} - +local whee t[#t + 1] = Def.ActorFrame { Def.Quad { - InitCommand = function(self) - self:zoomto(32, 32) + Name = "DootyMcBooty", + OnCommand = function(self) + self:zoomto(32, 32):valign(0.634522134234) + whee = SCREENMAN:GetTopScreen():GetMusicWheel() + end, + LeftClickMessageCommand = function(self) + if SCREEN_WIDTH - INPUTFILTER:GetMouseX() < 32 then + local idx = whee:GetCurrentIndex() + local num = whee:GetNumItems() + local dum = (INPUTFILTER:GetMouseY() - 45) / (SCREEN_HEIGHT - 103) + whee:Move(notShit.round(num * dum) - idx) + end end } } -return t +return t \ No newline at end of file diff --git a/src/WheelBase.cpp b/src/WheelBase.cpp index 784d229be6..362a754cf2 100644 --- a/src/WheelBase.cpp +++ b/src/WheelBase.cpp @@ -470,6 +470,8 @@ WheelBase::RebuildWheelItems(int iDist) } for (int i = iFirst; i <= iLast; i++) { + if (i > items.size()) + break; int iIndex = iFirstVisibleIndex + i; wrap(iIndex, data.size()); From 25742cb07baa71cbc09760b7e6f7bfbe70c37eac Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 08:48:05 -0300 Subject: [PATCH 147/320] Use a function instead of a lambda Weird stuff happens --- src/DownloadManager.cpp | 57 +++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 6afbfa7522..df6834e448 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1866,37 +1866,38 @@ DownloadManager::StartSession(string user, HTTPRequests.push_back(req); } +void uploadSequentially(deque toUpload) +{ + auto it = toUpload.begin(); + if (it != toUpload.end()) { + toUpload.pop_front(); + auto& hs = (*it); + DLMAN->UploadScoreWithReplayDataFromDisk( + hs->GetScoreKey(), [hs, toUpload]() { + hs->AddUploadedServer(serverURL.Get()); + uploadSequentially(toUpload); + }); + } + return; +} bool DownloadManager::UploadScores() { - if (!LoggedIn()) - return false; - auto scores = SCOREMAN->GetAllPBPtrs(); - deque toUpload; - for (auto& vec : scores) { - for (auto& scorePtr : vec) { - auto ts = scorePtr->GetTopScore(); - if ((ts == 1 || ts == 2) && - !scorePtr->IsUploadedToServer(serverURL.Get())) { - toUpload.emplace_back(scorePtr); - } - } - } - function lambda; - lambda = [toUpload, lambda]() mutable { - auto it = toUpload.begin(); - if (it != toUpload.end()) { - toUpload.pop_front(); - auto& hs = (*it); - DLMAN->UploadScoreWithReplayDataFromDisk( - hs->GetScoreKey(), [hs, toUpload, lambda]() { - hs->AddUploadedServer(serverURL.Get()); - lambda(); - }); - } - }; - lambda(); - return true; + if (!LoggedIn()) + return false; + auto scores = SCOREMAN->GetAllPBPtrs(); + deque toUpload; + for (auto& vec : scores) { + for (auto& scorePtr : vec) { + auto ts = scorePtr->GetTopScore(); + if ((ts == 1 || ts == 2) && + !scorePtr->IsUploadedToServer(serverURL.Get())) { + toUpload.emplace_back(scorePtr); + } + } + } + uploadSequentially(toUpload); + return true; } int From 757d4319235ab5f4ca33a85c72c25a49bdbb877c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 07:56:50 -0500 Subject: [PATCH 148/320] the gnat and the bat had a flat chat with a rat on a mat --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index e07c90f001..8eeda3f3eb 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -2,7 +2,7 @@ local lastx, lasty = 0, 0 local width, height = SCREEN_WIDTH, SCREEN_HEIGHT * 0.035 local maxlines = 5 local lineNumber = 5 -local inputLineNumber = 1 +local inputLineNumber = 2 local tabHeight = 1 local maxTabs = 10 local x, y = 0, SCREEN_HEIGHT - height * (lineNumber + inputLineNumber + tabHeight) From bab7a020313822b78a89eda4dc3e470b404ad160 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 07:57:51 -0500 Subject: [PATCH 149/320] du du du du du baby fart --- .../BGAnimations/superscoreboard.lua | 14 ++-- src/DownloadManager.cpp | 79 +++++++++++-------- 2 files changed, 52 insertions(+), 41 deletions(-) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index d73ea5fde5..ca384f47fc 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -461,15 +461,11 @@ local function makeScoreDisplay(i) end end, DisplayCommand = function(self) - DLMAN:RequestOnlineScoreReplayData(hs, - function(replay) - if #replay > 0 then - self:settext("Watch") - else - self:settext("") - end - end - ) + if DLMAN:Fart(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), ind + i) then + self:settext("Watch") + else + self:settext("") + end end, HighlightCommand = function(self) highlightIfOver(self) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index df6834e448..fbaba985b8 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1422,9 +1422,12 @@ DownloadManager::RequestReplayData(string scoreid, timestamps.emplace_back(note[0].get()); offsets.emplace_back(note[1].get() / 1000.f); - tracks.emplace_back(note[2].get()); - types.emplace_back( - static_cast(note[3].get())); + + if (note.size() > 2) { + tracks.emplace_back(note[2].get()); + types.emplace_back( + static_cast(note[3].get())); + } } auto& lbd = DLMAN->chartLeaderboards[chartkey]; auto it = find_if( @@ -1436,6 +1439,11 @@ DownloadManager::RequestReplayData(string scoreid, it->hs.SetOffsetVector(offsets); it->hs.SetTrackVector(tracks); it->hs.SetTapNoteTypeVector(types); + + if (tracks.empty()) + it->hs.SetReplayType(1); + else + it->hs.SetReplayType(2); } auto L = LUA->Get(); callback.PushSelf(L); @@ -1866,38 +1874,39 @@ DownloadManager::StartSession(string user, HTTPRequests.push_back(req); } -void uploadSequentially(deque toUpload) -{ - auto it = toUpload.begin(); - if (it != toUpload.end()) { - toUpload.pop_front(); - auto& hs = (*it); - DLMAN->UploadScoreWithReplayDataFromDisk( - hs->GetScoreKey(), [hs, toUpload]() { - hs->AddUploadedServer(serverURL.Get()); - uploadSequentially(toUpload); - }); - } - return; +void +uploadSequentially(deque toUpload) +{ + auto it = toUpload.begin(); + if (it != toUpload.end()) { + toUpload.pop_front(); + auto& hs = (*it); + DLMAN->UploadScoreWithReplayDataFromDisk( + hs->GetScoreKey(), [hs, toUpload]() { + hs->AddUploadedServer(serverURL.Get()); + uploadSequentially(toUpload); + }); + } + return; } bool DownloadManager::UploadScores() { - if (!LoggedIn()) - return false; - auto scores = SCOREMAN->GetAllPBPtrs(); - deque toUpload; - for (auto& vec : scores) { - for (auto& scorePtr : vec) { - auto ts = scorePtr->GetTopScore(); - if ((ts == 1 || ts == 2) && - !scorePtr->IsUploadedToServer(serverURL.Get())) { - toUpload.emplace_back(scorePtr); - } - } - } - uploadSequentially(toUpload); - return true; + if (!LoggedIn()) + return false; + auto scores = SCOREMAN->GetAllPBPtrs(); + deque toUpload; + for (auto& vec : scores) { + for (auto& scorePtr : vec) { + auto ts = scorePtr->GetTopScore(); + if ((ts == 1 || ts == 2) && + !scorePtr->IsUploadedToServer(serverURL.Get())) { + toUpload.emplace_back(scorePtr); + } + } + } + uploadSequentially(toUpload); + return true; } int @@ -2420,9 +2429,14 @@ class LunaDownloadManager : public Luna static int SendReplayDataForOldScore(T* p, lua_State* L) { DLMAN->UploadScoreWithReplayDataFromDisk(SArg(1)); + return 0; + } + static int Fart(T* p, lua_State* L) + { + lua_pushboolean( + L, DLMAN->chartLeaderboards[SArg(1)][IArg(2) - 1].hasReplay); return 1; } - LunaDownloadManager() { ADD_METHOD(GetCountryCodes); @@ -2456,6 +2470,7 @@ class LunaDownloadManager : public Luna ADD_METHOD(ToggleTopScoresOnlyFilter); ADD_METHOD(GetTopScoresOnlyFilter); ADD_METHOD(SendReplayDataForOldScore); + ADD_METHOD(Fart); ADD_METHOD(Logout); } }; From 315e8329d0721f388b380cfe952c2d728998433d Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 10:11:28 -0300 Subject: [PATCH 150/320] Fix chat showing up on gameplay --- .../ScreenChatOverlay overlay.lua | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index e07c90f001..3d6359ec61 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -65,23 +65,37 @@ end local i = 0 chat.InitCommand = function(self) online = IsNetSMOnline() and IsSMOnlineLoggedIn(PLAYER_1) and NSMAN:IsETTP() - self:visible(false); + self:visible(false) end -chat.AddMPChatInputMessageCommand = function(self) +local isGameplay +chat.ScreenChangedMessageCommand = function(self) local s = SCREENMAN:GetTopScreen() if not s then return end currentScreen = s:GetName() online = IsNetSMOnline() and IsSMOnlineLoggedIn(PLAYER_1) and NSMAN:IsETTP() - if (currentScreen == "ScreenGameplay" or currentScreen == "ScreenNetGameplay") then + isGameplay = (currentScreen == "ScreenGameplay" or currentScreen == "ScreenNetGameplay") + SCREENMAN:SystemMessage(currentScreen .. tostring(isGameplay)) + if isGameplay then self:visible(false) show = false typing = false + s:setInterval( + function() + self:visible(false) + end, + 0.01 + ) else self:visible(online) show = true - s:AddInputCallback(input) + s:setInterval( + function() + s:AddInputCallback(input) + end, + 0.01 + ) end MESSAGEMAN:Broadcast("UpdateChatOverlay") end @@ -208,7 +222,6 @@ chatWindow[#chatWindow + 1] = end end self:settext(t) - end } @@ -329,8 +342,8 @@ function overTab(mx, my) return nil, nil end function input(event) - if (not show or not online) then - return + if (not show or not online) or isGameplay then + return false end local update = false if event.DeviceInput.button == "DeviceButton_left mouse button" then @@ -347,7 +360,7 @@ function input(event) typing = true update = true elseif mx >= x and mx <= x + width and my >= y + moveY and my <= y + height + moveY then - mousex, mousey = mx, my -- no clue what this block of code is for + mousex, mousey = mx, my -- no clue what this block of code is for lastx, lasty = x, y update = true elseif not minimised then @@ -426,12 +439,11 @@ function input(event) lineNumber = lineNumber - 1 end update = true - end + end end - - + -- right click over the chat to minimize - if event.DeviceInput.button == "DeviceButton_right mouse button" and isOver(bg) then + if event.DeviceInput.button == "DeviceButton_right mouse button" and isOver(bg) then if event.type == "InputEventType_FirstPress" then minimised = not minimised MESSAGEMAN:Broadcast("Minimise") @@ -444,11 +456,12 @@ function input(event) end -- always eat mouse inputs if its within the broader chatbox - if event.DeviceInput.button == "DeviceButton_left mouse button" and isOver(bg) then + if event.DeviceInput.button == "DeviceButton_left mouse button" and isOver(bg) then return true end - return update or typing + returnInput = update or typing + return returnInput end return chat From 14d4335e4303984a7d6bc563c35a79ffb0e0753d Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 10:17:08 -0300 Subject: [PATCH 151/320] Remove forgotten trace --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 14364374bd..be341e2252 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -76,7 +76,6 @@ chat.ScreenChangedMessageCommand = function(self) currentScreen = s:GetName() online = IsNetSMOnline() and IsSMOnlineLoggedIn(PLAYER_1) and NSMAN:IsETTP() isGameplay = (currentScreen == "ScreenGameplay" or currentScreen == "ScreenNetGameplay") - SCREENMAN:SystemMessage(currentScreen .. tostring(isGameplay)) if isGameplay then self:visible(false) show = false From 75f62ee0a1a11a7428d0761458a9b4696f4a6e9b Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 08:17:54 -0500 Subject: [PATCH 152/320] oops cwashy washy --- src/WheelBase.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/WheelBase.cpp b/src/WheelBase.cpp index 362a754cf2..8ad33bbbac 100644 --- a/src/WheelBase.cpp +++ b/src/WheelBase.cpp @@ -469,9 +469,7 @@ WheelBase::RebuildWheelItems(int iDist) iLast = -iDist - 1; } - for (int i = iFirst; i <= iLast; i++) { - if (i > items.size()) - break; + for (size_t i = iFirst; i < items.size(); i++) { int iIndex = iFirstVisibleIndex + i; wrap(iIndex, data.size()); From 1e1118379c6293503e8d5dac7532f0a83671b024 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 08:20:58 -0500 Subject: [PATCH 153/320] remove unneeded callbacks --- .../BGAnimations/ScreenNetSelectMusic decorations.lua | 8 -------- .../BGAnimations/ScreenSelectMusic decorations/tabs.lua | 1 - 2 files changed, 9 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua index 623bf6b35e..dd803157ab 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua @@ -1,10 +1,2 @@ local t = LoadActor("ScreenSelectMusic decorations/default") - t[#t + 1] = - Def.ActorFrame { - BeginCommand = function(self) - MESSAGEMAN:Broadcast("AddMPChatInput") - SCREENMAN:GetTopScreen():AddInputCallback(input)-- not sure if we need this or fallback handles it -mina - end - } - return t \ No newline at end of file diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua index 5e609dfd44..a9acd0a6d0 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua @@ -32,7 +32,6 @@ end local t = Def.ActorFrame { BeginCommand = function(self) - MESSAGEMAN:Broadcast("AddMPChatInput") SCREENMAN:GetTopScreen():AddInputCallback(input) resetTabIndex() end, From 4d579747d370c7e6026b4fe1290753eea67f1690 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 29 Nov 2018 10:52:13 -0300 Subject: [PATCH 154/320] First attempt at multi gameplay leaderboard --- .../ScreenGameplay overlay/leaderboard.lua | 52 +++++++++++++++++-- 1 file changed, 49 insertions(+), 3 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 26f1fc6cc2..0c7ce1e062 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -1,5 +1,6 @@ local allowedCustomization = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).CustomizeGameplay -local leaderboardEnabled = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() +local leaderboardEnabled = + NSMAN:IsETTP() or (playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn()) local entryActors = {} local t = @@ -40,7 +41,36 @@ end if not DLMAN:GetCurrentRateFilter() then DLMAN:ToggleRateFilter() end -local onlineScores = DLMAN:GetChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey()) +local multiScores = {} +function scoreUsingMultiScore(idx) + return { + GetDisplayName = function() + return multiScores[idx] and multiScores[idx].user or nil + end, + GetWifeGrade = function() + return 0 + end, + GetWifeScore = function() + return multiScores[idx] and multiScores[idx].wife or -500 + end, + GetSkillsetSSR = function() + return -1 + end, + GetJudgmentString = function() + return "" + end + } +end +local onlineScores = {} +local isMulti = NSMAN:IsETTP() +if isMulti then + multiScores = NSMAN:GetGameplayLeaderboard() + for i = 1, 5 do + onlineScores[i] = scoreUsingMultiScore(i) + end +else + onlineScores = DLMAN:GetChartLeaderBoard(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey()) +end local sortFunction = function(h1, h2) return h1[CRITERIA](h1) > h2[CRITERIA](h2) end @@ -89,6 +119,7 @@ for i = 1, NUM_ENTRIES do done = true end end +table.sort(scoreboard, sortFunction) for i = 1, NUM_ENTRIES do entryActors[i] = {} @@ -142,6 +173,7 @@ function scoreEntry(i) scale = 0.4, x = (x - WIDTH / 2) * 0.4, y = 10 + y, + text = "", color = getLeaderboardColor("text") } ) @@ -169,7 +201,11 @@ function scoreEntry(i) addLabel( "name", function(self, hs) - self:settext(hs:GetDisplayName()) + local n = hs:GetDisplayName() + self:settext(n or "") + if entryActor then + entryActor:visible(not (not n)) + end end, WIDTH / 1.3 ) @@ -207,6 +243,9 @@ t.JudgmentMessageCommand = function(self, params) -- params.WifePercent is our current calculated wife percent. local old = curScore.curWifeScore curScore.curWifeScore = notShit.floor(params.WifePercent * 100) / 10000 + if isMulti then + multiScores = NSMAN:GetGameplayLeaderboard() + end if old ~= curScore.curWifeScore then table.sort(scoreboard, sortFunction) for i, entry in ipairs(entryActors) do @@ -236,5 +275,12 @@ t.OnCommand = function(self, params) self:zoomtowidth(MovableValues.LeaderboardWidth) self:zoomtoheight(MovableValues.LeaderboardHeight) end +t.InitCommand = function(self, params) + for i, entry in ipairs(entryActors) do + for name, label in pairs(entry) do + label:visible(not (not scoreboard[i]:GetDisplayName())) + end + end +end return t From 6c5818d17b9b1f1d925a2a930e45e3a601f60cdb Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 08:51:09 -0500 Subject: [PATCH 155/320] theme errors --- .../_fallback/Graphics/ScrollBar TickThumb.lua | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua index 34fcb5b308..39864ce2c6 100644 --- a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua +++ b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua @@ -4,16 +4,20 @@ t[#t + 1] = Def.ActorFrame { Def.Quad { Name = "DootyMcBooty", - OnCommand = function(self) + BeginCommand = function(self) self:zoomto(32, 32):valign(0.634522134234) - whee = SCREENMAN:GetTopScreen():GetMusicWheel() + if SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" or SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then + whee = SCREENMAN:GetTopScreen():GetMusicWheel() + end end, LeftClickMessageCommand = function(self) - if SCREEN_WIDTH - INPUTFILTER:GetMouseX() < 32 then - local idx = whee:GetCurrentIndex() - local num = whee:GetNumItems() - local dum = (INPUTFILTER:GetMouseY() - 45) / (SCREEN_HEIGHT - 103) - whee:Move(notShit.round(num * dum) - idx) + if SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" or SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then + if SCREEN_WIDTH - INPUTFILTER:GetMouseX() < 32 then + local idx = whee:GetCurrentIndex() + local num = whee:GetNumItems() + local dum = (INPUTFILTER:GetMouseY() - 45) / (SCREEN_HEIGHT - 103) + whee:Move(notShit.round(num * dum) - idx) + end end end } From 5e6c27d6cbf4c42e3335668a187a8f349da01cf5 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 08:51:57 -0500 Subject: [PATCH 156/320] load tabs first at music select for excellent mega good reasons --- .../BGAnimations/ScreenSelectMusic decorations/default.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua index 4485e07a18..b1de977aa0 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua @@ -1,9 +1,9 @@ local t = Def.ActorFrame {} +t[#t + 1] = LoadActor("tabs") t[#t + 1] = LoadActor("wifetwirl") t[#t + 1] = LoadActor("msd") t[#t + 1] = LoadActor("songsearch") -t[#t + 1] = LoadActor("tabs") t[#t + 1] = LoadActor("songinfo") t[#t + 1] = LoadActor("score") t[#t + 1] = LoadActor("profile") From 07269e04427967cd6eefba6d87b91762153d55f1 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 08:54:35 -0500 Subject: [PATCH 157/320] rename global chat input and just load it in regular ssm --- .../BGAnimations/ScreenSelectMusic decorations/tabs.lua | 1 + .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 1 + Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 4 ++-- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua index a9acd0a6d0..a79a2cb66e 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tabs.lua @@ -32,6 +32,7 @@ end local t = Def.ActorFrame { BeginCommand = function(self) + SCREENMAN:GetTopScreen():AddInputCallback(MPinput) SCREENMAN:GetTopScreen():AddInputCallback(input) resetTabIndex() end, diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 794e8208b9..a701ad8f0b 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -662,6 +662,7 @@ t[#t + 1] = LoadFont("Common Normal") .. { Name = "PreviewViewer", BeginCommand = function(self) mcbootlarder = self:GetParent():GetChild("ChartPreview") + SCREENMAN:GetTopScreen():AddInputCallback(MPinput) SCREENMAN:GetTopScreen():AddInputCallback(ihatestickinginputcallbackseverywhere) self:xy(20, 235) self:zoom(0.5) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index be341e2252..7cf902d995 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -91,7 +91,7 @@ chat.ScreenChangedMessageCommand = function(self) show = true s:setInterval( function() - s:AddInputCallback(input) + s:AddInputCallback(MPinput) end, 0.01 ) @@ -340,7 +340,7 @@ function overTab(mx, my) end return nil, nil end -function input(event) +function MPinput(event) if (not show or not online) or isGameplay then return false end From 9a39605cdf4b37bf9a866be80ee7e19f2bc8b73b Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 09:15:45 -0500 Subject: [PATCH 158/320] turns out we needed this one --- .../BGAnimations/ScreenNetSelectMusic decorations.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua index dd803157ab..d4c658520a 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua @@ -1,2 +1,9 @@ local t = LoadActor("ScreenSelectMusic decorations/default") + t[#t + 1] = + Def.ActorFrame { + BeginCommand = function(self) + SCREENMAN:GetTopScreen():AddInputCallback(MPinput) + end + } + return t \ No newline at end of file From 1b10cb36d76dced1f8e2ea29cf888e402ffa9988 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 09:29:41 -0500 Subject: [PATCH 159/320] most excelephantish lagmoncrabber --- Themes/_fallback/Graphics/ScrollBar TickThumb.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua index 39864ce2c6..a955354cbe 100644 --- a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua +++ b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua @@ -1,4 +1,5 @@ local t = Def.ActorFrame {} +local screname local whee t[#t + 1] = Def.ActorFrame { @@ -6,12 +7,13 @@ t[#t + 1] = Name = "DootyMcBooty", BeginCommand = function(self) self:zoomto(32, 32):valign(0.634522134234) - if SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" or SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then + screname = SCREENMAN:GetTopScreen():GetName() + if screname == "ScreenSelectMusic" or screname == "ScreenNetSelectMusic" then whee = SCREENMAN:GetTopScreen():GetMusicWheel() end end, LeftClickMessageCommand = function(self) - if SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" or SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then + if whee then if SCREEN_WIDTH - INPUTFILTER:GetMouseX() < 32 then local idx = whee:GetCurrentIndex() local num = whee:GetNumItems() From eb513040f7472c1ccbb964f893287d6a2824ccee Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 10:06:26 -0500 Subject: [PATCH 160/320] turns out we didnt need that one, but we do need this one --- Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua | 2 +- .../BGAnimations/ScreenNetSelectMusic decorations.lua | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua index 5553618d30..58fb4c9c29 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom underlay.lua @@ -8,7 +8,7 @@ t[#t + 1] = ) end, BeginCommand= function(self) - MESSAGEMAN:Broadcast("AddMPChatInput") + SCREENMAN:GetTopScreen():AddInputCallback(MPinput) end } diff --git a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua index d4c658520a..dd803157ab 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetSelectMusic decorations.lua @@ -1,9 +1,2 @@ local t = LoadActor("ScreenSelectMusic decorations/default") - t[#t + 1] = - Def.ActorFrame { - BeginCommand = function(self) - SCREENMAN:GetTopScreen():AddInputCallback(MPinput) - end - } - return t \ No newline at end of file From b9c41ce9110401670ff6466b56a62603ea8c3fcf Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 10:48:25 -0500 Subject: [PATCH 161/320] attang 4 stock sd on bf as falco --- Themes/_fallback/Graphics/ScrollBar TickThumb.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua index a955354cbe..85a3f93ce2 100644 --- a/Themes/_fallback/Graphics/ScrollBar TickThumb.lua +++ b/Themes/_fallback/Graphics/ScrollBar TickThumb.lua @@ -12,13 +12,15 @@ t[#t + 1] = whee = SCREENMAN:GetTopScreen():GetMusicWheel() end end, - LeftClickMessageCommand = function(self) + MouseLeftClickMessageCommand = function(self) if whee then - if SCREEN_WIDTH - INPUTFILTER:GetMouseX() < 32 then + local mx = SCREEN_WIDTH - INPUTFILTER:GetMouseX() + if mx < 32 and mx > 0 then local idx = whee:GetCurrentIndex() local num = whee:GetNumItems() local dum = (INPUTFILTER:GetMouseY() - 45) / (SCREEN_HEIGHT - 103) whee:Move(notShit.round(num * dum) - idx) + whee:Move(0) end end end From afb7ca66eec47fb7c1414cac25f3c055a669650c Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Thu, 29 Nov 2018 13:17:59 -0300 Subject: [PATCH 162/320] Fix leaderboard positioning on start --- .../BGAnimations/ScreenGameplay overlay/leaderboard.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 0c7ce1e062..e6a65b08f3 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -274,8 +274,6 @@ t.OnCommand = function(self, params) arbitraryLeaderboardSpacing(MovableValues.LeaderboardSpacing) self:zoomtowidth(MovableValues.LeaderboardWidth) self:zoomtoheight(MovableValues.LeaderboardHeight) -end -t.InitCommand = function(self, params) for i, entry in ipairs(entryActors) do for name, label in pairs(entry) do label:visible(not (not scoreboard[i]:GetDisplayName())) From 6268b3433921929d6d54ad2c583ab26278187aea Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 11:19:44 -0500 Subject: [PATCH 163/320] prevent entering back into multi with a null profile --- Themes/Til Death/Scripts/02 Branches.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/Scripts/02 Branches.lua b/Themes/Til Death/Scripts/02 Branches.lua index aed00d7011..0835f0ac31 100644 --- a/Themes/Til Death/Scripts/02 Branches.lua +++ b/Themes/Til Death/Scripts/02 Branches.lua @@ -136,8 +136,8 @@ Branch = { if not IsSMOnlineLoggedIn(PLAYER_1) then return "ScreenNetSelectProfile" else - return "ScreenNetRoom" -- cant do this, we need to select a local profile even - end -- if logged into smo -mina + return "ScreenNetSelectProfile" --return "ScreenNetRoom" -- cant do this, we need to select a local profile even + end -- if logged into smo -mina else return "ScreenNetworkOptions" end From cd422b4671e79b00189b61fcb3243e43b59acbe3 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 12:26:01 -0500 Subject: [PATCH 164/320] bpmcommand updates --- .../Til Death/Graphics/ScreenSelectMusic BPMDisplay.lua | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Themes/Til Death/Graphics/ScreenSelectMusic BPMDisplay.lua b/Themes/Til Death/Graphics/ScreenSelectMusic BPMDisplay.lua index 87d8f3158e..6e17de60ca 100644 --- a/Themes/Til Death/Graphics/ScreenSelectMusic BPMDisplay.lua +++ b/Themes/Til Death/Graphics/ScreenSelectMusic BPMDisplay.lua @@ -12,12 +12,6 @@ return Def.BPMDisplay { end end, CurrentSongChangedMessageCommand = function(self) - self:playcommand("Set") - end, - CurrentSongChangedMessageCommand = function(self) - self:playcommand("Set") - end, - CurrentCourseChangedMessageCommand = function(self) - self:playcommand("Set") + self:queuecommand("Set") end } From bbe157f10632a870bebe885c6b4fb3ed82d53701 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 12:26:41 -0500 Subject: [PATCH 165/320] dont bother tweening tags (they were overflowing in mp?) --- .../ScreenSelectMusic decorations/tags.lua | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua index adea42eb18..894a390c2b 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua @@ -66,16 +66,11 @@ end local t = Def.ActorFrame { + Name = "Tongo", BeginCommand = function(self) SCREENMAN:GetTopScreen():AddInputCallback(newTagInput) self:queuecommand("Set"):visible(false) end, - OffCommand = function(self) - self:bouncebegin(0.2):xy(-500, 0):diffusealpha(0) - end, - OnCommand = function(self) - self:bouncebegin(0.2):xy(0, 0):diffusealpha(1) - end, MouseRightClickMessageCommand = function(self) if onTab then hasFocus = false @@ -88,14 +83,13 @@ local t = SetCommand = function(self) self:finishtweening() if getTabIndex() == 9 then - self:queuecommand("On") self:visible(true) song = GAMESTATE:GetCurrentSong() steps = GAMESTATE:GetCurrentSteps(PLAYER_1) onTab = true MESSAGEMAN:Broadcast("RefreshTags") else - self:queuecommand("Off") + self:visible(false) onTab = false end end, From 5ec7f71d355d43f02afb9afea119f78162a4e98e Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 12:28:11 -0500 Subject: [PATCH 166/320] dont need to use playcommand here --- .../BGAnimations/ScreenSelectMusic decorations/score.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index ebce33fc9b..3b83e440a0 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -71,7 +71,7 @@ local function updateLeaderBoardForCurrentChart() DLMAN:RequestChartLeaderBoardFromOnline( steps:GetChartKey(), function(leaderboard) - moped:playcommand("SetFromLeaderboard", leaderboard) + moped:queuecommand("SetFromLeaderboard", leaderboard) end ) else From 8363efc8a57232fbe49fac63df3aa023631e42ba Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 13:47:17 -0500 Subject: [PATCH 167/320] yutjhf --- .../ScreenSelectMusic decorations/tags.lua | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua index 894a390c2b..4c713449b9 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/tags.lua @@ -69,7 +69,7 @@ local t = Name = "Tongo", BeginCommand = function(self) SCREENMAN:GetTopScreen():AddInputCallback(newTagInput) - self:queuecommand("Set"):visible(false) + self:queuecommand("BORPBORPNORFNORFc"):visible(false) end, MouseRightClickMessageCommand = function(self) if onTab then @@ -80,8 +80,7 @@ local t = MESSAGEMAN:Broadcast("RefreshTags") end end, - SetCommand = function(self) - self:finishtweening() + BORPBORPNORFNORFcCommand = function(self) if getTabIndex() == 9 then self:visible(true) song = GAMESTATE:GetCurrentSong() @@ -94,13 +93,13 @@ local t = end end, TabChangedMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end, CurrentStepsP1ChangedMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end, CurrentSongChangedMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end } @@ -311,7 +310,7 @@ local function funcButton(i) InitCommand = function(self) self:zoomto((frameWidth / 3 - 10), 30):halign(0.5):valign(0):diffuse(getMainColor("frames")):diffusealpha(0.35) end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) if tagFunction == i then self:diffusealpha(1) else @@ -325,7 +324,7 @@ local function funcButton(i) end end, UpdateTagsMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end }, LoadFont("Common Large") .. @@ -347,18 +346,18 @@ r[#r + 1] = InitCommand = function(self) self:xy(frameX + 10, frameY + capWideScale(80, 80) + 225) end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) self:visible(tagFunction == 1) end, UpdateTagsMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end, LoadFont("Common Large") .. { InitCommand = function(self) self:halign(0):zoom(fontScale) end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) self:settext("Add new tag:") end }, @@ -376,7 +375,7 @@ r[#r + 1] = MESSAGEMAN:Broadcast("NumericInputActive") end end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) if hasFocus then self:diffuse(color("#999999")) else @@ -384,7 +383,7 @@ r[#r + 1] = end end, UpdateTagsMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end }, LoadFont("Common Large") .. @@ -392,7 +391,7 @@ r[#r + 1] = InitCommand = function(self) self:addx(133):addy(1):halign(0):maxwidth(600):zoom(fontScale - 0.05) end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) self:settext(curInput) if curInput ~= "" or hasFocus then self:diffuse(color("#FFFFFF")) @@ -401,7 +400,7 @@ r[#r + 1] = end end, UpdateTagsMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end } } @@ -412,22 +411,22 @@ r[#r + 1] = InitCommand = function(self) self:xy(frameX + 10, frameY + capWideScale(80, 80) + 225) end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) self:visible(tagFunction == 2) end, UpdateTagsMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end, LoadFont("Common Large") .. { InitCommand = function(self) self:zoom(fontScale):halign(0) end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) self:settext("Mode: " .. (filterMode and "AND" or "OR")) end, UpdateTagsMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end }, Def.Quad { @@ -489,7 +488,7 @@ r[#r + 1] = InitCommand = function(self) self:x(175):halign(0.5):zoom(0.3):diffuse(getMainColor("positive")) end, - SetCommand = function(self) + BORPBORPNORFNORFcCommand = function(self) self:settextf( "Showing %i-%i of %i", math.min(((currenttagpage - 1) * tagsperpage) + 1, #displayindex), @@ -498,7 +497,7 @@ r[#r + 1] = ) end, UpdateTagsMessageCommand = function(self) - self:queuecommand("Set") + self:queuecommand("BORPBORPNORFNORFc") end } } From ab1c596e59ccf2f66a9e30c0d15cd338f9a1b1d1 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 14:20:38 -0500 Subject: [PATCH 168/320] nick wat r u doin --- .../_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 7cf902d995..1c87f10da9 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -84,17 +84,11 @@ chat.ScreenChangedMessageCommand = function(self) function() self:visible(false) end, - 0.01 + 0.025 ) else self:visible(online) show = true - s:setInterval( - function() - s:AddInputCallback(MPinput) - end, - 0.01 - ) end MESSAGEMAN:Broadcast("UpdateChatOverlay") end From 45da444686a93a43589bac211c8b0b62e8c2995b Mon Sep 17 00:00:00 2001 From: poco0317 Date: Thu, 29 Nov 2018 15:36:03 -0600 Subject: [PATCH 169/320] Fix softlock on profile edit screen bad temp fix --- .../BGAnimations/ScreenOptionsCustomizeProfile overlay.lua | 7 ++++--- Themes/_fallback/metrics.ini | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua b/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua index 0f7f8fb424..50b4ac2f63 100644 --- a/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenOptionsCustomizeProfile overlay.lua @@ -66,7 +66,8 @@ do end end -local menu_items = { +local menu_items = {} +--[[ { name = "weight", get = "GetWeightPounds", @@ -113,7 +114,7 @@ if #char_list > 0 then item_type = "list", list = char_list } -end +end]] menu_items[#menu_items + 1] = {name = "exit", item_type = "exit"} local menu_cursor @@ -171,7 +172,7 @@ end local function exit_screen() local profile_id = GAMESTATE:GetEditLocalProfileID() - PROFILEMAN:SaveLocalProfile(profile_id) + --PROFILEMAN:SaveLocalProfile(profile_id) SCREENMAN:GetTopScreen():StartTransitioningScreen("SM_GoToNextScreen") SOUND:PlayOnce(THEME:GetPathS("Common", "Start")) end diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 5d28e7117e..d53a097e5a 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -3113,7 +3113,7 @@ TimerSeconds=-1 [ScreenOptionsEditProfile] Class="ScreenOptionsEditProfile" -PageOnCommand=visible,false +PageOnCommand=visible,true [ScreenOptionsCustomizeProfile] Class="ScreenWithMenuElements" From 180feaaea25e3efbfcd77aec7dafd767ede77345 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Thu, 29 Nov 2018 16:06:31 -0600 Subject: [PATCH 170/320] Remove dead or useless metrics things move an options explanation tiny minor cleanup --- Themes/Til Death/Languages/en.ini | 1 - Themes/_fallback/Languages/en.ini | 3 ++- Themes/_fallback/metrics.ini | 20 +++++++------------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Themes/Til Death/Languages/en.ini b/Themes/Til Death/Languages/en.ini index 7e5d0bbe90..474f21b3c4 100644 --- a/Themes/Til Death/Languages/en.ini +++ b/Themes/Til Death/Languages/en.ini @@ -200,4 +200,3 @@ NPSWindow = Sets the time window (in seconds) of the NPS Display. Smaller window ReceptorSize=Sets the size of the receptors. MeasureLines=Toggle whether to display measure lines on the notefield. Please reload metrics afterwards. ProgressBar = Determines the location of the full progress bar during gameplay. -FullTapExplosions = Toggle whether to play the full tap explosion animation on taps. Short means that they instantly end when you release your tap. diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index b8b60195af..89d1a6a1b7 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -333,7 +333,7 @@ Accel=Accelerate, Decelerate or otherwise adjust the arrow speed. AllowExtraStage=When enabled (and Event Mode isn't on), allows the player to earn extra stages after completing certain requirements. AllowHoldForOptions=If set to double tap, holding start when selecting a song will not go to the options screen. AllowSongDeletion=Allow players to permanently delete songs from the system by pressing Ctrl+Backspace when browsing the music wheel. -AllowW1=Enable or disable fantastic judgement. NEVER - never show Fantastic, COURSES ONLY - only during nonstop/oni modes, ALWAYS - all modes of play. +AllowW1=Enable or disable the marvelous judgement in gameplay. AllowMultipleHighScoreWithSameName=If turned off, only the highest score with a given name will be saved. If turned on, it will allow mutliple high scores with a given name to be saved. AllowMultipleToasties=Allow multiple toasties to be shown in one song. Announcer=Choose from this list of installed announcer packs. @@ -403,6 +403,7 @@ FastLoad=If enabled, don't check songs for changes on load. FastLoadAdditionalSongs=If enabled, don't check songs for changes to Additional Songs on load. FastNoteRendering=If enabled, the z buffer is not cleared after every note. This causes 3d noteskins to collide, but substantially improves performance in gameplay. Fill Machine Stats= +FullTapExplosions = Toggle whether to play the full tap explosion animation on taps. Short means that they instantly end when you release your tap. Game=Change the current game type with this option. Get a better editor= Download Arrow Vortex, a powerful and flexible standalone editor that obsoletes the in-game one many times over. GetRankingName=Determines if name entry should never be shown, always be shown, or shown when the course is listed on the high scores screen. diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index d53a097e5a..642aaf5397 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -1816,7 +1816,8 @@ UpdateOnMessage="" # NumChoicesOnPage1=100 DefaultChoice="GameStart" -ChoiceNames="GameStart,Options,Edit,Jukebox,GameSelect,Exit" +#ChoiceNames="GameStart,Options,Edit,Jukebox,GameSelect,Exit" +ChoiceNames="GameStart,Options,GameSelect,AV,Exit" ChoiceGameStart="applydefaultoptions;text,Game Start;screen,"..Branch.AfterTitleMenu() #ChoiceQuickPlay="applydefaultoptions;text,Quick Play;" ChoiceOptions="screen,ScreenOptionsService;text,Options" @@ -1829,6 +1830,7 @@ ChoiceGameSelect="screen,ScreenSelectGame;text,Select Game" ChoiceJukebox="screen,ScreenJukeboxMenu;text,Jukebox" ChoiceReportBug="urlnoexit,https://github.com/etternagame/etterna/issues;text,Report Bug" ChoiceSandbox="screen,ScreenTest;text,Sandbox" +ChoiceAV="urlnoexit,https://www.ddrnl.com/viewtopic.php?f=13&t=156;text,Editor" # AllowRepeatingInput=true ShowCursor=false @@ -1984,7 +1986,7 @@ PrevScreen=Branch.TitleMenu() TimerSeconds=30 # DefaultChoice="Normal" -ChoiceNames="Normal,Rave,Nonstop,Oni,Endless" +ChoiceNames="Normal" # PerChoiceScrollElement=false PerChoiceIconElement=false @@ -2955,7 +2957,7 @@ PrevScreen="ScreenOptionsInputSub" Fallback="ScreenOptionsServiceChild" PrevScreen="ScreenOptionsService" NextScreen="ScreenOptionsService" -LineNames="1,2,3,4,5,FNR,6,7,8,9,FA,10,11,12,13,14,15,16,17,18,19,20,21,22" +LineNames="1,2,3,4,5,FNR,6,7,8,9,FA,12,13,14,15,16,17,18,20,21" Line1="conf,Windowed" Line2="conf,DisplayResolution" Line3="conf,DisplayAspectRatio" @@ -2967,8 +2969,6 @@ Line7="conf,TimingWindowScale" Line8="conf,LifeDifficulty" Line9="conf,AllowW1" LineFA="conf,DefaultFailType" -Line10="conf,AutogenSteps" -Line11="conf,ShowBanners" Line12="conf,ShowCaution" Line13="conf,ShowInstructions" Line14="conf,ShowDanger" @@ -2976,10 +2976,8 @@ Line15="conf,ShowSongOptions" Line16="conf,EasterEggs" Line17="conf,Theme" Line18="conf,DefaultNoteskin" -Line19="conf,PercentageScoring" Line20="conf,BGBrightness" Line21="conf,Center1Player" -Line22="conf,EventMode" [ScreenOptionsGraphicsSound] Fallback="ScreenOptionsServiceChild" @@ -3047,12 +3045,9 @@ LineNSA="conf,FullTapExplosions" Fallback="ScreenOptionsServiceChild" NextScreen="ScreenOptionsDisplaySub" PrevScreen="ScreenOptionsDisplaySub" -LineNames="1,3,4,6,7,8,9,10,11,12,14" +LineNames="1,6,8,9,10,11,12,14" Line1="conf,Center1Player" -Line3="conf,DancePointsForOni" -Line4="conf,MenuTimer" Line6="conf,MusicWheelUsesSections" -Line7="conf,ShowBanners" Line8="conf,ShowCaution" Line9="conf,ShowDanger" Line10="conf,ShowInstructions" @@ -3080,8 +3075,7 @@ Fallback="ScreenOptionsServiceChild" NextScreen="ScreenOptionsService" PrevScreen="ScreenOptionsService" # stuff tied to arcade features -LineNames="8,9" -Line8="conf,ComboContinuesBetweenSongs" +LineNames="9" Line9="conf,Disqualification" [ScreenOptionsTheme] From 2337ca063bcc10eee7ebd49b5bc36054c623ed42 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Thu, 29 Nov 2018 16:07:13 -0600 Subject: [PATCH 171/320] Remove "Course Only" from Fantastic Timing preference --- src/PrefsManager.cpp | 1 - src/PrefsManager.h | 1 - src/ScreenOptionsMasterPrefs.cpp | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index 3f5b48ed09..b65d4a5b28 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -32,7 +32,6 @@ LuaXType(MusicWheelUsesSections); static const char* AllowW1Names[] = { "Never", - "CoursesOnly", "Everywhere", }; XToString(AllowW1); diff --git a/src/PrefsManager.h b/src/PrefsManager.h index b82a44c36e..02118e5779 100644 --- a/src/PrefsManager.h +++ b/src/PrefsManager.h @@ -21,7 +21,6 @@ enum MusicWheelUsesSections enum AllowW1 { ALLOW_W1_NEVER, /**< The W1 timing is not used. */ - ALLOW_W1_COURSES_ONLY, /**< The W1 timing is used for courses only. */ ALLOW_W1_EVERYWHERE, /**< The W1 timing is used for all modes. */ NUM_AllowW1, AllowW1_Invalid diff --git a/src/ScreenOptionsMasterPrefs.cpp b/src/ScreenOptionsMasterPrefs.cpp index 181a3fd078..82fddd1123 100644 --- a/src/ScreenOptionsMasterPrefs.cpp +++ b/src/ScreenOptionsMasterPrefs.cpp @@ -872,7 +872,7 @@ InitializeConfOptions() ADD(ConfOption("EasterEggs", MovePref, "Off", "On")); // W1 is Fantastic Timing ADD(ConfOption( - "AllowW1", MovePref, "Never", "Courses Only", "Always")); + "AllowW1", MovePref, "Never", "Always")); ADD(ConfOption("AllowExtraStage", MovePref, "Off", "On")); ADD(ConfOption("Disqualification", MovePref, "Off", "On")); ADD(ConfOption("AllowSongDeletion", MovePref, "Off", "On")); From c516ef42afe83a1296f82dd33b66aa0058e17bd1 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 01:21:14 -0300 Subject: [PATCH 172/320] Finish chart requests (Lua bindings) --- src/NetworkSyncManager.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 1460b45678..18590f5b01 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -850,6 +850,8 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) } break; case ettps_chartrequest: { n->requests.emplace_back(ChartRequest(*payload)); + Message msg("ChartRequest"); + MESSAGEMAN->Broadcast(msg); } break; case ettps_enterroomresponse: { bool entered = (*payload)["entered"]; @@ -1810,6 +1812,7 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) LunaNetworkSyncManager() { ADD_METHOD(GetGameplayLeaderboard); + ADD_METHOD(GetChartRequests); ADD_METHOD(GetChatMsg); ADD_METHOD(SendChatMsg); ADD_METHOD(Login); @@ -1820,6 +1823,33 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) }; LUA_REGISTER_CLASS(NetworkSyncManager) + +class LunaChartRequest : public Luna +{ + public: + static int GetChartkey(T* p, lua_State* L) + { + lua_pushstring(L, p->chartkey.c_str()); + return 1; + } + static int GetUser(T* p, lua_State* L) + { + lua_pushstring(L, p->user.c_str()); + return 1; + } + static int GetRate(T* p, lua_State* L) + { + lua_pushnumber(L, p->rate/1000); + return 1; + } + LunaChartRequest() + { + ADD_METHOD(GetChartkey); + ADD_METHOD(GetUser); + ADD_METHOD(GetRate); + } +}; + // lua end /* * (c) 2003-2004 Charles Lohr, Joshua Allen From a0dbb004f0bca147516f4668d9ef0828d6ad5c22 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 01:29:28 -0300 Subject: [PATCH 173/320] Actually register chart requests with lua --- src/NetworkSyncManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 18590f5b01..10b8e85a65 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -1850,6 +1850,8 @@ class LunaChartRequest : public Luna } }; +LUA_REGISTER_CLASS(ChartRequest) + // lua end /* * (c) 2003-2004 Charles Lohr, Joshua Allen From 381ea183c0f0aa67f41cf2efdf2cd1d203811947 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 02:06:31 -0300 Subject: [PATCH 174/320] Delete old ScreenNetSelectMusic bganims folder in installer --- stepmania.nsi | 1 + 1 file changed, 1 insertion(+) diff --git a/stepmania.nsi b/stepmania.nsi index b72c52aaeb..90aa104dbc 100644 --- a/stepmania.nsi +++ b/stepmania.nsi @@ -412,6 +412,7 @@ Section "Main Section" SecMain ;File "Songs\Instructions.txt" ; remove and install themes RMDir /r "$INSTDIR\Themes\_fallback" + RMDir /r "$INSTDIR\Themes\Til Death\BGAnimations\ScreenNetSelectMusic decorations" RMDir /r "$INSTDIR\Themes\_portKit-sm4" RMDir /r "$INSTDIR\Themes\default" CreateDirectory "$INSTDIR\Themes" From 570bcaecb1ea20608f71243f957cb55391c60fee Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 21:29:35 -0500 Subject: [PATCH 175/320] fart jokes aren't very funny, but the word fart is --- src/DownloadManager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index fbaba985b8..50f6c7ed00 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -2433,8 +2433,12 @@ class LunaDownloadManager : public Luna } static int Fart(T* p, lua_State* L) { - lua_pushboolean( - L, DLMAN->chartLeaderboards[SArg(1)][IArg(2) - 1].hasReplay); + RString ck = SArg(1); + size_t idx = IArg(2) - 1; + if (idx < DLMAN->chartLeaderboards[ck].size()) + lua_pushboolean(L, DLMAN->chartLeaderboards[ck][idx].hasReplay); + else + lua_pushboolean(L, false); return 1; } LunaDownloadManager() From 4dedc2e5bf4e4cc8aeea9ca85d77e9030afd5300 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 21:31:14 -0500 Subject: [PATCH 176/320] improve status updates for online leaderboard --- Themes/Til Death/BGAnimations/superscoreboard.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index ca384f47fc..06dd4a6130 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -258,6 +258,16 @@ local o = self:settext("") end end + end, + CurrentSongChangedMessageCommand = function(self) + local online = DLMAN:IsLoggedIn() + if not GAMESTATE:GetCurrentSong() then + self:settext("") + elseif not online and #scoretable == 0 then + self:settext("Login to view scores") + else + self:settext("Retrieving scores...") + end end }, LoadFont("Common normal") .. @@ -325,6 +335,9 @@ local function makeScoreDisplay(i) self:visible(false) end end, + CurrentSongChangedMessageCommand = function(self) + self:visible(false) + end, UpdateCommand = function(self) hs = scoretable[(i + ind)] if hs and i <= numscores then From ade036b1f46f47bfc4bd686c6aaf597cd996e439 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 21:43:20 -0500 Subject: [PATCH 177/320] more fart jokes --- Themes/Til Death/BGAnimations/superscoreboard.lua | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index 06dd4a6130..ec36c6b70e 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -474,11 +474,13 @@ local function makeScoreDisplay(i) end end, DisplayCommand = function(self) - if DLMAN:Fart(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), ind + i) then - self:settext("Watch") - else - self:settext("") - end + if GAMESTATE:GetCurrentSteps(PLAYER_1) then + if DLMAN:Fart(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), ind + i) then + self:settext("Watch") + else + self:settext("") + end + end end, HighlightCommand = function(self) highlightIfOver(self) From 161c7dc73f0013ea4d0154a751f10abb19eea459 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 22:16:55 -0500 Subject: [PATCH 178/320] throw out numpad enter on netselect because it bugs regular enter --- src/ScreenNetSelectMusic.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index 2948deb1d1..de952b22b6 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -97,6 +97,13 @@ ScreenNetSelectMusic::DifferentialReload() bool ScreenNetSelectMusic::Input(const InputEventPlus& input) { + // if (input.pn == PLAYER_2) could use this to throw out all p2 inputs + // -mina + // return false; + + if (input.DeviceI.button == KEY_KP_ENTER) + return false; + if (!m_bAllowInput || IsTransitioning()) return ScreenWithMenuElements::Input(input); From 12807aec9abb08a81ee15b1f506963e0524e17b2 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 22:41:51 -0500 Subject: [PATCH 179/320] remove another redundant selectionstate check in mouseselect --- Themes/Til Death/BGAnimations/_mousewheelscroll.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua index 57ce82e0d4..37f7c8c8dd 100644 --- a/Themes/Til Death/BGAnimations/_mousewheelscroll.lua +++ b/Themes/Til Death/BGAnimations/_mousewheelscroll.lua @@ -35,13 +35,9 @@ local function scrollInput(event) moving = false end - if top:GetSelectionState() == 2 then - return - end - local mouseX = INPUTFILTER:GetMouseX() local mouseY = INPUTFILTER:GetMouseY() - + if mouseX > capWideScale(370, 500) and mouseX < SCREEN_WIDTH - 32 then if event.DeviceInput.button == "DeviceButton_left mouse button" and event.type == "InputEventType_FirstPress" then local n = 0 From 9636b74d3c5fd0adb0d5be82692c8c0edb992049 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 22:56:01 -0500 Subject: [PATCH 180/320] only load mp leaderboard if connected to mp and on netgameplay --- .../BGAnimations/ScreenGameplay overlay/leaderboard.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index e6a65b08f3..0eb355a2a2 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -1,7 +1,6 @@ local allowedCustomization = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).CustomizeGameplay local leaderboardEnabled = - NSMAN:IsETTP() or (playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn()) - + (NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation") or (playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn()) local entryActors = {} local t = Widg.Container { @@ -62,7 +61,7 @@ function scoreUsingMultiScore(idx) } end local onlineScores = {} -local isMulti = NSMAN:IsETTP() +local isMulti = NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation" if isMulti then multiScores = NSMAN:GetGameplayLeaderboard() for i = 1, 5 do From 80fc6f0eddbfd56c82d8736db404eb27cb6e8392 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Thu, 29 Nov 2018 23:33:34 -0500 Subject: [PATCH 181/320] improve mpleaderboard properly rename mpleaderboard stuff to... mpleaderboard add judgecount string to mpleaderboard --- .../ScreenGameplay overlay/leaderboard.lua | 8 ++--- src/NetworkSyncManager.cpp | 33 ++++++++++--------- src/NetworkSyncManager.h | 15 +++++---- src/ScreenGameplay.cpp | 17 ++++++++-- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 0eb355a2a2..6ff2969f62 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -41,7 +41,7 @@ if not DLMAN:GetCurrentRateFilter() then DLMAN:ToggleRateFilter() end local multiScores = {} -function scoreUsingMultiScore(idx) +local function scoreUsingMultiScore(idx) return { GetDisplayName = function() return multiScores[idx] and multiScores[idx].user or nil @@ -56,14 +56,14 @@ function scoreUsingMultiScore(idx) return -1 end, GetJudgmentString = function() - return "" + return multiScores[idx] and multiScores[idx].jdgstr or "" end } end local onlineScores = {} local isMulti = NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation" if isMulti then - multiScores = NSMAN:GetGameplayLeaderboard() + multiScores = NSMAN:GetMPLeaderboard() for i = 1, 5 do onlineScores[i] = scoreUsingMultiScore(i) end @@ -243,7 +243,7 @@ t.JudgmentMessageCommand = function(self, params) local old = curScore.curWifeScore curScore.curWifeScore = notShit.floor(params.WifePercent * 100) / 10000 if isMulti then - multiScores = NSMAN:GetGameplayLeaderboard() + multiScores = NSMAN:GetMPLeaderboard() end if old ~= curScore.curWifeScore then table.sort(scoreboard, sortFunction) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 10b8e85a65..579a9d9b74 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -31,7 +31,7 @@ std::map ettClientMessageMap = { { ettpc_ping, "ping" }, { ettpc_sendchat, "chat" }, { ettpc_sendscore, "score" }, - { ettpc_gameplayupdate, "gameplayupdate" }, + { ettpc_mpleaderboardupdate, "mpleaderboardupdate" }, { ettpc_createroom, "createroom" }, { ettpc_enterroom, "enterroom" }, { ettpc_selectchart, "selectchart" }, @@ -782,7 +782,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) } break; case ettps_selectchart: { - n->gameplayLeaderboard.clear(); + n->mpleaderboard.clear(); auto ch = (*payload).at("chart"); FindJsonChart(n, ch); json j; @@ -796,7 +796,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) Send(j); } break; case ettps_startchart: { - n->gameplayLeaderboard.clear(); + n->mpleaderboard.clear(); n->m_EvalPlayerData.clear(); auto ch = (*payload).at("chart"); FindJsonChart(n, ch); @@ -828,10 +828,12 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) for (json::iterator it = scores.begin(); it != scores.end(); ++it) { float wife = (*it)["wife"]; + RString jdgstr = (*it)["jdgstr"]; string user = (*it)["user"].get(); - n->gameplayLeaderboard[user].wife = wife; + n->mpleaderboard[user].wife = wife; + n->mpleaderboard[user].jdgstr = jdgstr; } - Message msg("GameplayUpdate"); + Message msg("MPLeaderboardUpdate"); MESSAGEMAN->Broadcast(msg); } break; case ettps_createroomresponse: { @@ -1040,14 +1042,15 @@ ETTProtocol::SendChat(const RString& message, string tab, int type) Send(chatMsg); } void -ETTProtocol::SendGameplayUpdate(float wife) +ETTProtocol::SendMPLeaderboardUpdate(float wife, RString& jdgstr) { if (ws == nullptr) return; json j; - j["type"] = ettClientMessageMap[ettpc_gameplayupdate]; + j["type"] = ettClientMessageMap[ettpc_mpleaderboardupdate]; auto& payload = j["payload"]; payload["wife"] = wife; + payload["jdgstr"] = jdgstr; j["id"] = msgId++; Send(j); } @@ -1316,10 +1319,10 @@ NetworkSyncManager::SendChat(const RString& message, string tab, int type) } void -NetworkSyncManager::SendGameplayUpdate(float wife) +NetworkSyncManager::SendMPLeaderboardUpdate(float wife, RString& jdgstr) { if (curProtocol != nullptr) - curProtocol->SendGameplayUpdate(wife); + curProtocol->SendMPLeaderboardUpdate(wife, jdgstr); } int @@ -1685,10 +1688,10 @@ NetworkSyncManager::GetCurrentSMBuild(LoadingWindow* ld) #endif void -NetworkSyncManager::PushGameplayLeaderboard(lua_State* L) +NetworkSyncManager::PushMPLeaderboard(lua_State* L) { lua_newtable(L); - for (auto& pair : gameplayLeaderboard) { + for (auto& pair : mpleaderboard) { lua_newtable(L); lua_pushnumber(L, pair.second.wife); lua_setfield(L, -2, "wife"); @@ -1753,10 +1756,10 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) lua_pushboolean(L, p->IsETTP()); return 1; } - static int GetGameplayLeaderboard(T* p, lua_State* L) + static int GetMPLeaderboard(T* p, lua_State* L) { - auto& lbd = NSMAN->gameplayLeaderboard; - NSMAN->PushGameplayLeaderboard(L); + auto& lbd = NSMAN->mpleaderboard; + NSMAN->PushMPLeaderboard(L); return 1; } static int GetChartRequests(T* p, lua_State* L) @@ -1811,7 +1814,7 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) } LunaNetworkSyncManager() { - ADD_METHOD(GetGameplayLeaderboard); + ADD_METHOD(GetMPLeaderboard); ADD_METHOD(GetChartRequests); ADD_METHOD(GetChatMsg); ADD_METHOD(SendChatMsg); diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index a3a14b334a..ef271dc6a2 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -1,4 +1,4 @@ -#ifndef NetworkSyncManager_H +#ifndef NetworkSyncManager_H #define NetworkSyncManager_H #include "Difficulty.h" @@ -105,7 +105,7 @@ enum ETTClientMessageTypes ettpc_ping, ettpc_sendchat, ettpc_sendscore, - ettpc_gameplayupdate, + ettpc_mpleaderboardupdate, ettpc_createroom, ettpc_enterroom, ettpc_leaveroom, @@ -154,6 +154,7 @@ class GameplayScore { public: float wife; + RString jdgstr; }; class PacketFunctions @@ -231,7 +232,7 @@ class NetProtocol virtual void OffOptions(){}; virtual void OnEval(){}; virtual void OffEval(){}; - virtual void SendGameplayUpdate(float wife){}; + virtual void SendMPLeaderboardUpdate(float wife, RString& jdgstr){}; }; class ETTProtocol : public NetProtocol @@ -270,7 +271,7 @@ class ETTProtocol : public NetProtocol void OffOptions() override; void OnEval() override; void OffEval() override; - void SendGameplayUpdate(float wife) override; + void SendMPLeaderboardUpdate(float wife, RString& jdgstr) override; void ReportHighScore(HighScore* hs, PlayerStageStats& pss) override; void Send(const char* msg); void Send(json msg); @@ -375,7 +376,7 @@ class NetworkSyncManager // since function was last called. RString m_Scoreboard[NUM_NSScoreBoardColumn]; - void SendGameplayUpdate(float wife); + void SendMPLeaderboardUpdate(float wife, RString& jdgstr); // Used for chatting void SendChat(const RString& message, @@ -391,8 +392,8 @@ class NetworkSyncManager string chartkey; Song* song{ nullptr }; Steps* steps{ nullptr }; - map gameplayLeaderboard; - void PushGameplayLeaderboard(lua_State* L); + map mpleaderboard; + void PushMPLeaderboard(lua_State* L); Difficulty difficulty; int meter; int rate; diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index aa9f447a38..cd453b85b6 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1363,8 +1363,21 @@ ScreenGameplay::BeginScreen() if (GAMESTATE->m_bPlayingMulti) { this->SetInterval( [this]() { - NSMAN->SendGameplayUpdate( - this->GetPlayerInfo(PLAYER_1)->m_pPlayer->curwifescore); + auto& ptns = this->GetPlayerInfo(PLAYER_1)->GetPlayerStageStats()->m_iTapNoteScores; + + RString doot = ssprintf("%d I %d I %d I %d I %d I %d x%d", + ptns[TNS_W1], + ptns[TNS_W2], + ptns[TNS_W3], + ptns[TNS_W4], + ptns[TNS_W5], + ptns[TNS_Miss], + this->GetPlayerInfo(PLAYER_1) + ->GetPlayerStageStats() + ->m_iCurCombo); + NSMAN->SendMPLeaderboardUpdate( + this->GetPlayerInfo(PLAYER_1)->m_pPlayer->curwifescore, doot); + }, 1, -1); From 16754ad174645c1294fbde01af8c988a62889ea3 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 00:20:08 -0500 Subject: [PATCH 182/320] improve mp chat behavior * ctrl + enter ignored for starting songs in screennetselect * minimize will always clear current message and disable typing * ctrl + enter will unmimize and activate chat input if minimized, or activate chat input if unminimized * insert will hard hard minimize the chat similar to the mouse click toggles, but will activate input automatically * pressing "/" will maximize and activate input as needed and auto place a "/" (for fast commands) * pressing enter while the typingtext is empty will turn off input (basically, double tap enter to disable input) * delete clears the current msg, since we have no cursor it does nothing anyway and hitting escape diabled --- .../ScreenChatOverlay overlay.lua | 46 ++++++++++++++++++- src/ScreenNetSelectMusic.cpp | 5 ++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 1c87f10da9..be67d39db1 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -58,7 +58,7 @@ local show = true local online = IsNetSMOnline() and IsSMOnlineLoggedIn(PLAYER_1) and NSMAN:IsETTP() chat.MinimiseMessageCommand = function(self) - self:linear(0.5) + self:linear(0.25) moveY = minimised and height * (lineNumber + inputLineNumber + tabHeight - 1) or 0 self:y(moveY) end @@ -334,6 +334,8 @@ function overTab(mx, my) end return nil, nil end + + function MPinput(event) if (not show or not online) or isGameplay then return false @@ -345,7 +347,7 @@ function MPinput(event) end typing = false local mx, my = INPUTFILTER:GetMouseX(), INPUTFILTER:GetMouseY() - if isOver(minbar) then + if isOver(minbar) then --hard mouse toggle -mina minimised = not minimised MESSAGEMAN:Broadcast("Minimise") update = true @@ -387,12 +389,37 @@ function MPinput(event) end end + -- hard kb toggle + if event.type == "InputEventType_Release" and event.DeviceInput.button == "DeviceButton_insert" then + minimised = not minimised + MESSAGEMAN:Broadcast("Minimise") + update = true + if not minimize then + typing = true + typingText = "" + end + end + + if not typing and event.type == "InputEventType_Release" then -- keys for auto turning on chat if not already on -mina + if event.DeviceInput.button == "DeviceButton_/" then + typing = true + update = true + if minimised then + minimised = not minimised + MESSAGEMAN:Broadcast("Minimise") + end + typingText = "/" + end + end + if typing then if event.type == "InputEventType_Release" then if event.DeviceInput.button == "DeviceButton_enter" then if typingText:len() > 0 then NSMAN:SendChatMsg(typingText, currentTabType, currentTabName) typingText = "" + elseif typingText == "" then + typing = false -- pressing enter when text is empty to deactive chat is expected behavior -mina end update = true end @@ -403,6 +430,9 @@ function MPinput(event) elseif event.DeviceInput.button == "DeviceButton_space" then typingText = typingText .. " " update = true + elseif event.DeviceInput.button == "DeviceButton_delete" then -- reset msg with delete (since there's no cursor) + typingText = "" + update = true elseif (INPUTFILTER:IsBeingPressed("left ctrl") or INPUTFILTER:IsBeingPressed("right ctrl")) and event.DeviceInput.button == "DeviceButton_v" @@ -444,7 +474,19 @@ function MPinput(event) return true end + -- kb activate chat input if not minimized (has to go after the above enter block) + if event.type == "InputEventType_Release" and INPUTFILTER:IsBeingPressed("left ctrl") then + if event.DeviceInput.button == "DeviceButton_enter" and not minimised then + typing = true + update = true + end + end + if update then + if minimised then -- minimise will be set in the above blocks, disable input and clear text -mina + typing = false + typingText = "" + end MESSAGEMAN:Broadcast("UpdateChatOverlay") end diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index de952b22b6..4c79c05215 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -584,6 +584,11 @@ ScreenNetSelectMusic::MenuDown(const InputEventPlus& input) bool ScreenNetSelectMusic::MenuStart(const InputEventPlus& input) { + // dont allow ctrl + enter to select songs... technically if there's enough + // lag for some reason we can hit here from a ctrl+enter input but ctrl may + // be released by now, though this is unlikely to happen -mina + if (INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL))) + return false; return SelectCurrent(); } bool From c211afb6db22a7b278e2f37fc8673ed195c58da7 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 01:20:17 -0500 Subject: [PATCH 183/320] upon entering a room auto set the tab to that room --- .../_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index be67d39db1..9557babec5 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -30,7 +30,7 @@ chats[1] = {} chats[2] = {} chats[0][""] = {} local tabs = {{0, ""}} ---chats[tabname][tabtype] +--chats[tabName][tabType] --tabtype: 0=lobby, 1=room, 2=pm local messages = chats[0][""] local currentTabName = "" @@ -90,6 +90,13 @@ chat.ScreenChangedMessageCommand = function(self) self:visible(online) show = true end + if currentScreen == "ScreenNetSelectMusic" then + for i=1, #tabs do + if tabs[i][2] == NSMAN:GetCurrentRoomName() then + changeTab(tabs[i][2], tabs[i][1]) + end + end + end MESSAGEMAN:Broadcast("UpdateChatOverlay") end chat.MultiplayerDisconnectionMessageCommand = function(self) From 0e4d75c1088aa44d84aaab22048441d423677abe Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 01:34:25 -0500 Subject: [PATCH 184/320] highlight chat when messages come in if minimised --- .../BGAnimations/ScreenChatOverlay overlay.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 9557babec5..dd3404669e 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -134,6 +134,17 @@ chat[#chat + 1] = self:diffuse(Colors.bar) self:diffusealpha(transparency) self:stretchto(x, y, width + x, height + y) + end, + ChatMessageCommand = function(self) + if minimised then + self:linear(0.25) + self:diffuse(Colors.activeInput) + end + end, + MinimiseMessageCommand = function(self) + if not minimised then + self:diffuse(Colors.bar) + end end } chat[#chat + 1] = From ad1294691a3f7b37c552c60e173b9cd5edbffad7 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 02:15:49 -0500 Subject: [PATCH 185/320] mpleaderboards are 100% broken --- .../BGAnimations/ScreenGameplay overlay/leaderboard.lua | 2 +- src/NetworkSyncManager.cpp | 6 +++--- src/NetworkSyncManager.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 6ff2969f62..b7838f73ae 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -243,7 +243,7 @@ t.JudgmentMessageCommand = function(self, params) local old = curScore.curWifeScore curScore.curWifeScore = notShit.floor(params.WifePercent * 100) / 10000 if isMulti then - multiScores = NSMAN:GetMPLeaderboard() + scoreboard = NSMAN:GetMPLeaderboard() end if old ~= curScore.curWifeScore then table.sort(scoreboard, sortFunction) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 579a9d9b74..05388162c3 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -56,7 +56,7 @@ std::map ettServerMessageMap = { { "chat", ettps_recievechat }, { "login", ettps_loginresponse }, { "score", ettps_recievescore }, - { "leaderboard", ettps_gameplayleaderboard }, + { "leaderboard", ettps_mpleaderboardupdate }, { "createroom", ettps_createroomresponse }, { "enterroom", ettps_enterroomresponse }, { "selectchart", ettps_selectchart }, @@ -823,7 +823,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) msg.SetParam("type", type); MESSAGEMAN->Broadcast(msg); } break; - case ettps_gameplayleaderboard: { + case ettps_mpleaderboardupdate: { auto& scores = (*payload)["scores"]; for (json::iterator it = scores.begin(); it != scores.end(); ++it) { @@ -1047,7 +1047,7 @@ ETTProtocol::SendMPLeaderboardUpdate(float wife, RString& jdgstr) if (ws == nullptr) return; json j; - j["type"] = ettClientMessageMap[ettpc_mpleaderboardupdate]; + j["type"] = "leaderboard"; auto& payload = j["payload"]; payload["wife"] = wife; payload["jdgstr"] = jdgstr; diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index ef271dc6a2..a75411e86e 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -87,7 +87,7 @@ enum ETTServerMessageTypes ettps_loginresponse, ettps_roomlist, ettps_recievescore, - ettps_gameplayleaderboard, + ettps_mpleaderboardupdate, ettps_createroomresponse, ettps_enterroomresponse, ettps_selectchart, From ef32fc20d23a992144d9a274960113a3e7d3f67d Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 03:27:08 -0500 Subject: [PATCH 186/320] comment out lua register chartrequests (breaks compile) --- src/NetworkSyncManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 05388162c3..5dd5fe5a94 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -1853,7 +1853,7 @@ class LunaChartRequest : public Luna } }; -LUA_REGISTER_CLASS(ChartRequest) +//LUA_REGISTER_CLASS(ChartRequest) // breaks compile, no clue why -mina // lua end /* From 73be952f8c275c564e222b4730b5fe6ddb6ef380 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 03:33:03 -0500 Subject: [PATCH 187/320] scale down roomsearch a little --- .../BGAnimations/ScreenNetRoom decorations/roomsearch.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua index fb5fea2926..ae392b0251 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/roomsearch.lua @@ -147,6 +147,9 @@ end local t = Def.ActorFrame { + InitCommand = function(self) + self:zoom(0.85) + end, BeginCommand = function(self) whee = SCREENMAN:GetTopScreen():GetMusicWheel() SCREENMAN:GetTopScreen():AddInputCallback(searchInput) From 4bab82fb12a066b491c6f1d4f996cd7b523bee68 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 04:00:05 -0500 Subject: [PATCH 188/320] ok we do need to use play we want this to update when changing nestedtabs --- .../BGAnimations/ScreenSelectMusic decorations/score.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 3b83e440a0..5879b65586 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -71,11 +71,11 @@ local function updateLeaderBoardForCurrentChart() DLMAN:RequestChartLeaderBoardFromOnline( steps:GetChartKey(), function(leaderboard) - moped:queuecommand("SetFromLeaderboard", leaderboard) + moped:playcommand("SetFromLeaderboard", leaderboard) end ) else - moped:queuecommand("SetFromLeaderboard", {}) + moped:playcommand("SetFromLeaderboard", {}) end end end From 10d4855cde5442c9ab8c241dc14ceef97e4f3137 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 04:00:32 -0500 Subject: [PATCH 189/320] send noterows for both basic and full replays when uploading from disk --- src/DownloadManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 50f6c7ed00..4930f7a8cc 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1068,12 +1068,13 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, for (size_t i = 0; i < offsets.size(); i++) { replayString += "["; replayString += to_string(timestamps[i]) + ","; - replayString += to_string(1000.f * offsets[i]); + replayString += to_string(1000.f * offsets[i]) + ","; if (hs->GetReplayType() == 2) { - replayString += "," + to_string(columns[i]) + ","; + replayString += to_string(columns[i]) + ","; replayString += to_string(types[i]) + ","; - replayString += to_string(rows[i]); + } + replayString += to_string(rows[i]); replayString += "],"; } replayString = From 23586b3ccbe1816551ceb52811bf5795e618896c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 04:05:59 -0500 Subject: [PATCH 190/320] prevent obscure theme error --- Themes/Til Death/BGAnimations/superscoreboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index ec36c6b70e..ba9ee48a92 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -68,7 +68,7 @@ end local filts = {"All Rates", "Current Rate"} local topornah = {"Top Scores", "All Scores"} -local scoretable +local scoretable = {} local o = Def.ActorFrame { Name = "ScoreDisplay", From 21d4393abbea29d5ebd7b55103ef893dd05790d3 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 04:24:01 -0500 Subject: [PATCH 191/320] make newly uploaded replays awesome --- src/DownloadManager.cpp | 11 +++++++++-- src/ScreenSelectMusic.cpp | 11 ++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 4930f7a8cc..f518f9e697 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1410,6 +1410,7 @@ DownloadManager::RequestReplayData(string scoreid, vector timestamps; vector offsets; vector tracks; + vector rows; vector types; auto j = json::parse(req.result); @@ -1423,12 +1424,17 @@ DownloadManager::RequestReplayData(string scoreid, timestamps.emplace_back(note[0].get()); offsets.emplace_back(note[1].get() / 1000.f); - - if (note.size() > 2) { + if (note.size() == 3) { // pre-0.6 with noterows + rows.emplace_back(note[2].get()); + } + if (note.size() > 3) { // 0.6 without noterows tracks.emplace_back(note[2].get()); types.emplace_back( static_cast(note[3].get())); } + if (note.size() == 5) { // 0.6 with noterows + rows.emplace_back(note[4].get()); + } } auto& lbd = DLMAN->chartLeaderboards[chartkey]; auto it = find_if( @@ -1440,6 +1446,7 @@ DownloadManager::RequestReplayData(string scoreid, it->hs.SetOffsetVector(offsets); it->hs.SetTrackVector(tracks); it->hs.SetTapNoteTypeVector(types); + it->hs.SetNoteRowVector(rows); if (tracks.empty()) it->hs.SetReplayType(1); diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 61117015cd..a106a26c96 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1705,8 +1705,11 @@ class LunaScreenSelectMusic : public Luna // from the existing, if the score was cc off then we need to fill in // extra rows for each tap in the chord -mina auto timestamps = hs->GetCopyOfSetOnlineReplayTimestampVector(); + auto noterows = hs->GetNoteRowVector(); auto REEEEEEEEEEEEEE = hs->GetOffsetVector(); - if (!timestamps.empty()) { + if (!timestamps.empty() && + noterows.empty()) { // if we have noterows from newer uploads, just + // use them -mina GAMESTATE->SetProcessedTimingData( GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData()); auto* td = GAMESTATE->m_pCurSteps[PLAYER_1]->GetTimingData(); @@ -1740,9 +1743,11 @@ class LunaScreenSelectMusic : public Luna GAMESTATE->SetProcessedTimingData(nullptr); // hs->SetNoteRowVector(ihatemylife); hs->SetNoteRowVector(noterows); + } - // Since we keep misses on EO as 180ms, we need to convert them - // back. + // Since we keep misses on EO as 180ms, we need to convert them + // back. + if (!timestamps.empty()) { auto offsets = hs->GetCopyOfOffsetVector(); for (auto& offset : offsets) { if (fabs(offset) >= .18f) From 00c04d466d970b8eb59fede941f3349a36c61811 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 05:22:31 -0500 Subject: [PATCH 192/320] null -> nullptr --- src/ScoreManager.cpp | 10 ++++++++++ src/SongManager.cpp | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ScoreManager.cpp b/src/ScoreManager.cpp index f85c6db016..0ba33bdbce 100644 --- a/src/ScoreManager.cpp +++ b/src/ScoreManager.cpp @@ -226,6 +226,16 @@ ScoresForChart::SetTopScores() eligiblescores.emplace_back(hs); } + if (eligiblescores.size() < 2) { + FOREACHM(int, ScoresAtRate, ScoresByRate, i) + { + auto& hs = i->second.PBptr; + if (hs && hs->GetSSRCalcVersion() == GetCalcVersion() && + hs->GetEtternaValid() && hs->GetGrade() != Grade_Failed) + eligiblescores.emplace_back(hs); + } + } + if (eligiblescores.empty()) return; diff --git a/src/SongManager.cpp b/src/SongManager.cpp index fcec3a253d..e4fb6ae6ad 100644 --- a/src/SongManager.cpp +++ b/src/SongManager.cpp @@ -637,7 +637,7 @@ SongManager::GetStepsByChartkey(RString ck) { if (StepsByKey.count(ck)) return StepsByKey[ck]; - return NULL; + return nullptr; } Song* @@ -645,7 +645,7 @@ SongManager::GetSongByChartkey(RString ck) { if (SongsByKey.count(ck)) return SongsByKey[ck]; - return NULL; + return nullptr; } static LocalizedString FOLDER_CONTAINS_MUSIC_FILES( From 8bd3e8f0f2d2e55fb28e53f146d6ca6ebf3ce3ab Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 05:29:40 -0500 Subject: [PATCH 193/320] fix callback dying once we hit a score with no replay only add files with replay to the deque, this makes more sense for the use case anyway --- src/DownloadManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index f518f9e697..21ef6f7460 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1909,7 +1909,8 @@ DownloadManager::UploadScores() auto ts = scorePtr->GetTopScore(); if ((ts == 1 || ts == 2) && !scorePtr->IsUploadedToServer(serverURL.Get())) { - toUpload.emplace_back(scorePtr); + if (scorePtr->HasReplayData()) + toUpload.emplace_back(scorePtr); } } } From 4052c14ae055d47fd79af3c0c73b3c2d60bf9587 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 05:30:14 -0500 Subject: [PATCH 194/320] pre-empt null steps crash when uploading replays this can only occur if ischartloaded() which counts [key] in songsbykey is true, but getstepsbykey which grabs [key] in stepsbykey returns a nullptr, which shoiuldn't be possible since songsbykey only has entries added after stepbykey has an entry added for the same key in other words this shouldn't be possible, yet it consistently is crashing for me on hi19s eternus chart --- src/DownloadManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 21ef6f7460..4dcef6683f 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -873,6 +873,8 @@ SetCURLPOSTScore(CURL*& curlHandle, curlHandle, form, lastPtr, "chartkey", hs->GetChartKey()); SetCURLFormPostField(curlHandle, form, lastPtr, "rate", hs->musics); auto chart = SONGMAN->GetStepsByChartkey(hs->GetChartKey()); + if (chart == nullptr) + return; SetCURLFormPostField(curlHandle, form, lastPtr, @@ -1062,6 +1064,8 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, if (offsets.size() > 0) { replayString = "["; auto steps = SONGMAN->GetStepsByChartkey(hs->GetChartKey()); + if (steps == nullptr) + return; vector timestamps = steps->GetTimingData()->ConvertReplayNoteRowsToTimestamps( hs->GetNoteRowVector(), hs->GetMusicRate()); From 95bc1a6a54b2ae7a1c480d7dde732e201d9dea14 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 05:33:20 -0500 Subject: [PATCH 195/320] context comment for earlier change --- src/ScoreManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ScoreManager.cpp b/src/ScoreManager.cpp index 0ba33bdbce..163ca1c9f3 100644 --- a/src/ScoreManager.cpp +++ b/src/ScoreManager.cpp @@ -226,6 +226,7 @@ ScoresForChart::SetTopScores() eligiblescores.emplace_back(hs); } + // if there aren't 2 noccpbs in top scores we might as well use old cc scores -mina if (eligiblescores.size() < 2) { FOREACHM(int, ScoresAtRate, ScoresByRate, i) { From 5ffb8aa925da9b26c9cf3feff6500c3d3b3ecd3b Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 06:11:19 -0500 Subject: [PATCH 196/320] this really shouldn't be necessary... however... it will only help --- src/SongManager.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/SongManager.h b/src/SongManager.h index cc5978f3d2..b22782ea31 100644 --- a/src/SongManager.h +++ b/src/SongManager.h @@ -1,4 +1,4 @@ -#ifndef SONGMANAGER_H +#ifndef SONGMANAGER_H #define SONGMANAGER_H class LoadingWindow; @@ -72,7 +72,10 @@ class SongManager // mina Steps* GetStepsByChartkey(RString ck); Song* GetSongByChartkey(RString ck); - bool IsChartLoaded(RString ck) { return SongsByKey.count(ck) == 1; } + bool IsChartLoaded(RString ck) + { + return SongsByKey.count(ck) == 1 && StepsByKey.count(ck) == 1; // shouldn't be necessary but apparently it is -mina + } void ResetGroupColors(); From 8eadffd0ea6c2c26c54ffb85423b2b2c34a6ea4c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 06:36:26 -0500 Subject: [PATCH 197/320] there's no override for functions for these so all it does is break it --- src/DownloadManager.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/DownloadManager.h b/src/DownloadManager.h index f687927e74..aa625da732 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -123,9 +123,6 @@ class OnlineTopScore }; struct OnlineHighScore : HighScore { - public: - int userid; - string scoreid; }; class OnlineScore { From db12e1237da9d96eb883ef25603a3bf2500ae33c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Fri, 30 Nov 2018 08:23:06 -0500 Subject: [PATCH 198/320] use wifegrade for neteval scores when determining rainbow scroll --- src/ScreenNetEvaluation.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/ScreenNetEvaluation.cpp b/src/ScreenNetEvaluation.cpp index 1945a9a6e6..30e04ab9c6 100644 --- a/src/ScreenNetEvaluation.cpp +++ b/src/ScreenNetEvaluation.cpp @@ -169,15 +169,8 @@ ScreenNetEvaluation::HandleScreenMessage(const ScreenMessage SM) ? NSMAN->m_PlayerNames[NSMAN->m_EvalPlayerData[i].name] : NSMAN->m_EvalPlayerData[i].nameStr); - // Yes, hardcoded (I'd like to leave it that way) -CNLohr (in - // reference to Grade_Tier03) Themes can read this differently. The - // correct solution depends... - // TODO: make this a server-side variable. -aj - if (NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetGrade() != - Grade_NoData - ? NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetGrade() - : NSMAN->m_EvalPlayerData[m_iCurrentPlayer].grade < - Grade_Tier03) + if (NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetWifeGrade() < + Grade_Tier03) m_textUsers[i].PlayCommand("Tier02OrBetter"); ON_COMMAND(m_textUsers[i]); @@ -250,10 +243,7 @@ ScreenNetEvaluation::UpdateStats() NSMAN->m_EvalPlayerData[m_iCurrentPlayer].difficulty); msg.SetParam("Score", NSMAN->m_EvalPlayerData[m_iCurrentPlayer].score); msg.SetParam("Grade", - NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetGrade() != - Grade_NoData - ? NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetGrade() - : NSMAN->m_EvalPlayerData[m_iCurrentPlayer].grade); + NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetWifeGrade()); msg.SetParam("PlayerOptions", NSMAN->m_EvalPlayerData[m_iCurrentPlayer].playerOptions); if (pSteps) From fef34cf79576e4049cb42d7ec775cd9e685e4743 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 19:57:35 -0300 Subject: [PATCH 199/320] Fix multy chartkey selection --- .../ScreenGameplay overlay/leaderboard.lua | 7 +- src/NetworkSyncManager.cpp | 26 +--- src/ScreenNetSelectMusic.cpp | 137 +++--------------- 3 files changed, 30 insertions(+), 140 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index b7838f73ae..2db3087cf5 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -1,6 +1,7 @@ local allowedCustomization = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).CustomizeGameplay local leaderboardEnabled = - (NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation") or (playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn()) + (NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation") or + (playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn()) local entryActors = {} local t = Widg.Container { @@ -47,13 +48,13 @@ local function scoreUsingMultiScore(idx) return multiScores[idx] and multiScores[idx].user or nil end, GetWifeGrade = function() - return 0 + return multiScores[idx] and GetGradeFromPercent(multiScores[idx].wife) or 0 end, GetWifeScore = function() return multiScores[idx] and multiScores[idx].wife or -500 end, GetSkillsetSSR = function() - return -1 + return 0 end, GetJudgmentString = function() return multiScores[idx] and multiScores[idx].jdgstr or "" diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 5dd5fe5a94..d58a486ecb 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -31,7 +31,7 @@ std::map ettClientMessageMap = { { ettpc_ping, "ping" }, { ettpc_sendchat, "chat" }, { ettpc_sendscore, "score" }, - { ettpc_mpleaderboardupdate, "mpleaderboardupdate" }, + { ettpc_mpleaderboardupdate, "gameplayupdate" }, { ettpc_createroom, "createroom" }, { ettpc_enterroom, "enterroom" }, { ettpc_selectchart, "selectchart" }, @@ -210,7 +210,6 @@ NetworkSyncManager::GetCurrentSMBuild(LoadingWindow* ld) #include "ezsockets.h" AutoScreenMessage(SM_AddToChat); -AutoScreenMessage(SM_ChangeSong); AutoScreenMessage(SM_GotEval); AutoScreenMessage(SM_UsersUpdate); AutoScreenMessage(SM_FriendsUpdate); @@ -609,8 +608,6 @@ ETTProtocol::FindJsonChart(NetworkSyncManager* n, json& ch) n->steps = steps; break; } - if (n->song != nullptr) - break; } } } else { @@ -1047,7 +1044,7 @@ ETTProtocol::SendMPLeaderboardUpdate(float wife, RString& jdgstr) if (ws == nullptr) return; json j; - j["type"] = "leaderboard"; + j["type"] = ettClientMessageMap[ettpc_mpleaderboardupdate]; auto& payload = j["payload"]; payload["wife"] = wife; payload["jdgstr"] = jdgstr; @@ -1695,21 +1692,14 @@ NetworkSyncManager::PushMPLeaderboard(lua_State* L) lua_newtable(L); lua_pushnumber(L, pair.second.wife); lua_setfield(L, -2, "wife"); + lua_pushstring(L, pair.second.jdgstr.c_str()); + lua_setfield(L, -2, "jdgstr"); + lua_pushstring(L, pair.first.c_str()); + lua_setfield(L, -2, "user"); lua_setfield(L, -2, pair.first.c_str()); } return; } -void -ChartRequest::PushSelf(lua_State* L) -{ - lua_createtable(L, 0, 3); - lua_pushstring(L, chartkey.c_str()); - lua_setfield(L, -2, "chartkey"); - lua_pushstring(L, user.c_str()); - lua_setfield(L, -2, "user"); - lua_pushnumber(L, rate / 1000); // should this be in [0,1] or [0, 1000] ???? - lua_setfield(L, -2, "rate"); -} static bool ConnectToServer(const RString& t) @@ -1842,7 +1832,7 @@ class LunaChartRequest : public Luna } static int GetRate(T* p, lua_State* L) { - lua_pushnumber(L, p->rate/1000); + lua_pushnumber(L, p->rate / 1000); return 1; } LunaChartRequest() @@ -1853,7 +1843,7 @@ class LunaChartRequest : public Luna } }; -//LUA_REGISTER_CLASS(ChartRequest) // breaks compile, no clue why -mina +LUA_REGISTER_CLASS(ChartRequest) // lua end /* diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index 4c79c05215..076c54c126 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -34,7 +34,6 @@ AutoScreenMessage(SM_AddToChat); AutoScreenMessage(SM_FriendsUpdate); AutoScreenMessage(SM_NoSongs); -AutoScreenMessage(SM_ChangeSong); AutoScreenMessage(SM_SetWheelSong); AutoScreenMessage(SM_RefreshWheelLocation); AutoScreenMessage(SM_SongChanged); @@ -263,123 +262,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) m_MusicWheel.Move(0); } else if (SM == SM_NoSongs) { SCREENMAN->SetNewScreen(THEME->GetMetric(m_sName, "NoSongsScreen")); - } else if (SM == SM_ChangeSong) { - // First check to see if this song is already selected. This is so that - // if you have multiple copies of the "same" song you can chose which - // copy to play. - Song* CurSong = m_MusicWheel.GetSelectedSong(); - - if (CurSong != NULL) - if ((!CurSong->GetTranslitArtist().CompareNoCase( - NSMAN->m_sArtist)) && - (!CurSong->GetTranslitMainTitle().CompareNoCase( - NSMAN->m_sMainTitle)) && - (!CurSong->GetTranslitSubTitle().CompareNoCase( - NSMAN->m_sSubTitle))) { - switch (NSMAN->m_iSelectMode) { - case 0: - case 1: - NSMAN->m_iSelectMode = 0; - NSMAN->SelectUserSong(); - break; - case 2: // Proper starting of song - case 3: // Blind starting of song - StartSelectedSong(); - goto done; - } - } else { - FOREACH_ENUM(Skillset, i) - { - FILTERMAN->SSFilterLowerBounds[i] = 0; - FILTERMAN->SSFilterUpperBounds[i] = 0; - } - m_MusicWheel.ReloadSongList(false, ""); - } - else { - FOREACH_ENUM(Skillset, i) - { - FILTERMAN->SSFilterLowerBounds[i] = 0; - FILTERMAN->SSFilterUpperBounds[i] = 0; - } - m_MusicWheel.ReloadSongList(false, ""); - } - - vector AllSongs = SONGMAN->GetAllSongs(); - unsigned i; - - bool found = false; - if (NSMAN->GetServerVersion() >= 129) { - // Dont earch by filehash if none was sent - if (!NSMAN->m_sFileHash.empty()) - for (i = 0; i < AllSongs.size(); i++) { - m_cSong = AllSongs[i]; - if (NSMAN->m_sArtist == m_cSong->GetTranslitArtist() && - NSMAN->m_sMainTitle == - m_cSong->GetTranslitMainTitle() && - NSMAN->m_sSubTitle == m_cSong->GetTranslitSubTitle() && - NSMAN->m_sFileHash == m_cSong->GetFileHash()) { - found = true; - break; - } - } - } - // If we couldnt find it using file hash search for it without using it, - // if using SMSERVER < 129 it will go here - if (!found) - for (i = 0; i < AllSongs.size(); i++) { - m_cSong = AllSongs[i]; - if (NSMAN->m_sArtist == m_cSong->GetTranslitArtist() && - NSMAN->m_sMainTitle == m_cSong->GetTranslitMainTitle() && - NSMAN->m_sSubTitle == m_cSong->GetTranslitSubTitle()) { - break; - } - } - - bool haveSong = i != AllSongs.size(); - - switch (NSMAN->m_iSelectMode) { - case 3: - StartSelectedSong(); - break; - case 2: // We need to do cmd 1 as well here - if (haveSong) { - if (!m_MusicWheel.SelectSong(m_cSong)) { - m_MusicWheel.ChangeSort(SORT_GROUP); - m_MusicWheel.FinishTweening(); - SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, - 0.710f); - } - m_MusicWheel.Select(); - m_MusicWheel.Move(-1); - m_MusicWheel.Move(1); - StartSelectedSong(); - m_MusicWheel.Select(); - } - break; - case 1: // Scroll to song as well - if (haveSong) { - if (!m_MusicWheel.SelectSong(m_cSong)) { - // m_MusicWheel.ChangeSort( SORT_GROUP ); - // m_MusicWheel.FinishTweening(); - // SCREENMAN->PostMessageToTopScreen( SM_SetWheelSong, - // 0.710f ); - m_MusicWheel.ChangeSort(SORT_GROUP); - m_MusicWheel.SetOpenSection(""); - } - m_MusicWheel.SelectSong(m_cSong); - m_MusicWheel.Select(); - m_MusicWheel.Move(-1); - m_MusicWheel.Move(1); - m_MusicWheel.Select(); - } - // don't break here - case 0: // See if client has song - if (haveSong) - NSMAN->m_iSelectMode = 0; - else - NSMAN->m_iSelectMode = 1; - NSMAN->SelectUserSong(); - } } else if (SM == SM_SetWheelSong) // After we've done the sort on wheel, // select song. { @@ -404,6 +286,13 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) } } else if (SM == ETTP_StartChart) { if (NSMAN->song != nullptr) { + GAMESTATE->m_pCurSong.Set(NSMAN->song); + if (NSMAN->steps != nullptr) { + m_vpSteps[m_iSelection[PLAYER_1]] = NSMAN->steps; + GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); + GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( + NSMAN->steps->GetDifficulty()); + } if (!m_MusicWheel.SelectSong(NSMAN->song)) { m_MusicWheel.ChangeSort(SORT_GROUP); m_MusicWheel.FinishTweening(); @@ -423,6 +312,13 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) } } else if (SM == ETTP_SelectChart) { if (NSMAN->song != nullptr) { + GAMESTATE->m_pCurSong.Set(NSMAN->song); + if (NSMAN->steps != nullptr) { + m_vpSteps[m_iSelection[PLAYER_1]] = NSMAN->steps; + GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); + GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( + NSMAN->steps->GetDifficulty()); + } if (!m_MusicWheel.SelectSong(NSMAN->song)) { m_MusicWheel.ChangeSort(SORT_GROUP); m_MusicWheel.FinishTweening(); @@ -609,6 +505,9 @@ ScreenNetSelectMusic::SelectCurrent() return false; GAMESTATE->m_pCurSong.Set(pSong); + Steps* pSteps = m_vpSteps[m_iSelection[PLAYER_1]]; + GAMESTATE->m_pCurSteps[PLAYER_1].Set(pSteps); + GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set(pSteps->GetDifficulty()); if (NSMAN->useSMserver) { NSMAN->m_sArtist = pSong->GetTranslitArtist(); @@ -647,7 +546,7 @@ ScreenNetSelectMusic::StartSelectedSong() { StepsType st = GAMESTATE->GetCurrentStyle(pn) ->m_StepsType; // StepsType_dance_single; - Steps* pSteps = m_vpSteps[pn]; + Steps* pSteps = m_vpSteps[m_iSelection[PLAYER_1]]; GAMESTATE->m_PreferredDifficulty[pn].Set(pSteps->GetDifficulty()); GAMESTATE->m_pCurSteps[pn].Set(pSteps); } From 0a441a373555a815e810bdd8970ddcaa1c82213a Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 20:45:38 -0300 Subject: [PATCH 200/320] Fix multi leaderboards --- .../BGAnimations/ScreenGameplay overlay/leaderboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 2db3087cf5..8f178588bc 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -244,7 +244,7 @@ t.JudgmentMessageCommand = function(self, params) local old = curScore.curWifeScore curScore.curWifeScore = notShit.floor(params.WifePercent * 100) / 10000 if isMulti then - scoreboard = NSMAN:GetMPLeaderboard() + multiScores = NSMAN:GetMPLeaderboard() end if old ~= curScore.curWifeScore then table.sort(scoreboard, sortFunction) From 63d09a7288eb2f036274e64d9546d3b4e0b8359f Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 21:11:06 -0300 Subject: [PATCH 201/320] Disable multi up=>options and disable multi double enter options --- src/ScreenNetSelectMusic.cpp | 70 ------------------------------------ src/ScreenNetSelectMusic.h | 1 - src/ScreenSelectMusic.cpp | 2 +- 3 files changed, 1 insertion(+), 72 deletions(-) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index 076c54c126..b624cce407 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -407,76 +407,6 @@ ScreenNetSelectMusic::MenuRight(const InputEventPlus& input) return true; } -bool -ScreenNetSelectMusic::MenuUp(const InputEventPlus& input) -{ - NSMAN->OnOptions(); - GAMESTATE->m_EditMode = EditMode_Full; - SCREENMAN->AddNewScreenToTop(PLAYER_OPTIONS_SCREEN, - SM_BackFromPlayerOptions); - return true; -} - -/* -bool -ScreenNetSelectMusic::MenuDown(const InputEventPlus& input) -{ - // I agree, that's a stupid idea -aj - - // Funny story: If the arrow keys are mapped to Player 2, but the person - // is playing as Player 1, then hitting down to change the difficulty will - // crash in UpdateDifficulties. So pretend the input came from the player - // that is enabled. -Kyz - - PlayerNumber pn = input.pn; - if (!GAMESTATE->IsPlayerEnabled(pn)) { - if (pn == PLAYER_1) { - pn = PLAYER_2; - } else { - pn = PLAYER_1; - } - } - - if (GAMESTATE->m_pCurSong == nullptr) - return false; - StepsType st = GAMESTATE->GetCurrentStyle(pn)->m_StepsType; - vector MultiSteps; - MultiSteps = GAMESTATE->m_pCurSong->GetStepsByStepsType(st); - if (MultiSteps.size() == 0) - m_DC[pn] = NUM_Difficulty; - else { - int i; - - bool dcs[NUM_Difficulty]; - - for (i = 0; i < NUM_Difficulty; ++i) - dcs[i] = false; - - for (i = 0; i < (int)MultiSteps.size(); ++i) - dcs[MultiSteps[i]->GetDifficulty()] = true; - - for (i = 0; i < NUM_Difficulty; ++i) { - if ((dcs[i]) && (i > m_DC[pn])) { - m_DC[pn] = static_cast(i); - break; - } - } - // If failed to go up, loop - if (i == NUM_Difficulty) { - for (i = 0; i < NUM_Difficulty; i++) { - if (dcs[i]) { - m_DC[pn] = static_cast(i); - break; - } - } - } - } - UpdateDifficulties(pn); - GAMESTATE->m_PreferredDifficulty[pn].Set(m_DC[pn]); - return true; -} -*/ - bool ScreenNetSelectMusic::MenuStart(const InputEventPlus& input) { diff --git a/src/ScreenNetSelectMusic.h b/src/ScreenNetSelectMusic.h index a9d99d3388..a2e9dc59a6 100644 --- a/src/ScreenNetSelectMusic.h +++ b/src/ScreenNetSelectMusic.h @@ -36,7 +36,6 @@ class ScreenNetSelectMusic : public ScreenSelectMusic bool MenuBack(const InputEventPlus& input) override; bool MenuLeft(const InputEventPlus& input) override; bool MenuRight(const InputEventPlus& input) override; - bool MenuUp(const InputEventPlus& input) override; bool LeftAndRightPressed(PlayerNumber pn); void Update(float fDeltaTime) override; diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index a106a26c96..1b00ae5920 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -573,7 +573,7 @@ ScreenSelectMusic::Input(const InputEventPlus& input) // Check for "Press START again for options" button press if (m_SelectionState == SelectionState_Finalized && input.MenuI == GAME_BUTTON_START && input.type != IET_RELEASE && - OPTIONS_MENU_AVAILABLE.GetValue()) { + OPTIONS_MENU_AVAILABLE.GetValue() && !GAMESTATE->m_bPlayingMulti) { if (m_bGoToOptions) return false; // got it already if (!m_bAllowOptionsMenu) From f265c0151ff7ef2d867d0bfcaea8f2f463e68414 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 22:12:53 -0300 Subject: [PATCH 202/320] Force start and rdy buttons --- .../wifeTwirl.lua | 614 ++++++++++-------- Themes/Til Death/Scripts/10 Widgets.lua | 20 +- .../ScreenChatOverlay overlay.lua | 17 +- 3 files changed, 361 insertions(+), 290 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index a701ad8f0b..9052f591a9 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -48,7 +48,7 @@ local t = end end if getTabIndex() == 0 then - if heyiwasusingthat and GAMESTATE:GetCurrentSong() and noteField then -- these can prolly be wrapped better too -mina + if heyiwasusingthat and GAMESTATE:GetCurrentSong() and noteField then -- these can prolly be wrapped better too -mina mcbootlarder:visible(true) mcbootlarder:GetChild("NoteField"):visible(true) MESSAGEMAN:Broadcast("ChartPreviewOn") @@ -61,7 +61,7 @@ local t = self:queuecommand("On") update = true else - if GAMESTATE:GetCurrentSong() and noteField and mcbootlarder:IsVisible() then + if GAMESTATE:GetCurrentSong() and noteField and mcbootlarder:IsVisible() then mcbootlarder:visible(false) mcbootlarder:GetChild("NoteField"):visible(false) MESSAGEMAN:Broadcast("ChartPreviewOff") @@ -71,8 +71,8 @@ local t = update = false end end, - MilkyTartsCommand=function(self) -- when entering pack screenselectmusic explicitly turns visibilty on notefield off -mina - if noteField and mcbootlarder:IsVisible() then + MilkyTartsCommand = function(self) -- when entering pack screenselectmusic explicitly turns visibilty on notefield off -mina + if noteField and mcbootlarder:IsVisible() then mcbootlarder:visible(false) MESSAGEMAN:Broadcast("ChartPreviewOff") heyiwasusingthat = true @@ -93,7 +93,8 @@ local t = InitCommand = function(self) self:xy(frameX, frameY - 76):zoomto(8, 144):halign(0):valign(0):diffuse(getMainColor("highlight")):diffusealpha(0.5) end - },Def.Quad { + }, + Def.Quad { InitCommand = function(self) self:xy(frameX, frameY + 18):zoomto(frameWidth + 4, 50):halign(0):valign(0):diffuse(color("#333333A6")) end @@ -102,10 +103,12 @@ local t = -- Music Rate Display t[#t + 1] = - LoadFont("Common Large") .. { + LoadFont("Common Large") .. + { InitCommand = function(self) self:xy(18, SCREEN_BOTTOM - 225):visible(true):halign(0):zoom(0.4):maxwidth( - capWideScale(get43size(360), 360) / capWideScale(get43size(0.45), 0.45)) + capWideScale(get43size(360), 360) / capWideScale(get43size(0.45), 0.45) + ) end, MintyFreshCommand = function(self) self:settext(getCurRateDisplayString()) @@ -121,19 +124,20 @@ t[#t + 1] = } local function toggleNoteField() - if song and not noteField then -- first time setup + if song and not noteField then -- first time setup noteField = true MESSAGEMAN:Broadcast("ChartPreviewOn") -- for banner reaction... lazy -mina mcbootlarder:playcommand("SetupNoteField") - mcbootlarder:xy(prevX,prevY) - mcbootlarder:GetChild("NoteField"):y(prevY*1.5) + mcbootlarder:xy(prevX, prevY) + mcbootlarder:GetChild("NoteField"):y(prevY * 1.5) if usingreverse then - mcbootlarder:GetChild("NoteField"):y(prevY*1.5 + prevrevY) + mcbootlarder:GetChild("NoteField"):y(prevY * 1.5 + prevrevY) end - song:Borp() -- catches a dumb bug that isn't worth explaining -mina - return end + song:Borp() -- catches a dumb bug that isn't worth explaining -mina + return + end - if song then + if song then if mcbootlarder:IsVisible() then mcbootlarder:visible(false) mcbootlarder:GetChild("NoteField"):visible(false) @@ -143,7 +147,7 @@ local function toggleNoteField() mcbootlarder:GetChild("NoteField"):visible(true) if boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone then song:Borp() - boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone = false + boolthatgetssettotrueonsongchangebutonlyifonatabthatisntthisone = false end MESSAGEMAN:Broadcast("ChartPreviewOn") end @@ -167,189 +171,200 @@ t[#t + 1] = end } -t[#t + 1] = Def.ActorFrame { - Name = "RateDependentStuff", -- msd/display score/bpm/songlength -mina +t[#t + 1] = + Def.ActorFrame { + Name = "RateDependentStuff", -- msd/display score/bpm/songlength -mina MintyFreshCommand = function() score = GetDisplayScore() end, CurrentRateChangedMessageCommand = function(self) - self:queuecommand("MintyFresh") --steps stuff + self:queuecommand("MintyFresh") --steps stuff self:queuecommand("MortyFarts") --songs stuff end, - LoadFont("Common Large") .. { - Name = "MSD", - InitCommand = function(self) - self:xy(frameX + 58, frameY - 62):halign(0.5):zoom(0.6):maxwidth(110 / 0.6) - end, - MintyFreshCommand = function(self) - if song then - if steps:GetStepsType() == "StepsType_Dance_Single" then - local meter = steps:GetMSD(getCurRateValue(), 1) - self:settextf("%05.2f", meter) - self:diffuse(byMSD(meter)) + LoadFont("Common Large") .. + { + Name = "MSD", + InitCommand = function(self) + self:xy(frameX + 58, frameY - 62):halign(0.5):zoom(0.6):maxwidth(110 / 0.6) + end, + MintyFreshCommand = function(self) + if song then + if steps:GetStepsType() == "StepsType_Dance_Single" then + local meter = steps:GetMSD(getCurRateValue(), 1) + self:settextf("%05.2f", meter) + self:diffuse(byMSD(meter)) + else + self:settextf("%5.2f", steps:GetMeter()) -- fallthrough to pre-defined meters for non 4k charts -mina + self:diffuse(byDifficulty(steps:GetDifficulty())) + end else - self:settextf("%5.2f", steps:GetMeter()) -- fallthrough to pre-defined meters for non 4k charts -mina - self:diffuse(byDifficulty(steps:GetDifficulty())) + self:settext("") end - else - self:settext("") end - end - }, + }, -- skillset suff (these 3 can prolly be wrapped) - LoadFont("Common Normal") .. { - InitCommand = function(self) - self:xy(frameX + 120, frameY - 60):halign(0):zoom(0.6, maxwidth, 125) - end, - MintyFreshCommand = function(self) - if song then - self:settext(steps:GetRelevantSkillsetsByMSDRank(getCurRateValue(), 1)) - else - self:settext("") + LoadFont("Common Normal") .. + { + InitCommand = function(self) + self:xy(frameX + 120, frameY - 60):halign(0):zoom(0.6, maxwidth, 125) + end, + MintyFreshCommand = function(self) + if song then + self:settext(steps:GetRelevantSkillsetsByMSDRank(getCurRateValue(), 1)) + else + self:settext("") + end + end, + ChartPreviewOnMessageCommand = function(self) + self:visible(false) + end, + ChartPreviewOffMessageCommand = function(self) + self:visible(true) end - end, - ChartPreviewOnMessageCommand = function(self) - self:visible(false) - end, - ChartPreviewOffMessageCommand = function(self) - self:visible(true) - end - }, - LoadFont("Common Normal") .. { - InitCommand = function(self) - self:xy(frameX + 120, frameY - 30):halign(0):zoom(0.6, maxwidth, 125) - end, - MintyFreshCommand = function(self) - if song then - self:settext(steps:GetRelevantSkillsetsByMSDRank(getCurRateValue(), 2)) - else - self:settext("") + }, + LoadFont("Common Normal") .. + { + InitCommand = function(self) + self:xy(frameX + 120, frameY - 30):halign(0):zoom(0.6, maxwidth, 125) + end, + MintyFreshCommand = function(self) + if song then + self:settext(steps:GetRelevantSkillsetsByMSDRank(getCurRateValue(), 2)) + else + self:settext("") + end + end, + ChartPreviewOnMessageCommand = function(self) + self:visible(false) + end, + ChartPreviewOffMessageCommand = function(self) + self:visible(true) end - end, - ChartPreviewOnMessageCommand = function(self) - self:visible(false) - end, - ChartPreviewOffMessageCommand = function(self) - self:visible(true) - end - }, - LoadFont("Common Normal") .. { - InitCommand = function(self) - self:xy(frameX + 120, frameY):halign(0):zoom(0.6, maxwidth, 125) - end, - MintyFreshCommand = function(self) - if song then - self:settext(steps:GetRelevantSkillsetsByMSDRank(getCurRateValue(), 3)) - else - self:settext("") + }, + LoadFont("Common Normal") .. + { + InitCommand = function(self) + self:xy(frameX + 120, frameY):halign(0):zoom(0.6, maxwidth, 125) + end, + MintyFreshCommand = function(self) + if song then + self:settext(steps:GetRelevantSkillsetsByMSDRank(getCurRateValue(), 3)) + else + self:settext("") + end + end, + ChartPreviewOnMessageCommand = function(self) + self:visible(false) + end, + ChartPreviewOffMessageCommand = function(self) + self:visible(true) end - end, - ChartPreviewOnMessageCommand = function(self) - self:visible(false) - end, - ChartPreviewOffMessageCommand = function(self) - self:visible(true) - end - }, + }, -- **score related stuff** These need to be updated with rate changed commands -- Primary percent score - LoadFont("Common Large") .. { - InitCommand = function(self) - self:xy(frameX + 55, frameY + 50):zoom(0.6):halign(0.5):maxwidth(125):valign(1) - end, - MintyFreshCommand = function(self) - if song and score then - self:settextf("%05.2f%%", notShit.floor(score:GetWifeScore() * 10000) / 100) - self:diffuse(getGradeColor(score:GetWifeGrade())) - else - self:settext("") + LoadFont("Common Large") .. + { + InitCommand = function(self) + self:xy(frameX + 55, frameY + 50):zoom(0.6):halign(0.5):maxwidth(125):valign(1) + end, + MintyFreshCommand = function(self) + if song and score then + self:settextf("%05.2f%%", notShit.floor(score:GetWifeScore() * 10000) / 100) + self:diffuse(getGradeColor(score:GetWifeGrade())) + else + self:settext("") + end end - end, - }, + }, -- Rate for the displayed score - LoadFont("Common Normal") .. { - InitCommand = function(self) - self:xy(frameX + 55, frameY + 58):zoom(0.5):halign(0.5) - end, - MintyFreshCommand = function(self) - if song and score then - local rate = notShit.round(score:GetMusicRate(), 3) - local notCurRate = notShit.round(getCurRateValue(), 3) ~= rate + LoadFont("Common Normal") .. + { + InitCommand = function(self) + self:xy(frameX + 55, frameY + 58):zoom(0.5):halign(0.5) + end, + MintyFreshCommand = function(self) + if song and score then + local rate = notShit.round(score:GetMusicRate(), 3) + local notCurRate = notShit.round(getCurRateValue(), 3) ~= rate local rate = string.format("%.2f", rate) - if rate:sub(#rate, #rate) == "0" then - rate = rate:sub(0, #rate - 1) - end - rate = rate .. "x" + if rate:sub(#rate, #rate) == "0" then + rate = rate:sub(0, #rate - 1) + end + rate = rate .. "x" if notCurRate then - self:settext("(" .. rate .. ")") + self:settext("(" .. rate .. ")") + else + self:settext(rate) + end else - self:settext(rate) + self:settext("") end - else - self:settext("") end - end - }, + }, -- goal for current rate if there is one stuff - LoadFont("Common Normal") .. { - Name = "Goalll", - InitCommand = function(self) - self:xy(frameX + 135, frameY + 33):zoom(0.6):halign(0.5):valign(0) - end, - MintyFreshCommand = function(self) - if song and steps then - local goal = profile:GetEasiestGoalForChartAndRate(steps:GetChartKey(), getCurRateValue()) - if goal then - self:settextf("Target\n%.2f%%", goal:GetPercent() * 100) + LoadFont("Common Normal") .. + { + Name = "Goalll", + InitCommand = function(self) + self:xy(frameX + 135, frameY + 33):zoom(0.6):halign(0.5):valign(0) + end, + MintyFreshCommand = function(self) + if song and steps then + local goal = profile:GetEasiestGoalForChartAndRate(steps:GetChartKey(), getCurRateValue()) + if goal then + self:settextf("Target\n%.2f%%", goal:GetPercent() * 100) + else + self:settext("") + end else self:settext("") end - else - self:settext("") end - end - }, + }, -- Date score achieved on - LoadFont("Common Normal") .. { - InitCommand = function(self) - self:xy(frameX + 185, frameY + 59):zoom(0.4):halign(0) - end, - MintyFreshCommand = function(self) - if song and score then - self:settext(score:GetDate()) - else - self:settext("") + LoadFont("Common Normal") .. + { + InitCommand = function(self) + self:xy(frameX + 185, frameY + 59):zoom(0.4):halign(0) + end, + MintyFreshCommand = function(self) + if song and score then + self:settext(score:GetDate()) + else + self:settext("") + end end - end - }, + }, -- MaxCombo - LoadFont("Common Normal") .. { - InitCommand = function(self) - self:xy(frameX + 185, frameY + 49):zoom(0.4):halign(0) - end, - MintyFreshCommand = function(self) - if song and score then - self:settextf("Max Combo: %d", score:GetMaxCombo()) - else - self:settext("") + LoadFont("Common Normal") .. + { + InitCommand = function(self) + self:xy(frameX + 185, frameY + 49):zoom(0.4):halign(0) + end, + MintyFreshCommand = function(self) + if song and score then + self:settextf("Max Combo: %d", score:GetMaxCombo()) + else + self:settext("") + end end - end - }, - LoadFont("Common Normal") .. { - Name = "ClearType", - InitCommand = function(self) - self:xy(frameX + 185, frameY + 35):zoom(0.6):halign(0) - end, - MintyFreshCommand = function(self) - if song and score then - self:visible(true) - self:settext(getClearTypeFromScore(PLAYER_1, score, 0)) - self:diffuse(getClearTypeFromScore(PLAYER_1, score, 2)) - else - self:visible(false) + }, + LoadFont("Common Normal") .. + { + Name = "ClearType", + InitCommand = function(self) + self:xy(frameX + 185, frameY + 35):zoom(0.6):halign(0) + end, + MintyFreshCommand = function(self) + if song and score then + self:visible(true) + self:settext(getClearTypeFromScore(PLAYER_1, score, 0)) + self:diffuse(getClearTypeFromScore(PLAYER_1, score, 2)) + else + self:visible(false) + end end - end - }, + }, -- **song stuff that scales with rate** Def.BPMDisplay { File = THEME:GetPathF("BPMDisplay", "bpm"), @@ -366,30 +381,32 @@ t[#t + 1] = Def.ActorFrame { end end }, - LoadFont("Common Large") .. { - Name = "PlayableDuration", - InitCommand = function(self) - self:xy((capWideScale(get43size(384), 384)) + 62, SCREEN_BOTTOM - 85):visible(true):halign(1):zoom( - capWideScale(get43size(0.6), 0.6) - ):maxwidth(capWideScale(get43size(360), 360) / capWideScale(get43size(0.45), 0.45)) - end, - MortyFartsCommand = function(self) - if song then - local playabletime = GetPlayableTime() - self:settext(SecondsToMMSS(playabletime)) - self:diffuse(byMusicLength(playabletime)) - else - self:settext("") + LoadFont("Common Large") .. + { + Name = "PlayableDuration", + InitCommand = function(self) + self:xy((capWideScale(get43size(384), 384)) + 62, SCREEN_BOTTOM - 85):visible(true):halign(1):zoom( + capWideScale(get43size(0.6), 0.6) + ):maxwidth(capWideScale(get43size(360), 360) / capWideScale(get43size(0.45), 0.45)) + end, + MortyFartsCommand = function(self) + if song then + local playabletime = GetPlayableTime() + self:settext(SecondsToMMSS(playabletime)) + self:diffuse(byMusicLength(playabletime)) + else + self:settext("") + end end - end - } + } } -- "Radar values", noteinfo that isn't rate dependent -mina local function radarPairs(i) local o = Def.ActorFrame { - LoadFont("Common Normal") .. { + LoadFont("Common Normal") .. + { InitCommand = function(self) self:xy(frameX + 13, frameY - 52 + 13 * i):zoom(0.5):halign(0):maxwidth(120) end, @@ -401,7 +418,8 @@ local function radarPairs(i) end end }, - LoadFont("Common Normal") .. { + LoadFont("Common Normal") .. + { InitCommand = function(self) self:xy(frameX + 105, frameY + -52 + 13 * i):zoom(0.5):halign(1):maxwidth(60) end, @@ -417,7 +435,8 @@ local function radarPairs(i) return o end -local r = Def.ActorFrame{ +local r = + Def.ActorFrame { Name = "RadarValues" } @@ -428,7 +447,8 @@ end -- putting neg bpm warning here i guess r[#r + 1] = - LoadFont("Common Normal") .. { + LoadFont("Common Normal") .. + { InitCommand = function(self) self:xy(frameX, frameY - 120):halign(0):zoom(0.6) end, @@ -445,7 +465,8 @@ t[#t + 1] = r -- song only stuff that doesnt change with rate t[#t + 1] = - LoadFont("Common Normal") .. { + LoadFont("Common Normal") .. + { InitCommand = function(self) self:xy(capWideScale(get43size(384), 384) + 41, SCREEN_BOTTOM - 100):halign(1):zoom(0.50) end, @@ -466,82 +487,117 @@ t[#t + 1] = end, MortyFartsCommand = function(self) self:finishtweening() - if song then - if song:HasCDTitle() then - self:visible(true) - self:Load(song:GetCDTitlePath()) - else - self:visible(false) - end + if song then + if song:HasCDTitle() then + self:visible(true) + self:Load(song:GetCDTitlePath()) else self:visible(false) end - local height = self:GetHeight() - local width = self:GetWidth() + else + self:visible(false) + end + local height = self:GetHeight() + local width = self:GetWidth() - if height >= 60 and width >= 75 then - if height * (75 / 60) >= width then - self:zoom(60 / height) - else - self:zoom(75 / width) - end - elseif height >= 60 then + if height >= 60 and width >= 75 then + if height * (75 / 60) >= width then self:zoom(60 / height) - elseif width >= 75 then - self:zoom(75 / width) else - self:zoom(1) + self:zoom(75 / width) end + elseif height >= 60 then + self:zoom(60 / height) + elseif width >= 75 then + self:zoom(75 / width) + else + self:zoom(1) + end end, - ChartPreviewOnMessageCommand=function(self) - self:addx(capWideScale(34,0)) + ChartPreviewOnMessageCommand = function(self) + self:addx(capWideScale(34, 0)) end, - ChartPreviewOffMessageCommand=function(self) - self:addx(capWideScale(-34,0)) + ChartPreviewOffMessageCommand = function(self) + self:addx(capWideScale(-34, 0)) end } -t[#t + 1] = +t[#t + 1] = Def.Sprite { - Name = "Banner", - InitCommand = function(self) - self:x(10):y(61):halign(0):valign(0) - self:scaletoclipped(capWideScale(get43size(384), 384), capWideScale(get43size(120), 120)):diffusealpha(1) - end, - MintyFreshCommand=function(self) - if INPUTFILTER:IsBeingPressed("tab") then - self:finishtweening():smooth(0.25):diffusealpha(0):sleep(0.2):queuecommand("ModifyBanner") - else - self:finishtweening():queuecommand("ModifyBanner") + Name = "Banner", + InitCommand = function(self) + self:x(10):y(61):halign(0):valign(0) + self:scaletoclipped(capWideScale(get43size(384), 384), capWideScale(get43size(120), 120)):diffusealpha(1) + end, + MintyFreshCommand = function(self) + if INPUTFILTER:IsBeingPressed("tab") then + self:finishtweening():smooth(0.25):diffusealpha(0):sleep(0.2):queuecommand("ModifyBanner") + else + self:finishtweening():queuecommand("ModifyBanner") + end + end, + ModifyBannerCommand = function(self) + self:finishtweening() + if song then + local bnpath = GAMESTATE:GetCurrentSong():GetBannerPath() + if not bnpath then + bnpath = THEME:GetPathG("Common", "fallback banner") end - end, - ModifyBannerCommand = function(self) - self:finishtweening() - if song then - local bnpath = GAMESTATE:GetCurrentSong():GetBannerPath() - if not bnpath then - bnpath = THEME:GetPathG("Common", "fallback banner") - end - self:LoadBackground(bnpath) - else - local bnpath = SONGMAN:GetSongGroupBannerPath(SCREENMAN:GetTopScreen():GetMusicWheel():GetSelectedSection()) - if not bnpath or bnpath == "" then - bnpath = THEME:GetPathG("Common", "fallback banner") - end - self:LoadBackground(bnpath) + self:LoadBackground(bnpath) + else + local bnpath = SONGMAN:GetSongGroupBannerPath(SCREENMAN:GetTopScreen():GetMusicWheel():GetSelectedSection()) + if not bnpath or bnpath == "" then + bnpath = THEME:GetPathG("Common", "fallback banner") end - self:scaletoclipped(capWideScale(get43size(384), 384), capWideScale(get43size(120), 120)):diffusealpha(1) - end, - ChartPreviewOnMessageCommand = function(self) - self:visible(false) - end, - ChartPreviewOffMessageCommand = function(self) - self:visible(true) + self:LoadBackground(bnpath) end + self:scaletoclipped(capWideScale(get43size(384), 384), capWideScale(get43size(120), 120)):diffusealpha(1) + end, + ChartPreviewOnMessageCommand = function(self) + self:visible(false) + end, + ChartPreviewOffMessageCommand = function(self) + self:visible(true) + end } +local enabledC = "#099948" +local disabledC = "#ff6666" +local force = false +local ready = false +function toggleButton(textEnabled, textDisabled, msg, x) + local enabled = false + return Widg.Button { + text = textDisabled, + width = 50, + height = 25, + border = false, + bgColor = color(disabledC), + highlight = {color = getMainColor("highlight")}, + x = 10 - 100 + capWideScale(get43size(384), 384) + x, + y = 61 + capWideScale(get43size(120), 120), + onClick = function(self) + enabled = not enabled + local a = self.bg.actor + self:diffuse(color(enabled and enabledC or disabledC)) + self:settext(enabled and textEnabled or textDisabled) + NSMAN:SendChatMsg(msg, 1, NSMAN:GetCurrentRoomName()) + end + } +end +local forceStart = toggleButton("Unforce Start", "Force Start", "/force", 0) +local ready = toggleButton("Unready", "Ready", "/ready", 50) +t[#t + 1] = forceStart +t[#t + 1] = ready t[#t + 1] = Def.Quad { + -- Little hack to only show forceStart and ready in netselect + BeginCommand = function() + if SCREENMAN:GetTopScreen():GetName() ~= "ScreenNetSelectMusic" then + ready:Disable() + forceStart:Disable() + end + end, InitCommand = function(self) self:xy(frameX + 135, frameY + 45):zoomto(50, 40):diffusealpha(0) end, @@ -602,10 +658,10 @@ t[#t + 1] = -- end -- } - -- tags? t[#t + 1] = - LoadFont("Common Normal") .. { + LoadFont("Common Normal") .. + { InitCommand = function(self) self:xy(frameX + 300, frameY - 60):halign(0):zoom(0.6):maxwidth(450) end, @@ -619,7 +675,8 @@ t[#t + 1] = } t[#t + 1] = - LoadFont("Common Normal") .. { + LoadFont("Common Normal") .. + { InitCommand = function(self) self:xy(frameX + 300, frameY - 30):halign(0):zoom(0.6):maxwidth(450) end, @@ -633,7 +690,8 @@ t[#t + 1] = } t[#t + 1] = - LoadFont("Common Normal") .. { + LoadFont("Common Normal") .. + { InitCommand = function(self) self:xy(frameX + 300, frameY):halign(0):zoom(0.6):maxwidth(450) end, @@ -651,38 +709,40 @@ local yesiwantnotefield = false local oldstyle local function ihatestickinginputcallbackseverywhere(event) if event.type ~= "InputEventType_Release" and getTabIndex() == 0 then - if event.DeviceInput.button == "DeviceButton_space" then - toggleNoteField() - end - end + if event.DeviceInput.button == "DeviceButton_space" then + toggleNoteField() + end + end return false end -t[#t + 1] = LoadFont("Common Normal") .. { - Name = "PreviewViewer", - BeginCommand = function(self) - mcbootlarder = self:GetParent():GetChild("ChartPreview") - SCREENMAN:GetTopScreen():AddInputCallback(MPinput) - SCREENMAN:GetTopScreen():AddInputCallback(ihatestickinginputcallbackseverywhere) - self:xy(20, 235) - self:zoom(0.5) - self:halign(0) - self:settext("Toggle Preview") - end, - MouseLeftClickMessageCommand = function(self) - if isOver(self) and (song or noteField) then - toggleNoteField() - end - end, - CurrentStyleChangedMessageCommand=function(self) -- need to regenerate the notefield when changing styles or crashman appears -mina - if noteField and oldstyle ~= GAMESTATE:GetCurrentStyle() then - SCREENMAN:GetTopScreen():DeletePreviewNoteField(mcbootlarder) - noteField = false - toggleNoteField() +t[#t + 1] = + LoadFont("Common Normal") .. + { + Name = "PreviewViewer", + BeginCommand = function(self) + mcbootlarder = self:GetParent():GetChild("ChartPreview") + SCREENMAN:GetTopScreen():AddInputCallback(MPinput) + SCREENMAN:GetTopScreen():AddInputCallback(ihatestickinginputcallbackseverywhere) + self:xy(20, 235) + self:zoom(0.5) + self:halign(0) + self:settext("Toggle Preview") + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) and (song or noteField) then + toggleNoteField() + end + end, + CurrentStyleChangedMessageCommand = function(self) -- need to regenerate the notefield when changing styles or crashman appears -mina + if noteField and oldstyle ~= GAMESTATE:GetCurrentStyle() then + SCREENMAN:GetTopScreen():DeletePreviewNoteField(mcbootlarder) + noteField = false + toggleNoteField() + end + oldstyle = GAMESTATE:GetCurrentStyle() end - oldstyle = GAMESTATE:GetCurrentStyle() - end -} + } - t[#t + 1] = LoadActor("../_chartpreview.lua") -return t \ No newline at end of file +t[#t + 1] = LoadActor("../_chartpreview.lua") +return t diff --git a/Themes/Til Death/Scripts/10 Widgets.lua b/Themes/Til Death/Scripts/10 Widgets.lua index 09281a431b..121c44ab2c 100644 --- a/Themes/Til Death/Scripts/10 Widgets.lua +++ b/Themes/Til Death/Scripts/10 Widgets.lua @@ -96,6 +96,9 @@ Widg.Label = function(params) initText = text end end + label.GetText = function(label, text) + return label.actor and label.actor:GetText() or initText + end return label end @@ -335,7 +338,9 @@ Widg.Button = function(params) button = Widg.Container { onInit = function(self) - params.onInit(self) + if params.onInit then + params.onInit(self) + end if params.highlight then self:SetUpdateFunction(highlight) end @@ -440,15 +445,22 @@ Widg.Button = function(params) } button.settext = function(button, text) - button.label:settext(text) + return (button.label):settext(text) + end + button.GetText = function(button) + return (button.label):GetText() + end + button.diffuse = function(button, color) + params.bgColor = color + return (button.bg.actor):diffuse(color) end button.Enable = function(button) button.enabled = true - (button.actor):visible(button.enabled) + return (button.actor):visible(button.enabled) end button.Disable = function(button) button.enabled = false - (button.actor):visible(button.enabled) + return (button.actor):visible(button.enabled) end button:add(button.bg) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index dd3404669e..c07d667b7e 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -91,8 +91,8 @@ chat.ScreenChangedMessageCommand = function(self) show = true end if currentScreen == "ScreenNetSelectMusic" then - for i=1, #tabs do - if tabs[i][2] == NSMAN:GetCurrentRoomName() then + for i = 1, #tabs do + if tabs[i] and tabs[i][2] == NSMAN:GetCurrentRoomName() then changeTab(tabs[i][2], tabs[i][1]) end end @@ -353,7 +353,6 @@ function overTab(mx, my) return nil, nil end - function MPinput(event) if (not show or not online) or isGameplay then return false @@ -365,7 +364,7 @@ function MPinput(event) end typing = false local mx, my = INPUTFILTER:GetMouseX(), INPUTFILTER:GetMouseY() - if isOver(minbar) then --hard mouse toggle -mina + if isOver(minbar) then --hard mouse toggle -mina minimised = not minimised MESSAGEMAN:Broadcast("Minimise") update = true @@ -408,7 +407,7 @@ function MPinput(event) end -- hard kb toggle - if event.type == "InputEventType_Release" and event.DeviceInput.button == "DeviceButton_insert" then + if event.type == "InputEventType_Release" and event.DeviceInput.button == "DeviceButton_insert" then minimised = not minimised MESSAGEMAN:Broadcast("Minimise") update = true @@ -418,7 +417,7 @@ function MPinput(event) end end - if not typing and event.type == "InputEventType_Release" then -- keys for auto turning on chat if not already on -mina + if not typing and event.type == "InputEventType_Release" then -- keys for auto turning on chat if not already on -mina if event.DeviceInput.button == "DeviceButton_/" then typing = true update = true @@ -437,7 +436,7 @@ function MPinput(event) NSMAN:SendChatMsg(typingText, currentTabType, currentTabName) typingText = "" elseif typingText == "" then - typing = false -- pressing enter when text is empty to deactive chat is expected behavior -mina + typing = false -- pressing enter when text is empty to deactive chat is expected behavior -mina end update = true end @@ -448,7 +447,7 @@ function MPinput(event) elseif event.DeviceInput.button == "DeviceButton_space" then typingText = typingText .. " " update = true - elseif event.DeviceInput.button == "DeviceButton_delete" then -- reset msg with delete (since there's no cursor) + elseif event.DeviceInput.button == "DeviceButton_delete" then -- reset msg with delete (since there's no cursor) typingText = "" update = true elseif @@ -501,7 +500,7 @@ function MPinput(event) end if update then - if minimised then -- minimise will be set in the above blocks, disable input and clear text -mina + if minimised then -- minimise will be set in the above blocks, disable input and clear text -mina typing = false typingText = "" end From e4156eaf6e7936f1fe6dcc3a6e460e3bc821258a Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 30 Nov 2018 22:36:56 -0300 Subject: [PATCH 203/320] Add options button --- .../ScreenSelectMusic overlay/default.lua | 15 +++++++++++++++ Themes/_fallback/metrics.ini | 4 +++- src/ScreenNetSelectMusic.cpp | 10 +++++++++- src/ScreenNetSelectMusic.h | 3 ++- src/ScreenSelectMusic.cpp | 13 +++++++++++++ src/ScreenSelectMusic.h | 2 ++ 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua index c016bf51fe..3a36da003a 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua @@ -44,4 +44,19 @@ GAMESTATE:UpdateDiscordMenu( ": " .. string.format("%5.2f", GetPlayerOrMachineProfile(PLAYER_1):GetPlayerRating()) ) +t[#t + 1] = + Widg.Button { + text = "Options", + width = 50, + height = 25, + border = false, + bgColor = BoostColor(getMainColor("frames"), 7.5), + highlight = {color = BoostColor(getMainColor("frames"), 10)}, + x = SCREEN_WIDTH / 2, + y = 5, + onClick = function(self) + SCREENMAN:GetTopScreen():OpenOptions() + end +} + return t diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 642aaf5397..eb0037c210 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -1,4 +1,4 @@ -# This probably is hard to understand from the way it was made in the first + get it to work and put it anywher# This probably is hard to understand from the way it was made in the first # place, so instead just pay attention to each group, which has tons of notes. # 01 # Global @@ -2068,6 +2068,8 @@ Fallback="ScreenWithMenuElements" NextScreen=Branch.PlayerOptions() PrevScreen=Branch.TitleMenu() # +PlayerOptionsScreen="ScreenPlayerOptions" +# MusicWheelType="MusicWheel" Codes="" # diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index b624cce407..3af3017e68 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -56,7 +56,6 @@ ScreenNetSelectMusic::Init() GAMESTATE->m_bPlayingMulti = true; SAMPLE_MUSIC_PREVIEW_MODE.Load(m_sName, "SampleMusicPreviewMode"); MUSIC_WHEEL_TYPE.Load(m_sName, "MusicWheelType"); - PLAYER_OPTIONS_SCREEN.Load(m_sName, "PlayerOptionsScreen"); // todo: handle me theme-side -aj FOREACH_EnabledPlayer(p) @@ -407,6 +406,15 @@ ScreenNetSelectMusic::MenuRight(const InputEventPlus& input) return true; } +void +ScreenNetSelectMusic::OpenOptions() +{ + NSMAN->OnOptions(); + GAMESTATE->m_EditMode = EditMode_Full; + SCREENMAN->AddNewScreenToTop(PLAYER_OPTIONS_SCREEN, + SM_BackFromPlayerOptions); +} + bool ScreenNetSelectMusic::MenuStart(const InputEventPlus& input) { diff --git a/src/ScreenNetSelectMusic.h b/src/ScreenNetSelectMusic.h index a2e9dc59a6..b3b77327d4 100644 --- a/src/ScreenNetSelectMusic.h +++ b/src/ScreenNetSelectMusic.h @@ -27,6 +27,8 @@ class ScreenNetSelectMusic : public ScreenSelectMusic void StartSelectedSong(); bool SelectCurrent(); + void OpenOptions() override; + MusicWheel* GetMusicWheel(); // Lua void PushSelf(lua_State* L) override; @@ -51,7 +53,6 @@ class ScreenNetSelectMusic : public ScreenSelectMusic RString m_sRandomMusicPath; ThemeMetric MUSIC_WHEEL_TYPE; - ThemeMetric PLAYER_OPTIONS_SCREEN; ThemeMetric SAMPLE_MUSIC_FALLBACK_FADE_IN_SECONDS; ThemeMetric SAMPLE_MUSIC_FADE_OUT_SECONDS; diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 1b00ae5920..de794fffe4 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -107,6 +107,7 @@ ScreenSelectMusic::Init() ROULETTE_TIMER_SECONDS.Load(m_sName, "RouletteTimerSeconds"); ALIGN_MUSIC_BEATS.Load(m_sName, "AlignMusicBeat"); CODES.Load(m_sName, "Codes"); + PLAYER_OPTIONS_SCREEN.Load(m_sName, "PlayerOptionsScreen"); MUSIC_WHEEL_TYPE.Load(m_sName, "MusicWheelType"); SELECT_MENU_AVAILABLE.Load(m_sName, "SelectMenuAvailable"); MODE_MENU_AVAILABLE.Load(m_sName, "ModeMenuAvailable"); @@ -376,6 +377,12 @@ ScreenSelectMusic::Update(float fDeltaTime) CheckBackgroundRequests(false); } +void +ScreenSelectMusic::OpenOptions() +{ + SCREENMAN->AddNewScreenToTop(PLAYER_OPTIONS_SCREEN, + SM_BackFromPlayerOptions); +} void ScreenSelectMusic::DifferentialReload() { @@ -1981,8 +1988,14 @@ class LunaScreenSelectMusic : public Luna p->ChangeSteps(PLAYER_1, IArg(1)); return 0; } + static int OpenOptions(T* p, lua_State* L) + { + p->OpenOptions(); + return 0; + } LunaScreenSelectMusic() { + ADD_METHOD(OpenOptions); ADD_METHOD(GetGoToOptions); ADD_METHOD(GetMusicWheel); ADD_METHOD(OpenOptionsList); diff --git a/src/ScreenSelectMusic.h b/src/ScreenSelectMusic.h index 9979c362aa..5d81d32715 100644 --- a/src/ScreenSelectMusic.h +++ b/src/ScreenSelectMusic.h @@ -50,6 +50,7 @@ class ScreenSelectMusic : public ScreenWithMenuElements // ScreenWithMenuElements override: never play music here; we do it ourself. void StartPlayingMusic() override {} + virtual void OpenOptions(); bool GetGoToOptions() const { return m_bGoToOptions; } MusicWheel* GetMusicWheel() { return &m_MusicWheel; } @@ -100,6 +101,7 @@ class ScreenSelectMusic : public ScreenWithMenuElements RageTimer m_timerIdleComment; ThemeMetric IDLE_COMMENT_SECONDS; + ThemeMetric PLAYER_OPTIONS_SCREEN; ThemeMetric SAMPLE_MUSIC_DELAY_INIT; ThemeMetric SAMPLE_MUSIC_DELAY; ThemeMetric SAMPLE_MUSIC_LOOPS; From d1c636c8cc0ab245237fe3a2ab5159856c34f0ac Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 20:37:38 -0600 Subject: [PATCH 204/320] Prevent crash related to missing data in old replay offset calculating --- src/PlayerAI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlayerAI.cpp b/src/PlayerAI.cpp index e2b757790f..3596330d7a 100644 --- a/src/PlayerAI.cpp +++ b/src/PlayerAI.cpp @@ -434,7 +434,7 @@ PlayerAI::GetTapNoteOffsetForReplay(TapNote* pTN, int noteRow, int col) // this gets caught by Player after it finds that the offset wasnt // -2.f (We check for an impossible offset of -2.f in Player to blow // up a mine) - if (pTN->type == TapNoteType_Mine) + if (pTN->type == TapNoteType_Mine || m_ReplayTapMap.count(noteRow) == 0) return -1.f; float offset = m_ReplayTapMap[noteRow].back().offset; From 537ed28b9fa066f20125f52877fdb723eda3fc33 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 20:38:49 -0600 Subject: [PATCH 205/320] Add HasReplayData convenience for OnlineHighScore this implementation is shaky i think --- src/DownloadManager.cpp | 1 + src/DownloadManager.h | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 4dcef6683f..0a6b3bca30 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1588,6 +1588,7 @@ DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) hs.scoreid = tmp.scoreid; hs.avatar = tmp.avatar; hs.countryCode = tmp.countryCode; + hs.hasReplay = tmp.hasReplay; vec.emplace_back(tmp); } diff --git a/src/DownloadManager.h b/src/DownloadManager.h index aa625da732..7c20d59504 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -123,6 +123,9 @@ class OnlineTopScore }; struct OnlineHighScore : HighScore { + public: + bool hasReplay; + bool HasReplayData() override { return hasReplay; } }; class OnlineScore { From 0251c75534b9158d093c1a56a8bf11c81d0fad2e Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 20:40:18 -0600 Subject: [PATCH 206/320] dont fart (utilize new HasReplayData utility for OnlineHighScore; remove unneeded stuff) --- Themes/Til Death/BGAnimations/superscoreboard.lua | 2 +- src/DownloadManager.cpp | 11 ----------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index ba9ee48a92..2d9375c0aa 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -475,7 +475,7 @@ local function makeScoreDisplay(i) end, DisplayCommand = function(self) if GAMESTATE:GetCurrentSteps(PLAYER_1) then - if DLMAN:Fart(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), ind + i) then + if hs:HasReplayData() then self:settext("Watch") else self:settext("") diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 0a6b3bca30..30fdfc1d04 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -2445,16 +2445,6 @@ class LunaDownloadManager : public Luna DLMAN->UploadScoreWithReplayDataFromDisk(SArg(1)); return 0; } - static int Fart(T* p, lua_State* L) - { - RString ck = SArg(1); - size_t idx = IArg(2) - 1; - if (idx < DLMAN->chartLeaderboards[ck].size()) - lua_pushboolean(L, DLMAN->chartLeaderboards[ck][idx].hasReplay); - else - lua_pushboolean(L, false); - return 1; - } LunaDownloadManager() { ADD_METHOD(GetCountryCodes); @@ -2488,7 +2478,6 @@ class LunaDownloadManager : public Luna ADD_METHOD(ToggleTopScoresOnlyFilter); ADD_METHOD(GetTopScoresOnlyFilter); ADD_METHOD(SendReplayDataForOldScore); - ADD_METHOD(Fart); ADD_METHOD(Logout); } }; From 436962e274b3b142c605c8cb41b5f3c44fecf3d7 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 21:03:31 -0600 Subject: [PATCH 207/320] Stop PlayerOptions from requesting the leaderboard because we can't grab the wheel --- .../ScreenSelectMusic decorations/score.lua | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 5879b65586..430c7c5965 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -65,17 +65,19 @@ local moped -- You know, if we can see the place where the scores should be. local function updateLeaderBoardForCurrentChart() local top = SCREENMAN:GetTopScreen() - if top:GetMusicWheel():IsSettled() and ((getTabIndex() == 2 and nestedTab == 2) or collapsed) then - local steps = GAMESTATE:GetCurrentSteps(PLAYER_1) - if steps then - DLMAN:RequestChartLeaderBoardFromOnline( - steps:GetChartKey(), - function(leaderboard) - moped:playcommand("SetFromLeaderboard", leaderboard) - end - ) - else - moped:playcommand("SetFromLeaderboard", {}) + if top:GetName() == "ScreenSelectMusic" or top:GetName() == "ScreenNetSelectMusic" then + if top:GetMusicWheel():IsSettled() and ((getTabIndex() == 2 and nestedTab == 2) or collapsed) then + local steps = GAMESTATE:GetCurrentSteps(PLAYER_1) + if steps then + DLMAN:RequestChartLeaderBoardFromOnline( + steps:GetChartKey(), + function(leaderboard) + moped:playcommand("SetFromLeaderboard", leaderboard) + end + ) + else + moped:playcommand("SetFromLeaderboard", {}) + end end end end From 563c0a540a33057d815fda6f78f5cfb5c2be4a9a Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 21:41:43 -0600 Subject: [PATCH 208/320] Relocate and Reimplement Player Options Button --- .../wifeTwirl.lua | 34 +++++++++++++++++++ .../ScreenSelectMusic overlay/default.lua | 15 -------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 9052f591a9..ef8a1973a4 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -743,6 +743,40 @@ t[#t + 1] = oldstyle = GAMESTATE:GetCurrentStyle() end } + +t[#t + 1] = + LoadFont("Common Normal") .. + { + Name = "PlayerOptionsButton", + BeginCommand = function(self) + SCREENMAN:GetTopScreen():AddInputCallback(MPinput) + self:xy(20, 218) + self:zoom(0.5) + self:halign(0) + self:settext("Player Options") + end, + MouseLeftClickMessageCommand = function(self) + if isOver(self) then + SCREENMAN:GetTopScreen():OpenOptions() + end + end + } + +--[[ -- This is the Widget Button alternative of the above implementation. +t[#t + 1] = + Widg.Button { + text = "Options", + width = 50, + height = 25, + border = false, + bgColor = BoostColor(getMainColor("frames"), 7.5), + highlight = {color = BoostColor(getMainColor("frames"), 10)}, + x = SCREEN_WIDTH / 2, + y = 5, + onClick = function(self) + SCREENMAN:GetTopScreen():OpenOptions() + end +}]] t[#t + 1] = LoadActor("../_chartpreview.lua") return t diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua index 3a36da003a..c016bf51fe 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic overlay/default.lua @@ -44,19 +44,4 @@ GAMESTATE:UpdateDiscordMenu( ": " .. string.format("%5.2f", GetPlayerOrMachineProfile(PLAYER_1):GetPlayerRating()) ) -t[#t + 1] = - Widg.Button { - text = "Options", - width = 50, - height = 25, - border = false, - bgColor = BoostColor(getMainColor("frames"), 7.5), - highlight = {color = BoostColor(getMainColor("frames"), 10)}, - x = SCREEN_WIDTH / 2, - y = 5, - onClick = function(self) - SCREENMAN:GetTopScreen():OpenOptions() - end -} - return t From 906e0140b9289516cec9a46f6e036d03e1dc4b1f Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 21:49:22 -0600 Subject: [PATCH 209/320] Hide ready and force start buttons when chart preview is on --- .../ScreenSelectMusic decorations/wifeTwirl.lua | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index ef8a1973a4..75db26bc9b 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -741,6 +741,14 @@ t[#t + 1] = toggleNoteField() end oldstyle = GAMESTATE:GetCurrentStyle() + end, + ChartPreviewOnMessageCommand = function(self) + ready:Disable() + forceStart:Disable() + end, + ChartPreviewOffMessageCommand = function(self) + ready:Enable() + forceStart:Enable() end } From dddf317d2de9e3f106010d25031fe012c2009f34 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 21:58:17 -0600 Subject: [PATCH 210/320] Don't reenable ready/forcestart if not in multiplayer --- .../ScreenSelectMusic decorations/wifeTwirl.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index 75db26bc9b..d1df2c7820 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -747,8 +747,10 @@ t[#t + 1] = forceStart:Disable() end, ChartPreviewOffMessageCommand = function(self) - ready:Enable() - forceStart:Enable() + if SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then + ready:Enable() + forceStart:Enable() + end end } From 8ef13679cecaad92854db75aabfd1382e4755f86 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Fri, 30 Nov 2018 23:41:37 -0600 Subject: [PATCH 211/320] Reposition negbpm text because of overlapping text --- .../BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua index d1df2c7820..771a1f3861 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/wifeTwirl.lua @@ -450,7 +450,9 @@ r[#r + 1] = LoadFont("Common Normal") .. { InitCommand = function(self) - self:xy(frameX, frameY - 120):halign(0):zoom(0.6) + self:xy(20, 200) + self:zoom(0.7) + self:halign(0) end, MintyFreshCommand = function(self) if song and steps:GetTimingData():HasWarps() then From 85679645a6cb6fd63888a13fa9a5e3dfe6d49ea5 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 1 Dec 2018 01:40:14 -0600 Subject: [PATCH 212/320] Fix the values for multiplayer gameplay leaderboard --- src/NetworkSyncManager.cpp | 4 +++- src/ScreenGameplay.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index d58a486ecb..9648ea011d 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -1688,6 +1688,7 @@ void NetworkSyncManager::PushMPLeaderboard(lua_State* L) { lua_newtable(L); + int i = 1; for (auto& pair : mpleaderboard) { lua_newtable(L); lua_pushnumber(L, pair.second.wife); @@ -1696,7 +1697,8 @@ NetworkSyncManager::PushMPLeaderboard(lua_State* L) lua_setfield(L, -2, "jdgstr"); lua_pushstring(L, pair.first.c_str()); lua_setfield(L, -2, "user"); - lua_setfield(L, -2, pair.first.c_str()); + lua_rawseti(L, -2, i); + i++; } return; } diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index cd453b85b6..61fdcb9b61 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1376,7 +1376,7 @@ ScreenGameplay::BeginScreen() ->GetPlayerStageStats() ->m_iCurCombo); NSMAN->SendMPLeaderboardUpdate( - this->GetPlayerInfo(PLAYER_1)->m_pPlayer->curwifescore, doot); + this->GetPlayerInfo(PLAYER_1)->m_pPlayer->curwifescore / this->GetPlayerInfo(PLAYER_1)->m_pPlayer->maxwifescore, doot); }, 1, From 498fe4474d95df89fe73e3197edbc62f93c33fd4 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 1 Dec 2018 01:41:58 -0600 Subject: [PATCH 213/320] Don't use realtime updates on multi gameplay leaderboard --- .../ScreenGameplay overlay/leaderboard.lua | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 8f178588bc..bae7fc6509 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -113,10 +113,12 @@ for i = 1, NUM_ENTRIES - 1 do scoreboard[i] = onlineScores[i] end local done = false -for i = 1, NUM_ENTRIES do - if not done and not scoreboard[i] then - scoreboard[i] = curScore - done = true +if not isMulti then + for i = 1, NUM_ENTRIES do + if not done and not scoreboard[i] then + scoreboard[i] = curScore + done = true + end end end table.sort(scoreboard, sortFunction) @@ -276,7 +278,9 @@ t.OnCommand = function(self, params) self:zoomtoheight(MovableValues.LeaderboardHeight) for i, entry in ipairs(entryActors) do for name, label in pairs(entry) do - label:visible(not (not scoreboard[i]:GetDisplayName())) + if scoreboard[i] ~= nil then + label:visible(not (not scoreboard[i]:GetDisplayName())) + end end end end From bc4af4c4c90dd2c9dfd224c7c04c6ede67ad889b Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 04:47:49 -0300 Subject: [PATCH 214/320] Maybe fix multi start crash --- src/ScreenNetSelectMusic.cpp | 225 ++++++----------------------------- src/ScreenNetSelectMusic.h | 17 +-- 2 files changed, 36 insertions(+), 206 deletions(-) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index 3af3017e68..dc2837812f 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -54,35 +54,14 @@ ScreenNetSelectMusic::Init() { ScreenSelectMusic::Init(); GAMESTATE->m_bPlayingMulti = true; - SAMPLE_MUSIC_PREVIEW_MODE.Load(m_sName, "SampleMusicPreviewMode"); - MUSIC_WHEEL_TYPE.Load(m_sName, "MusicWheelType"); - - // todo: handle me theme-side -aj - FOREACH_EnabledPlayer(p) - { - m_ModIconRow[p].SetName(ssprintf("ModIconsP%d", p + 1)); - m_ModIconRow[p].Load("ModIconRowSelectMusic", p); - m_ModIconRow[p].SetFromGameState(); - LOAD_ALL_COMMANDS_AND_SET_XY(m_ModIconRow[p]); - this->AddChild(&m_ModIconRow[p]); - } - // Load SFX and music m_soundChangeOpt.Load(THEME->GetPathS(m_sName, "change opt")); m_soundChangeSel.Load(THEME->GetPathS(m_sName, "change sel")); - m_sSectionMusicPath = THEME->GetPathS(m_sName, "section music"); - m_sRouletteMusicPath = THEME->GetPathS(m_sName, "roulette music"); - m_sRandomMusicPath = THEME->GetPathS(m_sName, "random music"); NSMAN->OnMusicSelect(); m_bInitialSelect = false; m_bAllowInput = NSMAN->IsETTP(); - - SAMPLE_MUSIC_FALLBACK_FADE_IN_SECONDS.Load( - m_sName, "SampleMusicFallbackFadeInSeconds"); - SAMPLE_MUSIC_FADE_OUT_SECONDS.Load(m_sName, "SampleMusicFadeOutSeconds"); - ALIGN_MUSIC_BEATS.Load(m_sName, "AlignMusicBeat"); } void @@ -113,133 +92,38 @@ ScreenNetSelectMusic::Input(const InputEventPlus& input) if (input.type != IET_FIRST_PRESS && input.type != IET_REPEAT) return false; - bool bHoldingCtrl = - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL)) || - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL)) || - (!NSMAN->useSMserver); // If we are disconnected, assume no chatting - - bool holding_shift = - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT)) || - INPUTFILTER->IsBeingPressed(DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT)); - - wchar_t c = INPUTMAN->DeviceInputToChar(input.DeviceI, false); - MakeUpper(&c, 1); - - bool handled = false; - - /* I'm commenting this here and adding the 2 ctrl+key and the ctrl+shift+key - inputs - // Ctrl+[A-Z] to go to that letter of the alphabet - if( bHoldingCtrl && ( c >= 'A' ) && ( c <= 'Z' ) ) - { - SortOrder so = GAMESTATE->m_SortOrder; - if( ( so != SORT_TITLE ) && ( so != SORT_ARTIST ) ) - { - so = SORT_TITLE; - - GAMESTATE->m_PreferredSortOrder = so; - GAMESTATE->m_SortOrder.Set( so ); - // Odd, changing the sort order requires us to call SetOpenSection - more than once m_MusicWheel.ChangeSort( so ); m_MusicWheel.SetOpenSection( - ssprintf("%c", c ) ); - } - m_MusicWheel.SelectSection( ssprintf("%c", c ) ); - m_MusicWheel.ChangeSort( so ); - m_MusicWheel.SetOpenSection( ssprintf("%c", c ) ); - m_MusicWheel.Move(+1); - handled = true; - } - */ - if (holding_shift && bHoldingCtrl && input.type == IET_FIRST_PRESS && - m_MusicWheel.IsSettled()) { - if (c == 'R') { - // Reload the currently selected song. -Kyz - Song* to_reload = m_MusicWheel.GetSelectedSong(); - if (to_reload != nullptr) { - to_reload->ReloadFromSongDir(); - this->AfterMusicChange(); - handled = true; - } - } else if (c == 'F') { - // Favorite the currently selected song. -Not Kyz - Song* fav_me_biatch = m_MusicWheel.GetSelectedSong(); - if (fav_me_biatch) { - Profile* pProfile = PROFILEMAN->GetProfile(PLAYER_1); - - if (!fav_me_biatch->IsFavorited()) { - fav_me_biatch->SetFavorited(true); - pProfile->AddToFavorites( - GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); - } else { - fav_me_biatch->SetFavorited(false); - pProfile->RemoveFromFavorites( - GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); - } - Message msg("FavoritesUpdated"); - MESSAGEMAN->Broadcast(msg); - m_MusicWheel.ChangeMusic(0); - return true; - } - } else if (c == 'M') { - // PermaMirror the currently selected song. -Not Kyz - Song* alwaysmirrorsmh = m_MusicWheel.GetSelectedSong(); - if (alwaysmirrorsmh) { - Profile* pProfile = PROFILEMAN->GetProfile(PLAYER_1); - - if (!alwaysmirrorsmh->IsPermaMirror()) { - alwaysmirrorsmh->SetPermaMirror(true); - pProfile->AddToPermaMirror( - GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); - } else { - alwaysmirrorsmh->SetPermaMirror(false); - pProfile->RemoveFromPermaMirror( - GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); - } - Message msg("FavoritesUpdated"); - MESSAGEMAN->Broadcast(msg); - m_MusicWheel.ChangeMusic(0); - return true; - } - } else if (c == 'G') { - Profile* pProfile = PROFILEMAN->GetProfile(PLAYER_1); - pProfile->AddGoal(GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); - Song* asonglol = m_MusicWheel.GetSelectedSong(); - asonglol->SetHasGoal(true); - MESSAGEMAN->Broadcast("FavoritesUpdated"); - m_MusicWheel.ChangeMusic(0); - return true; - } else if (c == 'Q') { - DifferentialReload(); - return true; - } else if (c == 'S') { - PROFILEMAN->SaveProfile(PLAYER_1); - SCREENMAN->SystemMessage("Profile Saved"); - return true; - } else if (input.DeviceI.device == DEVICE_KEYBOARD && - input.DeviceI.button == KEY_BACK) { - // Keyboard shortcut to delete a song from disk (ctrl + backspace) - Song* songToDelete = m_MusicWheel.GetSelectedSong(); - if (songToDelete && PREFSMAN->m_bAllowSongDeletion.Get()) { - m_pSongAwaitingDeletionConfirmation = songToDelete; - ScreenPrompt::Prompt( - SM_ConfirmDeleteSong, - ssprintf(PERMANENTLY_DELETE.GetValue(), - songToDelete->m_sMainTitle.c_str(), - songToDelete->GetSongDir().c_str()), - PROMPT_YES_NO); - return true; - } - } - } - return ScreenSelectMusic::Input(input) || handled; + return ScreenSelectMusic::Input(input); } void ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) { - if (SM == SM_GoToNextScreen) + if (SM == SM_GoToNextScreen) { SOUND->StopMusic(); - else if (SM == SM_UsersUpdate) { + if (NSMAN->song != nullptr) { + GAMESTATE->m_pCurSong.Set(NSMAN->song); + if (NSMAN->steps != nullptr) { + GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); + GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( + NSMAN->steps->GetDifficulty()); + } + if (!m_MusicWheel.SelectSong(NSMAN->song)) { + m_MusicWheel.ChangeSort(SORT_GROUP); + m_MusicWheel.FinishTweening(); + SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, 0.710f); + m_MusicWheel.SelectSong(NSMAN->song); + } + if (NSMAN->rate > 0) { + GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = + NSMAN->rate / 1000.f; + MESSAGEMAN->Broadcast("RateChanged"); + } + m_MusicWheel.Select(); + m_MusicWheel.Move(-1); + m_MusicWheel.Move(1); + m_MusicWheel.Move(0); + } + } else if (SM == SM_UsersUpdate) { MESSAGEMAN->Broadcast("UsersUpdate"); } else if (SM == SM_FriendsUpdate) { MESSAGEMAN->Broadcast("FriendsUpdate"); @@ -261,10 +145,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) m_MusicWheel.Move(0); } else if (SM == SM_NoSongs) { SCREENMAN->SetNewScreen(THEME->GetMetric(m_sName, "NoSongsScreen")); - } else if (SM == SM_SetWheelSong) // After we've done the sort on wheel, - // select song. - { - m_MusicWheel.SelectSong(m_cSong); } else if (SM == SM_RefreshWheelLocation) { m_MusicWheel.Select(); m_MusicWheel.Move(-1); @@ -275,9 +155,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) GAMESTATE->m_EditMode = EditMode_Invalid; // XXX HACK: This will cause ScreenSelectOptions to go back here. NSMAN->OffOptions(); - - // Update changes - FOREACH_EnabledPlayer(p) m_ModIconRow[p].SetFromGameState(); } else if (SM == SM_SongChanged) { if (m_MusicWheel.GetNumItems() > 0) { GAMESTATE->m_pCurSong.Set(m_MusicWheel.GetSelectedSong()); @@ -287,7 +164,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) if (NSMAN->song != nullptr) { GAMESTATE->m_pCurSong.Set(NSMAN->song); if (NSMAN->steps != nullptr) { - m_vpSteps[m_iSelection[PLAYER_1]] = NSMAN->steps; GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( NSMAN->steps->GetDifficulty()); @@ -313,7 +189,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) if (NSMAN->song != nullptr) { GAMESTATE->m_pCurSong.Set(NSMAN->song); if (NSMAN->steps != nullptr) { - m_vpSteps[m_iSelection[PLAYER_1]] = NSMAN->steps; GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( NSMAN->steps->GetDifficulty()); @@ -382,6 +257,12 @@ ScreenNetSelectMusic::LeftAndRightPressed(const PlayerNumber pn) INPUTMAPPER->IsBeingPressed(GAME_BUTTON_RIGHT, pn); } +ScreenNetSelectMusic::~ScreenNetSelectMusic() +{ + if (PREFSMAN->m_verbose_log > 1) + LOG->Trace("ScreenNetSelectMusic::~ScreenNetSelectMusic()"); +} + bool ScreenNetSelectMusic::MenuLeft(const InputEventPlus& input) { @@ -441,7 +322,8 @@ ScreenNetSelectMusic::SelectCurrent() if (pSong == NULL) return false; - + if (m_vpSteps.size() <= m_iSelection[PLAYER_1]) + return false; GAMESTATE->m_pCurSong.Set(pSong); Steps* pSteps = m_vpSteps[m_iSelection[PLAYER_1]]; GAMESTATE->m_pCurSteps[PLAYER_1].Set(pSteps); @@ -478,19 +360,8 @@ ScreenNetSelectMusic::TweenOffScreen() void ScreenNetSelectMusic::StartSelectedSong() { - Song* pSong = m_MusicWheel.GetSelectedSong(); - GAMESTATE->m_pCurSong.Set(pSong); - FOREACH_EnabledPlayer(pn) - { - StepsType st = GAMESTATE->GetCurrentStyle(pn) - ->m_StepsType; // StepsType_dance_single; - Steps* pSteps = m_vpSteps[m_iSelection[PLAYER_1]]; - GAMESTATE->m_PreferredDifficulty[pn].Set(pSteps->GetDifficulty()); - GAMESTATE->m_pCurSteps[pn].Set(pSteps); - } - GAMESTATE->m_PreferredSortOrder = GAMESTATE->m_SortOrder; - GAMESTATE->m_pPreferredSong = pSong; + GAMESTATE->m_pPreferredSong = GAMESTATE->m_pCurSong; // force event mode GAMESTATE->m_bTemporaryEventMode = true; @@ -499,32 +370,6 @@ ScreenNetSelectMusic::StartSelectedSong() StartTransitioningScreen(SM_GoToNextScreen); } -/* -void -ScreenNetSelectMusic::UpdateDifficulties(PlayerNumber pn) -{ - if (GAMESTATE->m_pCurSong == NULL) { - m_StepsDisplays[pn].SetFromStepsTypeAndMeterAndDifficultyAndCourseType( - StepsType_Invalid, 0, Difficulty_Beginner); - // m_DifficultyIcon[pn].SetFromSteps( pn, NULL ); // It will blank it - // out - return; - } - - StepsType st = GAMESTATE->GetCurrentStyle(pn)->m_StepsType; - - Steps* pSteps = - SongUtil::GetStepsByDifficulty(GAMESTATE->m_pCurSong, st, m_DC[pn]); - GAMESTATE->m_pCurSteps[pn].Set(pSteps); - - if ((m_DC[pn] < NUM_Difficulty) && (m_DC[pn] >= Difficulty_Beginner)) - m_StepsDisplays[pn].SetFromSteps(pSteps); - else - m_StepsDisplays[pn].SetFromStepsTypeAndMeterAndDifficultyAndCourseType( - StepsType_Invalid, 0, Difficulty_Beginner); -} -*/ - void ScreenNetSelectMusic::BeginScreen() { diff --git a/src/ScreenNetSelectMusic.h b/src/ScreenNetSelectMusic.h index b3b77327d4..adfd785347 100644 --- a/src/ScreenNetSelectMusic.h +++ b/src/ScreenNetSelectMusic.h @@ -16,6 +16,7 @@ class ScreenNetSelectMusic : public ScreenSelectMusic { public: + ~ScreenNetSelectMusic() override; void Init() override; void BeginScreen() override; @@ -47,26 +48,10 @@ class ScreenNetSelectMusic : public ScreenSelectMusic void TweenOffScreen() override; - ThemeMetric SAMPLE_MUSIC_PREVIEW_MODE; - RString m_sSectionMusicPath; - RString m_sRouletteMusicPath; - RString m_sRandomMusicPath; - - ThemeMetric MUSIC_WHEEL_TYPE; - - ThemeMetric SAMPLE_MUSIC_FALLBACK_FADE_IN_SECONDS; - ThemeMetric SAMPLE_MUSIC_FADE_OUT_SECONDS; - ThemeMetric ALIGN_MUSIC_BEATS; - private: RageSound m_soundChangeOpt; RageSound m_soundChangeSel; - // todo: do this theme-side instead. -aj - ModIconRow m_ModIconRow[NUM_PLAYERS]; - - Song* m_cSong; - bool m_bInitialSelect; bool m_bAllowInput; }; From 5a7e35213afe4976f7222e1e0505dcafeddfde79 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 04:58:30 -0300 Subject: [PATCH 215/320] Stop using left+right to sort select (up-down-up-down) --- src/ScreenNetSelectMusic.cpp | 17 ++--------------- src/ScreenNetSelectMusic.h | 1 - 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index dc2837812f..eb7b6ca646 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -250,13 +250,6 @@ ScreenNetSelectMusic::OnConfirmSongDeletion() m_pSongAwaitingDeletionConfirmation = NULL; } -bool -ScreenNetSelectMusic::LeftAndRightPressed(const PlayerNumber pn) -{ - return INPUTMAPPER->IsBeingPressed(GAME_BUTTON_LEFT, pn) && - INPUTMAPPER->IsBeingPressed(GAME_BUTTON_RIGHT, pn); -} - ScreenNetSelectMusic::~ScreenNetSelectMusic() { if (PREFSMAN->m_verbose_log > 1) @@ -268,10 +261,7 @@ ScreenNetSelectMusic::MenuLeft(const InputEventPlus& input) { PlayerNumber pn = input.pn; - if (LeftAndRightPressed(pn)) - m_MusicWheel.ChangeSort(SORT_MODE_MENU); - else - m_MusicWheel.Move(-1); + m_MusicWheel.Move(-1); return true; } @@ -280,10 +270,7 @@ ScreenNetSelectMusic::MenuRight(const InputEventPlus& input) { PlayerNumber pn = input.pn; - if (LeftAndRightPressed(pn)) - m_MusicWheel.ChangeSort(SORT_MODE_MENU); - else - m_MusicWheel.Move(+1); + m_MusicWheel.Move(+1); return true; } diff --git a/src/ScreenNetSelectMusic.h b/src/ScreenNetSelectMusic.h index adfd785347..32c9a0435f 100644 --- a/src/ScreenNetSelectMusic.h +++ b/src/ScreenNetSelectMusic.h @@ -39,7 +39,6 @@ class ScreenNetSelectMusic : public ScreenSelectMusic bool MenuBack(const InputEventPlus& input) override; bool MenuLeft(const InputEventPlus& input) override; bool MenuRight(const InputEventPlus& input) override; - bool LeftAndRightPressed(PlayerNumber pn); void Update(float fDeltaTime) override; From a9694d39f970c78affbf8c2a51a7ce96cf294832 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 01:57:06 -0500 Subject: [PATCH 216/320] minanyms --- Themes/Til Death/BGAnimations/ScreenInit background/default.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenInit background/default.lua b/Themes/Til Death/BGAnimations/ScreenInit background/default.lua index 649100b1c2..ffa5e84570 100644 --- a/Themes/Til Death/BGAnimations/ScreenInit background/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenInit background/default.lua @@ -98,6 +98,8 @@ local minanyms = { "MinaTallerThanBrandon", "confers monetary value to words", "notcool", + "mina restepped as a pad file", + "sapient typo conglomerate", } math.random() From e0ef8ea752413b5f9dd6d8c773f950b4764a5f7b Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 02:35:32 -0500 Subject: [PATCH 217/320] the fallback nextscreen on this is better; i didnt need to add this --- Themes/Til Death/metrics.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/Themes/Til Death/metrics.ini b/Themes/Til Death/metrics.ini index 153c5c6196..93e368d01e 100644 --- a/Themes/Til Death/metrics.ini +++ b/Themes/Til Death/metrics.ini @@ -832,8 +832,6 @@ LineHelpMenu="lua,HelpMenu()" LineNPSWindow="lua,NPSWindow()" LineMeasureLines="lua,MeasureLines()" -[ScreenNetworkOptions] -NextScreen=Branch.MultiScreen() [ScreenThemeColorChange] Fallback="ScreenTextEntry" From 471e805884e476b363ac59bb84686e23df608d20 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 1 Dec 2018 02:09:55 -0600 Subject: [PATCH 218/320] raise the limit to the number of diffs you can have (because i have files with 18 diffs on them and it crashed hahaha) --- src/DifficultyList.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/DifficultyList.cpp b/src/DifficultyList.cpp index b1186e127d..c8210e6487 100644 --- a/src/DifficultyList.cpp +++ b/src/DifficultyList.cpp @@ -13,7 +13,10 @@ /** @brief Specifies the max number of charts available for a song. * * This includes autogenned charts. */ -#define MAX_METERS 12 // kinda restrictive but im also as lazy as sm5 devs -mina +// reasonable limit to chart amount. if someone consistently crashes when +// scrolling on a chart that has 25 diffs, THIS IS WHY +// (this is a hardcoded value to optimize stepstype hover or something) -poco +#define MAX_METERS 24 REGISTER_ACTOR_CLASS(StepsDisplayList); From a9a46500100726b34153824fe3b9fa98b0038d46 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 03:28:16 -0500 Subject: [PATCH 219/320] add mpinput to neteval --- .../Til Death/BGAnimations/ScreenNetEvaluation decorations.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua index c7776889ca..c29293f2f6 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua @@ -18,6 +18,7 @@ t[#t + 1] = self:xy(SCREEN_CENTER_X, capWideScale(135, 150)):zoom(0.4):maxwidth(400 / 0.4) end, BeginCommand = function(self) + SCREENMAN:GetTopScreen():AddInputCallback(MPinput) self:queuecommand("Set") end, SetCommand = function(self) From 01ee35b2050ef4d85def90b1d2fd91725f0e3b5d Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 05:33:14 -0300 Subject: [PATCH 220/320] Fix lua error when offline --- .../BGAnimations/ScreenGameplay overlay/leaderboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index bae7fc6509..39ba41525f 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -1,6 +1,6 @@ local allowedCustomization = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).CustomizeGameplay local leaderboardEnabled = - (NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation") or + (NSMAN:IsETTP() and SCREENMAN:GetTopScreen() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation") or (playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn()) local entryActors = {} local t = From 1fd297384743bac25ba9b1f5c2ee1aa9f9999989 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 05:48:23 -0300 Subject: [PATCH 221/320] Expose multi eval scores to lua --- src/NetworkSyncManager.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 9648ea011d..05b99ea010 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -768,6 +768,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) n->m_EvalPlayerData.emplace_back(result); n->m_ActivePlayers = n->m_EvalPlayerData.size(); SCREENMAN->SendMessageToTopScreen(ETTP_NewScore); + MESSAGEMAN->Broadcast("NewMultiScore"); break; } case ettps_ping: @@ -1804,8 +1805,26 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) p->Login(user, pass); return 1; } + static int GetEvalScores(T* p, lua_State* L) + { + int i = 1; + lua_newtable(L); + for (auto& evalData : NSMAN->m_EvalPlayerData) { + lua_newtable(L); + lua_pushstring(L, evalData.nameStr.c_str()); + lua_setfield(L, -2, "user"); + evalData.hs.PushSelf(L); + lua_setfield(L, -2, "highscore"); + lua_pushstring(L, evalData.playerOptions.c_str()); + lua_setfield(L, -2, "options"); + lua_rawseti(L, -2, i); + i++; + } + return 1; + } LunaNetworkSyncManager() { + ADD_METHOD(GetEvalScores); ADD_METHOD(GetMPLeaderboard); ADD_METHOD(GetChartRequests); ADD_METHOD(GetChatMsg); From b23caafec69994a14fa36b576206698b0e326d2b Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 06:18:20 -0300 Subject: [PATCH 222/320] Add lobby userlist to ettp --- src/NetworkSyncManager.cpp | 34 ++++++++++++++++++++++++++++++++++ src/NetworkSyncManager.h | 4 ++++ 2 files changed, 38 insertions(+) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 05b99ea010..707d4c38cc 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -52,6 +52,8 @@ std::map ettClientMessageMap = { std::map ettServerMessageMap = { { "hello", ettps_hello }, { "roomlist", ettps_roomlist }, + { "lobbyuserlist", ettps_lobbyuserlist }, + { "lobbyuserlistupdate", ettps_lobbyuserlistupdate }, { "ping", ettps_ping }, { "chat", ettps_recievechat }, { "login", ettps_loginresponse }, @@ -926,6 +928,26 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) e.what()); } break; + case ettps_lobbyuserlist: { + NSMAN->lobbyuserlist.clear(); + auto users = payload->at("users"); + for (auto& user : users) { + NSMAN->lobbyuserlist.emplace_back(user.get()); + } + } break; + case ettps_lobbyuserlistupdate: { + auto newUsers = payload->at("on"); + for (auto& user : newUsers) { + auto& vec = NSMAN->lobbyuserlist; + vec.erase(std::remove( + vec.begin(), vec.end(), user.get()), + vec.end()); + } + auto removedUsers = payload->at("off"); + for (auto& user : removedUsers) { + NSMAN->lobbyuserlist.emplace_back(user.get()); + } + } break; case ettps_roomlist: { RoomData tmp; n->m_Rooms.clear(); @@ -1856,9 +1878,21 @@ class LunaChartRequest : public Luna lua_pushnumber(L, p->rate / 1000); return 1; } + static int GetLobbyUserList(T* p, lua_State* L) + { + lua_newtable(L); + int i = 1; + for (auto& user : NSMAN->lobbyuserlist) { + lua_pushstring(L, user.c_str()); + lua_rawseti(L, -2, i); + i++; + } + return 1; + } LunaChartRequest() { ADD_METHOD(GetChartkey); + ADD_METHOD(GetLobbyUserList); ADD_METHOD(GetUser); ADD_METHOD(GetRate); } diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index a75411e86e..155c71e308 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -86,6 +86,8 @@ enum ETTServerMessageTypes ettps_recievechat, ettps_loginresponse, ettps_roomlist, + ettps_lobbyuserlist, + ettps_lobbyuserlistupdate, ettps_recievescore, ettps_mpleaderboardupdate, ettps_createroomresponse, @@ -376,6 +378,8 @@ class NetworkSyncManager // since function was last called. RString m_Scoreboard[NUM_NSScoreBoardColumn]; + vector lobbyuserlist; + void SendMPLeaderboardUpdate(float wife, RString& jdgstr); // Used for chatting From bab95df269d699a7a7c127f76bc0123414988316 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 04:16:49 -0500 Subject: [PATCH 223/320] use refs in replay upload timestamp converter --- src/TimingData.cpp | 2 +- src/TimingData.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index bf1425a551..fe3a587c77 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1440,7 +1440,7 @@ TimingData::WhereUAtBroNoOffset(float beat) const } vector -TimingData::ConvertReplayNoteRowsToTimestamps(vector nrv, float rate) +TimingData::ConvertReplayNoteRowsToTimestamps(vector& nrv, float rate) { vector o; for (auto nr : nrv) diff --git a/src/TimingData.h b/src/TimingData.h index f1b90b5fd5..d820227844 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -675,7 +675,7 @@ class TimingData float WhereUAtBroNoOffset(float beat); float WhereUAtBro(int row); - vector ConvertReplayNoteRowsToTimestamps(vector nrv, + vector ConvertReplayNoteRowsToTimestamps(vector& nrv, float rate); bool ValidSequentialAssumption = true; From d1c403d2c82ea30530f0b2b71a94b7ca5c5f9215 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 04:35:24 -0500 Subject: [PATCH 224/320] already have this in the local --- src/DownloadManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 30fdfc1d04..69081dd383 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1068,7 +1068,7 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, return; vector timestamps = steps->GetTimingData()->ConvertReplayNoteRowsToTimestamps( - hs->GetNoteRowVector(), hs->GetMusicRate()); + rows, hs->GetMusicRate()); for (size_t i = 0; i < offsets.size(); i++) { replayString += "["; replayString += to_string(timestamps[i]) + ","; From aeb0ae6b8b632d4d394af13add1b15a36b091320 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 04:36:06 -0500 Subject: [PATCH 225/320] start adding updatereplaydata function --- src/DownloadManager.cpp | 140 +++++++++++++++++++++++++++++++++++++++- src/DownloadManager.h | 2 + 2 files changed, 139 insertions(+), 3 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 69081dd383..b4f5ac6528 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1142,6 +1142,106 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, HTTPRequests.push_back(req); return; } +void // for online replay viewing accuracy -mina +DownloadManager::UpdateOnlineScoreReplayData(string& sk, + function callback) +{ + if (!LoggedIn()) + return; + + auto hs = SCOREMAN->GetScoresByKey().at(sk); + CURL* curlHandle = initCURLHandle(true); + string url = serverURL.Get() + "/updatereplaydata"; + curl_httppost* form = nullptr; + curl_httppost* lastPtr = nullptr; + SetCURLFormPostField( + curlHandle, form, lastPtr, "scorekey", hs->GetScoreKey()); + string replayString; + vector offsets = hs->GetOffsetVector(); + vector columns = hs->GetTrackVector(); + vector types = hs->GetTapNoteTypeVector(); + auto& rows = hs->GetNoteRowVector(); + + if (!offsets.empty()) { + replayString = "["; + auto steps = SONGMAN->GetStepsByChartkey(hs->GetChartKey()); + if (steps == nullptr) + return; + vector timestamps = + steps->GetTimingData()->ConvertReplayNoteRowsToTimestamps( + rows, hs->GetMusicRate()); + for (size_t i = 0; i < offsets.size(); i++) { + replayString += "["; + replayString += to_string(timestamps[i]) + ","; + replayString += to_string(1000.f * offsets[i]) + ","; + if (hs->GetReplayType() == 2) { + replayString += to_string(columns[i]) + ","; + replayString += to_string(types[i]) + ","; + } + replayString += to_string(rows[i]); + replayString += "],"; + } + replayString = + replayString.substr(0, replayString.size() - 1); // remove "," + replayString += "]"; + hs->UnloadReplayData(); + } else + replayString = ""; + SetCURLFormPostField( + curlHandle, form, lastPtr, "replay_data", replayString); + SetCURLPostToURL(curlHandle, url); + curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); + auto done = [this, hs, callback](HTTPRequest& req, CURLMsg*) { + long response_code; + curl_easy_getinfo(req.handle, CURLINFO_RESPONSE_CODE, &response_code); + json j; + try { + j = json::parse(req.result); + bool delay = false; + try { + auto errors = j["errors"]; + for (auto error : errors) { + int status = error["status"]; + if (status == 22) { + delay = true; + DLMAN->StartSession( + DLMAN->sessionUser, + DLMAN->sessionPass, + [hs](bool logged) { + if (logged) { + DLMAN->UploadScoreWithReplayDataFromDisk( + hs->GetScoreKey()); + } + }); + } else if (status == 404 || status == 405 || + status == 406) { + hs->AddUploadedServer(serverURL.Get()); + } + } + } catch (exception e) { + } + if (!delay && j["data"]["type"] == "ssrResults") { + auto diffs = j["data"]["attributes"]["diff"]; + FOREACH_ENUM(Skillset, ss) + if (ss != Skill_Overall) + (DLMAN->sessionRatings)[ss] += + diffs.value(SkillsetToString(ss), 0.0); + (DLMAN->sessionRatings)[Skill_Overall] += + diffs.value("Rating", 0.0); + hs->AddUploadedServer(serverURL.Get()); + HTTPRunning = response_code; + } + } catch (exception e) { + } + if (callback) + callback(); + }; + HTTPRequest* req = new HTTPRequest(curlHandle, done); + SetCURLResultsString(curlHandle, &(req->result)); + curl_multi_add_handle(mHTTPHandle, req->handle); + HTTPRequests.push_back(req); + return; +} void DownloadManager::EndSessionIfExists() { @@ -1887,6 +1987,41 @@ DownloadManager::StartSession(string user, HTTPRequests.push_back(req); } +void +UpdateReplayDataSequentially(deque toUpload) +{ + auto it = toUpload.begin(); + if (it != toUpload.end()) { + toUpload.pop_front(); + auto& hs = (*it); + DLMAN->UpdateOnlineScoreReplayData( + hs->GetScoreKey(), [hs, toUpload]() { + hs->AddUploadedServer(serverURL.Get()); + UpdateReplayDataSequentially(toUpload); + }); + } + return; +} +bool +DownloadManager::UpdateOnlineScoreReplayData() +{ + if (!LoggedIn()) + return false; + auto scores = SCOREMAN->GetAllPBPtrs(); + deque toUpload; + for (auto& vec : scores) { + for (auto& scorePtr : vec) { + auto ts = scorePtr->GetTopScore(); + if ((ts == 1 || ts == 2) && + !scorePtr->IsUploadedToServer(serverURL.Get())) { + if (scorePtr->HasReplayData()) + toUpload.emplace_back(scorePtr); + } + } + } + UpdateReplayDataSequentially(toUpload); + return true; +} void uploadSequentially(deque toUpload) { @@ -1903,7 +2038,7 @@ uploadSequentially(deque toUpload) return; } bool -DownloadManager::UploadScores() +DownloadManager::UploadScores() // keeping in case we want to use this later -mina { if (!LoggedIn()) return false; @@ -1914,7 +2049,7 @@ DownloadManager::UploadScores() auto ts = scorePtr->GetTopScore(); if ((ts == 1 || ts == 2) && !scorePtr->IsUploadedToServer(serverURL.Get())) { - if (scorePtr->HasReplayData()) + if (scorePtr->HasReplayData()) // we should remove this check maybe -mina toUpload.emplace_back(scorePtr); } } @@ -1922,7 +2057,6 @@ DownloadManager::UploadScores() uploadSequentially(toUpload); return true; } - int DownloadManager::GetSkillsetRank(Skillset ss) { diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 7c20d59504..802eee4955 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -226,6 +226,7 @@ class DownloadManager done); // Sends login request if not already logging in void OnLogin(); bool UploadScores(); // Uploads all scores not yet uploaded to current + bool UpdateOnlineScoreReplayData(); // attempts updates existing replaydata // server (Async, 1 request per score) void RefreshPackList(string url); @@ -249,6 +250,7 @@ class DownloadManager void UploadScoreWithReplayDataFromDisk( string sk, function callback = function()); + void UpdateOnlineScoreReplayData(string& sk, function callback); void UploadScore(HighScore* hs); bool ShouldUploadScores(); From 3829803b2857990a6fdf04bac68c4a92018011c9 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 07:02:35 -0300 Subject: [PATCH 226/320] Improve UpdateOnlineReplayData a bit --- src/DownloadManager.cpp | 122 +++++++++++++++------------------------- 1 file changed, 46 insertions(+), 76 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index b4f5ac6528..f7cb49056b 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1076,7 +1076,6 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, if (hs->GetReplayType() == 2) { replayString += to_string(columns[i]) + ","; replayString += to_string(types[i]) + ","; - } replayString += to_string(rows[i]); replayString += "],"; @@ -1144,51 +1143,26 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, } void // for online replay viewing accuracy -mina DownloadManager::UpdateOnlineScoreReplayData(string& sk, - function callback) + function callback) { if (!LoggedIn()) return; auto hs = SCOREMAN->GetScoresByKey().at(sk); CURL* curlHandle = initCURLHandle(true); - string url = serverURL.Get() + "/updatereplaydata"; + string url = serverURL.Get() + "/updatereplaydata/" + sk; curl_httppost* form = nullptr; curl_httppost* lastPtr = nullptr; SetCURLFormPostField( curlHandle, form, lastPtr, "scorekey", hs->GetScoreKey()); - string replayString; - vector offsets = hs->GetOffsetVector(); - vector columns = hs->GetTrackVector(); - vector types = hs->GetTapNoteTypeVector(); + string toSend = "["; auto& rows = hs->GetNoteRowVector(); - - if (!offsets.empty()) { - replayString = "["; - auto steps = SONGMAN->GetStepsByChartkey(hs->GetChartKey()); - if (steps == nullptr) - return; - vector timestamps = - steps->GetTimingData()->ConvertReplayNoteRowsToTimestamps( - rows, hs->GetMusicRate()); - for (size_t i = 0; i < offsets.size(); i++) { - replayString += "["; - replayString += to_string(timestamps[i]) + ","; - replayString += to_string(1000.f * offsets[i]) + ","; - if (hs->GetReplayType() == 2) { - replayString += to_string(columns[i]) + ","; - replayString += to_string(types[i]) + ","; - } - replayString += to_string(rows[i]); - replayString += "],"; - } - replayString = - replayString.substr(0, replayString.size() - 1); // remove "," - replayString += "]"; - hs->UnloadReplayData(); - } else - replayString = ""; - SetCURLFormPostField( - curlHandle, form, lastPtr, "replay_data", replayString); + for (auto& row : rows) { + toSend += to_string(row) + ","; + } + toSend = toSend.substr(0, toSend.size() - 1); // remove , + toSend += "]"; + SetCURLFormPostField(curlHandle, form, lastPtr, "replay", toSend); SetCURLPostToURL(curlHandle, url); curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); auto done = [this, hs, callback](HTTPRequest& req, CURLMsg*) { @@ -1198,45 +1172,41 @@ DownloadManager::UpdateOnlineScoreReplayData(string& sk, try { j = json::parse(req.result); bool delay = false; - try { - auto errors = j["errors"]; - for (auto error : errors) { - int status = error["status"]; - if (status == 22) { - delay = true; - DLMAN->StartSession( - DLMAN->sessionUser, - DLMAN->sessionPass, - [hs](bool logged) { - if (logged) { - DLMAN->UploadScoreWithReplayDataFromDisk( - hs->GetScoreKey()); - } - }); - } else if (status == 404 || status == 405 || - status == 406) { - hs->AddUploadedServer(serverURL.Get()); + if (j.find("errors") == j.end()) + hs->AddUploadedServer(serverURL.Get()); + else + try { + auto errors = j["errors"]; + for (auto error : errors) { + int status = error["status"]; + if (status == 22) { + delay = true; + DLMAN->StartSession( + DLMAN->sessionUser, + DLMAN->sessionPass, + [hs](bool logged) { + if (logged) { + DLMAN->UploadScoreWithReplayDataFromDisk( + hs->GetScoreKey()); + } + }); + } else if (status == 404 || status == 405 || + status == 406) { + hs->AddUploadedServer(serverURL.Get()); + } } + } catch (exception e) { } - } catch (exception e) { - } - if (!delay && j["data"]["type"] == "ssrResults") { - auto diffs = j["data"]["attributes"]["diff"]; - FOREACH_ENUM(Skillset, ss) - if (ss != Skill_Overall) - (DLMAN->sessionRatings)[ss] += - diffs.value(SkillsetToString(ss), 0.0); - (DLMAN->sessionRatings)[Skill_Overall] += - diffs.value("Rating", 0.0); - hs->AddUploadedServer(serverURL.Get()); - HTTPRunning = response_code; - } } catch (exception e) { } if (callback) callback(); }; - HTTPRequest* req = new HTTPRequest(curlHandle, done); + auto fail = [callback](HTTPRequest& req, CURLMsg*) { + if (callback) + callback(); + }; + HTTPRequest* req = new HTTPRequest(curlHandle, done, fail); SetCURLResultsString(curlHandle, &(req->result)); curl_multi_add_handle(mHTTPHandle, req->handle); HTTPRequests.push_back(req); @@ -1528,10 +1498,10 @@ DownloadManager::RequestReplayData(string scoreid, timestamps.emplace_back(note[0].get()); offsets.emplace_back(note[1].get() / 1000.f); - if (note.size() == 3) { // pre-0.6 with noterows + if (note.size() == 3) { // pre-0.6 with noterows rows.emplace_back(note[2].get()); } - if (note.size() > 3) { // 0.6 without noterows + if (note.size() > 3) { // 0.6 without noterows tracks.emplace_back(note[2].get()); types.emplace_back( static_cast(note[3].get())); @@ -1994,11 +1964,9 @@ UpdateReplayDataSequentially(deque toUpload) if (it != toUpload.end()) { toUpload.pop_front(); auto& hs = (*it); - DLMAN->UpdateOnlineScoreReplayData( - hs->GetScoreKey(), [hs, toUpload]() { - hs->AddUploadedServer(serverURL.Get()); - UpdateReplayDataSequentially(toUpload); - }); + DLMAN->UpdateOnlineScoreReplayData(hs->GetScoreKey(), [hs, toUpload]() { + UpdateReplayDataSequentially(toUpload); + }); } return; } @@ -2038,7 +2006,8 @@ uploadSequentially(deque toUpload) return; } bool -DownloadManager::UploadScores() // keeping in case we want to use this later -mina +DownloadManager::UploadScores() // keeping in case we want to use this later + // -mina { if (!LoggedIn()) return false; @@ -2049,7 +2018,8 @@ DownloadManager::UploadScores() // keeping in case we want to use this later -m auto ts = scorePtr->GetTopScore(); if ((ts == 1 || ts == 2) && !scorePtr->IsUploadedToServer(serverURL.Get())) { - if (scorePtr->HasReplayData()) // we should remove this check maybe -mina + if (scorePtr->HasReplayData()) // we should remove this check + // maybe -mina toUpload.emplace_back(scorePtr); } } From 627cc69d45ea96e4693e86e792b3a885e0a2ea09 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 07:17:18 -0300 Subject: [PATCH 227/320] Fix typo --- src/DownloadManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index f7cb49056b..4d81958a89 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1206,7 +1206,7 @@ DownloadManager::UpdateOnlineScoreReplayData(string& sk, if (callback) callback(); }; - HTTPRequest* req = new HTTPRequest(curlHandle, done, fail); + HTTPRequest* req = new HTTPRequest(curlHandle, done, form, fail); SetCURLResultsString(curlHandle, &(req->result)); curl_multi_add_handle(mHTTPHandle, req->handle); HTTPRequests.push_back(req); From 79709a52905551539ce3752c7fe56d0249f1922f Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 07:40:15 -0300 Subject: [PATCH 228/320] Fix ctrl+g on packs --- src/ScreenSelectMusic.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index de794fffe4..ab091ae15d 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -515,7 +515,8 @@ ScreenSelectMusic::Input(const InputEventPlus& input) return true; } } else if (bHoldingCtrl && c == 'G' && m_MusicWheel.IsSettled() && - input.type == IET_FIRST_PRESS) { + input.type == IET_FIRST_PRESS && + GAMESTATE->m_pCurSteps[PLAYER_1] != nullptr) { Profile* pProfile = PROFILEMAN->GetProfile(PLAYER_1); pProfile->AddGoal(GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); Song* asonglol = m_MusicWheel.GetSelectedSong(); From 5d1ac8b16301164da67131a3d9c581d6d07d93d4 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 04:46:15 -0500 Subject: [PATCH 229/320] needs to be const refs oops --- src/TimingData.cpp | 2 +- src/TimingData.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TimingData.cpp b/src/TimingData.cpp index fe3a587c77..b6a37adea7 100644 --- a/src/TimingData.cpp +++ b/src/TimingData.cpp @@ -1440,7 +1440,7 @@ TimingData::WhereUAtBroNoOffset(float beat) const } vector -TimingData::ConvertReplayNoteRowsToTimestamps(vector& nrv, float rate) +TimingData::ConvertReplayNoteRowsToTimestamps(const vector& nrv, float rate) { vector o; for (auto nr : nrv) diff --git a/src/TimingData.h b/src/TimingData.h index d820227844..74bae40831 100644 --- a/src/TimingData.h +++ b/src/TimingData.h @@ -675,7 +675,7 @@ class TimingData float WhereUAtBroNoOffset(float beat); float WhereUAtBro(int row); - vector ConvertReplayNoteRowsToTimestamps(vector& nrv, + vector ConvertReplayNoteRowsToTimestamps(const vector& nrv, float rate); bool ValidSequentialAssumption = true; From 3471e61c51b31aa0c4c10ed312e4aa04e2d77131 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 06:26:24 -0500 Subject: [PATCH 230/320] ignore enter in neteval, add get/select current player binds --- src/ScreenNetEvaluation.cpp | 25 +++++++++++++++++++++++++ src/ScreenNetEvaluation.h | 7 ++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/ScreenNetEvaluation.cpp b/src/ScreenNetEvaluation.cpp index 30e04ab9c6..5ec9a66581 100644 --- a/src/ScreenNetEvaluation.cpp +++ b/src/ScreenNetEvaluation.cpp @@ -8,6 +8,7 @@ #include "Style.h" #include "ThemeManager.h" #include "NetworkSyncManager.h" +#include "InputEventPlus.h" static const int NUM_SCORE_DIGITS = 9; @@ -132,6 +133,17 @@ ScreenNetEvaluation::MenuDown(const InputEventPlus& input) return true; } +bool +ScreenNetEvaluation::Input(const InputEventPlus& input) +{ + // throw out "enter" inputs so players don't accidentally close the screen + // while talking about scores, force them to esc to the next screen -mina + if (input.DeviceI.button == KEY_ENTER) + return false; + + return Screen::Input(input); +} + void ScreenNetEvaluation::HandleScreenMessage(const ScreenMessage SM) { @@ -282,11 +294,24 @@ class LunaScreenNetEvaluation : public Luna lua_pushnil(L); return 1; } + static int GetCurrentPlayer(T* p, lua_State* L) + { + lua_pushnumber(L, p->m_iCurrentPlayer + 1); + return 1; + } + static int SelectPlayer(T* p, lua_State* L) + { + p->m_iCurrentPlayer = IArg(1) - 1; + p->UpdateStats(); + return 0; + } LunaScreenNetEvaluation() { ADD_METHOD(GetNumActivePlayers); ADD_METHOD(GetHighScore); ADD_METHOD(GetOptions); + ADD_METHOD(GetCurrentPlayer); + ADD_METHOD(SelectPlayer); } }; diff --git a/src/ScreenNetEvaluation.h b/src/ScreenNetEvaluation.h index 37e1b9903c..bf83d8a1ac 100644 --- a/src/ScreenNetEvaluation.h +++ b/src/ScreenNetEvaluation.h @@ -12,12 +12,12 @@ class ScreenNetEvaluation : public ScreenEvaluation // sm-ssc: int GetNumActivePlayers() { return m_iActivePlayers; } - + bool Input(const InputEventPlus& input) override; // Lua void PushSelf(lua_State* L) override; int m_iCurrentPlayer; - + void UpdateStats(); protected: bool MenuLeft(const InputEventPlus& input) override; bool MenuUp(const InputEventPlus& input) override; @@ -25,9 +25,6 @@ class ScreenNetEvaluation : public ScreenEvaluation bool MenuDown(const InputEventPlus& input) override; void HandleScreenMessage(ScreenMessage SM) override; void TweenOffScreen() override; - - void UpdateStats(); - private: // todo: Make this an AutoActor -aj Quad m_rectUsersBG; From 8cb3a8b2153175c4c00940fc8aa1526e133eed49 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 06:36:29 -0500 Subject: [PATCH 231/320] fix theme error breaking overlays with leaderboard in singleplayer --- .../BGAnimations/ScreenGameplay overlay/leaderboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 39ba41525f..9207beb983 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -62,7 +62,7 @@ local function scoreUsingMultiScore(idx) } end local onlineScores = {} -local isMulti = NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation" +local isMulti = NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation" or false if isMulti then multiScores = NSMAN:GetMPLeaderboard() for i = 1, 5 do From 7fb3f21075625b794e3e1e678f227dc9fc4d20e6 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 07:57:54 -0500 Subject: [PATCH 232/320] name consistency --- src/ScreenNetEvaluation.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ScreenNetEvaluation.cpp b/src/ScreenNetEvaluation.cpp index 5ec9a66581..e81531a9ef 100644 --- a/src/ScreenNetEvaluation.cpp +++ b/src/ScreenNetEvaluation.cpp @@ -299,7 +299,7 @@ class LunaScreenNetEvaluation : public Luna lua_pushnumber(L, p->m_iCurrentPlayer + 1); return 1; } - static int SelectPlayer(T* p, lua_State* L) + static int SetCurrentPlayer(T* p, lua_State* L) { p->m_iCurrentPlayer = IArg(1) - 1; p->UpdateStats(); @@ -311,7 +311,7 @@ class LunaScreenNetEvaluation : public Luna ADD_METHOD(GetHighScore); ADD_METHOD(GetOptions); ADD_METHOD(GetCurrentPlayer); - ADD_METHOD(SelectPlayer); + ADD_METHOD(SetCurrentPlayer); } }; From 66914159baf9ee2b676a9b4f578c1f5efdb06f25 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 07:58:06 -0500 Subject: [PATCH 233/320] draft rework mp scoreboard --- .../Til Death/BGAnimations/MPscoreboard.lua | 253 ++++++++++++++++++ .../ScreenNetEvaluation decorations.lua | 2 +- 2 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 Themes/Til Death/BGAnimations/MPscoreboard.lua diff --git a/Themes/Til Death/BGAnimations/MPscoreboard.lua b/Themes/Til Death/BGAnimations/MPscoreboard.lua new file mode 100644 index 0000000000..cafd45a4a4 --- /dev/null +++ b/Themes/Til Death/BGAnimations/MPscoreboard.lua @@ -0,0 +1,253 @@ + + +local lines = 6 -- number of scores to display +local framex = SCREEN_WIDTH - capWideScale(get43size(230), 230) +local framey = 60 +local frameWidth = capWideScale(get43size(220), 220) +local spacing = 34 + +--Input event for mouse clicks +local function input(event) + local scoreBoard = SCREENMAN:GetTopScreen():GetChildren().scoreBoard + if event.DeviceInput.button == "DeviceButton_left mouse button" and scoreBoard then + if event.type == "InputEventType_Release" then + for i = 1, #multiscores do + if isOver(scoreBoard:GetChild(i):GetChild("mouseOver")) then + SCREENMAN:GetTopScreen():SelectPlayer(i) + scoreBoard:GetChild(i):GetChild("grade"):visible( + not scoreBoard:GetChild(i):GetChild("grade"):GetVisible() + ) + scoreBoard:GetChild(i):GetChild("clear"):visible( + not scoreBoard:GetChild(i):GetChild("clear"):GetVisible() + ) + scoreBoard:GetChild(i):GetChild("wife"):visible( + not scoreBoard:GetChild(i):GetChild("wife"):GetVisible() + ) + scoreBoard:GetChild(i):GetChild("combo"):visible( + not scoreBoard:GetChild(i):GetChild("combo"):GetVisible() + ) + scoreBoard:GetChild(i):GetChild("judge"):visible( + not scoreBoard:GetChild(i):GetChild("judge"):GetVisible() + ) + scoreBoard:GetChild(i):GetChild("date"):visible( + not scoreBoard:GetChild(i):GetChild("date"):GetVisible() + ) + scoreBoard:GetChild(i):GetChild("option"):visible( + not scoreBoard:GetChild(i):GetChild("option"):GetVisible() + ) + end + end + end + end + return false +end + +local function Update(self) + for i = 1, lines do + if isOver(self:GetChild(i):GetChild("mouseOver")) then + self:GetChild(i):GetChild("mouseOver"):diffusealpha(0.2) + else + self:GetChild(i):GetChild("mouseOver"):diffusealpha(0) + self:GetChild(i):GetChild("grade"):visible(true) + self:GetChild(i):GetChild("wife"):visible(true) + self:GetChild(i):GetChild("combo"):visible(true) + self:GetChild(i):GetChild("judge"):visible(true) + self:GetChild(i):GetChild("clear"):visible(true) + self:GetChild(i):GetChild("date"):visible(false) + self:GetChild(i):GetChild("option"):visible(false) + end + end +end + + +local t = + Def.ActorFrame { + Name = "scoreBoard", + InitCommand = function(self) + self:SetUpdateFunction(Update) + end, + BeginCommand = function(self) + SCREENMAN:GetTopScreen():AddInputCallback(input) + multiscores = NSMAN:GetEvalScores() + for i=1, math.min(#multiscores) do + self:GetChild(i):queuecommand("UpdateNetScore") + end + end, + NewMultiScoreMessageCommand = function(self) + multiscores = NSMAN:GetEvalScores() + for i=1, math.min(#multiscores) do + self:GetChild(i):queuecommand("UpdateNetScore") + end + end +} + +local function scoreitem(pn, i) + local t = + Def.ActorFrame { + Name = tostring(i), + InitCommand = function(self) + self:visible(false) + end, + UpdateNetScoreCommand = function(self) + self:visible(i <= #multiscores) + end, + --The main quad + Def.Quad { + InitCommand = function(self) + self:xy(framex, framey + (i * spacing) - 4):zoomto(frameWidth, 30):halign(0):valign(0):diffuse( + color("#333333") + ):diffusealpha(1):diffuserightedge(color("#33333333")) + end + }, + --Highlight quad for the current score + Def.Quad { + InitCommand = function(self) + self:xy(framex, framey + (i * spacing) - 4):zoomto(frameWidth, 30):halign(0):valign(0):diffuse( + color("#ffffff") + ):diffusealpha(0.3):diffuserightedge(color("#33333300")) + end, + UpdateNetScoreCommand = function(self) + self:visible(SCREENMAN:GetTopScreen():GetCurrentPlayer() == i) + end, + UpdateNetEvalStatsMessageCommand = function(self) + self:visible(SCREENMAN:GetTopScreen():GetCurrentPlayer() == i) + end + }, + --Quad that will act as the bounding box for mouse rollover/click stuff. + Def.Quad { + Name = "mouseOver", + UpdateNetScoreCommand = function(self) + self:xy(framex, framey + (i * spacing) - 4):zoomto(frameWidth*2, 30):halign(0):valign(0):diffuse( + getMainColor("highlight") + ):diffusealpha(0) + end + }, + --ClearType lamps + Def.Quad { + UpdateNetScoreCommand = function(self) + self:xy(framex, framey + (i * spacing) - 4):zoomto(8, 30):halign(0):valign(0):diffuse( + getClearTypeFromScore(pn, hs, 2) + ) + end + }, + --rank + LoadFont("Common normal") .. + { + InitCommand = function(self) + self:xy(framex - 8, framey + 12 + (i * spacing)):zoom(0.35) + end, + UpdateNetScoreCommand = function(self) + self:settext(i) + if SCREENMAN:GetTopScreen():GetCurrentPlayer() == i then + self:diffuse(color("#ffcccc")) + else + self:diffuse(color("#FFFFFF")) + end + end, + UpdateNetEvalStatsMessageCommand = function(self) + self:playcommand("UpdateNetScore") + end + }, + LoadFont("Common normal") .. + { + Name = "wife", + InitCommand = function(self) + self:xy(framex + 10, framey + 11 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.3) + end, + UpdateNetScoreCommand = function(self) + self:settextf("%05.2f%% (%s)", notShit.floor(multiscores[i].highscore:GetWifeScore() * 10000) / 100, "Wife") + end + }, + LoadFont("Common normal") .. + { + Name = "user", + InitCommand = function(self) + self:xy(framex + 10, framey + 1 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.3) + end, + UpdateNetScoreCommand = function(self) + self:settextf(multiscores[i].user) + if Grade:Reverse()[GetGradeFromPercent(multiscores[i].highscore:GetWifeScore())] < 2 then -- this seeems right -mina + self:rainbowscroll(true) + end + end + }, + LoadFont("Common normal") .. + { + Name = "option", + InitCommand = function(self) + self:xy(framex + 10, framey + 11 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.35) + end, + UpdateNetScoreCommand = function(self) + self:settext(multiscores[i].highscore:GetModifiers()) + self:visible(false) + end + }, + LoadFont("Common normal") .. + { + Name = "grade", + InitCommand = function(self) + self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 2 + (i * spacing)):zoom(0.35):halign(0.5):maxwidth( + (frameWidth - 15) / 0.35 + ) + end, + UpdateNetScoreCommand = function(self) + self:settext(getGradeStrings(multiscores[i].highscore:GetWifeGrade())) + self:diffuse(getGradeColor(multiscores[i].highscore:GetWifeGrade())) + end + }, + LoadFont("Common normal") .. + { + Name = "clear", + InitCommand = function(self) + self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 12 + (i * spacing)):zoom(0.35):halign(0.5):maxwidth( + (frameWidth - 15) / 0.35 + ) + end, + UpdateNetScoreCommand = function(self) + self:settext(getClearTypeFromScore(pn, multiscores[i].highscore, 0)) + self:diffuse(getClearTypeFromScore(pn, multiscores[i].highscore, 2)) + end + }, + LoadFont("Common normal") .. + { + Name = "combo", + InitCommand = function(self) + self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 22 + (i * spacing)):zoom(0.35):halign(0.5):maxwidth( + (frameWidth - 15) / 0.35 + ) + end, + UpdateNetScoreCommand = function(self) + self:settextf("%sx", multiscores[i].highscore:GetMaxCombo()) + end + }, + LoadFont("Common normal") .. + { + Name = "judge", + InitCommand = function(self) + self:xy(framex + 10, framey + 20 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.35) + end, + UpdateNetScoreCommand = function(self) + self:settext(multiscores[i].highscore:GetJudgmentString()) + end + }, + LoadFont("Common normal") .. + { + Name = "date", + InitCommand = function(self) + self:xy(framex + 10, framey + 20 + (i * spacing)):zoom(0.35):halign(0) + end, + UpdateNetScoreCommand = function(self) + self:settext(multiscores[i].highscore:GetDate()) + self:visible(false) + end + } + } + return t +end + +for i=1,lines do + t[#t + 1] = scoreitem(1, i) +end + + +return t diff --git a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua index c29293f2f6..0853121a9d 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua @@ -8,7 +8,7 @@ local customWindows = timingWindowConfig:get_data().customWindows local scoreType = themeConfig:get_data().global.DefaultScoreType if GAMESTATE:GetNumPlayersEnabled() == 1 and themeConfig:get_data().eval.ScoreBoardEnabled then - t[#t + 1] = LoadActor("ScreenEvaluation decorations/scoreboard") + t[#t + 1] = LoadActor("MPscoreboard") end t[#t + 1] = From 4ffcd4cc760401e9bae4ba25fbfbeffcb5b778d3 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 08:23:21 -0500 Subject: [PATCH 234/320] rip out old neteval garbage --- src/ScreenNetEvaluation.cpp | 57 ------------------------------------- src/ScreenNetEvaluation.h | 4 --- 2 files changed, 61 deletions(-) diff --git a/src/ScreenNetEvaluation.cpp b/src/ScreenNetEvaluation.cpp index e81531a9ef..0962f9ca4d 100644 --- a/src/ScreenNetEvaluation.cpp +++ b/src/ScreenNetEvaluation.cpp @@ -36,64 +36,9 @@ ScreenNetEvaluation::Init() m_bHasStats = false; m_iCurrentPlayer = 0; - FOREACH_EnabledPlayer(pn) { m_pActivePlayer = pn; } - - m_iShowSide = (m_pActivePlayer == PLAYER_1) ? 2 : 1; - - m_rectUsersBG.SetWidth(USERSBG_WIDTH); - m_rectUsersBG.SetHeight(USERSBG_HEIGHT); - m_rectUsersBG.RunCommands(USERSBG_COMMAND); - // XXX: The name should be set with m_iShowSide and then - // LOAD_ALL_COMMANDS_AND_SET_XY_AND_ON_COMMAND should be used. -aj - m_rectUsersBG.SetName("UsersBG"); - - m_rectUsersBG.SetXY(THEME->GetMetricF("ScreenNetEvaluation", - ssprintf("UsersBG%dX", m_iShowSide)), - THEME->GetMetricF("ScreenNetEvaluation", - ssprintf("UsersBG%dY", m_iShowSide))); - LOAD_ALL_COMMANDS_AND_ON_COMMAND(m_rectUsersBG); - - this->AddChild(&m_rectUsersBG); - - RedoUserTexts(); - NSMAN->OnEval(); } -void -ScreenNetEvaluation::RedoUserTexts() -{ - m_iActivePlayers = NSMAN->m_ActivePlayers; - - // If unnecessary, just don't do this function. - if (m_iActivePlayers == (int)m_textUsers.size()) - return; - - for (unsigned int i = 0; i < m_textUsers.size(); ++i) - this->RemoveChild(&m_textUsers[i]); - - float cx = THEME->GetMetricF("ScreenNetEvaluation", - ssprintf("User%dX", m_iShowSide)); - float cy = THEME->GetMetricF("ScreenNetEvaluation", - ssprintf("User%dY", m_iShowSide)); - - m_iCurrentPlayer = 0; - m_textUsers.clear(); - m_textUsers.resize(m_iActivePlayers); - - for (int i = 0; i < m_iActivePlayers; ++i) { - m_textUsers[i].LoadFromFont(THEME->GetPathF(m_sName, "names")); - m_textUsers[i].SetName(ssprintf("User")); - m_textUsers[i].SetShadowLength(1); - m_textUsers[i].SetXY(cx, cy); - - this->AddChild(&m_textUsers[i]); - ActorUtil::LoadAllCommands(m_textUsers[i], m_sName); - cx += USERDX; - cy += USERDY; - } -} - bool ScreenNetEvaluation::MenuLeft(const InputEventPlus& input) { @@ -154,8 +99,6 @@ ScreenNetEvaluation::HandleScreenMessage(const ScreenMessage SM) m_iActivePlayers, NSMAN->m_ActivePlayers); - RedoUserTexts(); - LOG->Trace("SMNETCheckpoint"); for (int i = 0; i < m_iActivePlayers; ++i) { // Strange occurences because of timing cause these things not to diff --git a/src/ScreenNetEvaluation.h b/src/ScreenNetEvaluation.h index bf83d8a1ac..a20d5766da 100644 --- a/src/ScreenNetEvaluation.h +++ b/src/ScreenNetEvaluation.h @@ -39,10 +39,6 @@ class ScreenNetEvaluation : public ScreenEvaluation PlayerNumber m_pActivePlayer; bool m_bHasStats; - - int m_iShowSide; - - void RedoUserTexts(); }; /* From 2592c6b4c4d925208ef1356fe9f57c74a1d8a39c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 08:29:55 -0500 Subject: [PATCH 235/320] fix missing...misses in local scoreboard --- .../BGAnimations/ScreenGameplay overlay/leaderboard.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index 9207beb983..cc0cf8ee33 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -23,7 +23,8 @@ local jdgs = { "TapNoteScore_W2", "TapNoteScore_W3", "TapNoteScore_W4", - "TapNoteScore_W5" + "TapNoteScore_W5", + "TapNoteScore_Miss" } local function arbitraryLeaderboardSpacing(value) From e8f3cf42be4e12b6cc420e57817f6ae8dcef67b7 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 11:19:54 -0300 Subject: [PATCH 236/320] Fix weird crash for invalid utf charts --- src/NetworkSyncManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 707d4c38cc..3bf923131f 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -1176,7 +1176,11 @@ NetworkSyncManager::ReportHighScore(HighScore* hs, PlayerStageStats& pss) void ETTProtocol::Send(json msg) { - Send(msg.dump().c_str()); + try { + Send(msg.dump().c_str()); + } catch (exception e) { + SCREENMAN->SystemMessage("Error: Chart contains invalid utf8"); + } } void ETTProtocol::Send(const char* msg) From 12e420ab2ef6d010c005274951c3aaae30075cf9 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sat, 1 Dec 2018 11:51:34 -0300 Subject: [PATCH 237/320] Disable replay watching in multiplayer --- .../ScreenSelectMusic decorations/score.lua | 124 +++++++++--------- .../BGAnimations/superscoreboard.lua | 13 +- 2 files changed, 73 insertions(+), 64 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 430c7c5965..db11fd86c8 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -166,31 +166,31 @@ local ret = self:queuecommand("Set") updateLeaderBoardForCurrentChart() end, - CodeMessageCommand = function(self, params) -- this is intentionally bad to remind me to fix other things that are bad -mina + CodeMessageCommand = function(self, params) -- this is intentionally bad to remind me to fix other things that are bad -mina if ((getTabIndex() == 2 and nestedTab == 2) and not collapsed) and DLMAN:GetCurrentRateFilter() then local rate = getCurRateValue() - if params.Name == "PrevScore" and rate < 2.95 then - GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate + 0.1) - GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate + 0.1) - GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate + 0.1) - MESSAGEMAN:Broadcast("CurrentRateChanged") - elseif params.Name == "NextScore" and rate > 0.75 then - GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate - 0.1) - GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate - 0.1) - GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate - 0.1) - MESSAGEMAN:Broadcast("CurrentRateChanged") - end - if params.Name == "PrevRate" and rate < 3 then - GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate + 0.05) - GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate + 0.05) - GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate + 0.05) - MESSAGEMAN:Broadcast("CurrentRateChanged") - elseif params.Name == "NextRate" and rate > 0.7 then - GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate - 0.05) - GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate - 0.05) - GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate - 0.05) - MESSAGEMAN:Broadcast("CurrentRateChanged") - end + if params.Name == "PrevScore" and rate < 2.95 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate + 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate + 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate + 0.1) + MESSAGEMAN:Broadcast("CurrentRateChanged") + elseif params.Name == "NextScore" and rate > 0.75 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate - 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate - 0.1) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate - 0.1) + MESSAGEMAN:Broadcast("CurrentRateChanged") + end + if params.Name == "PrevRate" and rate < 3 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate + 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate + 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate + 0.05) + MESSAGEMAN:Broadcast("CurrentRateChanged") + elseif params.Name == "NextRate" and rate > 0.7 then + GAMESTATE:GetSongOptionsObject("ModsLevel_Preferred"):MusicRate(rate - 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Song"):MusicRate(rate - 0.05) + GAMESTATE:GetSongOptionsObject("ModsLevel_Current"):MusicRate(rate - 0.05) + MESSAGEMAN:Broadcast("CurrentRateChanged") + end end end, CurrentRateChangedMessageCommand = function(self) @@ -348,48 +348,45 @@ local l = end }, LoadFont("Common Normal") .. - { - Name = "Score", - InitCommand = function(self) - self:xy(55, 30):zoom(0.6):halign(0):settext("") - end, - DisplayCommand = function(self) - if score:GetWifeScore() == 0 then - self:settext("") - else - local overall = score:GetSkillsetSSR("Overall") - self:settextf("%.2f", overall):diffuse(byMSD(overall)) + { + Name = "Score", + InitCommand = function(self) + self:xy(55, 30):zoom(0.6):halign(0):settext("") + end, + DisplayCommand = function(self) + if score:GetWifeScore() == 0 then + self:settext("") + else + local overall = score:GetSkillsetSSR("Overall") + self:settextf("%.2f", overall):diffuse(byMSD(overall)) + end end - end - }, + }, LoadFont("Common Normal") .. - { - Name = "Score", - InitCommand = function(self) - self:xy(55, 43):zoom(0.5):halign(0):settext("") - end, - DisplayCommand = function(self) - if score:GetWifeScore() == 0 then - self:settext("") - else - self:settext(GAMESTATE:GetCurrentSteps(PLAYER_1):GetRelevantSkillsetsByMSDRank(getCurRateValue(), 1)) + { + Name = "Score", + InitCommand = function(self) + self:xy(55, 43):zoom(0.5):halign(0):settext("") + end, + DisplayCommand = function(self) + if score:GetWifeScore() == 0 then + self:settext("") + else + self:settext(GAMESTATE:GetCurrentSteps(PLAYER_1):GetRelevantSkillsetsByMSDRank(getCurRateValue(), 1)) + end end - end - }, - + }, LoadFont("Common Normal") .. - { - Name = "ClearType", - InitCommand = function(self) - self:y(43):zoom(0.5):halign(0):settext("No Play"):diffuse( - color(colorConfig:get_data().clearType["NoPlay"]) - ) - end, - DisplayCommand = function(self) - self:settext(getClearTypeFromScore(pn, score, 0)) - self:diffuse(getClearTypeFromScore(pn, score, 2)) - end - }, + { + Name = "ClearType", + InitCommand = function(self) + self:y(43):zoom(0.5):halign(0):settext("No Play"):diffuse(color(colorConfig:get_data().clearType["NoPlay"])) + end, + DisplayCommand = function(self) + self:settext(getClearTypeFromScore(pn, score, 0)) + self:diffuse(getClearTypeFromScore(pn, score, 2)) + end + }, LoadFont("Common Normal") .. { Name = "Combo", @@ -609,6 +606,11 @@ l[#l + 1] = InitCommand = function(self) self:xy((frameWidth - offsetX - frameX) / 2, frameHeight - headeroffY - 30 - offsetY):zoom(0.5):settext("") end, + BeginCommand = function(self) + if SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then + self:x(-10):zoom(0.0000001):maxwidth(1) + end + end, DisplayCommand = function(self) if hasReplayData then self:settext("View Replay") diff --git a/Themes/Til Death/BGAnimations/superscoreboard.lua b/Themes/Til Death/BGAnimations/superscoreboard.lua index 2d9375c0aa..2a4a9b7311 100644 --- a/Themes/Til Death/BGAnimations/superscoreboard.lua +++ b/Themes/Til Death/BGAnimations/superscoreboard.lua @@ -91,7 +91,7 @@ local o = SetFromLeaderboardCommand = function(self, lb) scoretable = lb ind = 0 - self:playcommand("GetFilteredLeaderboard") -- we can move all the filter stuff to lua so we're not being dumb hurr hur -mina + self:playcommand("GetFilteredLeaderboard") -- we can move all the filter stuff to lua so we're not being dumb hurr hur -mina self:playcommand("Update") end, UpdateCommand = function(self) @@ -338,7 +338,7 @@ local function makeScoreDisplay(i) CurrentSongChangedMessageCommand = function(self) self:visible(false) end, - UpdateCommand = function(self) + UpdateCommand = function(self) hs = scoretable[(i + ind)] if hs and i <= numscores then self:visible(true) @@ -470,7 +470,14 @@ local function makeScoreDisplay(i) Name = "Replay" .. i, InitCommand = function(self) if not collapsed then - self:x(capWideScale(c3x + 52, c3x) ):zoom(tzoom - 0.05):halign(1):valign(0):maxwidth(width / 2 / tzoom):addy(row2yoff):diffuse(getMainColor("enabled")) + self:x(capWideScale(c3x + 52, c3x)):zoom(tzoom - 0.05):halign(1):valign(0):maxwidth(width / 2 / tzoom):addy( + row2yoff + ):diffuse(getMainColor("enabled")) + end + end, + BeginCommand = function(self) + if SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic" then + self:x(-10):zoom(0.0000001):maxwidth(1) end end, DisplayCommand = function(self) From 232db26c64ec689a31ebac0689a3b69bb92ecaca Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 09:28:24 -0500 Subject: [PATCH 238/320] set mpleaderboard update interval to 0.25s --- src/ScreenGameplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 61fdcb9b61..29d4553acf 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1379,7 +1379,7 @@ ScreenGameplay::BeginScreen() this->GetPlayerInfo(PLAYER_1)->m_pPlayer->curwifescore / this->GetPlayerInfo(PLAYER_1)->m_pPlayer->maxwifescore, doot); }, - 1, + 0.25f, -1); } } From 42212e3d4a8eb30752e0438bd708138a0263e5a7 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 10:28:22 -0500 Subject: [PATCH 239/320] remove more trash from old neteval --- src/ScreenNetEvaluation.cpp | 60 ------------------------------------- src/ScreenNetEvaluation.h | 12 -------- 2 files changed, 72 deletions(-) diff --git a/src/ScreenNetEvaluation.cpp b/src/ScreenNetEvaluation.cpp index 0962f9ca4d..5139ba94ba 100644 --- a/src/ScreenNetEvaluation.cpp +++ b/src/ScreenNetEvaluation.cpp @@ -39,45 +39,6 @@ ScreenNetEvaluation::Init() NSMAN->OnEval(); } -bool -ScreenNetEvaluation::MenuLeft(const InputEventPlus& input) -{ - return MenuUp(input); -} - -bool -ScreenNetEvaluation::MenuUp(const InputEventPlus& input) -{ - if (m_iActivePlayers == 0 || !m_bHasStats) - return false; - - COMMAND(m_textUsers[m_iCurrentPlayer], "DeSel"); - m_iCurrentPlayer = - (m_iCurrentPlayer + m_iActivePlayers - 1) % m_iActivePlayers; - COMMAND(m_textUsers[m_iCurrentPlayer], "Sel"); - UpdateStats(); - return true; -} - -bool -ScreenNetEvaluation::MenuRight(const InputEventPlus& input) -{ - return MenuDown(input); -} - -bool -ScreenNetEvaluation::MenuDown(const InputEventPlus& input) -{ - if (m_iActivePlayers == 0 || !m_bHasStats) - return false; - - COMMAND(m_textUsers[m_iCurrentPlayer], "DeSel"); - m_iCurrentPlayer = (m_iCurrentPlayer + 1) % m_iActivePlayers; - COMMAND(m_textUsers[m_iCurrentPlayer], "Sel"); - UpdateStats(); - return true; -} - bool ScreenNetEvaluation::Input(const InputEventPlus& input) { @@ -116,19 +77,8 @@ ScreenNetEvaluation::HandleScreenMessage(const ScreenMessage SM) NSMAN->m_EvalPlayerData[i].name < 0) break; - if (size_t(i) >= m_textUsers.size()) - break; - - m_textUsers[i].SetText( - NSMAN->m_EvalPlayerData[i].nameStr.empty() - ? NSMAN->m_PlayerNames[NSMAN->m_EvalPlayerData[i].name] - : NSMAN->m_EvalPlayerData[i].nameStr); - if (NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetWifeGrade() < Grade_Tier03) - m_textUsers[i].PlayCommand("Tier02OrBetter"); - - ON_COMMAND(m_textUsers[i]); LOG->Trace("SMNETCheckpoint%d", i); } return; // No need to let ScreenEvaluation get a hold of this. @@ -142,9 +92,6 @@ ScreenNetEvaluation::HandleScreenMessage(const ScreenMessage SM) void ScreenNetEvaluation::TweenOffScreen() { - for (int i = 0; i < m_iActivePlayers; ++i) - OFF_COMMAND(m_textUsers[i]); - OFF_COMMAND(m_rectUsersBG); ScreenEvaluation::TweenOffScreen(); } @@ -166,13 +113,6 @@ ScreenNetEvaluation::UpdateStats() m_textScore[m_pActivePlayer].SetTargetNumber( static_cast(NSMAN->m_EvalPlayerData[m_iCurrentPlayer].score)); - // Values greater than 6 will cause a crash - if (NSMAN->m_EvalPlayerData[m_iCurrentPlayer].difficulty < 6) { - m_DifficultyIcon[m_pActivePlayer].SetPlayer(m_pActivePlayer); - m_DifficultyIcon[m_pActivePlayer].SetFromDifficulty( - NSMAN->m_EvalPlayerData[m_iCurrentPlayer].difficulty); - } - for (int j = 0; j < NETNUMTAPSCORES; ++j) { // The name will be blank if ScreenEvaluation determined the line // should not be shown. diff --git a/src/ScreenNetEvaluation.h b/src/ScreenNetEvaluation.h index a20d5766da..fcefaad0a3 100644 --- a/src/ScreenNetEvaluation.h +++ b/src/ScreenNetEvaluation.h @@ -19,21 +19,9 @@ class ScreenNetEvaluation : public ScreenEvaluation int m_iCurrentPlayer; void UpdateStats(); protected: - bool MenuLeft(const InputEventPlus& input) override; - bool MenuUp(const InputEventPlus& input) override; - bool MenuRight(const InputEventPlus& input) override; - bool MenuDown(const InputEventPlus& input) override; void HandleScreenMessage(ScreenMessage SM) override; void TweenOffScreen() override; private: - // todo: Make this an AutoActor -aj - Quad m_rectUsersBG; - - // todo: Make this a StepsDisplay -aj - DifficultyIcon m_DifficultyIcon[NUM_PLAYERS]; - // StepsDisplay m_StepsDisplays[NUM_PLAYERS]; - - vector m_textUsers; int m_iActivePlayers; PlayerNumber m_pActivePlayer; From e67ecf1ed0a8e529fafdedad2efe74c6dd36c2df Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 10:30:09 -0500 Subject: [PATCH 240/320] leaderboard fixes that arent fixes because mp should be separate but... - add grades - msd default to -1 for mp - proper grade default - wife default not low enough for autoplay sorting - theme blow up on line 66 --- .../ScreenGameplay overlay/leaderboard.lua | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua index cc0cf8ee33..26eb2c2a80 100644 --- a/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua +++ b/Themes/Til Death/BGAnimations/ScreenGameplay overlay/leaderboard.lua @@ -49,13 +49,13 @@ local function scoreUsingMultiScore(idx) return multiScores[idx] and multiScores[idx].user or nil end, GetWifeGrade = function() - return multiScores[idx] and GetGradeFromPercent(multiScores[idx].wife) or 0 + return multiScores[idx] and GetGradeFromPercent(multiScores[idx].wife) or "Grade_Tier01" end, GetWifeScore = function() - return multiScores[idx] and multiScores[idx].wife or -500 + return multiScores[idx] and multiScores[idx].wife or -5000000 end, GetSkillsetSSR = function() - return 0 + return -1 end, GetJudgmentString = function() return multiScores[idx] and multiScores[idx].jdgstr or "" @@ -63,7 +63,7 @@ local function scoreUsingMultiScore(idx) } end local onlineScores = {} -local isMulti = NSMAN:IsETTP() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation" or false +local isMulti = NSMAN:IsETTP() and SCREENMAN:GetTopScreen() and SCREENMAN:GetTopScreen():GetName() == "ScreenNetStageInformation" or false if isMulti then multiScores = NSMAN:GetMPLeaderboard() for i = 1, 5 do @@ -216,10 +216,20 @@ function scoreEntry(i) addLabel( "wife", function(self, hs) - self:settextf("%05.2f%%", hs:GetWifeScore() * 100):diffuse(byGrade(GetGradeFromPercent(hs:GetWifeScore()))) + self:settextf("%05.2f%%", hs:GetWifeScore() * 100):diffuse(byGrade(hs:GetWifeGrade())) end, 1.8 * WIDTH ) + addLabel( + "grade", + function(self, hs) + self:settext(getGradeStrings(hs:GetWifeGrade())) + self:diffuse(byGrade(hs:GetWifeGrade())) + self:halign(0.5) + end, + 2 * WIDTH, + ENTRY_HEIGHT / 2 + ) addLabel( "judges", function(self, hs) From 9fd97265ee725026b0ccf9287c9056eecc6b0636 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 10:55:52 -0500 Subject: [PATCH 241/320] replayupdater fixes maybe --- src/DownloadManager.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 4d81958a89..21f7ccbfa0 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1150,12 +1150,13 @@ DownloadManager::UpdateOnlineScoreReplayData(string& sk, auto hs = SCOREMAN->GetScoresByKey().at(sk); CURL* curlHandle = initCURLHandle(true); - string url = serverURL.Get() + "/updatereplaydata/" + sk; + string url = serverURL.Get() + "/updatereplaydata/"; curl_httppost* form = nullptr; curl_httppost* lastPtr = nullptr; SetCURLFormPostField( curlHandle, form, lastPtr, "scorekey", hs->GetScoreKey()); string toSend = "["; + hs->LoadReplayData(); auto& rows = hs->GetNoteRowVector(); for (auto& row : rows) { toSend += to_string(row) + ","; @@ -1889,8 +1890,11 @@ DownloadManager::OnLogin() DLMAN->RefreshCountryCodes(); FOREACH_ENUM(Skillset, ss) DLMAN->RefreshTop25(ss); - if (DLMAN->ShouldUploadScores()) + if (DLMAN->ShouldUploadScores()) { DLMAN->UploadScores(); + DLMAN->UpdateOnlineScoreReplayData(); + } + DLMAN->UpdateOnlineScoreReplayData(); if (GAMESTATE->m_pCurSteps[PLAYER_1] != nullptr) DLMAN->RequestChartLeaderBoard( GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); @@ -1980,8 +1984,7 @@ DownloadManager::UpdateOnlineScoreReplayData() for (auto& vec : scores) { for (auto& scorePtr : vec) { auto ts = scorePtr->GetTopScore(); - if ((ts == 1 || ts == 2) && - !scorePtr->IsUploadedToServer(serverURL.Get())) { + if ((ts == 1 || ts == 2) ){ if (scorePtr->HasReplayData()) toUpload.emplace_back(scorePtr); } From 9272e30343620c5a088469c49b7e66b945f141d5 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 11:42:08 -0500 Subject: [PATCH 242/320] removing more neteval garbage --- src/ScreenNetEvaluation.cpp | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/ScreenNetEvaluation.cpp b/src/ScreenNetEvaluation.cpp index 5139ba94ba..43d3f4186b 100644 --- a/src/ScreenNetEvaluation.cpp +++ b/src/ScreenNetEvaluation.cpp @@ -101,31 +101,6 @@ ScreenNetEvaluation::UpdateStats() if (m_iCurrentPlayer >= (int)NSMAN->m_EvalPlayerData.size()) return; - // Only run these commands if the theme has these things shown; not every - // theme has them, so don't assume. -aj - if (THEME->GetMetricB(m_sName, "ShowGradeArea")) - m_Grades[m_pActivePlayer].SetGrade(static_cast( - NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetGrade() != - Grade_NoData - ? NSMAN->m_EvalPlayerData[m_iCurrentPlayer].hs.GetGrade() - : NSMAN->m_EvalPlayerData[m_iCurrentPlayer].grade)); - if (THEME->GetMetricB(m_sName, "ShowScoreArea")) - m_textScore[m_pActivePlayer].SetTargetNumber( - static_cast(NSMAN->m_EvalPlayerData[m_iCurrentPlayer].score)); - - for (int j = 0; j < NETNUMTAPSCORES; ++j) { - // The name will be blank if ScreenEvaluation determined the line - // should not be shown. - if (!m_textJudgmentLineNumber[j][m_pActivePlayer].GetName().empty()) { - m_textJudgmentLineNumber[j][m_pActivePlayer].SetTargetNumber( - static_cast( - NSMAN->m_EvalPlayerData[m_iCurrentPlayer].tapScores[j])); - } - } - - m_textPlayerOptions[m_pActivePlayer].SetText( - NSMAN->m_EvalPlayerData[m_iCurrentPlayer].playerOptions); - StepsType st = GAMESTATE->GetCurrentStyle(PLAYER_INVALID)->m_StepsType; Difficulty dc = NSMAN->m_EvalPlayerData[m_iCurrentPlayer].difficulty; Steps* pSteps = SongUtil::GetOneSteps(GAMESTATE->m_pCurSong, st, dc); From 27991d5cb647ea8a78e8586085a39e337d68f1cc Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 11:42:21 -0500 Subject: [PATCH 243/320] name consistency --- Themes/Til Death/BGAnimations/MPscoreboard.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/MPscoreboard.lua b/Themes/Til Death/BGAnimations/MPscoreboard.lua index cafd45a4a4..2f2ab294a8 100644 --- a/Themes/Til Death/BGAnimations/MPscoreboard.lua +++ b/Themes/Til Death/BGAnimations/MPscoreboard.lua @@ -13,7 +13,7 @@ local function input(event) if event.type == "InputEventType_Release" then for i = 1, #multiscores do if isOver(scoreBoard:GetChild(i):GetChild("mouseOver")) then - SCREENMAN:GetTopScreen():SelectPlayer(i) + SCREENMAN:GetTopScreen():SetCurrentPlayer(i) scoreBoard:GetChild(i):GetChild("grade"):visible( not scoreBoard:GetChild(i):GetChild("grade"):GetVisible() ) From a36c0ff1b9e422ed4867c1b85515bc027ef48d3f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 11:53:20 -0500 Subject: [PATCH 244/320] add highlight toggles to eval --- Themes/Til Death/metrics.ini | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/metrics.ini b/Themes/Til Death/metrics.ini index 93e368d01e..ef7f1552d2 100644 --- a/Themes/Til Death/metrics.ini +++ b/Themes/Til Death/metrics.ini @@ -568,10 +568,12 @@ ComboGraphP2OnCommand= ComboGraphP2OffCommand= [ScreenNetEvaluation] -# judge changer listener i guess also on online omg -CodeNames="PrevJudge,NextJudge" +# judge changer listener i guess +CodeNames="ResetJudge,PrevJudge,NextJudge,ToggleHands" +CodeResetJudge="MenuUp" CodeNextJudge="EffectUp" CodePrevJudge="EffectDown" +CodeToggleHands="MenuDown" Class="ScreenNetEvaluation" From 4f0bc670310d7c9cbff67a2784de251127f973a7 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 12:00:19 -0500 Subject: [PATCH 245/320] fix some things with neteval --- .../ScreenNetEvaluation decorations.lua | 125 +++++++++++------- 1 file changed, 77 insertions(+), 48 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua index 0853121a9d..2b973b9a05 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua @@ -100,6 +100,7 @@ local judges = { "TapNoteScore_Miss" } + local pssP1 = STATSMAN:GetCurStageStats():GetPlayerStageStats(PLAYER_1) local frameX = 20 @@ -111,13 +112,10 @@ function scoreBoard(pn, position) local judge = enabledCustomWindows and 0 or GetTimingDifficulty() local pss = STATSMAN:GetCurStageStats():GetPlayerStageStats(pn) local score = SCOREMAN:GetMostRecentScore() - if not score then - score = SCOREMAN:GetTempReplayScore() - end local dvt = pss:GetOffsetVector() local totalTaps = pss:GetTotalTaps() - local smallest, largest local devianceTable + local tracks local t = Def.ActorFrame { @@ -131,7 +129,9 @@ function scoreBoard(pn, position) if s then score = s devianceTable = score:GetOffsetVector() - smallest, largest = wifeRange(devianceTable) + totalTaps = #devianceTable + dvt = devianceTable + tracks = score:GetTrackVector() MESSAGEMAN:Broadcast("ScoreChanged") end end @@ -315,7 +315,7 @@ function scoreBoard(pn, position) end, ScoreChangedMessageCommand = function(self) local rescoreJudges = score:RescoreJudges(judge) - self:zoomx(frameWidth * rescoreJudges[k] / (#(score:GetOffsetVector()))) + self:zoomx(frameWidth * rescoreJudges[k] / (#devianceTable)) end, CodeMessageCommand = function(self, params) if params.Name == "PrevJudge" or params.Name == "NextJudge" then @@ -472,52 +472,81 @@ function scoreBoard(pn, position) } end - -- stats stuff - local devianceTable = pss:GetOffsetVector() - t[#t + 1] = - Def.Quad { - InitCommand = function(self) - self:xy(frameWidth + 25, frameY + 230):zoomto(frameWidth / 2 + 10, 60):halign(1):valign(0):diffuse( - color("#333333CC") - ) - end - } - smallest, largest = wifeRange(devianceTable) - local doot = {"Mean", "Mean(Abs)", "Sd", "Smallest", "Largest"} - local mcscoot = { - function() - return wifeMean(devianceTable) - end, - function() - return wifeAbsMean(devianceTable) - end, - function() - return wifeSd(devianceTable) - end, - function() - return smallest - end, - function() - return largest + -- stats stuff + tracks = pss:GetTrackVector() + devianceTable = pss:GetOffsetVector() + + -- basic per-hand stats to be expanded on later + local tst = ms.JudgeScalers + local tso = tst[judge] + if enabledCustomWindows then + tso = 1 end - } - for i = 1, #doot do - t[#t + 1] = - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(frameX + capWideScale(get43size(130), 160), frameY + 230 + 10 * i):zoom(0.4):halign(0):settext(doot[i]) + local function cbs(dvt, x) + local cbs = 0 + for i = 1, #dvt do + if math.abs(dvt[i]) > tso * 90 then + if tracks[i + x] == 0 or tracks[i + x] == 1 then + cbs = cbs + 1 + end end - } + end + return cbs + end + t[#t + 1] = - LoadFont("Common Normal") .. - { - InitCommand = function(self) - self:xy(frameWidth + 20, frameY + 230 + 10 * i):zoom(0.4):halign(1):settextf("%5.2fms", mcscoot[i]()) - end - } - end + Def.Quad { + InitCommand = function(self) + self:xy(frameWidth + 25, frameY + 230):zoomto(frameWidth / 2 + 10, 60):halign(1):valign(0):diffuse( + color("#333333CC") + ) + end + } + local doot = {"Mean", "Mean(Abs)", "Sd", "Left cbs", "Right cbs"} + local mcscoot = { + function() + return wifeMean(devianceTable) + end, + function() + return wifeAbsMean(devianceTable) + end, + function() + return wifeSd(devianceTable) + end, + function() + return cbs(devianceTable, 0) + end, + function() + return cbs(devianceTable, 2) + end + } + for i = 1, #doot do + t[#t + 1] = + LoadFont("Common Normal") .. + { + InitCommand = function(self) + self:xy(frameX + capWideScale(get43size(130), 160), frameY + 230 + 10 * i):zoom(0.4):halign(0):settext(doot[i]) + end, + ScoreChangedMessageCommand = function(self) + self:queuecommand("Init") + end + } + t[#t + 1] = + LoadFont("Common Normal") .. + { + InitCommand = function(self) + if i < 4 then + self:xy(frameWidth + 20, frameY + 230 + 10 * i):zoom(0.4):halign(1):settextf("%5.2fms", mcscoot[i]()) + else + self:xy(frameWidth + 20, frameY + 230 + 10 * i):zoom(0.4):halign(1):settext(mcscoot[i]()) + end + end, + ScoreChangedMessageCommand = function(self) + self:queuecommand("Init") + end + } + end return t end From ac0e00c2b55ccf2c81da8b741dff8fd6be32a5e1 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:09:59 -0500 Subject: [PATCH 246/320] add tracks to net evaldata --- Themes/Til Death/BGAnimations/offsetplot.lua | 1 + src/NetworkSyncManager.cpp | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Themes/Til Death/BGAnimations/offsetplot.lua b/Themes/Til Death/BGAnimations/offsetplot.lua index 0d74f6015c..fa28529435 100644 --- a/Themes/Til Death/BGAnimations/offsetplot.lua +++ b/Themes/Til Death/BGAnimations/offsetplot.lua @@ -115,6 +115,7 @@ local o = score = s dvt = score:GetOffsetVector() nrt = score:GetNoteRowVector() + ctt = score:GetTrackVector() for i = 1, #nrt do wuab[i] = td:GetElapsedTimeFromNoteRow(nrt[i]) end diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 3bf923131f..6841ef4088 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -750,8 +750,10 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) json& replay = score["replay"]; json& jOffsets = replay["offsets"]; json& jNoterows = replay["noterows"]; + json& jTracks = replay["tracks"]; vector offsets; vector noterows; + vector tracks; for (json::iterator offsetIt = jOffsets.begin(); offsetIt != jOffsets.end(); ++offsetIt) @@ -760,8 +762,13 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) noterowIt != jNoterows.end(); ++noterowIt) noterows.emplace_back(noterowIt->get()); + for (json::iterator trackIt = jTracks.begin(); + trackIt != jTracks.end(); + ++trackIt) + noterows.emplace_back(trackIt->get()); hs.SetOffsetVector(offsets); hs.SetNoteRowVector(noterows); + hs.SetTrackVector(tracks); } catch (exception e) { } // No replay data for this score, its still valid result.nameStr = (*payload)["name"].get(); @@ -1238,16 +1245,20 @@ ETTProtocol::ReportHighScore(HighScore* hs, PlayerStageStats& pss) payload["topscore"] = hs->GetTopScore(); payload["uuid"] = hs->GetMachineGuid(); payload["hash"] = hs->GetValidationKey(ValidationKey_Brittle); - auto offsets = pss.GetOffsetVector(); - auto noterows = pss.GetNoteRowVector(); + auto& offsets = pss.GetOffsetVector(); + auto& noterows = pss.GetNoteRowVector(); + auto& tracks = pss.GetTrackVector(); if (offsets.size() > 0) { payload["replay"] = json::object(); payload["replay"]["noterows"] = json::array(); payload["replay"]["offsets"] = json::array(); + payload["replay"]["tracks"] = json::array(); for (size_t i = 0; i < noterows.size(); i++) payload["replay"]["noterows"].push_back(noterows[i]); for (size_t i = 0; i < offsets.size(); i++) payload["replay"]["offsets"].push_back(offsets[i]); + for (size_t i = 0; i < offsets.size(); i++) + payload["replay"]["tracks"].push_back(tracks[i]); } Send(j); } From ebee9f56dbee4b44c007b6879c9c232d978c6265 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:18:19 -0500 Subject: [PATCH 247/320] rescoring in mp is horribly broken, disable for now --- Themes/Til Death/metrics.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Themes/Til Death/metrics.ini b/Themes/Til Death/metrics.ini index ef7f1552d2..330564b19e 100644 --- a/Themes/Til Death/metrics.ini +++ b/Themes/Til Death/metrics.ini @@ -570,9 +570,9 @@ ComboGraphP2OffCommand= [ScreenNetEvaluation] # judge changer listener i guess CodeNames="ResetJudge,PrevJudge,NextJudge,ToggleHands" -CodeResetJudge="MenuUp" -CodeNextJudge="EffectUp" -CodePrevJudge="EffectDown" +#CodeResetJudge="MenuUp" +#CodeNextJudge="EffectUp" +#CodePrevJudge="EffectDown" CodeToggleHands="MenuDown" From ce2a40ba9ba5c7bc8f56b2d3e00d66070c4e7b4e Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:18:40 -0500 Subject: [PATCH 248/320] dont keep unloading replaydata when doing anything with it --- Themes/Til Death/BGAnimations/offsetplot.lua | 1 - src/HighScore.cpp | 11 ----------- 2 files changed, 12 deletions(-) diff --git a/Themes/Til Death/BGAnimations/offsetplot.lua b/Themes/Til Death/BGAnimations/offsetplot.lua index fa28529435..16caa8aa81 100644 --- a/Themes/Til Death/BGAnimations/offsetplot.lua +++ b/Themes/Til Death/BGAnimations/offsetplot.lua @@ -55,7 +55,6 @@ local o = nrt = pss:GetNoteRowVector() ctt = pss:GetTrackVector() -- column information for each offset ntt = pss:GetTapNoteTypeVector() -- notetype information (we use this to handle mine hits differently- currently that means not displaying them) - pss:UnloadReplayData() -- force unload replaydata in memory after loading it (not sure if i should allow this but i don't trust deconstructors) -mina elseif name == "ScreenScoreTabOffsetPlot" then -- loaded from scoretab not eval so we need to read from disk and adjust plot display plotWidth, plotHeight = SCREEN_WIDTH, SCREEN_WIDTH * 0.3 self:xy(SCREEN_CENTER_X, SCREEN_CENTER_Y) diff --git a/src/HighScore.cpp b/src/HighScore.cpp index 717554c2e3..89da99f005 100644 --- a/src/HighScore.cpp +++ b/src/HighScore.cpp @@ -1788,7 +1788,6 @@ HighScore::RescoreToWifeJudgeDuringLoad(int x) } float o = p / pmax; - UnloadReplayData(); return o; } @@ -2043,8 +2042,6 @@ class LunaHighScore : public Luna for (size_t i = 0; i < v.size(); ++i) v[i] = v[i] * 1000; LuaHelpers::CreateTableFromArray(v, L); - if (!loaded) - p->UnloadReplayData(); } else lua_pushnil(L); return 1; @@ -2055,11 +2052,7 @@ class LunaHighScore : public Luna auto* v = &(p->GetNoteRowVector()); bool loaded = v->size() > 0; if (loaded || p->LoadReplayData()) { - if (!loaded) - v = &(p->GetNoteRowVector()); LuaHelpers::CreateTableFromArray((*v), L); - if (!loaded) - p->UnloadReplayData(); } else lua_pushnil(L); return 1; @@ -2073,8 +2066,6 @@ class LunaHighScore : public Luna if (!loaded) v = &(p->GetTrackVector()); LuaHelpers::CreateTableFromArray((*v), L); - if (!loaded) - p->UnloadReplayData(); } else lua_pushnil(L); return 1; @@ -2088,8 +2079,6 @@ class LunaHighScore : public Luna if (!loaded) v = &(p->GetTapNoteTypeVector()); LuaHelpers::CreateTableFromArray((*v), L); - if (!loaded) - p->UnloadReplayData(); } else lua_pushnil(L); return 1; From d9c1ed694e2657c171e508362ef3796b53dea577 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:18:53 -0500 Subject: [PATCH 249/320] technically this isn't required however for consistency's sake --- src/NetworkSyncManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 6841ef4088..ab3a7ace76 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -1257,7 +1257,7 @@ ETTProtocol::ReportHighScore(HighScore* hs, PlayerStageStats& pss) payload["replay"]["noterows"].push_back(noterows[i]); for (size_t i = 0; i < offsets.size(); i++) payload["replay"]["offsets"].push_back(offsets[i]); - for (size_t i = 0; i < offsets.size(); i++) + for (size_t i = 0; i < tracks.size(); i++) payload["replay"]["tracks"].push_back(tracks[i]); } Send(j); From 81dc77b385f3a2c32f043f8904bb96a120ce4945 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:19:08 -0500 Subject: [PATCH 250/320] judgment string includes combo, reconstruct it without combo here --- Themes/Til Death/BGAnimations/MPscoreboard.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/MPscoreboard.lua b/Themes/Til Death/BGAnimations/MPscoreboard.lua index 2f2ab294a8..686fce2ec0 100644 --- a/Themes/Til Death/BGAnimations/MPscoreboard.lua +++ b/Themes/Til Death/BGAnimations/MPscoreboard.lua @@ -227,7 +227,14 @@ local function scoreitem(pn, i) self:xy(framex + 10, framey + 20 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.35) end, UpdateNetScoreCommand = function(self) - self:settext(multiscores[i].highscore:GetJudgmentString()) + self:settextf("%d / %d / %d / %d / %d / %d", + multiscores[i].highscore:GetTapNoteScore("TapNoteScore_W1"), + multiscores[i].highscore:GetTapNoteScore("TapNoteScore_W2"), + multiscores[i].highscore:GetTapNoteScore("TapNoteScore_W3"), + multiscores[i].highscore:GetTapNoteScore("TapNoteScore_W4"), + multiscores[i].highscore:GetTapNoteScore("TapNoteScore_W5"), + multiscores[i].highscore:GetTapNoteScore("TapNoteScore_Miss") + ) end }, LoadFont("Common normal") .. From 66e141d7831cfc3f743d894bbd91b4fa1f656d99 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:19:18 -0500 Subject: [PATCH 251/320] typo --- src/DownloadManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 21f7ccbfa0..152f25ed61 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1150,7 +1150,7 @@ DownloadManager::UpdateOnlineScoreReplayData(string& sk, auto hs = SCOREMAN->GetScoresByKey().at(sk); CURL* curlHandle = initCURLHandle(true); - string url = serverURL.Get() + "/updatereplaydata/"; + string url = serverURL.Get() + "/updatereplaydata"; curl_httppost* form = nullptr; curl_httppost* lastPtr = nullptr; SetCURLFormPostField( From 09aa87b653dd5bc37e680ec4e9f239acce96eb02 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:25:37 -0500 Subject: [PATCH 252/320] add unloadallreplaydata wrapper --- src/ScoreManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScoreManager.h b/src/ScoreManager.h index 70fd7d73c5..3a6c787ddc 100644 --- a/src/ScoreManager.h +++ b/src/ScoreManager.h @@ -212,7 +212,7 @@ class ScoreManager void PurgeProfileScores( const string& profileID = PROFILEMAN->GetProfile(PLAYER_1)->m_sProfileID); - + void UnloadAllReplayData() { for (auto& s: AllScores) s->UnloadReplayData(); } bool camefromreplay = false; HighScore* tempscoreforonlinereplayviewing; From 151e9eadd58a75aa86d4684fa48aa7251e416e22 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:28:42 -0500 Subject: [PATCH 253/320] disable judge rescore on net eval this way instead --- .../ScreenNetEvaluation decorations.lua | 16 ++++++++-------- Themes/Til Death/metrics.ini | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua index 2b973b9a05..026e1230f9 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetEvaluation decorations.lua @@ -230,7 +230,7 @@ function scoreBoard(pn, position) local minesHit = pss:GetRadarPossible():GetValue("RadarCategory_Mines") - score:GetRadarValues():GetValue("RadarCategory_Mines") if enabledCustomWindows then - if params.Name == "PrevJudge" then + if params.Name == "LULLTHISWASPREVJUDGE" then judge = judge < 2 and #customWindows or judge - 1 customWindow = timingWindowConfig:get_data()[customWindows[judge]] self:settextf( @@ -238,7 +238,7 @@ function scoreBoard(pn, position) getRescoredCustomPercentage(dvt, customWindow, totalHolds, holdsHit, minesHit, totalTaps), customWindow.name ) - elseif params.Name == "NextJudge" then + elseif params.Name == "LULLTHISWASNEXTJUDGE" then judge = judge == #customWindows and 1 or judge + 1 customWindow = timingWindowConfig:get_data()[customWindows[judge]] self:settextf( @@ -247,14 +247,14 @@ function scoreBoard(pn, position) customWindow.name ) end - elseif params.Name == "PrevJudge" and judge > 1 then + elseif params.Name == "LULLTHISWASPREVJUDGE" and judge > 1 then judge = judge - 1 self:settextf( "%05.2f%% (%s)", getRescoredWifeJudge(dvt, judge, totalHolds - holdsHit, minesHit, totalTaps), "Wife J" .. judge ) - elseif params.Name == "NextJudge" and judge < 9 then + elseif params.Name == "LULLTHISWASNEXTJUDGE" and judge < 9 then judge = judge + 1 if judge == 9 then self:settextf( @@ -318,7 +318,7 @@ function scoreBoard(pn, position) self:zoomx(frameWidth * rescoreJudges[k] / (#devianceTable)) end, CodeMessageCommand = function(self, params) - if params.Name == "PrevJudge" or params.Name == "NextJudge" then + if params.Name == "LULLTHISWASPREVJUDGE" or params.Name == "LULLTHISWASNEXTJUDGE" then if enabledCustomWindows then self:finishtweening():decelerate(2):zoomx( frameWidth * getRescoredCustomJudge(dvt, customWindow.judgeWindows, k) / totalTaps @@ -346,7 +346,7 @@ function scoreBoard(pn, position) self:settext(getJudgeStrings(v)) end, CodeMessageCommand = function(self, params) - if enabledCustomWindows and (params.Name == "PrevJudge" or params.Name == "NextJudge") then + if enabledCustomWindows and (params.Name == "LULLTHISWASPREVJUDGE" or params.Name == "LULLTHISWASNEXTJUDGE") then self:settext(getCustomJudgeString(customWindow.judgeNames, k)) end if params.Name == "ResetJudge" then @@ -370,7 +370,7 @@ function scoreBoard(pn, position) self:queuecommand("Set") end, CodeMessageCommand = function(self, params) - if params.Name == "PrevJudge" or params.Name == "NextJudge" then + if params.Name == "LULLTHISWASPREVJUDGE" or params.Name == "LULLTHISWASNEXTJUDGE" then if enabledCustomWindows then self:settext(getRescoredCustomJudge(dvt, customWindow.judgeWindows, k)) else @@ -398,7 +398,7 @@ function scoreBoard(pn, position) self:settextf("(%03.2f%%)", pss:GetPercentageOfTaps(v) * 100) end, CodeMessageCommand = function(self, params) - if params.Name == "PrevJudge" or params.Name == "NextJudge" then + if params.Name == "LULLTHISWASPREVJUDGE" or params.Name == "LULLTHISWASNEXTJUDGE" then local rescoredJudge if enabledCustomWindows then rescoredJudge = getRescoredCustomJudge(dvt, customWindow.judgeWindows, k) diff --git a/Themes/Til Death/metrics.ini b/Themes/Til Death/metrics.ini index 330564b19e..ef7f1552d2 100644 --- a/Themes/Til Death/metrics.ini +++ b/Themes/Til Death/metrics.ini @@ -570,9 +570,9 @@ ComboGraphP2OffCommand= [ScreenNetEvaluation] # judge changer listener i guess CodeNames="ResetJudge,PrevJudge,NextJudge,ToggleHands" -#CodeResetJudge="MenuUp" -#CodeNextJudge="EffectUp" -#CodePrevJudge="EffectDown" +CodeResetJudge="MenuUp" +CodeNextJudge="EffectUp" +CodePrevJudge="EffectDown" CodeToggleHands="MenuDown" From 54a0f9db0862cd317bfa95b1004cafb23f90e6eb Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:29:08 -0500 Subject: [PATCH 254/320] add replayunloader to the garbage collection --- src/RageTextureManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index 56f32ebf36..ef30d3c37b 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -31,6 +31,7 @@ #include "Screen.h" #include "ScreenManager.h" #include "arch/MovieTexture/MovieTexture.h" +#include "ScoreManager.h" #include @@ -351,6 +352,10 @@ RageTextureManager::GarbageCollect(GCType type) if (bDeleteThis) DeleteTexture(t); } + + // this may actually the best place for this -mina + LOG->Trace("Unloading replaydata."); + SCOREMAN->UnloadAllReplayData(); } void From e658b6763e1a07fc82ec848f47f22edf5c6bde7f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:37:04 -0500 Subject: [PATCH 255/320] add new screentype to prevent gc from unloading replays at eval --- src/RageTextureManager.cpp | 3 ++- src/Screen.cpp | 1 + src/Screen.h | 1 + src/ScreenEvaluation.h | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index ef30d3c37b..8d62c7edeb 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -67,7 +67,8 @@ RageTextureManager::Update(float fDeltaTime) static RageTimer garbageCollector; if (garbageCollector.PeekDeltaTime() >= 30.0f) { if ((SCREENMAN != nullptr) && (SCREENMAN->GetTopScreen() != nullptr) && - SCREENMAN->GetTopScreen()->GetScreenType() != gameplay) { + SCREENMAN->GetTopScreen()->GetScreenType() != gameplay && + SCREENMAN->GetTopScreen()->GetScreenType() != evaluation) { DoDelayedDelete(); garbageCollector.Touch(); } diff --git a/src/Screen.cpp b/src/Screen.cpp index a7c39d965a..dcc16c97dc 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -19,6 +19,7 @@ static const char* ScreenTypeNames[] = { "Attract", "GameMenu", "Gameplay", + "Evaluation", "SystemMenu", }; XToString(ScreenType); diff --git a/src/Screen.h b/src/Screen.h index 08f001d9cd..7ac55a482f 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -41,6 +41,7 @@ enum ScreenType game_menu, /**< The menu screens, where options can be set before playing. */ gameplay, /**< The gameplay screen, where the actual game takes place. */ + evaluation, system_menu, /**< The system/operator menu, where special options are set. */ NUM_ScreenType, /**< The number of screen types. */ diff --git a/src/ScreenEvaluation.h b/src/ScreenEvaluation.h index a56b504a0d..d3cdf09237 100644 --- a/src/ScreenEvaluation.h +++ b/src/ScreenEvaluation.h @@ -54,7 +54,7 @@ class ScreenEvaluation : public ScreenWithMenuElements void Init() override; bool Input(const InputEventPlus& input) override; void HandleScreenMessage(ScreenMessage SM) override; - + ScreenType GetScreenType() const override { return evaluation; } bool MenuBack(const InputEventPlus& input) override; bool MenuStart(const InputEventPlus& input) override; void PushSelf(lua_State* L) override; From 3bb4757c58b15eef79011b427d17e89d3f78ec7d Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 13:52:26 -0500 Subject: [PATCH 256/320] oh ok then, i guess just pout --- src/NetworkSyncManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index ab3a7ace76..2134cf50a5 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -1245,9 +1245,9 @@ ETTProtocol::ReportHighScore(HighScore* hs, PlayerStageStats& pss) payload["topscore"] = hs->GetTopScore(); payload["uuid"] = hs->GetMachineGuid(); payload["hash"] = hs->GetValidationKey(ValidationKey_Brittle); - auto& offsets = pss.GetOffsetVector(); - auto& noterows = pss.GetNoteRowVector(); - auto& tracks = pss.GetTrackVector(); + const auto& offsets = pss.GetOffsetVector(); + const auto& noterows = pss.GetNoteRowVector(); + const auto& tracks = pss.GetTrackVector(); if (offsets.size() > 0) { payload["replay"] = json::object(); payload["replay"]["noterows"] = json::array(); From d338256dfb9e22aa90f012663be097102878a891 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 15:26:51 -0500 Subject: [PATCH 257/320] help nothing works --- .../ScreenNetRoom decorations/default.lua | 1 + .../Til Death/BGAnimations/_lobbyuserlist.lua | 102 ++++++++++++++++++ src/NetworkSyncManager.cpp | 28 ++--- 3 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 Themes/Til Death/BGAnimations/_lobbyuserlist.lua diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua index 61781600ad..e1e2fec71a 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua @@ -5,6 +5,7 @@ end t[#t + 1] = LoadActor("profile") t[#t + 1] = LoadActor("roomsearch") t[#t + 1] = LoadActor("tabs") +t[#t + 1] = LoadActor("../_lobbyuserlist") local g = Def.ActorFrame { diff --git a/Themes/Til Death/BGAnimations/_lobbyuserlist.lua b/Themes/Til Death/BGAnimations/_lobbyuserlist.lua new file mode 100644 index 0000000000..2294131ca2 --- /dev/null +++ b/Themes/Til Death/BGAnimations/_lobbyuserlist.lua @@ -0,0 +1,102 @@ +local usersZoom = 0.45 +local usersWidth = 50 +local usersWidthSmall = 25 +local usersWidthZoom = 50 * (1 / usersZoom) +local usersWidthSmallZoom = 25 * (1 / usersZoom) +local usersRowSize = 4 +local usersX = SCREEN_WIDTH / 4 +local usersY = SCREEN_TOP + 15 +local usersHeight = 10 + +local top = SCREENMAN:GetTopScreen() +local qty = 0 +local posit = getMainColor("positive") +local negat = getMainColor("negative") +local enable = getMainColor("enabled") +local r = + Def.ActorFrame { + BeginCommand = function(self) + self:queuecommand("Set") + end, + InitCommand = function(self) + self:queuecommand("Set") + end, + SetCommand = function(self) + top = SCREENMAN:GetTopScreen() + end, + UsersUpdateMessageCommand = function(self) + self:queuecommand("Set") + end +} + +local function userLabel(i) + local x = 0 + local y = 0 + if i <= usersRowSize then + x = (usersX) + (i * usersWidth) + y = usersY + usersHeight + elseif i <= usersRowSize * 2 then + x = (usersX) + ((i - usersRowSize) * usersWidth) + y = usersY + elseif i <= usersRowSize * 3 then + x = (usersX) + ((i - usersRowSize * 2) * usersWidth) + usersWidthSmall + y = usersY + usersHeight + elseif i <= usersRowSize * 4 then + x = (usersX) + ((i - usersRowSize * 3) * usersWidth) + usersWidthSmall + y = usersY + elseif i <= usersRowSize * 5 then + x = (usersX) + (usersRowSize * usersWidth) + usersWidthSmall * (i - usersRowSize * 4) + y = usersY + else + x = (usersX) + (usersRowSize * usersWidth) + usersWidthSmall * (i - usersRowSize * 5) + y = usersY + usersHeight + end + local aux = + LoadFont("Common Normal") .. + { + Name = i, + BeginCommand = function(self) + self:xy(x, y):zoom(usersZoom):diffuse(posit):queuecommand("Set") + end, + SetCommand = function(self) + local num = self:GetName() + 0 + lobbos = NSMAN:GetLobbyUserList() + qty = #lobbos + if num <= qty then + local str = "" + str = str .. top:GetUser(num) + self:settext(str) + if top:GetUserState(num) == 2 or top:GetUserState(num) == 1 then + self:diffuse(posit) + elseif top:GetUserState(num) == 4 then + self:diffuse(negat) + else + self:diffuse(enable) + end + else + self:settext("") + end + if qty < 9 then + self:maxwidth(usersWidthZoom) + else + self:maxwidth(usersWidthSmallZoom) + end + end, + PlayerJoinedMessageCommand = function(self) + self:queuecommand("Set") + end, + PlayerUnjoinedMessageCommand = function(self) + self:queuecommand("Set") + end, + UsersUpdateMessageCommand = function(self) + self:queuecommand("Set") + end + } + return aux +end + +for i = 1, 32 do + r[#r + 1] = userLabel(i) +end + +return r diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 2134cf50a5..93f12d3554 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -954,6 +954,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) for (auto& user : removedUsers) { NSMAN->lobbyuserlist.emplace_back(user.get()); } + SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); } break; case ettps_roomlist: { RoomData tmp; @@ -999,7 +1000,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) } } } - SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); + SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); } break; } } catch (exception e) { @@ -1859,6 +1860,17 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) } return 1; } + static int GetLobbyUserList(T* p, lua_State* L) + { + lua_newtable(L); + int i = 1; + for (auto& user : NSMAN->lobbyuserlist) { + lua_pushstring(L, user.c_str()); + lua_rawseti(L, -2, i); + i++; + } + return 1; + } LunaNetworkSyncManager() { ADD_METHOD(GetEvalScores); @@ -1870,6 +1882,7 @@ LuaFunction(IsSMOnlineLoggedIn, NSMAN->loggedIn) ADD_METHOD(Logout); ADD_METHOD(IsETTP); ADD_METHOD(GetCurrentRoomName); + ADD_METHOD(GetLobbyUserList); } }; @@ -1893,21 +1906,10 @@ class LunaChartRequest : public Luna lua_pushnumber(L, p->rate / 1000); return 1; } - static int GetLobbyUserList(T* p, lua_State* L) - { - lua_newtable(L); - int i = 1; - for (auto& user : NSMAN->lobbyuserlist) { - lua_pushstring(L, user.c_str()); - lua_rawseti(L, -2, i); - i++; - } - return 1; - } + LunaChartRequest() { ADD_METHOD(GetChartkey); - ADD_METHOD(GetLobbyUserList); ADD_METHOD(GetUser); ADD_METHOD(GetRate); } From 49baed25be1eaf35459a5178f5ecbccce99f2c83 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 16:52:59 -0500 Subject: [PATCH 258/320] verbosity check frame dimensions warn and minor cleanup --- src/RageBitmapTexture.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/RageBitmapTexture.cpp b/src/RageBitmapTexture.cpp index 852fc8b826..09ac69940e 100644 --- a/src/RageBitmapTexture.cpp +++ b/src/RageBitmapTexture.cpp @@ -1,4 +1,4 @@ -#include "global.h" +#include "global.h" #include "RageBitmapTexture.h" #include "RageDisplay.h" #include "RageLog.h" @@ -12,9 +12,10 @@ #include "RageUtil.h" #include "StepMania.h" #include "arch/Dialog/Dialog.h" +#include "PrefsManager.h" static void -GetResolutionFromFileName(RString sPath, int& iWidth, int& iHeight) +GetResolutionFromFileName(RString& sPath, int& iWidth, int& iHeight) { /* Match: * Foo (res 512x128).png @@ -76,7 +77,7 @@ RageBitmapTexture::Create() /* Load the image into a RageSurface. */ RString error; - RageSurface* pImg = NULL; + RageSurface* pImg = nullptr; if (actualID.filename == TEXTUREMAN->GetScreenTextureID().filename) { pImg = TEXTUREMAN->GetScreenSurface(); } else { @@ -84,14 +85,14 @@ RageBitmapTexture::Create() } /* Tolerate corrupt/unknown images. */ - if (pImg == NULL) { + if (pImg == nullptr) { RString warning = ssprintf("RageBitmapTexture: Couldn't load %s: %s", actualID.filename.c_str(), error.c_str()); LOG->Warn("%s", warning.c_str()); Dialog::OK(warning, "missing_texture"); pImg = RageSurfaceUtils::MakeDummySurface(64, 64); - ASSERT(pImg != NULL); + ASSERT(pImg != nullptr); } if (actualID.bHotPinkColorKey) @@ -316,7 +317,7 @@ RageBitmapTexture::Create() bRunCheck = false; } - if (bRunCheck) { + if (bRunCheck && PREFSMAN->m_verbose_log > 1) { float fFrameWidth = this->GetSourceWidth() / static_cast(this->GetFramesWide()); float fFrameHeight = this->GetSourceHeight() / From 58de9442a9a8801c4012706ec9fbc4e82aea32ad Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 17:20:11 -0500 Subject: [PATCH 259/320] code maint --- src/RageTextureManager.cpp | 28 +++++++++------------------- src/RageTextureManager.h | 2 +- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index 8d62c7edeb..df0f723677 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -36,7 +36,7 @@ #include RageTextureManager* TEXTUREMAN = - NULL; // global and accessible from anywhere in our program + nullptr; // global and accessible from anywhere in our program namespace { map m_mapPathToTexture; @@ -74,9 +74,8 @@ RageTextureManager::Update(float fDeltaTime) } } - FOREACHM(RageTextureID, RageTexture*, m_textures_to_update, i) - { - RageTexture* pTexture = i->second; + for (auto& id : m_textures_to_update) { + RageTexture* pTexture = id.second; pTexture->Update(fDeltaTime); } } @@ -108,9 +107,7 @@ RageTextureManager::RegisterTexture(RageTextureID ID, RageTexture* pTexture) /* Make sure we don't already have a texture with this ID. If we do, the * caller should have used it. */ - std::map::iterator p = - m_mapPathToTexture.find(ID); - if (p != m_mapPathToTexture.end()) { + if (m_mapPathToTexture.count(ID) == 1) { /* Oops, found the texture. */ RageException::Throw("Custom texture \"%s\" already registered!", ID.filename.c_str()); @@ -234,7 +231,7 @@ RageTextureManager::VolatileTexture(const RageTextureID& ID) void RageTextureManager::UnloadTexture(RageTexture* t) { - if (t == NULL) + if (t == nullptr) return; t->m_iRefCount--; @@ -314,14 +311,8 @@ RageTextureManager::GarbageCollect(GCType type) if (PREFSMAN->m_verbose_log > 1) LOG->Trace("Performing texture garbage collection."); - for (std::map::iterator i = - m_mapPathToTexture.begin(); - i != m_mapPathToTexture.end();) { - std::map::iterator j = i; - i++; - - RString sPath = j->first.filename; - RageTexture* t = j->second; + for (auto ID : m_mapPathToTexture) { + RageTexture* t = ID.second; if (t->m_iRefCount) continue; /* Can't unload textures that are still referenced. */ @@ -368,9 +359,8 @@ RageTextureManager::ReloadAll() * ton of cached data that we're not necessarily going to use. */ DoDelayedDelete(); - FOREACHM(RageTextureID, RageTexture*, m_mapPathToTexture, i) - { - i->second->Reload(); + for (auto ID : m_mapPathToTexture) { + ID.second->Reload(); } EnableOddDimensionWarning(); diff --git a/src/RageTextureManager.h b/src/RageTextureManager.h index 9afcf21af8..a34e057233 100644 --- a/src/RageTextureManager.h +++ b/src/RageTextureManager.h @@ -1,4 +1,4 @@ -/* RageTextureManager - Interface for loading textures. */ +/* RageTextureManager - Interface for loading textures. */ #ifndef RAGE_TEXTURE_MANAGER_H #define RAGE_TEXTURE_MANAGER_H From dd031224e895838766fee22fc81aa4cdb4f01101 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 17:51:11 -0500 Subject: [PATCH 260/320] dlman maint + fix updateonlinereplay --- src/DownloadManager.cpp | 155 ++++++++++++---------------------------- src/DownloadManager.h | 40 ++++++----- 2 files changed, 65 insertions(+), 130 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 152f25ed61..93bdc571af 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -713,7 +713,7 @@ DownloadManager::LoggedIn() } void -DownloadManager::AddFavorite(string chartkey) +DownloadManager::AddFavorite(const string& chartkey) { string req = "user/" + DLMAN->sessionUser + "/favorites"; DLMAN->favorites.emplace_back(chartkey); @@ -724,7 +724,7 @@ DownloadManager::AddFavorite(string chartkey) } void -DownloadManager::RemoveFavorite(string chartkey) +DownloadManager::RemoveFavorite(const string& chartkey) { auto it = std::find(DLMAN->favorites.begin(), DLMAN->favorites.end(), chartkey); @@ -741,7 +741,7 @@ DownloadManager::RemoveFavorite(string chartkey) // we could pass scoregoal objects instead..? -mina void -DownloadManager::RemoveGoal(string chartkey, float wife, float rate) +DownloadManager::RemoveGoal(const string& chartkey, float wife, float rate) { string req = "user/" + DLMAN->sessionUser + "/goals/" + chartkey + "/" + to_string(wife) + "/" + to_string(rate); @@ -754,10 +754,10 @@ DownloadManager::RemoveGoal(string chartkey, float wife, float rate) } void -DownloadManager::AddGoal(string chartkey, +DownloadManager::AddGoal(const string& chartkey, float wife, float rate, - DateTime timeAssigned) + DateTime& timeAssigned) { string req = "user/" + DLMAN->sessionUser + "/goals"; auto done = [](HTTPRequest& req, CURLMsg*) { @@ -773,12 +773,12 @@ DownloadManager::AddGoal(string chartkey, } void -DownloadManager::UpdateGoal(string chartkey, +DownloadManager::UpdateGoal(const string& chartkey, float wife, float rate, bool achieved, - DateTime timeAssigned, - DateTime timeAchieved) + DateTime& timeAssigned, + DateTime& timeAchieved) { string doot = "0000:00:00 00:00:00"; if (achieved) @@ -965,10 +965,10 @@ DownloadManager::UploadScoreWithReplayData(HighScore* hs) curl_httppost* lastPtr = nullptr; SetCURLPOSTScore(curlHandle, form, lastPtr, hs); string replayString; - vector offsets = hs->GetOffsetVector(); - vector columns = hs->GetTrackVector(); - vector types = hs->GetTapNoteTypeVector(); - vector rows = hs->GetNoteRowVector(); + const auto& offsets = hs->GetOffsetVector(); + const auto& columns = hs->GetTrackVector(); + const auto& types = hs->GetTapNoteTypeVector(); + const auto& rows = hs->GetNoteRowVector(); if (offsets.size() > 0) { replayString = "["; vector& timestamps = hs->timeStamps; @@ -1039,16 +1039,16 @@ DownloadManager::UploadScoreWithReplayData(HighScore* hs) return; } void // not tested exhaustively -mina -DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, +DownloadManager::UploadScoreWithReplayDataFromDisk(const string& sk, function callback) { if (!LoggedIn()) return; - auto doot = SCOREMAN->GetScoresByKey(); - auto hs = doot[sk]; + auto* hs = SCOREMAN->GetScoresByKey().at(sk); if (!hs->LoadReplayData()) - return; + if (callback) + callback(); CURL* curlHandle = initCURLHandle(true); string url = serverURL.Get() + "/score"; @@ -1056,11 +1056,10 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, curl_httppost* lastPtr = nullptr; SetCURLPOSTScore(curlHandle, form, lastPtr, hs); string replayString; - vector offsets = hs->GetOffsetVector(); - vector columns = hs->GetTrackVector(); - vector types = hs->GetTapNoteTypeVector(); - auto& rows = hs->GetNoteRowVector(); - + const auto& offsets = hs->GetOffsetVector(); + const auto& columns = hs->GetTrackVector(); + const auto& types = hs->GetTapNoteTypeVector(); + const auto& rows = hs->GetNoteRowVector(); if (offsets.size() > 0) { replayString = "["; auto steps = SONGMAN->GetStepsByChartkey(hs->GetChartKey()); @@ -1142,15 +1141,15 @@ DownloadManager::UploadScoreWithReplayDataFromDisk(string sk, return; } void // for online replay viewing accuracy -mina -DownloadManager::UpdateOnlineScoreReplayData(string& sk, +DownloadManager::UpdateOnlineScoreReplayData(const string& sk, function callback) { if (!LoggedIn()) return; - auto hs = SCOREMAN->GetScoresByKey().at(sk); + auto* hs = SCOREMAN->GetScoresByKey().at(sk); CURL* curlHandle = initCURLHandle(true); - string url = serverURL.Get() + "/updatereplaydata"; + string url = serverURL.Get() + "/updateReplayData"; curl_httppost* form = nullptr; curl_httppost* lastPtr = nullptr; SetCURLFormPostField( @@ -1158,9 +1157,8 @@ DownloadManager::UpdateOnlineScoreReplayData(string& sk, string toSend = "["; hs->LoadReplayData(); auto& rows = hs->GetNoteRowVector(); - for (auto& row : rows) { + for (auto& row : rows) toSend += to_string(row) + ","; - } toSend = toSend.substr(0, toSend.size() - 1); // remove , toSend += "]"; SetCURLFormPostField(curlHandle, form, lastPtr, "replay", toSend); @@ -1187,7 +1185,7 @@ DownloadManager::UpdateOnlineScoreReplayData(string& sk, DLMAN->sessionPass, [hs](bool logged) { if (logged) { - DLMAN->UploadScoreWithReplayDataFromDisk( + DLMAN->UpdateOnlineScoreReplayData( hs->GetScoreKey()); } }); @@ -1376,73 +1374,6 @@ DownloadManager::SendRequestToURL( } return req; } - -float -mythicalmathymathsProbablyUnderratedness(string chartkey) -{ - auto& onlineScores = DLMAN->chartLeaderboards[chartkey]; - - float dsum = 0.f; - int num = 4; - for (auto& s : onlineScores) { - float adjRating = s.playerRating - 1.f; - if (s.playerRating > 1.f && s.SSRs[Skill_Overall] > 1.f && - abs(s.playerRating - s.SSRs[Skill_Overall]) < 7.5f) { - if (s.playerRating > s.SSRs[Skill_Overall]) { - float diff = adjRating - s.SSRs[Skill_Overall]; - dsum += diff; - } else { - float mcdoot = s.SSRs[Skill_Overall] + 1.f - s.playerRating; - dsum -= mcdoot * mcdoot; - } - ++num; - } - } - return dsum / num; -} - -float -overratedness(string chartkey) -{ - auto& onlineScores = DLMAN->chartLeaderboards[chartkey]; - vector values; - float offset = 5.f; - float dsum = 0.f; - int num = onlineScores.size(); - if (num == 0) - return 0.0f; - - for (auto& s : onlineScores) { - if (s.playerRating > 1.f && s.SSRs[Skill_Overall] > 1.f) { - float adjrating = s.playerRating * 1.026f; - float value = static_cast( - (2.0 / erfc(0.1 * (s.SSRs[Skill_Overall] - adjrating)))); - if (s.SSRs[Skill_Overall] - s.playerRating > 40) - value = 100.f; - if (value < 0) - value = 0.f; - values.emplace_back(value); - dsum += value; - } - } - - float zeeaverage = dsum / num; - - float overratedness = (dsum - offset) / num; - - overratedness /= zeeaverage; - overratedness -= 1.5f; - - float multiplier = 1.f - overratedness; - float mcdootMin = 1.f; - if (multiplier < mcdootMin - 0.2f) - multiplier = mcdootMin - 0.2f; - - float nerfE = (4.f * mcdootMin + multiplier) / 5.f; - nerfE = min(1.f, nerfE); - return overratedness; -} - void DownloadManager::RefreshCountryCodes() { @@ -1471,11 +1402,11 @@ DownloadManager::RefreshCountryCodes() } void -DownloadManager::RequestReplayData(string scoreid, +DownloadManager::RequestReplayData(const string& scoreid, int userid, - string username, - string chartkey, - LuaReference callback) + const string& username, + const string& chartkey, + LuaReference& callback) { auto done = [scoreid, callback, userid, username, chartkey]( HTTPRequest& req, CURLMsg*) { @@ -1559,7 +1490,7 @@ DownloadManager::RequestReplayData(string scoreid, } void -DownloadManager::RequestChartLeaderBoard(string chartkey, LuaReference ref) +DownloadManager::RequestChartLeaderBoard(const string& chartkey, LuaReference& ref) { auto done = [chartkey, ref](HTTPRequest& req, CURLMsg*) { vector& vec = DLMAN->chartLeaderboards[chartkey]; @@ -1723,14 +1654,14 @@ DownloadManager::RefreshCoreBundles() } vector -DownloadManager::GetCoreBundle(string whichoneyo) +DownloadManager::GetCoreBundle(const string& whichoneyo) { return bundles.count(whichoneyo) ? bundles[whichoneyo] : vector(); } void -DownloadManager::DownloadCoreBundle(string whichoneyo, bool mirror) +DownloadManager::DownloadCoreBundle(const string& whichoneyo, bool mirror) { auto bundle = GetCoreBundle(whichoneyo); sort(bundle.begin(), @@ -1894,7 +1825,6 @@ DownloadManager::OnLogin() DLMAN->UploadScores(); DLMAN->UpdateOnlineScoreReplayData(); } - DLMAN->UpdateOnlineScoreReplayData(); if (GAMESTATE->m_pCurSteps[PLAYER_1] != nullptr) DLMAN->RequestChartLeaderBoard( GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); @@ -1969,6 +1899,7 @@ UpdateReplayDataSequentially(deque toUpload) toUpload.pop_front(); auto& hs = (*it); DLMAN->UpdateOnlineScoreReplayData(hs->GetScoreKey(), [hs, toUpload]() { + hs->AddUploadedServer("nru"); UpdateReplayDataSequentially(toUpload); }); } @@ -1979,17 +1910,20 @@ DownloadManager::UpdateOnlineScoreReplayData() { if (!LoggedIn()) return false; - auto scores = SCOREMAN->GetAllPBPtrs(); + // we dont care if the chart is loaded for this function, only that there is + // a score that is already uploaded and already has replaydata, and that the + // source data is on disk to update it -mina + auto& scores = SCOREMAN->GetAllScores(); deque toUpload; - for (auto& vec : scores) { - for (auto& scorePtr : vec) { - auto ts = scorePtr->GetTopScore(); + for (auto& scorePtr : scores) { + auto ts = scorePtr->GetTopScore(); // still need to do this? if ((ts == 1 || ts == 2) ){ - if (scorePtr->HasReplayData()) + if (scorePtr->HasReplayData() && + scorePtr->IsUploadedToServer(serverURL.Get()) && + !scorePtr->IsUploadedToServer("nru")) toUpload.emplace_back(scorePtr); } } - } UpdateReplayDataSequentially(toUpload); return true; } @@ -2009,8 +1943,7 @@ uploadSequentially(deque toUpload) return; } bool -DownloadManager::UploadScores() // keeping in case we want to use this later - // -mina +DownloadManager::UploadScores() { if (!LoggedIn()) return false; @@ -2046,7 +1979,7 @@ DownloadManager::GetSkillsetRating(Skillset ss) return static_cast(sessionRatings[ss]); } void -DownloadManager::RefreshPackList(string url) +DownloadManager::RefreshPackList(const string& url) { if (url == "") return; diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 802eee4955..3d75e9f035 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -201,22 +201,22 @@ class DownloadManager map> topScores; bool LoggedIn(); - void AddFavorite(string chartkey); - void RemoveFavorite(string chartkey); + void AddFavorite(const string& chartkey); + void RemoveFavorite(const string& chartkey); void RefreshFavourites(); vector favorites; - void AddGoal(string chartkey, + void AddGoal(const string& chartkey, float wife, float rate, - DateTime timeAssigned); - void UpdateGoal(string chartkey, + DateTime& timeAssigned); + void UpdateGoal(const string& chartkey, float wife, float rate, bool achieved, - DateTime timeAssigned, - DateTime timeAchieved); - void RemoveGoal(string chartkey, float wife, float rate); + DateTime& timeAssigned, + DateTime& timeAchieved); + void RemoveGoal(const string& chartkey, float wife, float rate); void EndSessionIfExists(); // Calls EndSession if logged in void EndSession(); // Sends session destroy request @@ -228,7 +228,7 @@ class DownloadManager bool UploadScores(); // Uploads all scores not yet uploaded to current bool UpdateOnlineScoreReplayData(); // attempts updates existing replaydata // server (Async, 1 request per score) - void RefreshPackList(string url); + void RefreshPackList(const string& url); void init(); Download* DownloadAndInstallPack(const string& url, string filename = ""); @@ -248,9 +248,11 @@ class DownloadManager void UploadScoreWithReplayData(HighScore* hs); void UploadScoreWithReplayDataFromDisk( - string sk, + const string& sk, + function callback = function()); + void UpdateOnlineScoreReplayData( + const string& sk, function callback = function()); - void UpdateOnlineScoreReplayData(string& sk, function callback); void UploadScore(HighScore* hs); bool ShouldUploadScores(); @@ -278,21 +280,21 @@ class DownloadManager bool currentrateonly = false; bool topscoresonly = true; void RefreshCountryCodes(); - void RequestReplayData(string scorekey, + void RequestReplayData(const string& scorekey, int userid, - string username, - string chartkey, - LuaReference callback = LuaReference()); - void RequestChartLeaderBoard(string chartkey, - LuaReference ref = LuaReference()); + const string& username, + const string& chartkey, + LuaReference& callback = LuaReference()); + void RequestChartLeaderBoard(const string& chartkey, + LuaReference& ref = LuaReference()); void RefreshUserData(); string countryCode; void RefreshUserRank(); void RefreshTop25(Skillset ss); - void DownloadCoreBundle(string whichoneyo, bool mirror = false); + void DownloadCoreBundle(const string& whichoneyo, bool mirror = false); map> bundles; void RefreshCoreBundles(); - vector GetCoreBundle(string whichoneyo); + vector GetCoreBundle(const string& whichoneyo); OnlineTopScore GetTopSkillsetScore(unsigned int rank, Skillset ss, bool& result); From 6e0ae32e44fe0eb05697013e6a26fbe43df48cbb Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 1 Dec 2018 18:10:56 -0600 Subject: [PATCH 261/320] Fix song search stopping song selection in multi --- .../ScreenSelectMusic decorations/songsearch.lua | 6 ++++++ src/ScreenNetSelectMusic.cpp | 2 ++ 2 files changed, 8 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua index 49f7a6c15f..4ef3e85bf3 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua @@ -72,6 +72,12 @@ local t = TabChangedMessageCommand = function(self) self:queuecommand("Set") end, + MultiSongPickedMessageCommand = function(self) + lastsearchstring = "" + searchstring = "" + MESSAGEMAN:Broadcast("UpdateString") + whee:SongSearch(lastsearchstring) + end, LoadFont("Common Large") .. { InitCommand = function(self) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index eb7b6ca646..a23bf43a5f 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -162,6 +162,7 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) } } else if (SM == ETTP_StartChart) { if (NSMAN->song != nullptr) { + MESSAGEMAN->Broadcast("MultiSongPicked"); GAMESTATE->m_pCurSong.Set(NSMAN->song); if (NSMAN->steps != nullptr) { GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); @@ -187,6 +188,7 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) } } else if (SM == ETTP_SelectChart) { if (NSMAN->song != nullptr) { + MESSAGEMAN->Broadcast("MultiSongPicked"); GAMESTATE->m_pCurSong.Set(NSMAN->song); if (NSMAN->steps != nullptr) { GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); From c317ef96d46489a73a4472991af3338781d8d02f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sat, 1 Dec 2018 17:51:11 -0500 Subject: [PATCH 262/320] dlman maint + fix updateonlinereplay --- src/DownloadManager.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 93bdc571af..83df6568b2 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -301,7 +301,7 @@ CURLFormPostField(CURL* curlHandle, { curl_formadd(&form, &lastPtr, - CURLFORM_COPYNAME, + CURLFORM_COPYNAME, field, CURLFORM_COPYCONTENTS, value, @@ -1954,8 +1954,7 @@ DownloadManager::UploadScores() auto ts = scorePtr->GetTopScore(); if ((ts == 1 || ts == 2) && !scorePtr->IsUploadedToServer(serverURL.Get())) { - if (scorePtr->HasReplayData()) // we should remove this check - // maybe -mina + if (scorePtr->HasReplayData()) toUpload.emplace_back(scorePtr); } } From 0e6ef97ddb6f3908d37d046ec59ab764e03111ab Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 1 Dec 2018 20:37:39 -0600 Subject: [PATCH 263/320] Censor password entry screens for multi rooms --- src/ScreenNetRoom.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ScreenNetRoom.cpp b/src/ScreenNetRoom.cpp index 93347fa1d5..4dc252c2e4 100644 --- a/src/ScreenNetRoom.cpp +++ b/src/ScreenNetRoom.cpp @@ -100,8 +100,8 @@ ScreenNetRoom::HandleScreenMessage(const ScreenMessage SM) } else if (SM == SM_BackFromRoomDesc) { if (!ScreenTextEntry::s_bCancelledLast) { m_newRoomDesc = ScreenTextEntry::s_sLastAnswer; - ScreenTextEntry::TextEntry( - SM_BackFromRoomPass, ENTER_ROOM_PASSWORD, "", 255); + ScreenTextEntry::Password( + SM_BackFromRoomPass, ENTER_ROOM_PASSWORD); } } else if (SM == SM_BackFromRoomPass) { if (!ScreenTextEntry::s_bCancelledLast) { @@ -145,8 +145,8 @@ ScreenNetRoom::SelectCurrent() if (rwd != nullptr) { if (rwd->m_iFlags % 2 != 0u || rwd->hasPassword) { m_sLastPickedRoom = rwd->m_sText; - ScreenTextEntry::TextEntry( - SM_BackFromReqPass, ENTER_ROOM_REQPASSWORD, "", 255); + ScreenTextEntry::Password( + SM_BackFromReqPass, ENTER_ROOM_REQPASSWORD); } else { NSMAN->EnterRoom(rwd->m_sText); } From b16c1d3a9c6b94e6a6e3d110cde1198d766ac345 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 1 Dec 2018 20:47:35 -0600 Subject: [PATCH 264/320] Make popular sort look like it works but it really doesnt --- src/MusicWheel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/MusicWheel.cpp b/src/MusicWheel.cpp index 2602681f5d..e4ce33db96 100644 --- a/src/MusicWheel.cpp +++ b/src/MusicWheel.cpp @@ -381,8 +381,9 @@ MusicWheel::GetSongList(vector& arraySongs, SortOrder so) SONGMAN->GetPreferredSortSongs(apAllSongs); break; case SORT_POPULARITY: - apAllSongs = SONGMAN->GetPopularSongs(); - break; + // todo: make this work -poco + //apAllSongs = SONGMAN->GetPopularSongs(); + //break; case SORT_GROUP: // if we're not using sections with a preferred song group, and // there is a group to load, only load those songs. -aj From cbda3e4620b4b7a4c77422cba48a1e95a4423724 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sat, 1 Dec 2018 20:58:25 -0600 Subject: [PATCH 265/320] Decensor username entry having this censored vs passwords being censored can cause confusion and result in you making an account with your pass as your username --- src/ScreenSMOnlineLogin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ScreenSMOnlineLogin.cpp b/src/ScreenSMOnlineLogin.cpp index 489a620407..0f37ea40b4 100644 --- a/src/ScreenSMOnlineLogin.cpp +++ b/src/ScreenSMOnlineLogin.cpp @@ -158,10 +158,10 @@ ScreenSMOnlineLogin::HandleScreenMessage(const ScreenMessage SM) NULL); } else { sLoginQuestion = "Enter username"; - ScreenTextEntry::Password(SM_UsernameDone, + ScreenTextEntry::TextEntry(SM_UsernameDone, NSMAN->loginResponse + "\n\n" + sLoginQuestion, - NULL); + "", 255); } } } else if (SM == SM_GoToNextScreen) { @@ -197,10 +197,10 @@ ScreenSMOnlineLogin::HandleScreenMessage(const ScreenMessage SM) SM_PasswordDone, sLoginQuestion, NULL); } else { sLoginQuestion = "Enter username"; - ScreenTextEntry::Password(SM_UsernameDone, + ScreenTextEntry::TextEntry(SM_UsernameDone, NSMAN->loginResponse + "\n\n" + sLoginQuestion, - NULL); + "", 255); } } return; From d4124498efe919e4df482a919b256c4825e64018 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 05:04:42 -0300 Subject: [PATCH 266/320] Try to fix clang compile --- src/DownloadManager.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 3d75e9f035..6b0acfd7b9 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -161,6 +161,8 @@ class OnlineScore bool HasReplayData() { return hasReplay; } }; +LuaReference EMPTY_REFERENCE; + class DownloadManager { public: @@ -284,9 +286,9 @@ class DownloadManager int userid, const string& username, const string& chartkey, - LuaReference& callback = LuaReference()); + LuaReference& callback = EMPTY_REFERENCE); void RequestChartLeaderBoard(const string& chartkey, - LuaReference& ref = LuaReference()); + LuaReference& ref = EMPTY_REFERENCE); void RefreshUserData(); string countryCode; void RefreshUserRank(); From 06c987c3c5fe00f3ec9ab99a41b3f341e609926a Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 05:05:29 -0300 Subject: [PATCH 267/320] Check if lua function isnt set or is nil before pushing --- src/DownloadManager.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 83df6568b2..bda1d79cdf 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1459,24 +1459,27 @@ DownloadManager::RequestReplayData(const string& scoreid, else it->hs.SetReplayType(2); } - auto L = LUA->Get(); - callback.PushSelf(L); - RString Error = - "Error running RequestChartLeaderBoard Finish Function: "; - lua_newtable(L); // dunno whats going on here -mina - for (unsigned i = 0; i < replayData.size(); ++i) { - auto& pair = replayData[i]; - lua_newtable(L); - lua_pushnumber(L, pair.first); - lua_rawseti(L, -2, 1); - lua_pushnumber(L, pair.second); - lua_rawseti(L, -2, 2); - lua_rawseti(L, -2, i + 1); + + if (!callback.IsNil() && callback.IsSet()) { + auto L = LUA->Get(); + callback.PushSelf(L); + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + lua_newtable(L); // dunno whats going on here -mina + for (unsigned i = 0; i < replayData.size(); ++i) { + auto& pair = replayData[i]; + lua_newtable(L); + lua_pushnumber(L, pair.first); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, pair.second); + lua_rawseti(L, -2, 2); + lua_rawseti(L, -2, i + 1); + } + it->hs.PushSelf(L); + LuaHelpers::RunScriptOnStack( + L, Error, 2, 0, true); // 2 args, 0 results + LUA->Release(L); } - it->hs.PushSelf(L); - LuaHelpers::RunScriptOnStack( - L, Error, 2, 0, true); // 2 args, 0 results - LUA->Release(L); } catch (exception e) { LOG->Trace( (string("Replay data request failed for") + scoreid + e.what()) From 589324ff5efa743cbfdeb195bb5487507bc087af Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 05:49:45 -0300 Subject: [PATCH 268/320] Actually fix clang --- src/DownloadManager.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 6b0acfd7b9..442a6eb3ac 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -161,11 +161,10 @@ class OnlineScore bool HasReplayData() { return hasReplay; } }; -LuaReference EMPTY_REFERENCE; - class DownloadManager { public: + static LuaReference EMPTY_REFERENCE = LuaReference(); DownloadManager(); ~DownloadManager(); map downloads; // Active downloads From 0af69fa4522c056426f5fbcc631a246025d3eabb Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 06:48:34 -0300 Subject: [PATCH 269/320] Actually actually fix clang --- src/DownloadManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 442a6eb3ac..0c38c678ba 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -164,7 +164,7 @@ class OnlineScore class DownloadManager { public: - static LuaReference EMPTY_REFERENCE = LuaReference(); + static constexpr LuaReference EMPTY_REFERENCE = LuaReference(); DownloadManager(); ~DownloadManager(); map downloads; // Active downloads From b52fa5a88eb547744bc58040aeaf0c4234e7c81c Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 06:54:42 -0300 Subject: [PATCH 270/320] Update DownloadManager.h --- src/DownloadManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 0c38c678ba..47951d76fb 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -164,7 +164,7 @@ class OnlineScore class DownloadManager { public: - static constexpr LuaReference EMPTY_REFERENCE = LuaReference(); + static const LuaReference EMPTY_REFERENCE = LuaReference(); DownloadManager(); ~DownloadManager(); map downloads; // Active downloads From 0b8386ea41f5ebae0833f992f634552062b1d695 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 07:09:15 -0300 Subject: [PATCH 271/320] Update DownloadManager.h --- src/DownloadManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 47951d76fb..8d240956ae 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -164,7 +164,7 @@ class OnlineScore class DownloadManager { public: - static const LuaReference EMPTY_REFERENCE = LuaReference(); + static const LuaReference EMPTY_REFERENCE; DownloadManager(); ~DownloadManager(); map downloads; // Active downloads From 4187ee0eeddc0223dd71f9f9f5fe73698f0c5b6b Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 07:09:47 -0300 Subject: [PATCH 272/320] Update DownloadManager.cpp --- src/DownloadManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index bda1d79cdf..b9bc5625e3 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -32,6 +32,7 @@ using json = nlohmann::json; #include #endif shared_ptr DLMAN = nullptr; +const LuaReference DownloadManager::EMPTY_REFERENCE = LuaReference(); static Preference maxDLPerSecond( "maximumBytesDownloadedPerSecond", From 52305413ab79647935a1297d1b81c5a7775bad5e Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 07:16:53 -0300 Subject: [PATCH 273/320] Update DownloadManager.h --- src/DownloadManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.h b/src/DownloadManager.h index 8d240956ae..85ae1a9485 100644 --- a/src/DownloadManager.h +++ b/src/DownloadManager.h @@ -164,7 +164,7 @@ class OnlineScore class DownloadManager { public: - static const LuaReference EMPTY_REFERENCE; + static LuaReference EMPTY_REFERENCE; DownloadManager(); ~DownloadManager(); map downloads; // Active downloads From 3f0c97c3bf6b04774afc3bdfb0fb1eb60a9cfbad Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sun, 2 Dec 2018 04:19:53 -0600 Subject: [PATCH 274/320] Prevent chat from showing up when not in multiplayer screens --- .../BGAnimations/ScreenChatOverlay overlay.lua | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index c07d667b7e..7b0f009088 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -68,15 +68,27 @@ chat.InitCommand = function(self) self:visible(false) end local isGameplay +local isInSinglePlayer chat.ScreenChangedMessageCommand = function(self) local s = SCREENMAN:GetTopScreen() if not s then return end + local oldScreen = currentScreen currentScreen = s:GetName() + + -- prevent the chat from showing in singleplayer because it can be annoying + if oldScreen ~= currentScreen and (currentScreen == "ScreenSelectMusic" or currentScreen == "ScreenTitleMenu" or currentScreen == "ScreenOptionsService") then + isInSinglePlayer = true + end + if string.sub(currentScreen, 1, 9) == "ScreenNet" and currentScreen ~= "ScreenNetSelectProfile" then + isInSinglePlayer = false + end + online = IsNetSMOnline() and IsSMOnlineLoggedIn(PLAYER_1) and NSMAN:IsETTP() isGameplay = (currentScreen == "ScreenGameplay" or currentScreen == "ScreenNetGameplay") - if isGameplay then + + if isGameplay or isInSinglePlayer then self:visible(false) show = false typing = false @@ -87,7 +99,7 @@ chat.ScreenChangedMessageCommand = function(self) 0.025 ) else - self:visible(online) + self:visible(online and not isInSinglePlayer) show = true end if currentScreen == "ScreenNetSelectMusic" then From 5a33963a52e4d3ae254e7a364406ff4340f9720d Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 07:43:05 -0300 Subject: [PATCH 275/320] Update DownloadManager.cpp --- src/DownloadManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index b9bc5625e3..7e73e56469 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -32,7 +32,7 @@ using json = nlohmann::json; #include #endif shared_ptr DLMAN = nullptr; -const LuaReference DownloadManager::EMPTY_REFERENCE = LuaReference(); +LuaReference DownloadManager::EMPTY_REFERENCE = LuaReference(); static Preference maxDLPerSecond( "maximumBytesDownloadedPerSecond", From ffee38b3b06a891766094163cdf32bf7db1840af Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 07:43:43 -0300 Subject: [PATCH 276/320] Fix setTimeout --- src/Actor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index dcfef0489a..4f4e1b5bb0 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -959,10 +959,10 @@ Actor::UpdateInternal(float delta_time) } } // Doing this in place did weird things - std::remove_if( + delayedFunctions.erase(std::remove_if( delayedFunctions.begin(), delayedFunctions.end(), - [](pair, float>& x) { return x.second <= 0; }); + [](pair, float>& x) { return x.second <= 0; }), delayedFunctions.end()); for (auto it = this->delayedPeriodicFunctions.begin(); it != this->delayedPeriodicFunctions.end(); ++it) { From 21f198435b633f0bd691a39cbf4a36881504579c Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 08:04:36 -0300 Subject: [PATCH 277/320] Actually add the clearInterval lua actor method --- src/Actor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Actor.cpp b/src/Actor.cpp index 4f4e1b5bb0..174f3e24e5 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -2784,6 +2784,7 @@ class LunaActor : public Luna ADD_METHOD(name); ADD_METHOD(setInterval); ADD_METHOD(setTimeout); + ADD_METHOD(clearInterval); ADD_METHOD(name); ADD_METHOD(sleep); ADD_METHOD(linear); From 3690d47c80ef1bf5c16defcc678e6e95261cf7c3 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 15:13:58 -0300 Subject: [PATCH 278/320] Fix a bug when using clearInterval inside setInterval --- src/Actor.cpp | 35 +++++++++++++++++++++++++---------- src/Actor.h | 1 + 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 174f3e24e5..0fcf58ae6f 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -959,10 +959,26 @@ Actor::UpdateInternal(float delta_time) } } // Doing this in place did weird things - delayedFunctions.erase(std::remove_if( - delayedFunctions.begin(), - delayedFunctions.end(), - [](pair, float>& x) { return x.second <= 0; }), delayedFunctions.end()); + delayedFunctions.erase(std::remove_if(delayedFunctions.begin(), + delayedFunctions.end(), + [](pair, float>& x) { + return x.second <= 0; + }), + delayedFunctions.end()); + auto L = LUA->Get(); + for (auto id : delayedPeriodicFunctionIdsToDelete) { + luaL_unref(L, LUA_REGISTRYINDEX, id); + auto& vec = this->delayedPeriodicFunctions; + vec.erase( + std::remove_if(vec.begin(), + vec.end(), + [id](tuple, float, float, int>& x) { + return std::get<3>(x) == id; + }), + vec.end()); + } + LUA->Release(L); + delayedPeriodicFunctionIdsToDelete.clear(); for (auto it = this->delayedPeriodicFunctions.begin(); it != this->delayedPeriodicFunctions.end(); ++it) { @@ -1754,15 +1770,14 @@ class LunaActor : public Luna static int clearInterval(T* p, lua_State* L) { int r = IArg(1); - auto& l = p->delayedPeriodicFunctions; - auto it = find_if(l.begin(), - l.end(), + auto& vec = p->delayedPeriodicFunctions; + auto it = find_if(vec.begin(), + vec.end(), [r](tuple, float, float, int>& x) { return std::get<3>(x) == r; }); - if (it != l.end()) { - luaL_unref(L, LUA_REGISTRYINDEX, r); - l.erase(it); + if (it != vec.end()) { + p->delayedPeriodicFunctionIdsToDelete.emplace_back(r); } else { LuaHelpers::ReportScriptError( "Interval function not found (When triying to clearInterval() )"); diff --git a/src/Actor.h b/src/Actor.h index 596658537c..4c158655d4 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -753,6 +753,7 @@ class Actor : public MessageSubscriber void SetTimeout(function f, float ms); std::list, float, float, int>> delayedPeriodicFunctions; // This is a list to allow safe iterators + vector delayedPeriodicFunctionIdsToDelete; void SetInterval(function f, float ms, int fRemove); // Named commands From 06c862530e18a53406b6f6675c892d1af5229db0 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Sun, 2 Dec 2018 19:12:00 -0300 Subject: [PATCH 279/320] Fix lobby userlist --- src/NetworkSyncManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 93f12d3554..6f245fa60f 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -943,16 +943,16 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) } } break; case ettps_lobbyuserlistupdate: { + auto& vec = NSMAN->lobbyuserlist; auto newUsers = payload->at("on"); for (auto& user : newUsers) { - auto& vec = NSMAN->lobbyuserlist; - vec.erase(std::remove( - vec.begin(), vec.end(), user.get()), - vec.end()); + NSMAN->lobbyuserlist.emplace_back(user.get()); } auto removedUsers = payload->at("off"); for (auto& user : removedUsers) { - NSMAN->lobbyuserlist.emplace_back(user.get()); + vec.erase(std::remove( + vec.begin(), vec.end(), user.get()), + vec.end()); } SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); } break; @@ -1000,7 +1000,7 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) } } } - SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); + SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); } break; } } catch (exception e) { From 1fc925bb96e20e45a116e0722e3406d9ebc2cae5 Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Sun, 2 Dec 2018 19:40:05 -0300 Subject: [PATCH 280/320] Update maxwidth for tab labels in chat overlay --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 7b0f009088..7a0361f8c5 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -273,7 +273,7 @@ for i = 0, maxTabs - 1 do { InitCommand = function(self) self:halign(0):valign(0) - self:maxwidth(tabWidth) + self:maxwidth(tabWidth*2) self:zoom(scale) self:diffuse(color("#000000")) self:xy(x + tabWidth * i + 4, y + height * (1 + (tabHeight / 4))) From 54372aa612cc97829b72bc2d1cb75c96e89da723 Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Sun, 2 Dec 2018 20:13:43 -0300 Subject: [PATCH 281/320] Change NSMAN lobbyuserlist to std::set Instead of a vector, so we have quick erases and no duplicates. --- src/NetworkSyncManager.cpp | 8 +++----- src/NetworkSyncManager.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 6f245fa60f..12ae1db42b 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -939,20 +939,18 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) NSMAN->lobbyuserlist.clear(); auto users = payload->at("users"); for (auto& user : users) { - NSMAN->lobbyuserlist.emplace_back(user.get()); + NSMAN->lobbyuserlist.insert(user.get()); } } break; case ettps_lobbyuserlistupdate: { auto& vec = NSMAN->lobbyuserlist; auto newUsers = payload->at("on"); for (auto& user : newUsers) { - NSMAN->lobbyuserlist.emplace_back(user.get()); + NSMAN->lobbyuserlist.insert(user.get()); } auto removedUsers = payload->at("off"); for (auto& user : removedUsers) { - vec.erase(std::remove( - vec.begin(), vec.end(), user.get()), - vec.end()); + NSMAN->lobbyuserlist.erase(user.get()); } SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); } break; diff --git a/src/NetworkSyncManager.h b/src/NetworkSyncManager.h index 155c71e308..ec46666ed2 100644 --- a/src/NetworkSyncManager.h +++ b/src/NetworkSyncManager.h @@ -378,7 +378,7 @@ class NetworkSyncManager // since function was last called. RString m_Scoreboard[NUM_NSScoreBoardColumn]; - vector lobbyuserlist; + set lobbyuserlist; void SendMPLeaderboardUpdate(float wife, RString& jdgstr); From 7d0af343607c1a184514a941ef3d661bbd3c8446 Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Sun, 2 Dec 2018 20:14:17 -0300 Subject: [PATCH 282/320] Add a check for valid payloads on lobbyuserlistupdate --- src/NetworkSyncManager.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 12ae1db42b..2c5afca4a5 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -944,13 +944,17 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) } break; case ettps_lobbyuserlistupdate: { auto& vec = NSMAN->lobbyuserlist; - auto newUsers = payload->at("on"); - for (auto& user : newUsers) { - NSMAN->lobbyuserlist.insert(user.get()); + if (payload->find("on") != payload->end()) { + auto newUsers = payload->at("on"); + for (auto& user : newUsers) { + NSMAN->lobbyuserlist.insert(user.get()); + } } - auto removedUsers = payload->at("off"); - for (auto& user : removedUsers) { - NSMAN->lobbyuserlist.erase(user.get()); + if (payload->find("off") != payload->end()) { + auto removedUsers = payload->at("off"); + for (auto& user : removedUsers) { + NSMAN->lobbyuserlist.erase(user.get()); + } } SCREENMAN->SendMessageToTopScreen(SM_UsersUpdate); } break; From d9e1e569e9a32f5df85d5747b9f8f08d76d9e46d Mon Sep 17 00:00:00 2001 From: Caio Rodrigues Date: Sun, 2 Dec 2018 20:15:35 -0300 Subject: [PATCH 283/320] Make the lobbyuserlist somewhat functional --- .../ScreenNetRoom decorations/default.lua | 2 +- .../ScreenNetRoom overlay/default.lua | 1 + .../Til Death/BGAnimations/_lobbyuserlist.lua | 24 +++++++++---------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua index e1e2fec71a..e5515c2eef 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom decorations/default.lua @@ -2,10 +2,10 @@ local t = Def.ActorFrame {} if not NSMAN:IsETTP() then t[#t + 1] = LoadActor("../_chatbox") end + t[#t + 1] = LoadActor("profile") t[#t + 1] = LoadActor("roomsearch") t[#t + 1] = LoadActor("tabs") -t[#t + 1] = LoadActor("../_lobbyuserlist") local g = Def.ActorFrame { diff --git a/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua b/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua index 1fba2ead08..abcc80b74e 100644 --- a/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenNetRoom overlay/default.lua @@ -49,5 +49,6 @@ t[#t + 1] = LoadActor("../_mousewheelscroll") t[#t + 1] = LoadActor("currenttime") t[#t + 1] = LoadActor("../_halppls") t[#t + 1] = LoadActor("../_userlist") +t[#t + 1] = LoadActor("../_lobbyuserlist") return t diff --git a/Themes/Til Death/BGAnimations/_lobbyuserlist.lua b/Themes/Til Death/BGAnimations/_lobbyuserlist.lua index 2294131ca2..f80e092771 100644 --- a/Themes/Til Death/BGAnimations/_lobbyuserlist.lua +++ b/Themes/Til Death/BGAnimations/_lobbyuserlist.lua @@ -8,6 +8,7 @@ local usersX = SCREEN_WIDTH / 4 local usersY = SCREEN_TOP + 15 local usersHeight = 10 +local lobbos local top = SCREENMAN:GetTopScreen() local qty = 0 local posit = getMainColor("positive") @@ -23,6 +24,7 @@ local r = end, SetCommand = function(self) top = SCREENMAN:GetTopScreen() + lobbos = NSMAN:GetLobbyUserList() end, UsersUpdateMessageCommand = function(self) self:queuecommand("Set") @@ -60,19 +62,15 @@ local function userLabel(i) end, SetCommand = function(self) local num = self:GetName() + 0 - lobbos = NSMAN:GetLobbyUserList() - qty = #lobbos - if num <= qty then - local str = "" - str = str .. top:GetUser(num) - self:settext(str) - if top:GetUserState(num) == 2 or top:GetUserState(num) == 1 then - self:diffuse(posit) - elseif top:GetUserState(num) == 4 then - self:diffuse(negat) - else - self:diffuse(enable) - end + if num <= #lobbos then + self:settext(lobbos[num]) + -- if top:GetUserState(num) == 2 or top:GetUserState(num) == 1 then + -- self:diffuse(posit) + -- elseif top:GetUserState(num) == 4 then + -- self:diffuse(negat) + -- else + -- self:diffuse(enable) + -- end else self:settext("") end From a5272622fcfd91816abbce60cd2cfea0d3de5bac Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 2 Dec 2018 16:26:27 -0500 Subject: [PATCH 284/320] pragma disable of 4275 (socket::poll) and 4996 (lua deprecated funcs) --- src/global.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/global.h b/src/global.h index 0e8d361de2..bbfee94349 100644 --- a/src/global.h +++ b/src/global.h @@ -1,4 +1,4 @@ -#ifndef GLOBAL_H +#ifndef GLOBAL_H #define GLOBAL_H #if defined(CMAKE_POWERED) @@ -11,6 +11,8 @@ #pragma once #endif // _MSC_VER >= 1000 #pragma warning(disable : 4251) +#pragma warning(disable : 4275) +#pragma warning(disable : 4996) /** @brief This macro is for INT8_MIN, etc. */ #define __STDC_LIMIT_MACROS /** @brief This macro is for INT64_C, etc. */ From afd7214dc6ada1152a424b78ff4d9f529deb08ab Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 2 Dec 2018 16:26:39 -0500 Subject: [PATCH 285/320] yourmompiler warnings --- src/BitmapText.cpp | 4 ++-- src/ScreenNetSelectMusic.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/BitmapText.cpp b/src/BitmapText.cpp index fa78d2c777..2a902d47d9 100644 --- a/src/BitmapText.cpp +++ b/src/BitmapText.cpp @@ -1,4 +1,4 @@ -#include "global.h" +#include "global.h" #include "ActorUtil.h" #include "BitmapText.h" #include "Font.h" @@ -1438,7 +1438,7 @@ class LunaBitmapText : public Luna static int getGlyphRect(T* p, lua_State* L) { int idx = (IArg(1) - 1) * 4; // lua idx start at 1 and 4 verts per glyph - if (idx < 0 || idx >= p->m_aVertices.size()) { + if (idx < 0 || idx >= static_cast(p->m_aVertices.size())) { lua_pushnil(L); return 1; } diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index a23bf43a5f..4a4547db11 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -220,7 +220,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) } } -done: // Must be at end, as so it is last resort for SMOnline packets. // If it doesn't know what to do, then it'll just remove them. ScreenSelectMusic::HandleScreenMessage(SM); @@ -311,7 +310,7 @@ ScreenNetSelectMusic::SelectCurrent() if (pSong == NULL) return false; - if (m_vpSteps.size() <= m_iSelection[PLAYER_1]) + if (static_cast(m_vpSteps.size()) <= m_iSelection[PLAYER_1]) return false; GAMESTATE->m_pCurSong.Set(pSong); Steps* pSteps = m_vpSteps[m_iSelection[PLAYER_1]]; From 41a5c242d15e705116e9caced8f6f8dccf832032 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Sun, 2 Dec 2018 18:58:05 -0500 Subject: [PATCH 286/320] only call lia->get() if we actually have functions to delete --- src/Actor.cpp | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 0fcf58ae6f..799f26e1c8 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -965,28 +965,30 @@ Actor::UpdateInternal(float delta_time) return x.second <= 0; }), delayedFunctions.end()); - auto L = LUA->Get(); - for (auto id : delayedPeriodicFunctionIdsToDelete) { - luaL_unref(L, LUA_REGISTRYINDEX, id); - auto& vec = this->delayedPeriodicFunctions; - vec.erase( - std::remove_if(vec.begin(), - vec.end(), - [id](tuple, float, float, int>& x) { - return std::get<3>(x) == id; - }), - vec.end()); - } - LUA->Release(L); - delayedPeriodicFunctionIdsToDelete.clear(); - for (auto it = this->delayedPeriodicFunctions.begin(); - it != this->delayedPeriodicFunctions.end(); - ++it) { - auto& delayedF = *it; - std::get<1>(delayedF) -= delta_time; - if (std::get<1>(delayedF) <= 0) { - std::get<0>(delayedF)(); - std::get<1>(delayedF) = std::get<2>(delayedF); + if (!delayedPeriodicFunctionIdsToDelete.empty()) { + auto* L = LUA->Get(); + for (auto id : delayedPeriodicFunctionIdsToDelete) { + luaL_unref(L, LUA_REGISTRYINDEX, id); + auto& vec = this->delayedPeriodicFunctions; + vec.erase(std::remove_if( + vec.begin(), + vec.end(), + [id](tuple, float, float, int>& x) { + return std::get<3>(x) == id; + }), + vec.end()); + } + LUA->Release(L); + delayedPeriodicFunctionIdsToDelete.clear(); + for (auto it = this->delayedPeriodicFunctions.begin(); + it != this->delayedPeriodicFunctions.end(); + ++it) { + auto& delayedF = *it; + std::get<1>(delayedF) -= delta_time; + if (std::get<1>(delayedF) <= 0) { + std::get<0>(delayedF)(); + std::get<1>(delayedF) = std::get<2>(delayedF); + } } } } From 30c345a362c4492d72d7f331b12bdc8bcdee9f45 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Sun, 2 Dec 2018 22:39:10 -0600 Subject: [PATCH 287/320] Fix crash when adding nothing to a playlist --- src/ScreenSelectMusic.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index ab091ae15d..403c57796a 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -542,7 +542,8 @@ ScreenSelectMusic::Input(const InputEventPlus& input) MESSAGEMAN->Broadcast("DisplayAll"); return true; } else if (bHoldingCtrl && c == 'A' && m_MusicWheel.IsSettled() && - input.type == IET_FIRST_PRESS) { + input.type == IET_FIRST_PRESS && + GAMESTATE->m_pCurSteps[PLAYER_1] != nullptr) { if (SONGMAN->GetPlaylists().empty()) return true; From 37b7412a1890437caf932a60245e7a0503d1cff7 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 3 Dec 2018 07:45:55 -0300 Subject: [PATCH 288/320] Revert "Fix song search stopping song selection in multi" This reverts commit 6e0ae32e44fe0eb05697013e6a26fbe43df48cbb. --- .../ScreenSelectMusic decorations/songsearch.lua | 6 ------ src/ScreenNetSelectMusic.cpp | 2 -- 2 files changed, 8 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua index 4ef3e85bf3..49f7a6c15f 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/songsearch.lua @@ -72,12 +72,6 @@ local t = TabChangedMessageCommand = function(self) self:queuecommand("Set") end, - MultiSongPickedMessageCommand = function(self) - lastsearchstring = "" - searchstring = "" - MESSAGEMAN:Broadcast("UpdateString") - whee:SongSearch(lastsearchstring) - end, LoadFont("Common Large") .. { InitCommand = function(self) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index 4a4547db11..951f0df15c 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -162,7 +162,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) } } else if (SM == ETTP_StartChart) { if (NSMAN->song != nullptr) { - MESSAGEMAN->Broadcast("MultiSongPicked"); GAMESTATE->m_pCurSong.Set(NSMAN->song); if (NSMAN->steps != nullptr) { GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); @@ -188,7 +187,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) } } else if (SM == ETTP_SelectChart) { if (NSMAN->song != nullptr) { - MESSAGEMAN->Broadcast("MultiSongPicked"); GAMESTATE->m_pCurSong.Set(NSMAN->song); if (NSMAN->steps != nullptr) { GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); From c59523b78da742fb6c65b9240e40c739f90823a2 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 3 Dec 2018 08:13:41 -0300 Subject: [PATCH 289/320] Fix multi select/start while searching without relying on til death lua --- src/ScreenNetSelectMusic.cpp | 85 ++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 48 deletions(-) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index 951f0df15c..cf564cde0e 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -95,6 +95,40 @@ ScreenNetSelectMusic::Input(const InputEventPlus& input) return ScreenSelectMusic::Input(input); } +void +SelectSongUsingNSMAN(ScreenNetSelectMusic* s, bool start) +{ + auto ptrMusicWheel = s->GetMusicWheel(); + auto& m_MusicWheel = *ptrMusicWheel; + if (NSMAN->song != nullptr) { + GAMESTATE->m_pCurSong.Set(NSMAN->song); + if (NSMAN->steps != nullptr) { + GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); + GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( + NSMAN->steps->GetDifficulty()); + } + if (!m_MusicWheel.SelectSong(NSMAN->song)) { + m_MusicWheel.ChangeSort(SORT_GROUP); + m_MusicWheel.FinishTweening(); + m_MusicWheel.ReloadSongList(false, ""); + SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, 0.710f); + m_MusicWheel.SelectSong(NSMAN->song); + } + if (NSMAN->rate > 0) { + GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = + NSMAN->rate / 1000.f; + MESSAGEMAN->Broadcast("RateChanged"); + } + m_MusicWheel.Select(); + m_MusicWheel.Move(-1); + m_MusicWheel.Move(1); + m_MusicWheel.Move(0); + if (start) { + s->StartSelectedSong(); + m_MusicWheel.Select(); + } + } +} void ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) { @@ -110,6 +144,7 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) if (!m_MusicWheel.SelectSong(NSMAN->song)) { m_MusicWheel.ChangeSort(SORT_GROUP); m_MusicWheel.FinishTweening(); + m_MusicWheel.ReloadSongList(false, ""); SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, 0.710f); m_MusicWheel.SelectSong(NSMAN->song); } @@ -121,7 +156,6 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) m_MusicWheel.Select(); m_MusicWheel.Move(-1); m_MusicWheel.Move(1); - m_MusicWheel.Move(0); } } else if (SM == SM_UsersUpdate) { MESSAGEMAN->Broadcast("UsersUpdate"); @@ -161,54 +195,9 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) this->AfterMusicChange(); } } else if (SM == ETTP_StartChart) { - if (NSMAN->song != nullptr) { - GAMESTATE->m_pCurSong.Set(NSMAN->song); - if (NSMAN->steps != nullptr) { - GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); - GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( - NSMAN->steps->GetDifficulty()); - } - if (!m_MusicWheel.SelectSong(NSMAN->song)) { - m_MusicWheel.ChangeSort(SORT_GROUP); - m_MusicWheel.FinishTweening(); - SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, 0.710f); - m_MusicWheel.SelectSong(NSMAN->song); - } - if (NSMAN->rate > 0) { - GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = - NSMAN->rate / 1000.f; - MESSAGEMAN->Broadcast("RateChanged"); - } - m_MusicWheel.Select(); - m_MusicWheel.Move(-1); - m_MusicWheel.Move(1); - StartSelectedSong(); - m_MusicWheel.Select(); - } + SelectSongUsingNSMAN(this, true); } else if (SM == ETTP_SelectChart) { - if (NSMAN->song != nullptr) { - GAMESTATE->m_pCurSong.Set(NSMAN->song); - if (NSMAN->steps != nullptr) { - GAMESTATE->m_pCurSteps[PLAYER_1].Set(NSMAN->steps); - GAMESTATE->m_PreferredDifficulty[PLAYER_1].Set( - NSMAN->steps->GetDifficulty()); - } - if (!m_MusicWheel.SelectSong(NSMAN->song)) { - m_MusicWheel.ChangeSort(SORT_GROUP); - m_MusicWheel.FinishTweening(); - SCREENMAN->PostMessageToTopScreen(SM_SetWheelSong, 0.710f); - m_MusicWheel.SelectSong(NSMAN->song); - } - if (NSMAN->rate > 0) { - GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = - NSMAN->rate / 1000.f; - MESSAGEMAN->Broadcast("RateChanged"); - } - m_MusicWheel.Select(); - m_MusicWheel.Move(-1); - m_MusicWheel.Move(1); - m_MusicWheel.Select(); - } + SelectSongUsingNSMAN(this, false); } else if (SM == SM_ConfirmDeleteSong) { if (ScreenPrompt::s_LastAnswer == ANSWER_YES) { OnConfirmSongDeletion(); From dc0337a2a18305f4d287d931593669004a0ba8de Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 3 Dec 2018 08:37:10 -0300 Subject: [PATCH 290/320] Fix setinterval --- src/Actor.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 799f26e1c8..64bca39a5b 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -980,15 +980,12 @@ Actor::UpdateInternal(float delta_time) } LUA->Release(L); delayedPeriodicFunctionIdsToDelete.clear(); - for (auto it = this->delayedPeriodicFunctions.begin(); - it != this->delayedPeriodicFunctions.end(); - ++it) { - auto& delayedF = *it; - std::get<1>(delayedF) -= delta_time; - if (std::get<1>(delayedF) <= 0) { - std::get<0>(delayedF)(); - std::get<1>(delayedF) = std::get<2>(delayedF); - } + } + for (auto& delayedF : delayedPeriodicFunctions) { + std::get<1>(delayedF) -= delta_time; + if (std::get<1>(delayedF) <= 0) { + std::get<0>(delayedF)(); + std::get<1>(delayedF) = std::get<2>(delayedF); } } } From ee81d6d04e5eda69c146b6a12e91921e68f851c9 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 3 Dec 2018 08:58:28 -0300 Subject: [PATCH 291/320] Move interval functions to screen --- src/Actor.cpp | 110 ---------------------------------------------- src/Actor.h | 7 --- src/Screen.cpp | 115 ++++++++++++++++++++++++++++++++++++++++++++++--- src/Screen.h | 15 +++++-- 4 files changed, 121 insertions(+), 126 deletions(-) diff --git a/src/Actor.cpp b/src/Actor.cpp index 64bca39a5b..af0a60becb 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -949,45 +949,6 @@ Actor::UpdateInternal(float delta_time) delta_time = m_fEffectDelta; } this->UpdateTweening(delta_time); - - for (auto it = delayedFunctions.begin(); it != delayedFunctions.end(); - ++it) { - auto& delayedF = *it; - delayedF.second -= delta_time; - if (delayedF.second <= 0) { - delayedF.first(); - } - } - // Doing this in place did weird things - delayedFunctions.erase(std::remove_if(delayedFunctions.begin(), - delayedFunctions.end(), - [](pair, float>& x) { - return x.second <= 0; - }), - delayedFunctions.end()); - if (!delayedPeriodicFunctionIdsToDelete.empty()) { - auto* L = LUA->Get(); - for (auto id : delayedPeriodicFunctionIdsToDelete) { - luaL_unref(L, LUA_REGISTRYINDEX, id); - auto& vec = this->delayedPeriodicFunctions; - vec.erase(std::remove_if( - vec.begin(), - vec.end(), - [id](tuple, float, float, int>& x) { - return std::get<3>(x) == id; - }), - vec.end()); - } - LUA->Release(L); - delayedPeriodicFunctionIdsToDelete.clear(); - } - for (auto& delayedF : delayedPeriodicFunctions) { - std::get<1>(delayedF) -= delta_time; - if (std::get<1>(delayedF) <= 0) { - std::get<0>(delayedF)(); - std::get<1>(delayedF) = std::get<2>(delayedF); - } - } } RString @@ -1704,20 +1665,6 @@ Actor::TweenInfo::operator=(const TweenInfo& rhs) return *this; } -void -Actor::SetTimeout(function f, float ms) -{ - delayedFunctions.emplace_back(make_pair(f, ms)); - return; -} - -void -Actor::SetInterval(function f, float ms, int id) -{ - delayedPeriodicFunctions.emplace_back(make_tuple(f, ms, ms, id)); - return; -} - // lua start #include "LuaBinding.h" @@ -1730,59 +1677,6 @@ class LunaActor : public Luna p->SetName(SArg(1)); COMMON_RETURN_SELF; } - static int setTimeout(T* p, lua_State* L) - { - auto f = GetFuncArg(1, L); - std::function execF = [f]() { - Lua* L = LUA->Get(); - f.PushSelf(L); - if (!lua_isnil(L, -1)) { - RString Error = - "Error running RequestChartLeaderBoard Finish Function: "; - LuaHelpers::RunScriptOnStack( - L, Error, 0, 0, true); // 1 args, 0 results - } - LUA->Release(L); - }; - p->SetTimeout(execF, FArg(2)); - COMMON_RETURN_SELF; - } - static int setInterval(T* p, lua_State* L) - { - lua_pushvalue(L, 1); - auto f = luaL_ref(L, LUA_REGISTRYINDEX); - std::function execF = [f]() { - Lua* L = LUA->Get(); - lua_rawgeti(L, LUA_REGISTRYINDEX, f); - if (!lua_isnil(L, -1)) { - RString Error = - "Error running RequestChartLeaderBoard Finish Function: "; - LuaHelpers::RunScriptOnStack( - L, Error, 0, 0, true); // 1 args, 0 results - } - LUA->Release(L); - }; - p->SetInterval(execF, FArg(2), f); - lua_pushnumber(L, f); - return 1; - } - static int clearInterval(T* p, lua_State* L) - { - int r = IArg(1); - auto& vec = p->delayedPeriodicFunctions; - auto it = find_if(vec.begin(), - vec.end(), - [r](tuple, float, float, int>& x) { - return std::get<3>(x) == r; - }); - if (it != vec.end()) { - p->delayedPeriodicFunctionIdsToDelete.emplace_back(r); - } else { - LuaHelpers::ReportScriptError( - "Interval function not found (When triying to clearInterval() )"); - } - return 0; - } static int sleep(T* p, lua_State* L) { float fTime = FArg(1); @@ -2795,10 +2689,6 @@ class LunaActor : public Luna DEFINE_METHOD(IsVisible, IsVisible()); LunaActor() { - ADD_METHOD(name); - ADD_METHOD(setInterval); - ADD_METHOD(setTimeout); - ADD_METHOD(clearInterval); ADD_METHOD(name); ADD_METHOD(sleep); ADD_METHOD(linear); diff --git a/src/Actor.h b/src/Actor.h index 4c158655d4..d3e71c3048 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -749,13 +749,6 @@ class Actor : public MessageSubscriber virtual void PushSelf(lua_State* L); virtual void PushContext(lua_State* L); - vector, float>> delayedFunctions; - void SetTimeout(function f, float ms); - std::list, float, float, int>> - delayedPeriodicFunctions; // This is a list to allow safe iterators - vector delayedPeriodicFunctionIdsToDelete; - void SetInterval(function f, float ms, int fRemove); - // Named commands void AddCommand(const RString& sCmdName, apActorCommands apac, diff --git a/src/Screen.cpp b/src/Screen.cpp index dcc16c97dc..58e3ff31d0 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -16,11 +16,7 @@ #define GROUPED_SCREENS THEME->GetMetric(m_sName, "GroupedScreens") static const char* ScreenTypeNames[] = { - "Attract", - "GameMenu", - "Gameplay", - "Evaluation", - "SystemMenu", + "Attract", "GameMenu", "Gameplay", "Evaluation", "SystemMenu", }; XToString(ScreenType); LuaXType(ScreenType); @@ -175,6 +171,45 @@ Screen::Update(float fDeltaTime) if (iSize != m_QueuedMessages.size()) i = 0; } + + for (auto it = delayedFunctions.begin(); it != delayedFunctions.end(); + ++it) { + auto& delayedF = *it; + delayedF.second -= fDeltaTime; + if (delayedF.second <= 0) { + delayedF.first(); + } + } + // Doing this in place did weird things + delayedFunctions.erase(std::remove_if(delayedFunctions.begin(), + delayedFunctions.end(), + [](pair, float>& x) { + return x.second <= 0; + }), + delayedFunctions.end()); + if (!delayedPeriodicFunctionIdsToDelete.empty()) { + auto* L = LUA->Get(); + for (auto id : delayedPeriodicFunctionIdsToDelete) { + luaL_unref(L, LUA_REGISTRYINDEX, id); + auto& vec = this->delayedPeriodicFunctions; + vec.erase(std::remove_if( + vec.begin(), + vec.end(), + [id](tuple, float, float, int>& x) { + return std::get<3>(x) == id; + }), + vec.end()); + } + LUA->Release(L); + delayedPeriodicFunctionIdsToDelete.clear(); + } + for (auto& delayedF : delayedPeriodicFunctions) { + std::get<1>(delayedF) -= fDeltaTime; + if (std::get<1>(delayedF) <= 0) { + std::get<0>(delayedF)(); + std::get<1>(delayedF) = std::get<2>(delayedF); + } + } } /* Returns true if the input was handled, or false if not handled. For @@ -401,6 +436,20 @@ Screen::PassInputToLua(const InputEventPlus& input) return handled; } +void +Screen::SetTimeout(function f, float ms) +{ + delayedFunctions.emplace_back(make_pair(f, ms)); + return; +} + +void +Screen::SetInterval(function f, float ms, int id) +{ + delayedPeriodicFunctions.emplace_back(make_tuple(f, ms, ms, id)); + return; +} + void Screen::AddInputCallbackFromStack(lua_State* L) { @@ -489,9 +538,65 @@ class LunaScreen : public Luna p->RemoveInputCallback(L); COMMON_RETURN_SELF; } + static int setTimeout(T* p, lua_State* L) + { + auto f = GetFuncArg(1, L); + std::function execF = [f]() { + Lua* L = LUA->Get(); + f.PushSelf(L); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::RunScriptOnStack( + L, Error, 0, 0, true); // 1 args, 0 results + } + LUA->Release(L); + }; + p->SetTimeout(execF, FArg(2)); + COMMON_RETURN_SELF; + } + static int setInterval(T* p, lua_State* L) + { + lua_pushvalue(L, 1); + auto f = luaL_ref(L, LUA_REGISTRYINDEX); + std::function execF = [f]() { + Lua* L = LUA->Get(); + lua_rawgeti(L, LUA_REGISTRYINDEX, f); + if (!lua_isnil(L, -1)) { + RString Error = + "Error running RequestChartLeaderBoard Finish Function: "; + LuaHelpers::RunScriptOnStack( + L, Error, 0, 0, true); // 1 args, 0 results + } + LUA->Release(L); + }; + p->SetInterval(execF, FArg(2), f); + lua_pushnumber(L, f); + return 1; + } + static int clearInterval(T* p, lua_State* L) + { + int r = IArg(1); + auto& vec = p->delayedPeriodicFunctions; + auto it = find_if(vec.begin(), + vec.end(), + [r](tuple, float, float, int>& x) { + return std::get<3>(x) == r; + }); + if (it != vec.end()) { + p->delayedPeriodicFunctionIdsToDelete.emplace_back(r); + } else { + LuaHelpers::ReportScriptError( + "Interval function not found (When triying to clearInterval() )"); + } + return 0; + } LunaScreen() { + ADD_METHOD(setInterval); + ADD_METHOD(setTimeout); + ADD_METHOD(clearInterval); ADD_METHOD(GetNextScreenName); ADD_METHOD(SetNextScreenName); ADD_METHOD(GetPrevScreenName); diff --git a/src/Screen.h b/src/Screen.h index 7ac55a482f..7c4b454b82 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -37,10 +37,10 @@ struct RegisterScreenClass /** @brief The different types of screens available. */ enum ScreenType { - attract, /**< The attract/demo mode, inviting players to play. */ - game_menu, /**< The menu screens, where options can be set before playing. - */ - gameplay, /**< The gameplay screen, where the actual game takes place. */ + attract, /**< The attract/demo mode, inviting players to play. */ + game_menu, /**< The menu screens, where options can be set before playing. + */ + gameplay, /**< The gameplay screen, where the actual game takes place. */ evaluation, system_menu, /**< The system/operator menu, where special options are set. */ @@ -103,6 +103,13 @@ class Screen : public ActorFrame // Lua void PushSelf(lua_State* L) override; + vector, float>> delayedFunctions; + void SetTimeout(function f, float ms); + std::list, float, float, int>> + delayedPeriodicFunctions; // This is a list to allow safe iterators + vector delayedPeriodicFunctionIdsToDelete; + void SetInterval(function f, float ms, int fRemove); + protected: /** @brief Holds the messages sent to a Screen. */ struct QueuedScreenMessage From a739d7c9d814e2715692a8a178a79eaf3c0beb4a Mon Sep 17 00:00:00 2001 From: Nicolas Date: Mon, 3 Dec 2018 12:32:59 -0300 Subject: [PATCH 292/320] Don't copy RageTextures when GC'ing them --- src/RageTextureManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index df0f723677..ff67b4bc4f 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -311,7 +311,7 @@ RageTextureManager::GarbageCollect(GCType type) if (PREFSMAN->m_verbose_log > 1) LOG->Trace("Performing texture garbage collection."); - for (auto ID : m_mapPathToTexture) { + for (auto& ID : m_mapPathToTexture) { RageTexture* t = ID.second; if (t->m_iRefCount) From e95c5d659e6d0e81f20b08af32d48fa121c92fe8 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Mon, 3 Dec 2018 21:54:50 -0600 Subject: [PATCH 293/320] Fix misc net eval scoreboard display stuff score sorting, positioning, max amount of scores --- .../Til Death/BGAnimations/MPscoreboard.lua | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Themes/Til Death/BGAnimations/MPscoreboard.lua b/Themes/Til Death/BGAnimations/MPscoreboard.lua index 686fce2ec0..f616e7b2fd 100644 --- a/Themes/Til Death/BGAnimations/MPscoreboard.lua +++ b/Themes/Til Death/BGAnimations/MPscoreboard.lua @@ -1,6 +1,6 @@ -local lines = 6 -- number of scores to display +local lines = 10 -- number of scores to display local framex = SCREEN_WIDTH - capWideScale(get43size(230), 230) local framey = 60 local frameWidth = capWideScale(get43size(220), 220) @@ -59,6 +59,9 @@ local function Update(self) end end +local sortFunction = function(first, second) + return first["highscore"]:GetWifeScore() > second["highscore"]:GetWifeScore() +end local t = Def.ActorFrame { @@ -69,12 +72,14 @@ local t = BeginCommand = function(self) SCREENMAN:GetTopScreen():AddInputCallback(input) multiscores = NSMAN:GetEvalScores() + table.sort(multiscores, sortFunction) for i=1, math.min(#multiscores) do self:GetChild(i):queuecommand("UpdateNetScore") end end, NewMultiScoreMessageCommand = function(self) multiscores = NSMAN:GetEvalScores() + table.sort(multiscores, sortFunction) for i=1, math.min(#multiscores) do self:GetChild(i):queuecommand("UpdateNetScore") end @@ -94,7 +99,7 @@ local function scoreitem(pn, i) --The main quad Def.Quad { InitCommand = function(self) - self:xy(framex, framey + (i * spacing) - 4):zoomto(frameWidth, 30):halign(0):valign(0):diffuse( + self:xy(framex, framey + ((i-1) * spacing) - 4):zoomto(frameWidth, 30):halign(0):valign(0):diffuse( color("#333333") ):diffusealpha(1):diffuserightedge(color("#33333333")) end @@ -102,7 +107,7 @@ local function scoreitem(pn, i) --Highlight quad for the current score Def.Quad { InitCommand = function(self) - self:xy(framex, framey + (i * spacing) - 4):zoomto(frameWidth, 30):halign(0):valign(0):diffuse( + self:xy(framex, framey + ((i-1) * spacing) - 4):zoomto(frameWidth, 30):halign(0):valign(0):diffuse( color("#ffffff") ):diffusealpha(0.3):diffuserightedge(color("#33333300")) end, @@ -117,7 +122,7 @@ local function scoreitem(pn, i) Def.Quad { Name = "mouseOver", UpdateNetScoreCommand = function(self) - self:xy(framex, framey + (i * spacing) - 4):zoomto(frameWidth*2, 30):halign(0):valign(0):diffuse( + self:xy(framex, framey + ((i-1) * spacing) - 4):zoomto(frameWidth*2, 30):halign(0):valign(0):diffuse( getMainColor("highlight") ):diffusealpha(0) end @@ -125,7 +130,7 @@ local function scoreitem(pn, i) --ClearType lamps Def.Quad { UpdateNetScoreCommand = function(self) - self:xy(framex, framey + (i * spacing) - 4):zoomto(8, 30):halign(0):valign(0):diffuse( + self:xy(framex, framey + ((i-1) * spacing) - 4):zoomto(8, 30):halign(0):valign(0):diffuse( getClearTypeFromScore(pn, hs, 2) ) end @@ -134,7 +139,7 @@ local function scoreitem(pn, i) LoadFont("Common normal") .. { InitCommand = function(self) - self:xy(framex - 8, framey + 12 + (i * spacing)):zoom(0.35) + self:xy(framex - 8, framey + 12 + ((i-1) * spacing)):zoom(0.35) end, UpdateNetScoreCommand = function(self) self:settext(i) @@ -152,7 +157,7 @@ local function scoreitem(pn, i) { Name = "wife", InitCommand = function(self) - self:xy(framex + 10, framey + 11 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.3) + self:xy(framex + 10, framey + 11 + ((i-1) * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.3) end, UpdateNetScoreCommand = function(self) self:settextf("%05.2f%% (%s)", notShit.floor(multiscores[i].highscore:GetWifeScore() * 10000) / 100, "Wife") @@ -162,7 +167,7 @@ local function scoreitem(pn, i) { Name = "user", InitCommand = function(self) - self:xy(framex + 10, framey + 1 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.3) + self:xy(framex + 10, framey + 1 + ((i-1) * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.3) end, UpdateNetScoreCommand = function(self) self:settextf(multiscores[i].user) @@ -175,7 +180,7 @@ local function scoreitem(pn, i) { Name = "option", InitCommand = function(self) - self:xy(framex + 10, framey + 11 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.35) + self:xy(framex + 10, framey + 11 + ((i-1) * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.35) end, UpdateNetScoreCommand = function(self) self:settext(multiscores[i].highscore:GetModifiers()) @@ -186,7 +191,7 @@ local function scoreitem(pn, i) { Name = "grade", InitCommand = function(self) - self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 2 + (i * spacing)):zoom(0.35):halign(0.5):maxwidth( + self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 2 + ((i-1) * spacing)):zoom(0.35):halign(0.5):maxwidth( (frameWidth - 15) / 0.35 ) end, @@ -199,7 +204,7 @@ local function scoreitem(pn, i) { Name = "clear", InitCommand = function(self) - self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 12 + (i * spacing)):zoom(0.35):halign(0.5):maxwidth( + self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 12 + ((i-1) * spacing)):zoom(0.35):halign(0.5):maxwidth( (frameWidth - 15) / 0.35 ) end, @@ -212,7 +217,7 @@ local function scoreitem(pn, i) { Name = "combo", InitCommand = function(self) - self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 22 + (i * spacing)):zoom(0.35):halign(0.5):maxwidth( + self:xy(framex + 130 + capWideScale(get43size(0), 50), framey + 22 + ((i-1) * spacing)):zoom(0.35):halign(0.5):maxwidth( (frameWidth - 15) / 0.35 ) end, @@ -224,7 +229,7 @@ local function scoreitem(pn, i) { Name = "judge", InitCommand = function(self) - self:xy(framex + 10, framey + 20 + (i * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.35) + self:xy(framex + 10, framey + 20 + ((i-1) * spacing)):zoom(0.35):halign(0):maxwidth((frameWidth - 15) / 0.35) end, UpdateNetScoreCommand = function(self) self:settextf("%d / %d / %d / %d / %d / %d", @@ -241,7 +246,7 @@ local function scoreitem(pn, i) { Name = "date", InitCommand = function(self) - self:xy(framex + 10, framey + 20 + (i * spacing)):zoom(0.35):halign(0) + self:xy(framex + 10, framey + 20 + ((i-1) * spacing)):zoom(0.35):halign(0) end, UpdateNetScoreCommand = function(self) self:settext(multiscores[i].highscore:GetDate()) From 391327b5d92d6caf935902b03ab1cfa5428e9a1e Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 01:16:59 -0500 Subject: [PATCH 294/320] ok no it wasnt but it should be now --- src/RageTextureManager.cpp | 4 ---- src/ScreenGameplay.cpp | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index ff67b4bc4f..b09c123093 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -344,10 +344,6 @@ RageTextureManager::GarbageCollect(GCType type) if (bDeleteThis) DeleteTexture(t); } - - // this may actually the best place for this -mina - LOG->Trace("Unloading replaydata."); - SCOREMAN->UnloadAllReplayData(); } void diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 29d4553acf..0e4ae3ab1a 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -50,6 +50,7 @@ #include "XmlFileUtil.h" #include "Profile.h" // for replay data stuff #include "DownloadManager.h" +#include "ScoreManager.h" // Defines #define SHOW_LIFE_METER_FOR_DISABLED_PLAYERS \ @@ -306,6 +307,10 @@ ScreenGameplay::ScreenGameplay() #if !defined(WITHOUT_NETWORKING) DLMAN->UpdateDLSpeed(true); #endif + if (GamePreferences::m_AutoPlay != PC_REPLAY) { + LOG->Trace("Unloading replaydata."); + SCOREMAN->UnloadAllReplayData(); + } } void From 1c3b3d967f16de9e4270f1076dbf4217ee6dd0a6 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 01:22:42 -0500 Subject: [PATCH 295/320] dont auto activate input when using insert to toggle chat --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 7a0361f8c5..3f6eec207e 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -424,7 +424,6 @@ function MPinput(event) MESSAGEMAN:Broadcast("Minimise") update = true if not minimize then - typing = true typingText = "" end end From 4689f71e692d3e82a7b789d5e1c3872eee67d085 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 02:04:12 -0500 Subject: [PATCH 296/320] allow and make ssm lock the wheel directly on song finalize --- src/ScreenSelectMusic.cpp | 2 +- src/WheelBase.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index 403c57796a..de38b888c6 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1229,7 +1229,7 @@ ScreenSelectMusic::SelectCurrent(PlayerNumber pn) * requests come through, the music will still start. */ m_BackgroundLoader.Abort(); CheckBackgroundRequests(true); - + m_MusicWheel.Lock(); if (OPTIONS_MENU_AVAILABLE) { // show "hold START for options" this->PlayCommand("ShowPressStartForOptions"); diff --git a/src/WheelBase.h b/src/WheelBase.h index c8bba41a55..6ae4d0feec 100644 --- a/src/WheelBase.h +++ b/src/WheelBase.h @@ -61,6 +61,7 @@ class WheelBase : public ActorFrame virtual bool Select(); // return true if this selection can end the screen WheelState GetWheelState() { return m_WheelState; } + void Lock() { m_WheelState = STATE_LOCKED; } bool WheelIsLocked() { return (m_WheelState == STATE_LOCKED ? true : false); From 7692d4e87586f18d6659044d5c7418dd8981d1e1 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 02:07:04 -0500 Subject: [PATCH 297/320] these were out of place and it was making me mad --- src/DownloadManager.cpp | 143 ++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 7e73e56469..b667fc66c2 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -1213,6 +1213,77 @@ DownloadManager::UpdateOnlineScoreReplayData(const string& sk, return; } void +UpdateReplayDataSequentially(deque toUpload) +{ + auto it = toUpload.begin(); + if (it != toUpload.end()) { + toUpload.pop_front(); + auto& hs = (*it); + DLMAN->UpdateOnlineScoreReplayData(hs->GetScoreKey(), [hs, toUpload]() { + hs->AddUploadedServer("nru"); + UpdateReplayDataSequentially(toUpload); + }); + } + return; +} +bool +DownloadManager::UpdateOnlineScoreReplayData() +{ + if (!LoggedIn()) + return false; + // we dont care if the chart is loaded for this function, only that there is + // a score that is already uploaded and already has replaydata, and that the + // source data is on disk to update it -mina + auto& scores = SCOREMAN->GetAllScores(); + deque toUpload; + for (auto& scorePtr : scores) { + auto ts = scorePtr->GetTopScore(); // still need to do this? + if ((ts == 1 || ts == 2)) { + if (scorePtr->HasReplayData() && + scorePtr->IsUploadedToServer(serverURL.Get()) && + !scorePtr->IsUploadedToServer("nru")) + toUpload.emplace_back(scorePtr); + } + } + UpdateReplayDataSequentially(toUpload); + return true; +} +void +uploadSequentially(deque toUpload) +{ + auto it = toUpload.begin(); + if (it != toUpload.end()) { + toUpload.pop_front(); + auto& hs = (*it); + DLMAN->UploadScoreWithReplayDataFromDisk( + hs->GetScoreKey(), [hs, toUpload]() { + hs->AddUploadedServer(serverURL.Get()); + uploadSequentially(toUpload); + }); + } + return; +} +bool +DownloadManager::UploadScores() +{ + if (!LoggedIn()) + return false; + auto scores = SCOREMAN->GetAllPBPtrs(); + deque toUpload; + for (auto& vec : scores) { + for (auto& scorePtr : vec) { + auto ts = scorePtr->GetTopScore(); + if ((ts == 1 || ts == 2) && + !scorePtr->IsUploadedToServer(serverURL.Get())) { + if (scorePtr->HasReplayData()) + toUpload.emplace_back(scorePtr); + } + } + } + uploadSequentially(toUpload); + return true; +} +void DownloadManager::EndSessionIfExists() { if (!LoggedIn()) @@ -1894,78 +1965,6 @@ DownloadManager::StartSession(string user, curl_multi_add_handle(mHTTPHandle, req->handle); HTTPRequests.push_back(req); } - -void -UpdateReplayDataSequentially(deque toUpload) -{ - auto it = toUpload.begin(); - if (it != toUpload.end()) { - toUpload.pop_front(); - auto& hs = (*it); - DLMAN->UpdateOnlineScoreReplayData(hs->GetScoreKey(), [hs, toUpload]() { - hs->AddUploadedServer("nru"); - UpdateReplayDataSequentially(toUpload); - }); - } - return; -} -bool -DownloadManager::UpdateOnlineScoreReplayData() -{ - if (!LoggedIn()) - return false; - // we dont care if the chart is loaded for this function, only that there is - // a score that is already uploaded and already has replaydata, and that the - // source data is on disk to update it -mina - auto& scores = SCOREMAN->GetAllScores(); - deque toUpload; - for (auto& scorePtr : scores) { - auto ts = scorePtr->GetTopScore(); // still need to do this? - if ((ts == 1 || ts == 2) ){ - if (scorePtr->HasReplayData() && - scorePtr->IsUploadedToServer(serverURL.Get()) && - !scorePtr->IsUploadedToServer("nru")) - toUpload.emplace_back(scorePtr); - } - } - UpdateReplayDataSequentially(toUpload); - return true; -} -void -uploadSequentially(deque toUpload) -{ - auto it = toUpload.begin(); - if (it != toUpload.end()) { - toUpload.pop_front(); - auto& hs = (*it); - DLMAN->UploadScoreWithReplayDataFromDisk( - hs->GetScoreKey(), [hs, toUpload]() { - hs->AddUploadedServer(serverURL.Get()); - uploadSequentially(toUpload); - }); - } - return; -} -bool -DownloadManager::UploadScores() -{ - if (!LoggedIn()) - return false; - auto scores = SCOREMAN->GetAllPBPtrs(); - deque toUpload; - for (auto& vec : scores) { - for (auto& scorePtr : vec) { - auto ts = scorePtr->GetTopScore(); - if ((ts == 1 || ts == 2) && - !scorePtr->IsUploadedToServer(serverURL.Get())) { - if (scorePtr->HasReplayData()) - toUpload.emplace_back(scorePtr); - } - } - } - uploadSequentially(toUpload); - return true; -} int DownloadManager::GetSkillsetRank(Skillset ss) { From 6a8db24719a3580354acf112cf5ba4614abb7f37 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 02:48:05 -0500 Subject: [PATCH 298/320] oops i wasnt paying attention --- src/RageTextureManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index b09c123093..d059a70479 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -311,8 +311,14 @@ RageTextureManager::GarbageCollect(GCType type) if (PREFSMAN->m_verbose_log > 1) LOG->Trace("Performing texture garbage collection."); - for (auto& ID : m_mapPathToTexture) { - RageTexture* t = ID.second; + for (std::map::iterator i = + m_mapPathToTexture.begin(); + i != m_mapPathToTexture.end();) { + std::map::iterator j = i; + i++; + + RString sPath = j->first.filename; + RageTexture* t = j->second; if (t->m_iRefCount) continue; /* Can't unload textures that are still referenced. */ From cd1cb97add49357f4bb8c5bad3587f085224abc2 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Tue, 4 Dec 2018 11:23:22 -0600 Subject: [PATCH 299/320] Improve lua access to changing player on net eval --- .../Til Death/BGAnimations/MPscoreboard.lua | 2 +- src/ScreenNetEvaluation.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Themes/Til Death/BGAnimations/MPscoreboard.lua b/Themes/Til Death/BGAnimations/MPscoreboard.lua index f616e7b2fd..e7796e726f 100644 --- a/Themes/Til Death/BGAnimations/MPscoreboard.lua +++ b/Themes/Til Death/BGAnimations/MPscoreboard.lua @@ -13,7 +13,7 @@ local function input(event) if event.type == "InputEventType_Release" then for i = 1, #multiscores do if isOver(scoreBoard:GetChild(i):GetChild("mouseOver")) then - SCREENMAN:GetTopScreen():SetCurrentPlayer(i) + SCREENMAN:GetTopScreen():SetCurrentPlayerByName(multiscores[i].user) scoreBoard:GetChild(i):GetChild("grade"):visible( not scoreBoard:GetChild(i):GetChild("grade"):GetVisible() ) diff --git a/src/ScreenNetEvaluation.cpp b/src/ScreenNetEvaluation.cpp index 43d3f4186b..cb6e19a824 100644 --- a/src/ScreenNetEvaluation.cpp +++ b/src/ScreenNetEvaluation.cpp @@ -163,6 +163,24 @@ class LunaScreenNetEvaluation : public Luna p->UpdateStats(); return 0; } + static int SetCurrentPlayerByName(T* p, lua_State* L) + { + int theNumber = 0; + RString given = SArg(1); + for (size_t i = 0; i < NSMAN->m_EvalPlayerData.size(); i++) + { + EndOfGame_PlayerData& pd = NSMAN->m_EvalPlayerData[i]; + RString name = pd.nameStr; + name.MakeLower(); + if (name == given) + { + p->m_iCurrentPlayer = (int)i; + p->UpdateStats(); + break; + } + } + return 0; + } LunaScreenNetEvaluation() { ADD_METHOD(GetNumActivePlayers); @@ -170,6 +188,7 @@ class LunaScreenNetEvaluation : public Luna ADD_METHOD(GetOptions); ADD_METHOD(GetCurrentPlayer); ADD_METHOD(SetCurrentPlayer); + ADD_METHOD(SetCurrentPlayerByName); } }; From e277fb90739b6e91459f0c51059ce07da2cd23cf Mon Sep 17 00:00:00 2001 From: poco0317 Date: Tue, 4 Dec 2018 12:15:20 -0600 Subject: [PATCH 300/320] Move chat tabs over when you close them --- .../ScreenChatOverlay overlay.lua | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 3f6eec207e..3c54e2d071 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -351,6 +351,23 @@ chat[#chat + 1] = chatWindow chat.UpdateChatOverlayMessageCommand = function(self) SCREENMAN:set_input_redirected("PlayerNumber_P1", typing) end + +function shiftTab(fromIndex, toIndex) + -- tabs[index of tab][parameter table....] + -- [1 is type, 2 is tab contents?] + -- type 0 cant be deleted + tabs[toIndex] = tabs[fromIndex] + tabs[fromIndex] = nil +end + +function shiftAllTabs(emptyIndex) + for i = emptyIndex + 1, maxTabs - 1 do + --if not (tabs[i][1] == 0 and tabs[i][2] == "") then -- dont delete the lobby tab + shiftTab(i, i-1) + --end + end +end + function overTab(mx, my) for i = 0, maxTabs - 1 do if tabs[i + 1] then @@ -395,25 +412,28 @@ function MPinput(event) update = true end else - if not closeTab then - changeTab(tabs[tabButton][2], tabs[tabButton][1]) - else - local tabT = tabs[tabButton][1] - local tabN = tabs[tabButton][2] - if (tabT == 0 and tabN == "") or (tabT == 1 and tabN ~= nil and tabN == NSMAN:GetCurrentRoomName()) then - return false - end - tabs[tabButton] = nil - if chats[tabT][tabN] == messages then - for i = #tabs, 1, -1 do - if tabs[i] then - changeTab(tabs[i][2], tabs[i][1]) + if event.type == "InputEventType_Release" then -- only change tabs on release (to stop repeatedly closing tabs or changing to a tab we close) -poco + if not closeTab then + changeTab(tabs[tabButton][2], tabs[tabButton][1]) + else + local tabT = tabs[tabButton][1] + local tabN = tabs[tabButton][2] + if (tabT == 0 and tabN == "") or (tabT == 1 and tabN ~= nil and tabN == NSMAN:GetCurrentRoomName()) then + return false + end + tabs[tabButton] = nil + if chats[tabT][tabN] == messages then + for i = #tabs, 1, -1 do + if tabs[i] then + changeTab(tabs[i][2], tabs[i][1]) + end end end + chats[tabT][tabN] = nil + shiftAllTabs(tabButton) end - chats[tabT][tabN] = nil + update = true end - update = true end end end From 794c2badb06efb5dc867723cc1cbfb46e4a8e5e6 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Tue, 4 Dec 2018 12:18:05 -0600 Subject: [PATCH 301/320] Use a better event type for chat tab touching --- Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua index 3c54e2d071..5608b471f4 100644 --- a/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua +++ b/Themes/_fallback/BGAnimations/ScreenChatOverlay overlay.lua @@ -355,16 +355,13 @@ end function shiftTab(fromIndex, toIndex) -- tabs[index of tab][parameter table....] -- [1 is type, 2 is tab contents?] - -- type 0 cant be deleted tabs[toIndex] = tabs[fromIndex] tabs[fromIndex] = nil end function shiftAllTabs(emptyIndex) for i = emptyIndex + 1, maxTabs - 1 do - --if not (tabs[i][1] == 0 and tabs[i][2] == "") then -- dont delete the lobby tab shiftTab(i, i-1) - --end end end @@ -412,7 +409,7 @@ function MPinput(event) update = true end else - if event.type == "InputEventType_Release" then -- only change tabs on release (to stop repeatedly closing tabs or changing to a tab we close) -poco + if event.type == "InputEventType_FirstPress" then -- only change tabs on press (to stop repeatedly closing tabs or changing to a tab we close) -poco if not closeTab then changeTab(tabs[tabButton][2], tabs[tabButton][1]) else From 2a6d3ec88995155dd2f6ca0109773e046bd7b2a9 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Tue, 4 Dec 2018 12:27:40 -0600 Subject: [PATCH 302/320] Fix incomplete changing of rates in multi --- src/ScreenNetSelectMusic.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ScreenNetSelectMusic.cpp b/src/ScreenNetSelectMusic.cpp index cf564cde0e..286d83be14 100644 --- a/src/ScreenNetSelectMusic.cpp +++ b/src/ScreenNetSelectMusic.cpp @@ -117,7 +117,13 @@ SelectSongUsingNSMAN(ScreenNetSelectMusic* s, bool start) if (NSMAN->rate > 0) { GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = NSMAN->rate / 1000.f; + GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate = + NSMAN->rate / 1000.f; + GAMESTATE->m_SongOptions.GetSong().m_fMusicRate = + NSMAN->rate / 1000.f; MESSAGEMAN->Broadcast("RateChanged"); + MESSAGEMAN->Broadcast("CurrentRateChanged"); + } m_MusicWheel.Select(); m_MusicWheel.Move(-1); @@ -151,7 +157,12 @@ ScreenNetSelectMusic::HandleScreenMessage(const ScreenMessage SM) if (NSMAN->rate > 0) { GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = NSMAN->rate / 1000.f; + GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate = + NSMAN->rate / 1000.f; + GAMESTATE->m_SongOptions.GetSong().m_fMusicRate = + NSMAN->rate / 1000.f; MESSAGEMAN->Broadcast("RateChanged"); + MESSAGEMAN->Broadcast("CurrentRateChanged"); } m_MusicWheel.Select(); m_MusicWheel.Move(-1); From 23faeac5f59d7268ac18ffd55f798d6c90027b6e Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 17:49:16 -0500 Subject: [PATCH 303/320] add stb image libs --- src/stb_image.h | 7462 ++++++++++++++++++++++++++++++++++++++++ src/stb_image_resize.h | 2627 ++++++++++++++ 2 files changed, 10089 insertions(+) create mode 100644 src/stb_image.h create mode 100644 src/stb_image_resize.h diff --git a/src/stb_image.h b/src/stb_image.h new file mode 100644 index 0000000000..d9c21bc813 --- /dev/null +++ b/src/stb_image.h @@ -0,0 +1,7462 @@ +/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine + John-Mark Allen + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar + Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex + Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 + Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus + Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo + Christian Floisand Kevin Schmidt github:darealshinji + Blazej Dariusz Roszkowski github:Michaelangel007 +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy to use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// make more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4]; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v >= 0 && v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->history = (stbi_uc *) stbi__malloc(g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "tranparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to teh color that was there the previous frame. + memset( g->out, 0x00, 4 * g->w * g->h ); + memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent) + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (o == NULL) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) *comp = info.ma ? 4 : 3; + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + (void) stbi__get32be(s); + (void) stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/src/stb_image_resize.h b/src/stb_image_resize.h new file mode 100644 index 0000000000..031ca99dc3 --- /dev/null +++ b/src/stb_image_resize.h @@ -0,0 +1,2627 @@ +/* stb_image_resize - v0.95 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters + to use, you can change the compile-time defaults with + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#endif + +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + +#ifndef STBIR_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n < max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ From 4930af50bd0f1924d9e0ba6b4738bea85b85e81a Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 17:51:16 -0500 Subject: [PATCH 304/320] call stb image free in ragesurface destructor --- src/RageSurface.cpp | 16 +++++++++------- src/RageSurface.h | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/RageSurface.cpp b/src/RageSurface.cpp index 02170983a6..938778ec8d 100644 --- a/src/RageSurface.cpp +++ b/src/RageSurface.cpp @@ -1,7 +1,7 @@ -#include "global.h" +#include "global.h" #include "RageSurface.h" #include "RageUtil.h" - +#include "../../extern/stb-master/stb_image.h" #include int32_t @@ -135,8 +135,9 @@ RageSurfaceFormat::Equivalent(const RageSurfaceFormat& rhs) const RageSurface::RageSurface() { - pixels = NULL; + pixels = nullptr; pixels_owned = true; + stb_loadpoint = false; } RageSurface::RageSurface(const RageSurface& cpy) @@ -153,10 +154,11 @@ RageSurface::RageSurface(const RageSurface& cpy) pixels = NULL; } -RageSurface::~RageSurface() -{ - if (pixels_owned) - delete[] pixels; +RageSurface::~RageSurface(){ + + if (pixels_owned) delete[] pixels; + if (stb_loadpoint) + stbi_image_free(pixels); } static int diff --git a/src/RageSurface.h b/src/RageSurface.h index b5a6a4e6e9..6155332e93 100644 --- a/src/RageSurface.h +++ b/src/RageSurface.h @@ -1,4 +1,4 @@ -/* RageSurface - holds a simple 2d graphic surface */ +/* RageSurface - holds a simple 2d graphic surface */ #ifndef RAGE_SURFACE_H #define RAGE_SURFACE_H @@ -84,9 +84,9 @@ struct RageSurfaceFormat struct RageSurface { RageSurfaceFormat fmt; - uint8_t* pixels; bool pixels_owned; + bool stb_loadpoint; int32_t w, h, pitch; int32_t flags; From 319f4b0fc1b79da939157c37d34f64749fd3591d Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 13:47:20 -0500 Subject: [PATCH 305/320] these are already double res --- ...=> _japanese 24px [kanji-jis1-stroke] 32x32.png} | Bin ...s).png => _japanese 24px [kanji-jis1] 32x32.png} | Bin ...=> _japanese 24px [kanji-jis2-stroke] 63x54.png} | Bin ...s).png => _japanese 24px [kanji-jis2] 63x54.png} | Bin ..._japanese 24px [kanji-regular-stroke] 48x41.png} | Bin ...png => _japanese 24px [kanji-regular] 48x41.png} | Bin 6 files changed, 0 insertions(+), 0 deletions(-) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis1-stroke] 32x32 (doubleres).png => _japanese 24px [kanji-jis1-stroke] 32x32.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis1] 32x32 (doubleres).png => _japanese 24px [kanji-jis1] 32x32.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis2-stroke] 63x54 (doubleres).png => _japanese 24px [kanji-jis2-stroke] 63x54.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis2] 63x54 (doubleres).png => _japanese 24px [kanji-jis2] 63x54.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-regular-stroke] 48x41 (doubleres).png => _japanese 24px [kanji-regular-stroke] 48x41.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-regular] 48x41 (doubleres).png => _japanese 24px [kanji-regular] 48x41.png} (100%) diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41.png From a16f36d7e2d389280bf7a41d89943164d130ea81 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Tue, 4 Dec 2018 17:01:14 -0600 Subject: [PATCH 306/320] Set failoff for all replays (galaxy brain) --- src/GameManager.cpp | 3 ++- src/GameManager.h | 3 ++- src/ScreenEvaluation.cpp | 11 +++++++++++ src/ScreenGameplay.cpp | 26 ++++++++++++++++++++++++++ src/ScreenSelectMusic.cpp | 18 ++++++++++++++++++ 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/GameManager.cpp b/src/GameManager.cpp index 33155a54a1..b65ad10cee 100644 --- a/src/GameManager.cpp +++ b/src/GameManager.cpp @@ -1,4 +1,4 @@ -#include "global.h" +#include "global.h" #include "Foreach.h" #include "Game.h" #include "GameConstantsAndTypes.h" @@ -3227,6 +3227,7 @@ GameManager::GameManager() m_fPreviousRate = 1.f; m_sModsToReset; m_vTurnsToReset; + m_iPreviousFail; // Register with Lua. { Lua* L = LUA->Get(); diff --git a/src/GameManager.h b/src/GameManager.h index f17be774a5..51930668b7 100644 --- a/src/GameManager.h +++ b/src/GameManager.h @@ -1,4 +1,4 @@ -/** @brief GameManager - Manages Games and Styles. */ +/** @brief GameManager - Manages Games and Styles. */ #ifndef GAMEMANAGER_H #define GAMEMANAGER_H @@ -63,6 +63,7 @@ class GameManager float m_fPreviousRate; RString m_sModsToReset; vector m_vTurnsToReset; + FailType m_iPreviousFail; // Lua void PushSelf(lua_State* L); diff --git a/src/ScreenEvaluation.cpp b/src/ScreenEvaluation.cpp index 42259234c1..ee4c8e1bb3 100644 --- a/src/ScreenEvaluation.cpp +++ b/src/ScreenEvaluation.cpp @@ -852,10 +852,21 @@ ScreenEvaluation::HandleMenuStart() GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetCurrent().FromString(mods); GAMESTATE->m_pPlayerState[PLAYER_1]->m_PlayerOptions.GetPreferred().FromString(mods); */ + FailType failreset = GAMEMAN->m_iPreviousFail; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .m_FailType = failreset; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .m_FailType = failreset; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .m_FailType = failreset; GAMESTATE->m_SongOptions.GetSong().m_fMusicRate = oldRate; GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate = oldRate; GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = oldRate; GAMEMAN->m_bResetModifiers = false; + const vector oldturns = GAMEMAN->m_vTurnsToReset; if (GAMEMAN->m_bResetTurns) { GAMESTATE->m_pPlayerState[PLAYER_1] diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index 0e4ae3ab1a..667c330787 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -1770,6 +1770,19 @@ ScreenGameplay::Update(float fDeltaTime) oldRate; GAMESTATE->m_SongOptions.GetPreferred() .m_fMusicRate = oldRate; + FailType failreset = GAMEMAN->m_iPreviousFail; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .m_FailType = + failreset; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .m_FailType = + failreset; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .m_FailType = + failreset; GAMEMAN->m_bResetModifiers = false; GAMEMAN->m_sModsToReset = ""; MESSAGEMAN->Broadcast("RateChanged"); @@ -2119,6 +2132,19 @@ ScreenGameplay::Input(const InputEventPlus& input) oldRate; GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = oldRate; + FailType failreset = GAMEMAN->m_iPreviousFail; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .m_FailType = + failreset; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .m_FailType = + failreset; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .m_FailType = + failreset; GAMEMAN->m_bResetModifiers = false; GAMEMAN->m_sModsToReset = ""; MESSAGEMAN->Broadcast("RateChanged"); diff --git a/src/ScreenSelectMusic.cpp b/src/ScreenSelectMusic.cpp index de38b888c6..07b2312492 100644 --- a/src/ScreenSelectMusic.cpp +++ b/src/ScreenSelectMusic.cpp @@ -1822,6 +1822,20 @@ class LunaScreenSelectMusic : public Luna } GAMEMAN->m_bResetTurns = true; GAMEMAN->m_vTurnsToReset = oldTurns; + GAMEMAN->m_iPreviousFail = GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .m_FailType; + + // REALLY BAD way to set fail off for a replay + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .m_FailType = FailType_Off; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetCurrent() + .m_FailType = FailType_Off; + GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetPreferred() + .m_FailType = FailType_Off; // lock the game into replay mode and GO LOG->Trace("Viewing replay for score key %s", @@ -1900,6 +1914,10 @@ class LunaScreenSelectMusic : public Luna GAMESTATE->m_SongOptions.GetCurrent().m_fMusicRate = scoreRate; GAMESTATE->m_SongOptions.GetPreferred().m_fMusicRate = scoreRate; MESSAGEMAN->Broadcast("RateChanged"); + + GAMEMAN->m_iPreviousFail = GAMESTATE->m_pPlayerState[PLAYER_1] + ->m_PlayerOptions.GetSong() + .m_FailType; // go LOG->Trace("Viewing evaluation screen for score key %s", From 2768f10766206f0f39c0077af115139e0380ab78 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 18:02:05 -0500 Subject: [PATCH 307/320] add a preference to enable stb_image use --- src/PrefsManager.cpp | 1 + src/PrefsManager.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index b65d4a5b28..eb98296583 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -204,6 +204,7 @@ PrefsManager::PrefsManager() , m_bCelShadeModels("CelShadeModels", false) , // Work-In-Progress.. disable by default. m_bPreferredSortUsesGroups("PreferredSortUsesGroups", true) + , UseStbImageLibrary("UseStbImageLibrary", false) , m_fPadStickSeconds("PadStickSeconds", 0) , m_EditRecordModeLeadIn("EditRecordModeLeadIn", 1.0f) , m_bForceMipMaps("ForceMipMaps", false) diff --git a/src/PrefsManager.h b/src/PrefsManager.h index 02118e5779..d4f49395ea 100644 --- a/src/PrefsManager.h +++ b/src/PrefsManager.h @@ -203,6 +203,7 @@ class PrefsManager Preference m_DisableUploadDir; Preference m_bCelShadeModels; Preference m_bPreferredSortUsesGroups; + Preference UseStbImageLibrary; // Number of seconds it takes for a button on the controller to release // after pressed. From f7a2d2e6bb2602371074747942bb7d8b63310783 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 18:24:18 -0500 Subject: [PATCH 308/320] obey network leaderboard preference when sending updates --- src/NetworkSyncManager.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 2c5afca4a5..a6c0f19adb 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -831,17 +831,20 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) MESSAGEMAN->Broadcast(msg); } break; case ettps_mpleaderboardupdate: { - auto& scores = (*payload)["scores"]; - for (json::iterator it = scores.begin(); it != scores.end(); - ++it) { - float wife = (*it)["wife"]; - RString jdgstr = (*it)["jdgstr"]; - string user = (*it)["user"].get(); - n->mpleaderboard[user].wife = wife; - n->mpleaderboard[user].jdgstr = jdgstr; + if (PREFSMAN->m_bEnableScoreboard) { + auto& scores = (*payload)["scores"]; + for (json::iterator it = scores.begin(); + it != scores.end(); + ++it) { + float wife = (*it)["wife"]; + RString jdgstr = (*it)["jdgstr"]; + string user = (*it)["user"].get(); + n->mpleaderboard[user].wife = wife; + n->mpleaderboard[user].jdgstr = jdgstr; + } + Message msg("MPLeaderboardUpdate"); + MESSAGEMAN->Broadcast(msg); } - Message msg("MPLeaderboardUpdate"); - MESSAGEMAN->Broadcast(msg); } break; case ettps_createroomresponse: { bool created = (*payload)["created"]; From bcd2e810d8db08cc83fdd0b25972a8f1ca83b066 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 18:52:42 -0500 Subject: [PATCH 309/320] set default res to 1024 for textures --- src/PrefsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index eb98296583..b166a2d59f 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -143,7 +143,7 @@ PrefsManager::PrefsManager() , m_BGFitMode("BackgroundFitMode", BFM_CoverPreserve) , m_HighResolutionTextures("HighResolutionTextures", HighResolutionTextures_Auto) - , m_iMaxTextureResolution("MaxTextureResolution", 2048) + , m_iMaxTextureResolution("MaxTextureResolution", 1024) , m_iRefreshRate("RefreshRate", REFRESH_DEFAULT) , m_bAllowMultitexture("AllowMultitexture", true) , m_bAllowedLag("AllowedLag", 0.001f) From 3a249f3e887337ef79462758eeaee891210617aa Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 18:53:05 -0500 Subject: [PATCH 310/320] add ragesurface load function that using stb_image --- src/RageSurface.cpp | 2 +- src/RageSurface_Load.cpp | 48 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/RageSurface.cpp b/src/RageSurface.cpp index 938778ec8d..3f6410d4e3 100644 --- a/src/RageSurface.cpp +++ b/src/RageSurface.cpp @@ -1,7 +1,7 @@ #include "global.h" #include "RageSurface.h" #include "RageUtil.h" -#include "../../extern/stb-master/stb_image.h" +#include "stb_image.h" #include int32_t diff --git a/src/RageSurface_Load.cpp b/src/RageSurface_Load.cpp index c46636ba79..c3af0f0cff 100644 --- a/src/RageSurface_Load.cpp +++ b/src/RageSurface_Load.cpp @@ -1,4 +1,4 @@ -#include "global.h" +#include "global.h" #include "ActorUtil.h" #include "RageFile.h" #include "RageLog.h" @@ -7,9 +7,49 @@ #include "RageSurface_Load_GIF.h" #include "RageSurface_Load_JPEG.h" #include "RageSurface_Load_PNG.h" +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" +#include "PrefsManager.h" #include "RageUtil.h" +#include "RageSurface.h" #include +RageSurfaceUtils::OpenResult +RageSurface_stb_Load(const RString& sPath, + RageSurface*& ret, + bool bHeaderOnly, + RString& error) +{ + RageFile f; + if (!f.Open(sPath)) { + error = f.GetError(); + return RageSurfaceUtils::OPEN_FATAL_ERROR; + } + + int x, y, n; + auto* doot = stbi_load(f.GetPath(), &x, &y, &n, 4); + if (bHeaderOnly) { + ret = CreateSurfaceFrom(x, y, 32, 0, 0, 0, 0, nullptr, x * 4); + } else { + ret = + CreateSurfaceFrom(x, + y, + 32, + Swap32BE(0xFF000000), + Swap32BE(0x00FF0000), + Swap32BE(0x0000FF00), + Swap32BE(0x000000FF), + doot, + x * 4); + } + + if (ret == nullptr) { + stbi_image_free(doot); + return RageSurfaceUtils::OPEN_UNKNOWN_FILE_FORMAT; // XXX + } + ret->stb_loadpoint = true; + return RageSurfaceUtils::OPEN_OK; +} static RageSurface* TryOpenFile(RString sPath, bool bHeaderOnly, @@ -19,7 +59,10 @@ TryOpenFile(RString sPath, { RageSurface* ret = nullptr; RageSurfaceUtils::OpenResult result; - if (!format.CompareNoCase("png")) + + if (PREFSMAN->UseStbImageLibrary) + result = RageSurface_stb_Load(sPath, ret, bHeaderOnly, error); + else if (!format.CompareNoCase("png")) result = RageSurface_Load_PNG(sPath, ret, bHeaderOnly, error); else if (!format.CompareNoCase("gif")) result = RageSurface_Load_GIF(sPath, ret, bHeaderOnly, error); @@ -127,6 +170,7 @@ RageSurfaceUtils::LoadFile(const RString& sPath, return nullptr; } + /* * (c) 2004 Glenn Maynard * All rights reserved. From 73b4b2b95c8c371e0d1b69b567ec640c41e3bd43 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 19:15:12 -0500 Subject: [PATCH 311/320] add stb_resize to replace zoomsurface (disabled cuz crashy and cba atm) --- src/RageSurfaceUtils_Zoom.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/RageSurfaceUtils_Zoom.cpp b/src/RageSurfaceUtils_Zoom.cpp index 533ae74f18..7a0ceaaf49 100644 --- a/src/RageSurfaceUtils_Zoom.cpp +++ b/src/RageSurfaceUtils_Zoom.cpp @@ -1,8 +1,11 @@ -#include "global.h" +#include "global.h" #include "RageSurface.h" #include "RageSurfaceUtils.h" #include "RageSurfaceUtils_Zoom.h" #include "RageUtil.h" +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include "stb_image_resize.h" +#include "PrefsManager.h" #include using namespace std; @@ -169,11 +172,20 @@ RageSurfaceUtils::Zoom(RageSurface*& src, int dstwidth, int dstheight) src->fmt.Gmask, src->fmt.Bmask, src->fmt.Amask); - - ZoomSurface(src, dst); - + if (0) // cwashy,-mina + stbir_resize_uint8(src->pixels, + src->w, + src->h, + 0, + dst->pixels, + dstwidth, + dstheight, + 0, + 4); + + else + ZoomSurface(src, dst); delete src; - src = dst; } } From c144da5374454c030a4d363f80239a90668cb567 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 19:52:36 -0500 Subject: [PATCH 312/320] im fairly certain this does what it is supposed to --- .../ScreenSelectMusic decorations/default.lua | 12 ++++++---- .../ScreenSelectMusic decorations/score.lua | 23 ++++++++++++++++--- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua index b1de977aa0..2e9417d1c8 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/default.lua @@ -48,11 +48,13 @@ t[#t + 1] = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() if leaderboardEnabled and GAMESTATE:GetCurrentSteps(PLAYER_1) then local chartkey = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() - DLMAN:RequestChartLeaderBoardFromOnline( - chartkey, - function(leaderboard) - end - ) + if SCREENMAN:GetTopScreen():GetMusicWheel():IsSettled() then + DLMAN:RequestChartLeaderBoardFromOnline( + chartkey, + function(leaderboard) + end + ) + end end end, ChartPreviewOnMessageCommand = function(self) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index db11fd86c8..d80313cdc9 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -72,7 +72,7 @@ local function updateLeaderBoardForCurrentChart() DLMAN:RequestChartLeaderBoardFromOnline( steps:GetChartKey(), function(leaderboard) - moped:playcommand("SetFromLeaderboard", leaderboard) + moped:queuecommand("SetFromLeaderboard", leaderboard) end ) else @@ -154,8 +154,25 @@ local ret = PlayingSampleMusicMessageCommand = function(self) local leaderboardEnabled = playerConfig:get_data(pn_to_profile_slot(PLAYER_1)).leaderboardEnabled and DLMAN:IsLoggedIn() - if not leaderboardEnabled then -- this is taken care of by default.lua instead. - updateLeaderBoardForCurrentChart() + if GAMESTATE:GetCurrentSteps(PLAYER_1) then + local chartkey = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() + if SCREENMAN:GetTopScreen():GetMusicWheel():IsSettled() then + if leaderboardEnabled then + DLMAN:RequestChartLeaderBoardFromOnline( + chartkey, + function(leaderboard) + moped:playcommand("SetFromLeaderboard", leaderboard) + end + ) -- this is also intentionally super bad so we actually do something about it -mina + elseif (SCREENMAN:GetTopScreen():GetName() == "ScreenSelectMusic" or SCREENMAN:GetTopScreen():GetName() == "ScreenNetSelectMusic") and ((getTabIndex() == 2 and nestedTab == 2) or collapsed) then + DLMAN:RequestChartLeaderBoardFromOnline( + chartkey, + function(leaderboard) + moped:playcommand("SetFromLeaderboard", leaderboard) + end + ) + end + end end end, NestedTabChangedMessageCommand = function(self) From 0e3801bd1964e9d34eb6f2f6811ec6efac2048b0 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 18:24:18 -0500 Subject: [PATCH 313/320] obey network leaderboard preference when sending updates --- src/NetworkSyncManager.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/NetworkSyncManager.cpp b/src/NetworkSyncManager.cpp index 2c5afca4a5..a6c0f19adb 100644 --- a/src/NetworkSyncManager.cpp +++ b/src/NetworkSyncManager.cpp @@ -831,17 +831,20 @@ ETTProtocol::Update(NetworkSyncManager* n, float fDeltaTime) MESSAGEMAN->Broadcast(msg); } break; case ettps_mpleaderboardupdate: { - auto& scores = (*payload)["scores"]; - for (json::iterator it = scores.begin(); it != scores.end(); - ++it) { - float wife = (*it)["wife"]; - RString jdgstr = (*it)["jdgstr"]; - string user = (*it)["user"].get(); - n->mpleaderboard[user].wife = wife; - n->mpleaderboard[user].jdgstr = jdgstr; + if (PREFSMAN->m_bEnableScoreboard) { + auto& scores = (*payload)["scores"]; + for (json::iterator it = scores.begin(); + it != scores.end(); + ++it) { + float wife = (*it)["wife"]; + RString jdgstr = (*it)["jdgstr"]; + string user = (*it)["user"].get(); + n->mpleaderboard[user].wife = wife; + n->mpleaderboard[user].jdgstr = jdgstr; + } + Message msg("MPLeaderboardUpdate"); + MESSAGEMAN->Broadcast(msg); } - Message msg("MPLeaderboardUpdate"); - MESSAGEMAN->Broadcast(msg); } break; case ettps_createroomresponse: { bool created = (*payload)["created"]; From 2c08d630adf262dadbc1dc908274d944ab6aa92c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 18:52:42 -0500 Subject: [PATCH 314/320] set default res to 1024 for textures --- src/PrefsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PrefsManager.cpp b/src/PrefsManager.cpp index b65d4a5b28..a37e1ce303 100644 --- a/src/PrefsManager.cpp +++ b/src/PrefsManager.cpp @@ -143,7 +143,7 @@ PrefsManager::PrefsManager() , m_BGFitMode("BackgroundFitMode", BFM_CoverPreserve) , m_HighResolutionTextures("HighResolutionTextures", HighResolutionTextures_Auto) - , m_iMaxTextureResolution("MaxTextureResolution", 2048) + , m_iMaxTextureResolution("MaxTextureResolution", 1024) , m_iRefreshRate("RefreshRate", REFRESH_DEFAULT) , m_bAllowMultitexture("AllowMultitexture", true) , m_bAllowedLag("AllowedLag", 0.001f) From b3104b931823773d35e95fcc190de4d81e24e18c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 13:47:20 -0500 Subject: [PATCH 315/320] these are already double res --- ...=> _japanese 24px [kanji-jis1-stroke] 32x32.png} | Bin ...s).png => _japanese 24px [kanji-jis1] 32x32.png} | Bin ...=> _japanese 24px [kanji-jis2-stroke] 63x54.png} | Bin ...s).png => _japanese 24px [kanji-jis2] 63x54.png} | Bin ..._japanese 24px [kanji-regular-stroke] 48x41.png} | Bin ...png => _japanese 24px [kanji-regular] 48x41.png} | Bin 6 files changed, 0 insertions(+), 0 deletions(-) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis1-stroke] 32x32 (doubleres).png => _japanese 24px [kanji-jis1-stroke] 32x32.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis1] 32x32 (doubleres).png => _japanese 24px [kanji-jis1] 32x32.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis2-stroke] 63x54 (doubleres).png => _japanese 24px [kanji-jis2-stroke] 63x54.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-jis2] 63x54 (doubleres).png => _japanese 24px [kanji-jis2] 63x54.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-regular-stroke] 48x41 (doubleres).png => _japanese 24px [kanji-regular-stroke] 48x41.png} (100%) rename Themes/_fallback/Fonts/{_japanese 24px [kanji-regular] 48x41 (doubleres).png => _japanese 24px [kanji-regular] 48x41.png} (100%) diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis1-stroke] 32x32.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis1] 32x32.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis2-stroke] 63x54.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-jis2] 63x54.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-regular-stroke] 48x41.png diff --git a/Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41 (doubleres).png b/Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41.png similarity index 100% rename from Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41 (doubleres).png rename to Themes/_fallback/Fonts/_japanese 24px [kanji-regular] 48x41.png From 3e45e24a01d4040cc79ed3dce80a30ade506f7be Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 17:49:16 -0500 Subject: [PATCH 316/320] add stb image libs --- src/stb_image.h | 7462 ++++++++++++++++++++++++++++++++++++++++ src/stb_image_resize.h | 2627 ++++++++++++++ 2 files changed, 10089 insertions(+) create mode 100644 src/stb_image.h create mode 100644 src/stb_image_resize.h diff --git a/src/stb_image.h b/src/stb_image.h new file mode 100644 index 0000000000..d9c21bc813 --- /dev/null +++ b/src/stb_image.h @@ -0,0 +1,7462 @@ +/* stb_image - v2.19 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine + John-Mark Allen + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Phil Jordan + Dave Moore Roy Eltham Hayaki Saito Nathan Reed + Won Chun Luke Graham Johan Duparc Nick Verigakis + the Horde3D community Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Laurent Gomila Cort Stratton Sergio Gonzalez github:snagar + Aruelien Pocheville Thibault Reuille Cass Everitt github:Zelex + Ryamond Barbiero Paul Du Bois Engin Manap github:grim210 + Aldo Culquicondor Philipp Wiesemann Dale Weiler github:sammyhw + Oriol Ferrer Mesia Josh Tobin Matthew Gregan github:phprus + Julian Raschke Gregory Mullen Baldur Karlsson github:poppolopoppo + Christian Floisand Kevin Schmidt github:darealshinji + Blazej Dariusz Roszkowski github:Michaelangel007 +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data) +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy to use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// make more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image now supports loading HDR images in general, and currently +// the Radiance .HDR file format, although the support is provided +// generically. You can still load any file through the existing interface; +// if you attempt to load an HDR file, it will be automatically remapped to +// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// By default we convert iphone-formatted PNGs back to RGB, even though +// they are internally encoded differently. You can disable this conversion +// by by calling stbi_convert_iphone_png_to_rgb(0), in which case +// you will always just get the native iphone "format" through (which +// is BGR stored in RGB). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// + + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// NOT THREADSAFE +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + + +#ifdef _MSC_VER +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +// assume GCC or Clang on ARM targets +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + fseek((FILE*) user, n, SEEK_CUR); +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +// this is not threadsafe +static const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load = flag_true_if_should_flip; +} + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 8) { + STBI_ASSERT(ri.bits_per_channel == 16); + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + if (ri.bits_per_channel != 16) { + STBI_ASSERT(ri.bits_per_channel == 8); + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) || !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} + +static void stbi__skip(stbi__context *s, int n) +{ + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} + +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} + +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} + +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + return z + (stbi__get16le(s) << 16); +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + + +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} + +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break; + default: STBI_ASSERT(0); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) + for (j=0; j < count[i]; ++j) + h->size[k++] = (stbi_uc) (i+1); + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + + sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB + k = stbi_lrot(j->code_buffer, n); + STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & ~sgn); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + diff = t ? stbi__extend_receive(j, t) : 0; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + data[0] = (short) (dc << j->succ_low); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) << shift); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) << shift); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + m = stbi__get_marker(j); + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4]; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[288]; + stbi__uint16 value[288]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + if (z->zbuffer >= z->zbuffer_end) return 0; + return *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s == 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + STBI_ASSERT(z->size[b] == s); + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) stbi__fill_bits(a); + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (int) (z->zout - z->zout_start); + limit = old_limit = (int) (z->zout_end - z->zout_start); + while (cur + n > limit) + limit *= 2; + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) + c = stbi__zreceive(a,3)+3; + else { + STBI_ASSERT(c == 18); + c = stbi__zreceive(a,7)+11; + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + STBI_ASSERT(a->num_bits == 0); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[288] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + STBI_ASSERT(img_width_bytes <= x); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load = 0; +static int stbi__de_iphone_flag = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag = flag_true_if_should_convert; +} + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + if (scan == STBI__SCAN_header) return 1; + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + // if SCAN_header, have to scan to see if we have a tRNS + } + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth < 8) + ri->bits_per_channel = 8; + else + ri->bits_per_channel = p->depth; + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) n += 16, z >>= 16; + if (z >= 0x00100) n += 8, z >>= 8; + if (z >= 0x00010) n += 4, z >>= 4; + if (z >= 0x00004) n += 2, z >>= 2; + if (z >= 0x00002) n += 1, z >>= 1; + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v >= 0 && v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; +} stbi__bmp_data; + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - 14 - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - 14 - info.hsz) >> 2; + } + + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - 14 - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i], p1[i] = p2[i], p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->background = (stbi_uc *) stbi__malloc(4 * g->w * g->h); + g->history = (stbi_uc *) stbi__malloc(g->w * g->h); + if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "tranparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to teh color that was there the previous frame. + memset( g->out, 0x00, 4 * g->w * g->h ); + memset( g->background, 0x00, 4 * g->w * g->h ); // state of the background (starts transparent) + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispoase of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (o == NULL) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + out = (stbi_uc*) STBI_REALLOC( out, layers * stride ); + if (delays) { + *delays = (int*) STBI_REALLOC( *delays, sizeof(int) * layers ); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + stbi__rewind( s ); + if (p == NULL) + return 0; + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) *comp = info.ma ? 4 : 3; + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + (void) stbi__get32be(s); + (void) stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) +// Does not support 16-bit-per-channel + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) + return 0; + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad3sizes_valid(s->img_n, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad3(s->img_n, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y); + + if (req_comp && req_comp != s->img_n) { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + + if (maxv > 255) + return stbi__err("max value > 255", "PPM image not 8-bit"); + else + return 1; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ diff --git a/src/stb_image_resize.h b/src/stb_image_resize.h new file mode 100644 index 0000000000..031ca99dc3 --- /dev/null +++ b/src/stb_image_resize.h @@ -0,0 +1,2627 @@ +/* stb_image_resize - v0.95 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters + to use, you can change the compile-time defaults with + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#endif + +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif + + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + +#ifndef STBIR_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n < max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((type) * (STBIR_MAX_COLORSPACES) + (colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +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 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. +------------------------------------------------------------------------------ +*/ From faed128e301bbe6a2a012b389386043cfbe5c65c Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 20:48:14 -0500 Subject: [PATCH 317/320] tone down some highlight updates --- .../BGAnimations/ScreenSelectMusic decorations/score.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index db11fd86c8..70714b422d 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -228,6 +228,7 @@ local t = InitCommand = function(self) rtTable = nil self:SetUpdateFunction(highlight) + self:SetUpdateFunctionInterval(0.025) cheese = self end, BeginCommand = function(self) @@ -704,6 +705,7 @@ function nestedTabButton(i) InitCommand = function(self) self:xy(frameX + offsetX + (i - 1) * (nestedTabButtonWidth - capWideScale(100, 80)), frameY + offsetY - 2) self:SetUpdateFunction(highlight) + self:SetUpdateFunctionInterval(0.025) end, CollapseCommand = function(self) self:visible(false) From c34aa6191f0151019358d6a4c80e7bae14d02e6f Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 20:51:40 -0500 Subject: [PATCH 318/320] dont need this --- src/RageTextureManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/RageTextureManager.cpp b/src/RageTextureManager.cpp index d059a70479..2e1c7bef37 100644 --- a/src/RageTextureManager.cpp +++ b/src/RageTextureManager.cpp @@ -67,8 +67,7 @@ RageTextureManager::Update(float fDeltaTime) static RageTimer garbageCollector; if (garbageCollector.PeekDeltaTime() >= 30.0f) { if ((SCREENMAN != nullptr) && (SCREENMAN->GetTopScreen() != nullptr) && - SCREENMAN->GetTopScreen()->GetScreenType() != gameplay && - SCREENMAN->GetTopScreen()->GetScreenType() != evaluation) { + SCREENMAN->GetTopScreen()->GetScreenType() != gameplay) { DoDelayedDelete(); garbageCollector.Touch(); } From 7d58c1bb721f617f4b926bd7718411ce1d4e6de2 Mon Sep 17 00:00:00 2001 From: "born a rick, raised a morty, died a jerry" Date: Tue, 4 Dec 2018 21:17:16 -0500 Subject: [PATCH 319/320] obvious bug is obvious --- src/RageSurfaceUtils_Zoom.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/RageSurfaceUtils_Zoom.cpp b/src/RageSurfaceUtils_Zoom.cpp index 7a0ceaaf49..f0c3b5efdf 100644 --- a/src/RageSurfaceUtils_Zoom.cpp +++ b/src/RageSurfaceUtils_Zoom.cpp @@ -165,14 +165,15 @@ RageSurfaceUtils::Zoom(RageSurface*& src, int dstwidth, int dstheight) int target_width = lround(src->w * xscale); int target_height = lround(src->h * yscale); - RageSurface* dst = CreateSurface(target_width, - target_height, - 32, - src->fmt.Rmask, - src->fmt.Gmask, - src->fmt.Bmask, - src->fmt.Amask); - if (0) // cwashy,-mina + RageSurface* dst = nullptr; + if (PREFSMAN->UseStbImageLibrary) { + dst = CreateSurface(dstwidth, + dstheight, + 32, + src->fmt.Rmask, + src->fmt.Gmask, + src->fmt.Bmask, + src->fmt.Amask); stbir_resize_uint8(src->pixels, src->w, src->h, @@ -182,9 +183,18 @@ RageSurfaceUtils::Zoom(RageSurface*& src, int dstwidth, int dstheight) dstheight, 0, 4); - - else - ZoomSurface(src, dst); + delete src; + src = dst; + return; + } + dst = CreateSurface(target_width, + target_height, + 32, + src->fmt.Rmask, + src->fmt.Gmask, + src->fmt.Bmask, + src->fmt.Amask); + ZoomSurface(src, dst); delete src; src = dst; } From 4c0339daf4a2e9edc924d67a00458a9fcaaf008d Mon Sep 17 00:00:00 2001 From: MinaciousGrace Date: Tue, 4 Dec 2018 22:01:50 -0500 Subject: [PATCH 320/320] the realest minas --- Themes/Til Death/BGAnimations/ScreenInit background/default.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Themes/Til Death/BGAnimations/ScreenInit background/default.lua b/Themes/Til Death/BGAnimations/ScreenInit background/default.lua index ffa5e84570..bed02046e1 100644 --- a/Themes/Til Death/BGAnimations/ScreenInit background/default.lua +++ b/Themes/Til Death/BGAnimations/ScreenInit background/default.lua @@ -100,6 +100,7 @@ local minanyms = { "notcool", "mina restepped as a pad file", "sapient typo conglomerate", + "Real Stepmania Client", } math.random()