From e8b67e864330595d36ae6ee0fe561f555fa9dc0d Mon Sep 17 00:00:00 2001 From: Ryan Herriman Date: Thu, 4 Jan 2024 09:53:47 -0700 Subject: [PATCH 1/5] Completely ignore TeamColor elements for now --- src/level/LevelLoader.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/level/LevelLoader.cpp b/src/level/LevelLoader.cpp index 3d4283cd..e3318d93 100644 --- a/src/level/LevelLoader.cpp +++ b/src/level/LevelLoader.cpp @@ -154,12 +154,19 @@ struct ALFWalker: pugi::xml_tree_walker { } void handle_element(pugi::xml_node& node, std::string& name) { - // eval ALL node attributes and put them into the symbol table - // unless it's a 'unique' and then it doesn't make any sense - if (name.compare("unique") != 0) - handle_set(node); - // Read any global state we can from the element. - read_context(node); + // Eval ALL node attributes and put them into the symbol table + // unless it's a 'unique' and then it doesn't make any sense. If + // it's a 'TeamColor' (ScoreKeeper plugin) we also want to ignore + // it just to make sure it doesn't interfere with anything. + if (name.compare("unique") != 0 && name.compare("TeamColor") != 0) { + handle_set(node); + } + + // Read any global state we can from the element, unless it's + // 'TeamColor' in which case we still want to keep it separate. + if (name.compare("TeamColor") != 0) { + read_context(node); + } if (name.compare("map") == 0) handle_map(node); else if (name.compare("enum") == 0) handle_enum(node); @@ -183,6 +190,7 @@ struct ALFWalker: pugi::xml_tree_walker { handle_object(node, name); } else if (name.compare("Wall") == 0) handle_wall(node); + else if (name.compare("TeamColor") == 0) handle_teamcolor(node); else if (name.compare("include") == 0) handle_include(node); else handle_object(node, name); } @@ -326,6 +334,9 @@ struct ALFWalker: pugi::xml_tree_walker { theWall->MakeWallFromRect(&gLastBoxRect, gLastBoxRounding, 0, true); } + void handle_teamcolor(pugi::xml_node& node) { + } + void handle_include(pugi::xml_node& node) { std::string path = node.attribute("alf").value(); if (depth < 5 && From 01b61299f254699b4e9b5bddd43de82822b6924e Mon Sep 17 00:00:00 2001 From: Ryan Herriman Date: Fri, 5 Jan 2024 20:39:42 -0700 Subject: [PATCH 2/5] Move objects.json loading into AssetManager Also cleaned up several extraneous Resource.h includes and misunderstood syntax I introduced. This work is in preparation for attempting to add an additional object type, CTeamColorAdjuster. --- Avara.xcodeproj/project.pbxproj | 2 +- src/assets/AssetManager.cpp | 25 ++++++++++++++++++++++++- src/assets/AssetManager.h | 21 ++++++++++++++++++++- src/audio/CSoundHub.cpp | 1 - src/bsp/CBSPPart.cpp | 1 - src/bsp/CScaledBSP.cpp | 1 - src/game/CAbstractActor.h | 1 - src/game/CAvaraGame.cpp | 1 - src/game/CWorldShader.cpp | 1 - src/{game => level}/LinkLoose.cpp | 28 +++++----------------------- src/level/LinkLoose.h | 1 - src/net/CCommManager.cpp | 1 - src/util/CStringDictionary.cpp | 1 - 13 files changed, 50 insertions(+), 35 deletions(-) rename src/{game => level}/LinkLoose.cpp (87%) diff --git a/Avara.xcodeproj/project.pbxproj b/Avara.xcodeproj/project.pbxproj index 5b283cb9..ba1f8cc3 100644 --- a/Avara.xcodeproj/project.pbxproj +++ b/Avara.xcodeproj/project.pbxproj @@ -1337,7 +1337,6 @@ E5890C2129895118007A875D /* GoodyRecord.h */, E5890C1029895118007A875D /* InfoMessages.h */, E5890C4129895118007A875D /* KeyFuncs.h */, - E5890C0229895118007A875D /* LinkLoose.cpp */, E5890BDD29895118007A875D /* Messages.h */, E5890BE429895118007A875D /* PlayerConfig.h */, E247DE222A0EB51B001CA630 /* PlayerRatingsSimpleElo.cpp */, @@ -1419,6 +1418,7 @@ E5890C9129895118007A875D /* InternalVars.h */, E5890C9329895118007A875D /* LevelLoader.cpp */, E5890C9529895118007A875D /* LevelLoader.h */, + E5890C0229895118007A875D /* LinkLoose.cpp */, E5890C9229895118007A875D /* LinkLoose.h */, E5890C9629895118007A875D /* Parser.cpp */, E5890C9429895118007A875D /* Parser.h */, diff --git a/src/assets/AssetManager.cpp b/src/assets/AssetManager.cpp index 50c8a1d9..3e1b436a 100644 --- a/src/assets/AssetManager.cpp +++ b/src/assets/AssetManager.cpp @@ -45,6 +45,7 @@ std::shared_ptr AssetManager::assetStorage = _localStorage; std::vector> AssetManager::repositoryStack = { _localRepo }; +std::shared_ptr AssetManager::objectTypes = nullptr; SimpleAssetCache AssetManager::manifestCache = {}; SimpleAssetCache AssetManager::avarascriptCache = {}; AssetCache AssetManager::bspCache = {}; @@ -64,6 +65,15 @@ std::vector AssetManager::GetAvailablePackages() return pkgs; } +std::shared_ptr AssetManager::GetEnumeratedObjectTypes() +{ + if (objectTypes == nullptr) { + LoadEnumeratedObjectTypes(); + } + + return objectTypes; +} + std::optional AssetManager::GetResolvedAlfPath(std::string relativePath) { // Attempt to load from packages in priority order. @@ -170,6 +180,7 @@ void AssetManager::Init() { LoadManifest(NoPackage); LoadScript(NoPackage); + LoadEnumeratedObjectTypes(); } OSErr AssetManager::LoadLevel(std::string packageName, std::string relativePath, std::string &levelName) @@ -219,7 +230,7 @@ bool AssetManager::PackageInStorage(std::string packageName) return (bool)GetPackagePath(packageName); } -std::string AssetManager::GetBasePackagePath(BasePackage basePackage) throw() +std::string AssetManager::GetBasePackagePath(BasePackage basePackage) { std::stringstream path; path << baseStorage->GetRootPath(); @@ -298,6 +309,18 @@ std::string AssetManager::GetOggPath(MaybePackage package, int16_t id) return GetFullPath(package, relativePath.str()); } +void AssetManager::LoadEnumeratedObjectTypes() +{ + std::stringstream path; + path << baseStorage->GetRootPath() << PATHSEP << "objects.json"; + std::ifstream file(path.str()); + if (file.fail()) { + throw std::runtime_error("Failed to load objects.json"); + } else { + objectTypes = std::make_shared(nlohmann::json::parse(file)); + } +} + void AssetManager::LoadManifest(MaybePackage package) { std::string path = GetManifestPath(package); diff --git a/src/assets/AssetManager.h b/src/assets/AssetManager.h index a9470a24..c04a80a2 100644 --- a/src/assets/AssetManager.h +++ b/src/assets/AssetManager.h @@ -79,6 +79,15 @@ class AssetManager { */ static std::vector GetAvailablePackages(); + /** + * Get a JSON object containing descriptions of every Avarascript object that can be + * instantiated, listed in their properly enumerated order. The order is critical for + * `LinkLoose`, which maps Avarascript object names with their actual C++ types. + * + * @return the enumerated object descriptions + */ + static std::shared_ptr GetEnumeratedObjectTypes(); + /** * Get the full filesystem path for an ALF file, if it is available. * @@ -155,6 +164,7 @@ class AssetManager { static std::shared_ptr baseStorage; static std::shared_ptr assetStorage; static std::vector> repositoryStack; + static std::shared_ptr objectTypes; static SimpleAssetCache manifestCache; static SimpleAssetCache avarascriptCache; static AssetCache bspCache; @@ -168,7 +178,7 @@ class AssetManager { * @throws std::invalid_argument Thrown when there is no path defined for the base package. * @return the path to the base package */ - static std::string GetBasePackagePath(BasePackage basePackage) throw(); + static std::string GetBasePackagePath(BasePackage basePackage); /** * Get the filesystem path for the specified package, if it's available. @@ -229,6 +239,15 @@ class AssetManager { */ static std::string GetOggPath(MaybePackage package, int16_t id); + /** + * Load the JSON file containing descriptions of every Avarascript object that can be + * instantiated, listed in their properly enumerated order. The order is critical for + * `LinkLoose`, which maps Avarascript object names with their actual C++ types. + * + * @throws std::runtime_error Thrown when the JSON file cannot be read. + */ + static void LoadEnumeratedObjectTypes(); + /** * Load the specified package's manifest file. * diff --git a/src/audio/CSoundHub.cpp b/src/audio/CSoundHub.cpp index 845812d1..27de44b9 100644 --- a/src/audio/CSoundHub.cpp +++ b/src/audio/CSoundHub.cpp @@ -15,7 +15,6 @@ #include "CRateSound.h" #include "CSoundMixer.h" #include "Memory.h" -#include "Resource.h" #include diff --git a/src/bsp/CBSPPart.cpp b/src/bsp/CBSPPart.cpp index 07e3743e..6c8cdc21 100644 --- a/src/bsp/CBSPPart.cpp +++ b/src/bsp/CBSPPart.cpp @@ -13,7 +13,6 @@ #include "CViewParameters.h" #include "Memory.h" -#include "Resource.h" #include "AvaraDefines.h" #include diff --git a/src/bsp/CScaledBSP.cpp b/src/bsp/CScaledBSP.cpp index 38f0b227..196b648c 100644 --- a/src/bsp/CScaledBSP.cpp +++ b/src/bsp/CScaledBSP.cpp @@ -10,7 +10,6 @@ #include "CScaledBSP.h" #include "Memory.h" -#include "Resource.h" #include "AvaraGL.h" void CScaledBSP::IScaledBSP(Fixed scale, short resId, CAbstractActor *anActor, short aPartCode) { diff --git a/src/game/CAbstractActor.h b/src/game/CAbstractActor.h index fe8c185d..11dc512d 100644 --- a/src/game/CAbstractActor.h +++ b/src/game/CAbstractActor.h @@ -16,7 +16,6 @@ #include "FastMat.h" #include "LevelLoader.h" #include "RayHit.h" -#include "Resource.h" // define ENABLE_FPS_DEBUG in files where you want FPS_DEBUG output, BEFORE including this header #ifdef ENABLE_FPS_DEBUG diff --git a/src/game/CAvaraGame.cpp b/src/game/CAvaraGame.cpp index b0423ecf..d47e028f 100755 --- a/src/game/CAvaraGame.cpp +++ b/src/game/CAvaraGame.cpp @@ -49,7 +49,6 @@ //#include "Sound.h" #include "CHUD.h" #include "Preferences.h" -#include "Resource.h" #include "ARGBColor.h" #include "Debug.h" diff --git a/src/game/CWorldShader.cpp b/src/game/CWorldShader.cpp index a71359f5..9ee94cdb 100644 --- a/src/game/CWorldShader.cpp +++ b/src/game/CWorldShader.cpp @@ -12,7 +12,6 @@ #include "CAvaraApp.h" #include "CAvaraGame.h" #include "CViewParameters.h" -#include "Resource.h" #include "CBSPPart.h" #include "AvaraGL.h" diff --git a/src/game/LinkLoose.cpp b/src/level/LinkLoose.cpp similarity index 87% rename from src/game/LinkLoose.cpp rename to src/level/LinkLoose.cpp index 8475da40..44224ab2 100644 --- a/src/game/LinkLoose.cpp +++ b/src/level/LinkLoose.cpp @@ -9,6 +9,7 @@ #include "LinkLoose.h" +#include "AssetManager.h" #include "CAreaActor.h" #include "CBall.h" #include "CDome.h" @@ -49,13 +50,9 @@ #include -#include -#include +#include #include - -static json objectDescriptor; - enum { koNoObject = 0, koWalker, @@ -188,30 +185,15 @@ void *CreateObjectByIndex(short objectId) { } } -void InitLinkLoose() { - char *objectsPath = new char [1024]; - BundlePath("rsrc/objects.json", objectsPath); - std::ifstream infile(objectsPath); - if (infile.fail()) { - SDL_Log("*** Failed to load objects.json"); - } - else { - objectDescriptor = json::parse(infile); - infile.close(); - } - delete [] objectsPath; -} - void *CreateNamedObject(StringPtr theName) { - if (objectDescriptor.empty()) - InitLinkLoose(); + static auto objectDescriptor = AssetManager::GetEnumeratedObjectTypes(); std::string objectName((char *)theName + 1, theName[0]); - if (objectDescriptor["objects"].count(objectName) == 0) { + if (objectDescriptor->value("objects", {}).count(objectName) == 0) { SDL_Log("UNKNOWN OBJECT TYPE in CreateNamedObject(%s)\n", objectName.c_str()); return NULL; } - short index = objectDescriptor["objects"][objectName]["index"]; + short index = objectDescriptor->value("objects", {})[objectName]["index"]; return CreateObjectByIndex(index); } diff --git a/src/level/LinkLoose.h b/src/level/LinkLoose.h index 3299309c..f2e81395 100644 --- a/src/level/LinkLoose.h +++ b/src/level/LinkLoose.h @@ -12,4 +12,3 @@ void *CreateObjectByIndex(short objectId); void *CreateNamedObject(StringPtr theName); -void InitLinkLoose(); diff --git a/src/net/CCommManager.cpp b/src/net/CCommManager.cpp index 98bb47f9..7aba592f 100644 --- a/src/net/CCommManager.cpp +++ b/src/net/CCommManager.cpp @@ -10,7 +10,6 @@ #include "CCommManager.h" #include "Memory.h" -#include "Resource.h" #include "System.h" #include "Debug.h" diff --git a/src/util/CStringDictionary.cpp b/src/util/CStringDictionary.cpp index a63468a4..7e35b01a 100644 --- a/src/util/CStringDictionary.cpp +++ b/src/util/CStringDictionary.cpp @@ -13,7 +13,6 @@ #include "CStringDictionary.h" #include "RamFiles.h" -#include "Resource.h" #include "PascalStrings.h" #include From 3882825832af01158c63a6a74a85d5792bae7ca3 Mon Sep 17 00:00:00 2001 From: Ryan Herriman Date: Sat, 6 Jan 2024 16:47:28 -0700 Subject: [PATCH 3/5] Working `CTeamColorAdjuster` --- Avara.xcodeproj/project.pbxproj | 8 ++++++++ rsrc/objects.json | 11 +++++++++++ src/game/CAvaraApp.cpp | 3 +++ src/game/CTeamColorAdjuster.cpp | 32 ++++++++++++++++++++++++++++++++ src/game/CTeamColorAdjuster.h | 10 ++++++++++ src/gui/CApplication.cpp | 7 +++++-- src/gui/CApplication.h | 6 +++--- src/gui/CPlayerWindow.cpp | 2 +- src/gui/ColorManager.cpp | 7 +++++++ src/gui/ColorManager.h | 2 ++ src/level/LevelLoader.cpp | 16 +++------------- src/level/LinkLoose.cpp | 8 ++++++++ 12 files changed, 93 insertions(+), 19 deletions(-) create mode 100644 src/game/CTeamColorAdjuster.cpp create mode 100644 src/game/CTeamColorAdjuster.h diff --git a/Avara.xcodeproj/project.pbxproj b/Avara.xcodeproj/project.pbxproj index ba1f8cc3..15414af4 100644 --- a/Avara.xcodeproj/project.pbxproj +++ b/Avara.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 9419E8472B49ECB1007C50D0 /* CTeamColorAdjuster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9419E8462B49ECB1007C50D0 /* CTeamColorAdjuster.cpp */; }; + 9419E8482B49ECB1007C50D0 /* CTeamColorAdjuster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9419E8462B49ECB1007C50D0 /* CTeamColorAdjuster.cpp */; }; 944F2F702B323F1900856E53 /* LocalAssetRepository.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 944F2F6F2B323F1900856E53 /* LocalAssetRepository.cpp */; }; 944F2F712B323F1900856E53 /* LocalAssetRepository.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 944F2F6F2B323F1900856E53 /* LocalAssetRepository.cpp */; }; 9465BFD22B30C2A00050681C /* AssetManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9465BFD12B30C2A00050681C /* AssetManager.cpp */; }; @@ -365,6 +367,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 9419E8452B49EC89007C50D0 /* CTeamColorAdjuster.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CTeamColorAdjuster.h; sourceTree = ""; }; + 9419E8462B49ECB1007C50D0 /* CTeamColorAdjuster.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = CTeamColorAdjuster.cpp; sourceTree = ""; }; 944F2F6D2B32379C00856E53 /* AssetRepository.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AssetRepository.h; sourceTree = ""; }; 944F2F6E2B323E2100856E53 /* LocalAssetRepository.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalAssetRepository.h; sourceTree = ""; }; 944F2F6F2B323F1900856E53 /* LocalAssetRepository.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LocalAssetRepository.cpp; sourceTree = ""; }; @@ -1308,6 +1312,8 @@ E5890C1C29895118007A875D /* CSphereActor.h */, E5890BF529895118007A875D /* CSwitchActor.cpp */, E5890BDB29895118007A875D /* CSwitchActor.h */, + 9419E8462B49ECB1007C50D0 /* CTeamColorAdjuster.cpp */, + 9419E8452B49EC89007C50D0 /* CTeamColorAdjuster.h */, E5890C4629895118007A875D /* CTeleporter.cpp */, E5890BE129895118007A875D /* CTeleporter.h */, E5890C2B29895118007A875D /* CTextActor.cpp */, @@ -2115,6 +2121,7 @@ 94924EB02B3A894900197378 /* OggFile.cpp in Sources */, E517F09D299713DB0036B206 /* CSwitchActor.cpp in Sources */, E517F09E299713DB0036B206 /* CTeleporter.cpp in Sources */, + 9419E8482B49ECB1007C50D0 /* CTeamColorAdjuster.cpp in Sources */, E517F09F299713DB0036B206 /* CTextActor.cpp in Sources */, E517F0A0299713DB0036B206 /* CTriPyramidActor.cpp in Sources */, E517F0A1299713DB0036B206 /* CUfo.cpp in Sources */, @@ -2281,6 +2288,7 @@ 94924EAF2B3A894900197378 /* OggFile.cpp in Sources */, E5890EFB29895124007A875D /* darwin.mm in Sources */, E5890CBC29895118007A875D /* CAbstractMissile.cpp in Sources */, + 9419E8472B49ECB1007C50D0 /* CTeamColorAdjuster.cpp in Sources */, E5890CD229895118007A875D /* CBall.cpp in Sources */, E5890CC929895118007A875D /* CPlayerMissile.cpp in Sources */, E5890F0729895124007A875D /* desccombobox.cpp in Sources */, diff --git a/rsrc/objects.json b/rsrc/objects.json index 93caee2e..5d4ccea9 100644 --- a/rsrc/objects.json +++ b/rsrc/objects.json @@ -551,6 +551,17 @@ "attrs": {}, "index": 37, "description": "" + }, + "TeamColor": { + "type": "actor", + "attrs": { + "mask": { + "default": "allTeams", + "description": "Specifies the team(s) whose colors will be overridden by this adjuster. Usable values include `T1`, `T2`, ...`T8`, or even expressions like `T1 + T3 + T5 + T7`." + } + }, + "index": 38, + "description": "Adjusts the team color value for the specified team(s)." } } } diff --git a/src/game/CAvaraApp.cpp b/src/game/CAvaraApp.cpp index e391ca04..2ed87431 100755 --- a/src/game/CAvaraApp.cpp +++ b/src/game/CAvaraApp.cpp @@ -12,6 +12,7 @@ #include "CAvaraApp.h" #include "AssetManager.h" +#include "ColorManager.h" #include "AvaraGL.h" #include "AvaraScoreInterface.h" #include "AvaraTCP.h" @@ -270,6 +271,8 @@ OSErr CAvaraAppImpl::LoadLevel(std::string set, std::string levelTag, CPlayerMan gCurrentGame = itsGame.get(); itsGame->loadedSet = set; + ColorManager::refresh(this); + std::string levelName; OSErr result = AssetManager::LoadLevel(set, levelTag, levelName); diff --git a/src/game/CTeamColorAdjuster.cpp b/src/game/CTeamColorAdjuster.cpp new file mode 100644 index 00000000..fd2391dd --- /dev/null +++ b/src/game/CTeamColorAdjuster.cpp @@ -0,0 +1,32 @@ +#include "CTeamColorAdjuster.h" + +#include "ARGBColor.h" +#include "AvaraDefines.h" +#include "ColorManager.h" + +void CTeamColorAdjuster::BeginScript() { + CAbstractActor::BeginScript(); + + ProgramVariable(iMask, -1); +} + +CAbstractActor *CTeamColorAdjuster::EndScript() { + CAbstractActor::EndScript(); + + colorMask = ReadLongVar(iMask); + + ARGBColor newColor = GetPixelColor(); + + // Currently unused, but theoretically should be supported. We just don't do highlighting yet. + // auto newHighlightColor = GetOtherPixelColor(); + + for (uint8_t i = 1; i <= kMaxTeamColors; i++) { + uint16_t teamMask = 1 << i; + if (colorMask & teamMask) { + ColorManager::overrideTeamColor(i, newColor); + } + } + + Dispose(); + return NULL; +} diff --git a/src/game/CTeamColorAdjuster.h b/src/game/CTeamColorAdjuster.h new file mode 100644 index 00000000..3f6eab5c --- /dev/null +++ b/src/game/CTeamColorAdjuster.h @@ -0,0 +1,10 @@ +#pragma once +#include "CAbstractActor.h" + +class CTeamColorAdjuster : public CAbstractActor { +public: + long colorMask; + + void BeginScript(); + virtual CAbstractActor *EndScript(); +}; diff --git a/src/gui/CApplication.cpp b/src/gui/CApplication.cpp index 1f607b57..12c7af54 100755 --- a/src/gui/CApplication.cpp +++ b/src/gui/CApplication.cpp @@ -51,8 +51,11 @@ void CApplication::BroadcastCommand(int theCommand) { } } -void CApplication::PrefChanged(std::string name) { - ColorManager::refresh(this); +void CApplication::PrefChanged(std::string name, const bool refreshColors) { + if (refreshColors) { + ColorManager::refresh(this); + } + for (auto win : windowList) { win->PrefChanged(name); } diff --git a/src/gui/CApplication.h b/src/gui/CApplication.h index 9eff7694..0b03f74f 100755 --- a/src/gui/CApplication.h +++ b/src/gui/CApplication.h @@ -30,7 +30,7 @@ class CApplication : public nanogui::Screen { virtual bool HandleEvent(SDL_Event &event) { return false; } // Called when preference values change. - virtual void PrefChanged(std::string name); + virtual void PrefChanged(std::string name, const bool refreshColors = true); virtual void WindowResized(int width, int height) {} @@ -59,9 +59,9 @@ class CApplication : public nanogui::Screen { std::vector Matches(const std::string matchStr); - template void Set(const std::string name, const T value) { + template void Set(const std::string name, const T value, const bool refreshColors = true) { _prefs[name] = value; - PrefChanged(name); + PrefChanged(name, refreshColors); } bool Update(const std::string name, std::string &value); diff --git a/src/gui/CPlayerWindow.cpp b/src/gui/CPlayerWindow.cpp index d36ad111..321f425a 100644 --- a/src/gui/CPlayerWindow.cpp +++ b/src/gui/CPlayerWindow.cpp @@ -35,7 +35,7 @@ CPlayerWindow::CPlayerWindow(CApplication *app) : CWindow(app, "Player") { hullBox = new nanogui::ComboBox(this, hullTypes); hullBox->setCallback([app, this](int selectedIdx) { - app->Set(kHullTypeTag, hullValues[selectedIdx]); + app->Set(kHullTypeTag, hullValues[selectedIdx], false); }); hullBox->popup()->setSize(nanogui::Vector2i(180, 140)); hullBox->setSelectedIndex(app->Get(kHullTypeTag)); diff --git a/src/gui/ColorManager.cpp b/src/gui/ColorManager.cpp index d37e423d..3abc12fd 100644 --- a/src/gui/ColorManager.cpp +++ b/src/gui/ColorManager.cpp @@ -300,6 +300,13 @@ void ColorManager::setMissileLaunchedColor(ARGBColor color) { ColorManager::missileLaunchedColor = color; } +void ColorManager::overrideTeamColor(uint8_t num, ARGBColor color) { + if (num <= kMaxTeamColors) { + ColorManager::teamColors[num] = color; + ColorManager::teamTextColors[num] = 0xff333333; + } +} + void ColorManager::refresh(CApplication *app) { ColorManager::setColorBlind(app->Get(kColorBlindMode)); ColorManager::setHUDColor(ARGBColor::Parse(app->String(kHUDColor)).value_or(0xff03f5f5)); diff --git a/src/gui/ColorManager.h b/src/gui/ColorManager.h index 6f759f35..f25976d9 100644 --- a/src/gui/ColorManager.h +++ b/src/gui/ColorManager.h @@ -186,6 +186,8 @@ class ColorManager { static void setMissileArmedColor(ARGBColor color); static void setMissileLaunchedColor(ARGBColor color); + static void overrideTeamColor(uint8_t num, ARGBColor color); + static void refresh(CApplication *app); private: ColorManager() {} diff --git a/src/level/LevelLoader.cpp b/src/level/LevelLoader.cpp index e3318d93..f83853c8 100644 --- a/src/level/LevelLoader.cpp +++ b/src/level/LevelLoader.cpp @@ -155,18 +155,12 @@ struct ALFWalker: pugi::xml_tree_walker { void handle_element(pugi::xml_node& node, std::string& name) { // Eval ALL node attributes and put them into the symbol table - // unless it's a 'unique' and then it doesn't make any sense. If - // it's a 'TeamColor' (ScoreKeeper plugin) we also want to ignore - // it just to make sure it doesn't interfere with anything. - if (name.compare("unique") != 0 && name.compare("TeamColor") != 0) { + // unless it's a 'unique' and then it doesn't make any sense. + if (name.compare("unique") != 0) { handle_set(node); } - // Read any global state we can from the element, unless it's - // 'TeamColor' in which case we still want to keep it separate. - if (name.compare("TeamColor") != 0) { - read_context(node); - } + read_context(node); if (name.compare("map") == 0) handle_map(node); else if (name.compare("enum") == 0) handle_enum(node); @@ -190,7 +184,6 @@ struct ALFWalker: pugi::xml_tree_walker { handle_object(node, name); } else if (name.compare("Wall") == 0) handle_wall(node); - else if (name.compare("TeamColor") == 0) handle_teamcolor(node); else if (name.compare("include") == 0) handle_include(node); else handle_object(node, name); } @@ -334,9 +327,6 @@ struct ALFWalker: pugi::xml_tree_walker { theWall->MakeWallFromRect(&gLastBoxRect, gLastBoxRounding, 0, true); } - void handle_teamcolor(pugi::xml_node& node) { - } - void handle_include(pugi::xml_node& node) { std::string path = node.attribute("alf").value(); if (depth < 5 && diff --git a/src/level/LinkLoose.cpp b/src/level/LinkLoose.cpp index 44224ab2..94057db8 100644 --- a/src/level/LinkLoose.cpp +++ b/src/level/LinkLoose.cpp @@ -38,6 +38,7 @@ #include "CSoundActor.h" #include "CSphereActor.h" #include "CSwitchActor.h" +#include "CTeamColorAdjuster.h" #include "CTeleporter.h" #include "CTextActor.h" #include "CTriPyramidActor.h" @@ -95,6 +96,9 @@ enum { koYonBox, koYonSphere, + // New additions: + koTeamColor, + koLastObject }; @@ -179,6 +183,10 @@ void *CreateObjectByIndex(short objectId) { case koYonSphere: return new CYonSphere; + // New additions: + case koTeamColor: + return new CTeamColorAdjuster; + default: SDL_Log("UNKNOWN OBJECT TYPE in CreateObjectByIndex(%d)\n", objectId); return NULL; From 676d7fbedbbb3e126cbf9be0e695673508c5e660 Mon Sep 17 00:00:00 2001 From: Ryan Herriman Date: Sun, 7 Jan 2024 14:05:26 -0700 Subject: [PATCH 4/5] Better implementation of SK-style color overrides Also includes a new preference for opting out of them! --- src/game/CAvaraApp.cpp | 2 +- src/game/CTeamColorAdjuster.cpp | 20 ++++++++++++-------- src/gui/CApplication.cpp | 6 ++---- src/gui/CApplication.h | 6 +++--- src/gui/CPlayerWindow.cpp | 2 +- src/gui/ColorManager.cpp | 14 ++++++++++++-- src/gui/ColorManager.h | 17 ++++++++++++----- src/gui/Preferences.h | 2 ++ 8 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/game/CAvaraApp.cpp b/src/game/CAvaraApp.cpp index 2ed87431..9b4ad61e 100755 --- a/src/game/CAvaraApp.cpp +++ b/src/game/CAvaraApp.cpp @@ -271,7 +271,7 @@ OSErr CAvaraAppImpl::LoadLevel(std::string set, std::string levelTag, CPlayerMan gCurrentGame = itsGame.get(); itsGame->loadedSet = set; - ColorManager::refresh(this); + ColorManager::resetOverrides(); std::string levelName; OSErr result = AssetManager::LoadLevel(set, levelTag, levelName); diff --git a/src/game/CTeamColorAdjuster.cpp b/src/game/CTeamColorAdjuster.cpp index fd2391dd..56271986 100644 --- a/src/game/CTeamColorAdjuster.cpp +++ b/src/game/CTeamColorAdjuster.cpp @@ -2,7 +2,9 @@ #include "ARGBColor.h" #include "AvaraDefines.h" +#include "CAvaraApp.h" #include "ColorManager.h" +#include "Preferences.h" void CTeamColorAdjuster::BeginScript() { CAbstractActor::BeginScript(); @@ -13,17 +15,19 @@ void CTeamColorAdjuster::BeginScript() { CAbstractActor *CTeamColorAdjuster::EndScript() { CAbstractActor::EndScript(); - colorMask = ReadLongVar(iMask); + if (!itsGame->itsApp->Boolean(kIgnoreLevelCustomColorsTag)) { + colorMask = ReadLongVar(iMask); - ARGBColor newColor = GetPixelColor(); + ARGBColor newColor = GetPixelColor(); - // Currently unused, but theoretically should be supported. We just don't do highlighting yet. - // auto newHighlightColor = GetOtherPixelColor(); + // Currently unused, but theoretically should be supported. (We don't do highlighting yet.) + // auto newHighlightColor = GetOtherPixelColor(); - for (uint8_t i = 1; i <= kMaxTeamColors; i++) { - uint16_t teamMask = 1 << i; - if (colorMask & teamMask) { - ColorManager::overrideTeamColor(i, newColor); + for (uint8_t i = 1; i <= kMaxTeamColors; i++) { + uint16_t teamMask = 1 << i; + if (colorMask & teamMask) { + ColorManager::overrideTeamColor(i, newColor); + } } } diff --git a/src/gui/CApplication.cpp b/src/gui/CApplication.cpp index 12c7af54..8be066b3 100755 --- a/src/gui/CApplication.cpp +++ b/src/gui/CApplication.cpp @@ -51,10 +51,8 @@ void CApplication::BroadcastCommand(int theCommand) { } } -void CApplication::PrefChanged(std::string name, const bool refreshColors) { - if (refreshColors) { - ColorManager::refresh(this); - } +void CApplication::PrefChanged(std::string name) { + ColorManager::refresh(this); for (auto win : windowList) { win->PrefChanged(name); diff --git a/src/gui/CApplication.h b/src/gui/CApplication.h index 0b03f74f..9eff7694 100755 --- a/src/gui/CApplication.h +++ b/src/gui/CApplication.h @@ -30,7 +30,7 @@ class CApplication : public nanogui::Screen { virtual bool HandleEvent(SDL_Event &event) { return false; } // Called when preference values change. - virtual void PrefChanged(std::string name, const bool refreshColors = true); + virtual void PrefChanged(std::string name); virtual void WindowResized(int width, int height) {} @@ -59,9 +59,9 @@ class CApplication : public nanogui::Screen { std::vector Matches(const std::string matchStr); - template void Set(const std::string name, const T value, const bool refreshColors = true) { + template void Set(const std::string name, const T value) { _prefs[name] = value; - PrefChanged(name, refreshColors); + PrefChanged(name); } bool Update(const std::string name, std::string &value); diff --git a/src/gui/CPlayerWindow.cpp b/src/gui/CPlayerWindow.cpp index 321f425a..d36ad111 100644 --- a/src/gui/CPlayerWindow.cpp +++ b/src/gui/CPlayerWindow.cpp @@ -35,7 +35,7 @@ CPlayerWindow::CPlayerWindow(CApplication *app) : CWindow(app, "Player") { hullBox = new nanogui::ComboBox(this, hullTypes); hullBox->setCallback([app, this](int selectedIdx) { - app->Set(kHullTypeTag, hullValues[selectedIdx], false); + app->Set(kHullTypeTag, hullValues[selectedIdx]); }); hullBox->popup()->setSize(nanogui::Vector2i(180, 140)); hullBox->setSelectedIndex(app->Get(kHullTypeTag)); diff --git a/src/gui/ColorManager.cpp b/src/gui/ColorManager.cpp index 3abc12fd..9e53637e 100644 --- a/src/gui/ColorManager.cpp +++ b/src/gui/ColorManager.cpp @@ -66,6 +66,9 @@ std::string ColorManager::teamColorNames[kMaxTeamColors + 1] = { "White" }; +std::optional ColorManager::teamColorOverrides[kMaxTeamColors + 1] = {}; +std::optional ColorManager::teamTextColorOverrides[kMaxTeamColors + 1] = {}; + ARGBColor ColorManager::messageColors[3] = { 0xffffffff, 0xff92ebe9, @@ -302,8 +305,8 @@ void ColorManager::setMissileLaunchedColor(ARGBColor color) { void ColorManager::overrideTeamColor(uint8_t num, ARGBColor color) { if (num <= kMaxTeamColors) { - ColorManager::teamColors[num] = color; - ColorManager::teamTextColors[num] = 0xff333333; + ColorManager::teamColorOverrides[num] = color; + ColorManager::teamTextColorOverrides[num] = 0xff333333; } } @@ -315,3 +318,10 @@ void ColorManager::refresh(CApplication *app) { ColorManager::setHUDCriticalColor(ARGBColor::Parse(app->String(kHUDCriticalColor)).value_or(0xfffa1313)); ColorManager::setHUDAlpha(app->Get(kHUDAlpha)); } + +void ColorManager::resetOverrides() { + for (uint8_t i = 0; i < kMaxTeamColors + 1; i++) { + ColorManager::teamColorOverrides[i] = {}; + ColorManager::teamTextColorOverrides[i] = {}; + } +} diff --git a/src/gui/ColorManager.h b/src/gui/ColorManager.h index f25976d9..f4b5c257 100644 --- a/src/gui/ColorManager.h +++ b/src/gui/ColorManager.h @@ -144,20 +144,24 @@ class ColorManager { static inline std::optional getTeamColor(uint8_t num) { return (num <= kMaxTeamColors) - ? teamColors[num] + ? (teamColorOverrides[num]) + ? teamColorOverrides[num] + : teamColors[num] : std::optional{}; } static inline std::optional getTeamTextColor(uint8_t num) { return (num <= kMaxTeamColors) - ? teamTextColors[num] + ? (teamTextColorOverrides[num]) + ? teamTextColorOverrides[num] + : teamTextColors[num] : std::optional{}; } static inline std::optional getTeamColorName(uint8_t num) { return (num <= kMaxTeamColors) - ? teamColorNames[num] - : std::optional{}; + ? teamColorNames[num] + : std::optional{}; } static inline ARGBColor getMessageColor(MsgCategory category) { @@ -170,7 +174,7 @@ class ColorManager { } static inline ARGBColor getPingColor(uint8_t num) { - return pingColors[num]; + return pingColors[num]; } static inline float getHUDAlpha() { @@ -189,6 +193,7 @@ class ColorManager { static void overrideTeamColor(uint8_t num, ARGBColor color); static void refresh(CApplication *app); + static void resetOverrides(); private: ColorManager() {} @@ -224,6 +229,8 @@ class ColorManager { static ARGBColor teamColors[kMaxTeamColors + 1]; static ARGBColor teamTextColors[kMaxTeamColors + 1]; static std::string teamColorNames[kMaxTeamColors + 1]; + static std::optional teamColorOverrides[kMaxTeamColors + 1]; + static std::optional teamTextColorOverrides[kMaxTeamColors + 1]; static ARGBColor messageColors[3]; static ARGBColor pingColors[3]; }; diff --git a/src/gui/Preferences.h b/src/gui/Preferences.h index f4ce592c..ed7bb393 100755 --- a/src/gui/Preferences.h +++ b/src/gui/Preferences.h @@ -69,6 +69,7 @@ using json = nlohmann::json; #define kHUDShowTime "hudShowTime" #define kHUDShowKillFeed "hudShowKillFeed" #define kShowNewHUD "showNewHUD" +#define kIgnoreLevelCustomColorsTag "ignoreLevelCustomColors" // Network & Tracker #define kLastAddress "lastAddress" @@ -184,6 +185,7 @@ static json defaultPrefs = { {kRecentLevels, {}}, {kSoundVolume, 100}, {kIgnoreCustomColorsTag, false}, + {kIgnoreLevelCustomColorsTag, false}, {kIgnoreCustomGoodySound, false}, {kThrottle, 0}, {kGoodGamePhrases, {}}, From 385cb43db7052e8e73367ff6deaa21399a3581fa Mon Sep 17 00:00:00 2001 From: Ryan Herriman Date: Sun, 7 Jan 2024 14:21:44 -0700 Subject: [PATCH 5/5] Cleanups --- src/gui/ColorManager.h | 4 ++-- src/level/LinkLoose.cpp | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/ColorManager.h b/src/gui/ColorManager.h index f4b5c257..d508e42c 100644 --- a/src/gui/ColorManager.h +++ b/src/gui/ColorManager.h @@ -160,8 +160,8 @@ class ColorManager { static inline std::optional getTeamColorName(uint8_t num) { return (num <= kMaxTeamColors) - ? teamColorNames[num] - : std::optional{}; + ? teamColorNames[num] + : std::optional{}; } static inline ARGBColor getMessageColor(MsgCategory category) { diff --git a/src/level/LinkLoose.cpp b/src/level/LinkLoose.cpp index 94057db8..262bd460 100644 --- a/src/level/LinkLoose.cpp +++ b/src/level/LinkLoose.cpp @@ -51,7 +51,6 @@ #include -#include #include enum {