diff --git a/.clang-tidy b/.clang-tidy index 69fe82afafb..135f35e4664 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -87,8 +87,11 @@ Checks: > # Treat warnings as errors for CI/CD WarningsAsErrors: false -# Header filter to include project headers -HeaderFilterRegex: '(Core|Generals|GeneralsMD|Dependencies)/.*\.(h|hpp)$' +# Header filter to include project headers. +# Match relative paths (Core/Foo.h, Core\Foo.h) and absolute ones (.../Core/Foo.h). +# Accept both / and \ so Windows diagnostics are not dropped. +HeaderFilterRegex: '(^|[/\\])(Core|GeneralsMD|Generals|Dependencies)[/\\].*\.(h|hpp)$' +ExcludeHeaderFilterRegex: '(^|[/\\])(MaxSDK|_deps)[/\\]' # Check options for specific rules CheckOptions: diff --git a/AI_POLICY.md b/AI_POLICY.md new file mode 100644 index 00000000000..ac02cc6bd2d --- /dev/null +++ b/AI_POLICY.md @@ -0,0 +1,55 @@ +# AI Contribution Policy + +Today, artificial intelligence (AI) tools are being deployed in many coding environments. In this policy, **AI-assisted** refers to the broader development workflow, including AI coding assistants, agentic development tools, and related services. **LLM-generated** refers specifically to content produced by the large language models (LLMs) used by many of these tools. Some of the "lower-end" features like keyword-driven code completion can be useful aids; other LLM-based tools make it very easy to generate contributions without the submitter fully understanding how the code works, or the consequences of specific implementation choices. These latter forms of AI assistance cause major overhead for project maintainers. + +To protect the quality of the project and the sanity of our contributors, we have adopted the following policy regarding AI-generated content. + +## 1. Accountability + +**The human contributor is the sole party responsible for the contribution.** + +If you submit a pull request that includes LLM-generated code, documentation, or comments: + +- You must fully understand every line of code in the submission. +- You must be able to explain the "why" behind the implementation during the review process. +- You are responsible for verifying that the code is human-readable, maintainable and logically correct. +- All code needs to be tested and verified. + +"The AI generated it and it works for me" is never an acceptable answer to a reviewer's question. You must write review responses yourself. AI tools may assist with translation, meaning-preserving edits, or formatting, but you must verify the final wording. If unsure of an answer, say so rather than presenting an AI tool's output as your own. + +Autonomous AI agents may not submit pull requests, nor comments in other pull requests, issues or discussions. + +## 2. Disclosure + +If an LLM was used to generate a significant portion of your contribution, we require you to **disclose it** in the pull request description. You must clarify to what extent the generated content was polished by human intervention. + +You must not use AI to create the pull request description itself (unless you’ve used it for translation) - as discussed above, we expect pull requests to be submitted by humans. + +## 3. Intentionality + +We do not accept pull requests and issues that result from running an AI tool over the codebase to find improvements without prior context or alignment with the project. + +- **Focused changes:** Do not submit pull requests that perform broad refactoring or cleanup suggested by AI unless a maintainer specifically requests it. +- **Design First:** For any non-trivial change, we strongly recommend opening an **Issue** or **Discussion** first, or reach out to the **Discord**. Pull requests that arrive out of the blue with significant AI-generated logic that doesn't align with our roadmap or architecture will be closed. +- **Quality over Quantity:** We value one thoughtful, manually crafted pull request over ten AI-assisted fixes for nonexistent or trivial issues. + +New contributors are discouraged from submitting pull requests with thousands of lines changed or added with the help of AI, because human code reviewers cannot attend such volumes at the risk of wasting precious time with potentially poor LLM-generated code. + +## 4. Prohibited Uses + +The following are strictly prohibited and will result in immediate closure of a pull request or issue and potentially a block from the organization: + +- **Automated Pull Request Description:** Using AI to write the entire pull request description. The description the AI generates is often vague, overly elaborate, or fails to accurately describe the technical changes. We want to hear from *you* - the developer - why this change matters (see points 1 & 2). +- **Unvetted Boilerplate:** Submitting large blocks of LLM-generated boilerplate that haven't been trimmed to what's actually necessary. If you don't understand what the code does, don't submit the pull request. +- **Hallucinated Features:** Submitting pull requests for features or bug fixes that don't exist, based on AI hallucinations about the project's capabilities. + +## 5. Enforcement + +TheSuperHackers project maintainers reserve the right to close any pull request that appears to be a low-effort AI contribution, without providing a detailed technical critique. If a maintainer suspects you do not understand your pull request, it will be closed immediately. + +Cases of repeated violations of these (or any of our other contributor guidelines) could result in a ban from our repositories. + +### Acknowledgement + +This policy was written by humans, based on the work in the [Mastodon AI Policy](https://github.com/mastodon/.github/blob/main/AI_POLICY.md), the [CloudNativePG AI Policy](https://github.com/cloudnative-pg/governance/blob/main/AI_POLICY.md), the [Ghostty AI Policy](https://github.com/ghostty-org/ghostty/blob/main/AI_POLICY.md), and the Linux Foundation's [Generative AI Policy](https://www.linuxfoundation.org/legal/generative-ai). + diff --git a/CMakeLists.txt b/CMakeLists.txt index 98bc8ca8bde..2fa3022238e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,10 @@ if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR) message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt") endif() +# Define VCPKG feature before the project block +# since they need to be initialized before the toolchain is +include(cmake/config-vcpkg.cmake) + # Top level project, doesn't really affect anything. project(genzh LANGUAGES C CXX) diff --git a/CMakePresets.json b/CMakePresets.json index a15058115b1..9ae40e205cb 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -83,8 +83,7 @@ "CMAKE_EXPORT_COMPILE_COMMANDS": "ON", "CMAKE_MSVC_DEBUG_INFORMATION_FORMAT": "$<$:Embedded>", "CMAKE_MSVC_RUNTIME_LIBRARY": "MultiThreaded$<$:Debug>DLL", - "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", - "VCPKG_OVERLAY_TRIPLETS": "${sourceDir}/triplets" + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" } }, { diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 364822257b4..3239e584a79 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,13 +8,9 @@ To contribute, fork this repository to create your own copy that you can clone l Prefer opening fewer high quality Pull Requests over many low quality ones. Prioritize polishing existing Pull Requests instead of creating new ones. Do not open Pull Requests as draft unless there are specific requirements that justify it, because draft Pull Requests are generally not looked at and pollute the Pull Request section. -## AI code generation guidelines +## AI contribution policy -Creating changes with LLM generated code is generally allowed. The author is responsible for verifying that all generated code is human readable, maintainable and logically correct. Furthermore, all generated code needs to be tested and verified. The author is not allowed to outsource the polishing of the generated code to the human code reviewers. In a Pull Request, generated code needs to be announced as such and to what extent it was polished by human intervention. - -### New code contributors and AI generated code - -New contributors are discouraged from submitting Pull Requests with thousands of lines changed or added with the help of LLMs, because human code reviewers cannot attend such volumes at the risk of wasting precious time with potentially poorly generated code. +Ensure that you have read and understood the [AI Contribution Policy](AI_POLICY.md). ## Code guidelines diff --git a/Core/GameEngine/CMakeLists.txt b/Core/GameEngine/CMakeLists.txt index 79716b52d3c..4ea43e5a550 100644 --- a/Core/GameEngine/CMakeLists.txt +++ b/Core/GameEngine/CMakeLists.txt @@ -142,7 +142,7 @@ set(GAMEENGINE_SRC Include/Common/XferLoad.h Include/Common/XferSave.h Include/GameClient/Anim2D.h -# Include/GameClient/AnimateWindowManager.h + Include/GameClient/AnimateWindowManager.h # Include/GameClient/CampaignManager.h Include/GameClient/ChallengeGenerals.h Include/GameClient/ClientInstance.h @@ -184,8 +184,8 @@ set(GAMEENGINE_SRC Include/GameClient/GameText.h Include/GameClient/GameWindow.h Include/GameClient/GameWindowGlobal.h -# Include/GameClient/GameWindowID.h -# Include/GameClient/GameWindowManager.h + Include/GameClient/GameWindowID.h + Include/GameClient/GameWindowManager.h Include/GameClient/GameWindowTransitions.h Include/GameClient/GlobalLanguage.h Include/GameClient/GraphDraw.h @@ -711,7 +711,7 @@ set(GAMEENGINE_SRC Source/GameClient/GameText.cpp Source/GameClient/GlobalLanguage.cpp Source/GameClient/GraphDraw.cpp -# Source/GameClient/GUI/AnimateWindowManager.cpp + Source/GameClient/GUI/AnimateWindowManager.cpp Source/GameClient/GUI/ChallengeGenerals.cpp Source/GameClient/GUI/ControlBar/ControlBar.cpp Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp @@ -741,10 +741,10 @@ set(GAMEENGINE_SRC Source/GameClient/GUI/GameFont.cpp Source/GameClient/GUI/GameWindow.cpp Source/GameClient/GUI/GameWindowGlobal.cpp -# Source/GameClient/GUI/GameWindowManager.cpp -# Source/GameClient/GUI/GameWindowManagerScript.cpp + Source/GameClient/GUI/GameWindowManager.cpp + Source/GameClient/GUI/GameWindowManagerScript.cpp Source/GameClient/GUI/GameWindowTransitions.cpp -# Source/GameClient/GUI/GameWindowTransitionsStyles.cpp + Source/GameClient/GUI/GameWindowTransitionsStyles.cpp Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp diff --git a/Core/GameEngine/Include/Common/GameAudio.h b/Core/GameEngine/Include/Common/GameAudio.h index 7816b306d32..e9d0a38b9f6 100644 --- a/Core/GameEngine/Include/Common/GameAudio.h +++ b/Core/GameEngine/Include/Common/GameAudio.h @@ -244,8 +244,6 @@ class AudioManager : public SubsystemInterface // on zoom. virtual void set3DVolumeAdjustment( Real volumeAdjustment ); - virtual Bool has3DSensitiveStreamsPlaying() const = 0; - virtual void *getHandleForBink() = 0; virtual void releaseHandleForBink() = 0; diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/AnimateWindowManager.h b/Core/GameEngine/Include/GameClient/AnimateWindowManager.h similarity index 100% rename from GeneralsMD/Code/GameEngine/Include/GameClient/AnimateWindowManager.h rename to Core/GameEngine/Include/GameClient/AnimateWindowManager.h diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowID.h b/Core/GameEngine/Include/GameClient/GameWindowID.h similarity index 100% rename from GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowID.h rename to Core/GameEngine/Include/GameClient/GameWindowID.h diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowManager.h b/Core/GameEngine/Include/GameClient/GameWindowManager.h similarity index 100% rename from GeneralsMD/Code/GameEngine/Include/GameClient/GameWindowManager.h rename to Core/GameEngine/Include/GameClient/GameWindowManager.h diff --git a/Core/GameEngine/Include/GameClient/ParticleSys.h b/Core/GameEngine/Include/GameClient/ParticleSys.h index 54b93e2bc60..17284b84566 100644 --- a/Core/GameEngine/Include/GameClient/ParticleSys.h +++ b/Core/GameEngine/Include/GameClient/ParticleSys.h @@ -515,7 +515,7 @@ class ParticleSystemTemplate : public MemoryPoolObject, protected ParticleSystem void validate(); - AsciiString getName() const { return m_name; } + const AsciiString& getName() const { return m_name; } // This function was made const because of update modules' module data being all const. ParticleSystem *createSlaveSystem( Bool createSlaves = TRUE ) const ; ///< if returns non-null, it is a slave system for use @@ -607,15 +607,16 @@ class ParticleSystem : public MemoryPoolObject, void setInitialDelay( UnsignedInt delay ) { m_delayLeft = delay; } const AsciiString& getParticleTypeName() const { return m_particleTypeName; } ///< return the name of the particles - const Bool isUsingDrawables() const { return m_particleType == DRAWABLE; } - const Bool isUsingStreak() const { return m_particleType == STREAK; } - const Bool isUsingSmudge() const { return m_particleType == SMUDGE; } - const Bool isUsingVolumeParticles() const { return m_particleType == VOLUME_PARTICLE; } - const UnsignedInt getVolumeParticleDepth() const { return m_volumeParticleDepth; } + Bool isUsingParticles() const { return m_particleType == PARTICLE; } + Bool isUsingDrawables() const { return m_particleType == DRAWABLE; } + Bool isUsingStreak() const { return m_particleType == STREAK; } + Bool isUsingSmudge() const { return m_particleType == SMUDGE; } + Bool isUsingVolumeParticles() const { return m_particleType == VOLUME_PARTICLE; } + UnsignedInt getVolumeParticleDepth() const { return m_volumeParticleDepth; } - Bool shouldBillboard() { return !m_isGroundAligned; } + Bool shouldBillboard() const { return !m_isGroundAligned; } - ParticleShaderType getShaderType() { return m_shaderType; } + ParticleShaderType getShaderType() const { return m_shaderType; } void setSlave( ParticleSystem *slave ); ///< set a slave system for us ParticleSystem *getSlave() { return m_slaveSystem; } diff --git a/Core/GameEngine/Include/GameClient/VideoPlayer.h b/Core/GameEngine/Include/GameClient/VideoPlayer.h index 98a7d4c8d67..a7380a2114c 100644 --- a/Core/GameEngine/Include/GameClient/VideoPlayer.h +++ b/Core/GameEngine/Include/GameClient/VideoPlayer.h @@ -245,6 +245,8 @@ class VideoPlayerInterface : public SubsystemInterface virtual const FieldParse *getFieldParse() const = 0; ///< Return the field parse info virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ) = 0; ///< Notify the video player that they can now ask for an audio handle, or they need to give theirs up. + + virtual void setVolume( Real volume ) = 0; ///< Push a new speech volume to the video player's audio output }; @@ -299,6 +301,13 @@ class VideoPlayer : public VideoPlayerInterface }; +class NullVideoPlayer : public VideoPlayer +{ + public: + + virtual void setVolume( Real ) override { } +}; + extern VideoPlayerInterface *TheVideoPlayer; //---------------------------------------------------------------------------- diff --git a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp index 12aa807920e..79e6277de93 100644 --- a/Core/GameEngine/Source/Common/Audio/GameAudio.cpp +++ b/Core/GameEngine/Source/Common/Audio/GameAudio.cpp @@ -708,7 +708,12 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) m_scriptMusicVolume = volume; } - m_musicVolume = m_scriptMusicVolume * m_systemMusicVolume; + const Real newVolume = m_scriptMusicVolume * m_systemMusicVolume; + if (m_musicVolume != newVolume) + { + m_musicVolume = newVolume; + m_volumeHasChanged = true; + } } if (whichToAffect & AudioAffect_Sound) { @@ -718,7 +723,12 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) m_scriptSoundVolume = volume; } - m_soundVolume = m_scriptSoundVolume * m_systemSoundVolume; + const Real newVolume = m_scriptSoundVolume * m_systemSoundVolume; + if (m_soundVolume != newVolume) + { + m_soundVolume = newVolume; + m_volumeHasChanged = true; + } } if (whichToAffect & AudioAffect_Sound3D) { @@ -727,7 +737,13 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) } else { m_scriptSound3DVolume = volume; } - m_sound3DVolume = m_scriptSound3DVolume * m_systemSound3DVolume; + + const Real newVolume = m_scriptSound3DVolume * m_systemSound3DVolume; + if (m_sound3DVolume != newVolume) + { + m_sound3DVolume = newVolume; + m_volumeHasChanged = true; + } } if (whichToAffect & AudioAffect_Speech) { @@ -736,10 +752,14 @@ void AudioManager::setVolume( Real volume, AudioAffect whichToAffect ) } else { m_scriptSpeechVolume = volume; } - m_speechVolume = m_scriptSpeechVolume * m_systemSpeechVolume; - } - m_volumeHasChanged = true; + const Real newVolume = m_scriptSpeechVolume * m_systemSpeechVolume; + if (m_speechVolume != newVolume) + { + m_speechVolume = newVolume; + m_volumeHasChanged = true; + } + } } //------------------------------------------------------------------------------------------------- @@ -760,17 +780,13 @@ Real AudioManager::getVolume( AudioAffect whichToGet ) //------------------------------------------------------------------------------------------------- void AudioManager::set3DVolumeAdjustment( Real volumeAdjustment ) { - m_sound3DVolume = volumeAdjustment * m_scriptSound3DVolume * m_systemSound3DVolume; - - // clamp - if (m_sound3DVolume < 0.0f) - m_sound3DVolume = 0.0f; + const Real newVolume = clamp(0.0f, volumeAdjustment * m_scriptSound3DVolume * m_systemSound3DVolume, 1.0f); - if (m_sound3DVolume > 1.0f) - m_sound3DVolume = 1.0f; - - if ( ! has3DSensitiveStreamsPlaying() ) - m_volumeHasChanged = TRUE; + if (m_sound3DVolume != newVolume) + { + m_sound3DVolume = newVolume; + m_volumeHasChanged = true; + } } //------------------------------------------------------------------------------------------------- diff --git a/Core/GameEngine/Source/Common/CommandLine.cpp b/Core/GameEngine/Source/Common/CommandLine.cpp index caff2d12b05..45215bbbf09 100644 --- a/Core/GameEngine/Source/Common/CommandLine.cpp +++ b/Core/GameEngine/Source/Common/CommandLine.cpp @@ -732,8 +732,10 @@ Int parseLoadSave(char *args[], int num) TheWritableGlobalData->m_shellMapOn = FALSE; TheWritableGlobalData->m_playIntro = FALSE; TheWritableGlobalData->m_playSizzle = FALSE; + + return 2; } - return 2; + return 1; } //============================================================================= diff --git a/Core/GameEngine/Source/Common/ReplaySimulation.cpp b/Core/GameEngine/Source/Common/ReplaySimulation.cpp index fec11454cce..404aee373e3 100644 --- a/Core/GameEngine/Source/Common/ReplaySimulation.cpp +++ b/Core/GameEngine/Source/Common/ReplaySimulation.cpp @@ -87,7 +87,7 @@ int ReplaySimulation::simulateReplaysInThisProcess(const std::vectorgetScienceVec(); + const ScienceVec &sv = commandButton->getScienceVec(); if (! sv.empty()) { st = sv[ 0 ]; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp rename to Core/GameEngine/Source/GameClient/GUI/GameWindowManager.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp similarity index 100% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp rename to Core/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp similarity index 97% rename from GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp rename to Core/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp index 09ebceef16c..083ce94a4c2 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp +++ b/Core/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp @@ -66,6 +66,24 @@ // DEFINES //////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- static void drawTypeText( GameWindow *window, DisplayString *str); + +static Color getFlashTransitionColor( UnsignedByte alpha ) +{ +#if RTS_GENERALS + return GameMakeColor( 255, 203, 45, alpha ); +#elif RTS_ZEROHOUR + return GameMakeColor( 255, 255, 255, alpha ); +#endif +} + +static Color getFullFadeTransitionColor( UnsignedByte alpha ) +{ +#if RTS_GENERALS + return GameMakeColor( 255, 190, 0, alpha ); +#elif RTS_ZEROHOUR + return GameMakeColor( 60, 60, 180, alpha ); +#endif +} //----------------------------------------------------------------------------- // PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- @@ -185,44 +203,44 @@ void FlashTransition::draw() { case FLASHTRANSITION_FADE_IN_1: { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 255, 255,100)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 255, 255, 33)); + TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, getFlashTransitionColor( 100 )); + TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, getFlashTransitionColor( 33 )); } break; case FLASHTRANSITION_FADE_IN_2: { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 255, 255,150)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 255, 255, 66)); + TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, getFlashTransitionColor( 150 )); + TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, getFlashTransitionColor( 66 )); } break; case FLASHTRANSITION_FADE_IN_3: { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 255, 255,200)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 255, 255, 99)); + TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, getFlashTransitionColor( 200 )); + TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, getFlashTransitionColor( 99 )); } break; case FLASHTRANSITION_FADE_TO_BACKGROUND_1: { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 255, 255, 75)); + TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, getFlashTransitionColor( 75 )); } break; case FLASHTRANSITION_FADE_TO_BACKGROUND_2: { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 255, 255,50)); + TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, getFlashTransitionColor( 50 )); } break; case FLASHTRANSITION_FADE_TO_BACKGROUND_3: { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 255, 255, 25)); + TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, getFlashTransitionColor( 25 )); } break; case FLASHTRANSITION_FADE_TO_BACKGROUND_4: { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 255, 255, 10)); + TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, getFlashTransitionColor( 10 )); } break; } @@ -503,50 +521,50 @@ void ButtonFlashTransition::draw() case BUTTONFLASHTRANSITION_FADE_IN_1: { //PushButtonImageDrawThree(m_win, 100); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 255, 255,100)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 255, 255, 75)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, getFlashTransitionColor( 100 )); + TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, getFlashTransitionColor( 75 )); } break; case BUTTONFLASHTRANSITION_FADE_IN_2: { //PushButtonImageDrawThree(m_win, 150); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 255, 255,150)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 255, 255, 150)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, getFlashTransitionColor( 150 )); + TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, getFlashTransitionColor( 150 )); } break; case BUTTONFLASHTRANSITION_FADE_IN_3: { //PushButtonImageDrawThree(m_win, 200); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 255, 255,200)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 255, 255, 200)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, getFlashTransitionColor( 200 )); + TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, getFlashTransitionColor( 200 )); } break; case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_1: { PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 255, 255, 150)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, getFlashTransitionColor( 150 )); } break; case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_2: { PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 255, 255,100)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, getFlashTransitionColor( 100 )); } break; case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_3: { PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 255, 255, 50)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, getFlashTransitionColor( 50 )); } break; case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_4: { PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 255, 255,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 255, 255, 15)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, getFlashTransitionColor( 250 )); + TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, getFlashTransitionColor( 15 )); } break; case BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_1: @@ -1876,7 +1894,7 @@ void FullFadeTransition::draw() if(alpha > 255) alpha = 255; TheDisplay->drawFillRect(m_pos.x, m_pos.y, m_size.x, m_size.y , GameMakeColor(0,0,0,alpha)); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y, m_size.x, m_size.y , 1.0f, GameMakeColor(60,60,180,alpha)); + TheDisplay->drawOpenRect(m_pos.x, m_pos.y, m_size.x, m_size.y , 1.0f, getFullFadeTransitionColor( alpha )); } void FullFadeTransition::skip() diff --git a/Core/GameEngine/Source/GameClient/GUI/IMEManager.cpp b/Core/GameEngine/Source/GameClient/GUI/IMEManager.cpp index d0daa15839b..8698de746a7 100644 --- a/Core/GameEngine/Source/GameClient/GUI/IMEManager.cpp +++ b/Core/GameEngine/Source/GameClient/GUI/IMEManager.cpp @@ -104,29 +104,29 @@ class IMEManager : public IMEManagerInterface public: IMEManager(); - ~IMEManager(); + ~IMEManager() override; - virtual void init(); - virtual void reset(); - virtual void update(); + virtual void init() override; + virtual void reset() override; + virtual void update() override; - virtual void attach( GameWindow *window ); ///< attach IME to specified window - virtual void detach(); ///< detach IME from current window - virtual void enable(); ///< Enable IME - virtual void disable(); ///< Disable IME - virtual Bool isEnabled(); ///< Is IME enabled - virtual Bool isAttachedTo( GameWindow *window ); ///< Is the manager attached toa window - virtual GameWindow* getWindow(); ///< Returns the window we are currently attached to - virtual Bool isComposing(); ///< Manager is currently composing new input string - virtual void getCompositionString( UnicodeString &string ); ///< Return the current composition string - virtual Int getCompositionCursorPosition(); ///< Returns the composition cursor position - virtual Int getIndexBase(); ///< Get index base for candidate list + virtual void attach( GameWindow *window ) override; ///< attach IME to specified window + virtual void detach() override; ///< detach IME from current window + virtual void enable() override; ///< Enable IME + virtual void disable() override; ///< Disable IME + virtual Bool isEnabled() override; ///< Is IME enabled + virtual Bool isAttachedTo( GameWindow *window ) override; ///< Is the manager attached toa window + virtual GameWindow* getWindow() override; ///< Returns the window we are currently attached to + virtual Bool isComposing() override; ///< Manager is currently composing new input string + virtual void getCompositionString( UnicodeString &string ) override; ///< Return the current composition string + virtual Int getCompositionCursorPosition() override; ///< Returns the composition cursor position + virtual Int getIndexBase() override; ///< Get index base for candidate list - virtual Int getCandidateCount(); ///< Returns the total number of candidates - virtual const UnicodeString* getCandidate( Int index ); ///< Returns the candidate string - virtual Int getSelectedCandidateIndex(); ///< Returns the indexed of the currently selected candidate - virtual Int getCandidatePageSize(); ///< Returns the page size for the candidates list - virtual Int getCandidatePageStart(); ///< Returns the index of the first visibel candidate + virtual Int getCandidateCount() override; ///< Returns the total number of candidates + virtual const UnicodeString* getCandidate( Int index ) override; ///< Returns the candidate string + virtual Int getSelectedCandidateIndex() override; ///< Returns the indexed of the currently selected candidate + virtual Int getCandidatePageSize() override; ///< Returns the page size for the candidates list + virtual Int getCandidatePageStart() override; ///< Returns the index of the first visibel candidate @@ -134,8 +134,8 @@ class IMEManager : public IMEManagerInterface virtual Bool serviceIMEMessage( void *windowsHandle, UnsignedInt message, Int wParam, - Int lParam ); - virtual Int result(); ///< result return value of last serviced IME message + Int lParam ) override; + virtual Int result() override; ///< result return value of last serviced IME message protected: diff --git a/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp b/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp index 321423df5b1..21689c864c5 100644 --- a/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp +++ b/Core/GameEngine/Source/GameClient/MessageStream/SelectionXlat.cpp @@ -1176,7 +1176,7 @@ GameMessageDisposition SelectionTranslator::onMetaSelectTeam(MAYBE_UNUSED const Squad *selectedSquad = player->getHotkeySquad(group); if (selectedSquad != nullptr) { - VecObjectPtr objlist = selectedSquad->getLiveObjects(); + const VecObjectPtr& objlist = selectedSquad->getLiveObjects(); Int numObjs = objlist.size(); if (numObjs > 0) { @@ -1201,7 +1201,7 @@ GameMessageDisposition SelectionTranslator::onMetaSelectTeam(MAYBE_UNUSED const Squad *selectedSquad = player->getHotkeySquad(group); if (selectedSquad != nullptr) { - VecObjectPtr objlist = selectedSquad->getLiveObjects(); + const VecObjectPtr& objlist = selectedSquad->getLiveObjects(); Int numObjs = objlist.size(); for (Int i = 0; i < numObjs; ++i) { @@ -1244,7 +1244,7 @@ GameMessageDisposition SelectionTranslator::onMetaAddTeam(MAYBE_UNUSED const Gam Squad *selectedSquad = player->getHotkeySquad(group); if (selectedSquad != nullptr) { - VecObjectPtr objlist = selectedSquad->getLiveObjects(); + const VecObjectPtr& objlist = selectedSquad->getLiveObjects(); Int numObjs = objlist.size(); if (numObjs > 0) { @@ -1275,7 +1275,7 @@ GameMessageDisposition SelectionTranslator::onMetaAddTeam(MAYBE_UNUSED const Gam Squad *selectedSquad = player->getHotkeySquad(group); if (selectedSquad != nullptr) { - VecObjectPtr objlist = selectedSquad->getLiveObjects(); + const VecObjectPtr& objlist = selectedSquad->getLiveObjects(); Int numObjs = objlist.size(); // TheSuperHackers @bugfix skyaero 22/07/2025 Can't select other units if you have a structure selected. So deselect the structure to prevent group force attack exploit. @@ -1311,7 +1311,7 @@ GameMessageDisposition SelectionTranslator::onMetaViewTeam(MAYBE_UNUSED const Ga Squad *selectedSquad = player->getHotkeySquad(group); if (selectedSquad != nullptr) { - VecObjectPtr objlist = selectedSquad->getLiveObjects(); + const VecObjectPtr& objlist = selectedSquad->getLiveObjects(); Int numObjs = objlist.size(); if (numObjs > 0) { diff --git a/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp b/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp index 7ed2614f029..1eb12589158 100644 --- a/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp +++ b/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp @@ -2125,9 +2125,15 @@ Bool ParticleSystem::update( Int localPlayerIndex ) // If we have been "destroyed", wait for all of our particles to die off, // then destroy ourselves (return false). // + // TheSuperHackers @bugfix Mauller 30/08/2026 Delay destruction to prevent finite-lifetime slave particle systems being orphaned. + // Orphaned particle systems lack positional data, render at the world origin and do not complete their full lifecycle. if (m_isDestroyed && !m_systemParticlesHead) - return false; + { + if (m_slaveSystem && !m_slaveSystem->isSystemForever()) + return true; + return false; + } // monitor particle system lifetime if (m_isForever == false) @@ -2142,7 +2148,12 @@ Bool ParticleSystem::update( Int localPlayerIndex ) // check if time is up if (m_systemLifetimeLeft == 0) - return false; + { + if (m_slaveSystem && !m_slaveSystem->isSystemForever()) + m_isDestroyed = true; + else + return false; + } } return true; diff --git a/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp b/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp index 74f722cfabe..d1c3ea6cd58 100644 --- a/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp +++ b/Core/GameEngine/Source/GameLogic/AI/AIPathfind.cpp @@ -9577,6 +9577,13 @@ Bool Pathfinder::isAttackViewBlockedByObstacle(const Object* attacker, const Coo } if (w) { +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Stubbjax 23/08/2026 Don't consider the attack blocked if it is a contact weapon. + // This allows weapons such as suicide bombs to be triggered if the unit is blocked by building geometry. + if (w->isContactWeapon()) + return false; +#endif + Bool viewBlocked; if (victim) viewBlocked = !w->isClearGoalFiringLineOfSightTerrain(attacker, attackerPos, victim); diff --git a/Core/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp b/Core/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp index 9d98350bd0b..2375e07e58a 100644 --- a/Core/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp +++ b/Core/GameEngine/Source/GameNetwork/GameSpy/LadderDefs.cpp @@ -183,7 +183,7 @@ static LadderInfo *parseLadder(AsciiString raw) AsciiStringList validFactions = lad->validFactions; for (AsciiStringListIterator it = validFactions.begin(); it != validFactions.end(); ++it) { - AsciiString faction = *it; + const AsciiString &faction = *it; AsciiString marker; marker.format("INI:Faction%s", faction.str()); DEBUG_LOG(("Faction %s has marker %s corresponding to str %ls", faction.str(), marker.str(), TheGameText->fetch(marker).str())); @@ -196,7 +196,7 @@ static LadderInfo *parseLadder(AsciiString raw) std::list qmMaps = TheGameSpyConfig->getQMMaps(); for (std::list::const_iterator it = qmMaps.begin(); it != qmMaps.end(); ++it) { - AsciiString mapName = *it; + const AsciiString &mapName = *it; // check sizes on the maps before allowing them const MapMetaData *md = TheMapCache->findMap(mapName); diff --git a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h index ab03a842bc0..fd00a31629f 100644 --- a/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h +++ b/Core/GameEngineDevice/Include/MilesAudioDevice/MilesAudioManager.h @@ -229,10 +229,6 @@ class MilesAudioManager : public AudioManager virtual void closeAnySamplesUsingFile( const void *fileToClose ) override; - - virtual Bool has3DSensitiveStreamsPlaying() const override; - - protected: // 3-D functions virtual void setDeviceListenerPosition() override; @@ -382,7 +378,6 @@ class MilesAudioManagerDummy : public MilesAudioManager virtual void adjustVolumeOfPlayingAudio(AsciiString eventName, Real newVolume) override {} virtual void removePlayingAudio(AsciiString eventName) override {} virtual void removeAllDisabledAudio() override {} - virtual Bool has3DSensitiveStreamsPlaying() const override { return false; } virtual void* getHandleForBink() override { return nullptr; } virtual void releaseHandleForBink() override {} virtual void friend_forcePlayAudioEventRTS(const AudioEventRTS* eventToPlay) override {} diff --git a/Core/GameEngineDevice/Include/MiniAudioDevice/MiniAudioManager.h b/Core/GameEngineDevice/Include/MiniAudioDevice/MiniAudioManager.h index 1b938608755..28aa59d2634 100644 --- a/Core/GameEngineDevice/Include/MiniAudioDevice/MiniAudioManager.h +++ b/Core/GameEngineDevice/Include/MiniAudioDevice/MiniAudioManager.h @@ -153,8 +153,6 @@ class MiniAudioManager : public AudioManager virtual void closeAnySamplesUsingFile(const void *fileToClose); - virtual Bool has3DSensitiveStreamsPlaying(void) const; - protected: // 3-D functions virtual void setDeviceListenerPosition(void); diff --git a/Core/GameEngineDevice/Include/OpenALAudioDevice/OpenALAudioManager.h b/Core/GameEngineDevice/Include/OpenALAudioDevice/OpenALAudioManager.h index 553f03eace9..f4a1ef1c8a1 100644 --- a/Core/GameEngineDevice/Include/OpenALAudioDevice/OpenALAudioManager.h +++ b/Core/GameEngineDevice/Include/OpenALAudioDevice/OpenALAudioManager.h @@ -157,8 +157,6 @@ friend class OpenALAudioFileCache; virtual void closeAnySamplesUsingFile(const void *fileToClose) override; - virtual Bool has3DSensitiveStreamsPlaying(void) const; - protected: // 3-D functions virtual void setDeviceListenerPosition(void); diff --git a/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h b/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h index db992c268c4..0f1c7d8ed08 100644 --- a/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h +++ b/Core/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h @@ -105,11 +105,6 @@ class BinkVideoStream : public VideoStream class BinkVideoPlayer : public VideoPlayer { - - protected: - - VideoStreamInterface* createStream( HBINK handle ); - public: // subsytem requirements @@ -131,7 +126,16 @@ class BinkVideoPlayer : public VideoPlayer virtual VideoStreamInterface* load( AsciiString movieTitle ) override; ///< Load video file in to memory for playback virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ) override; + virtual void setVolume( Real volume ) override; virtual void initializeBinkWithMiles(); + + protected: + + VideoStreamInterface* createStream( HBINK handle ); + + private: + + static Int calculateMovieAudioVolume( Real volume ); }; diff --git a/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h b/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h index 2d6e55d7053..3635aa78e02 100644 --- a/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h +++ b/Core/GameEngineDevice/Include/VideoDevice/FFmpeg/FFmpegVideoPlayer.h @@ -121,6 +121,7 @@ class FFmpegVideoPlayer : public VideoPlayer virtual VideoStreamInterface* load( AsciiString movieTitle ); ///< Load video file in to memory for playback virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ); + virtual void setVolume( Real ) override { } virtual void initializeBinkWithMiles(); }; diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DParticleSys.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DParticleSys.h index 41481701474..cf17783902e 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DParticleSys.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DParticleSys.h @@ -50,13 +50,21 @@ class W3DParticleSystemManager : public ParticleSystemManager virtual Int getOnScreenParticleCount() override { return m_onScreenParticleCount; } private: + Bool finishedBatch(const ParticleSystem& system, const RefCountPtr& texture); + void initializeBatch(const ParticleSystem& system, const RefCountPtr& texture); + void flushParticleBatch(RenderInfoClass& rinfo, UnsignedInt& pointCount); + enum { MAX_POINTS_PER_GROUP = 512 }; + RefCountPtr m_batchTexture; ///< the texture used as the drawing surface for batched particle draws PointGroupClass *m_pointGroup; ///< the point group that contains all of the particles StreakLineClass *m_streakLine; ///< the streak class that contains all of the streaks ShareBufferClass *m_posBuffer; ///< array of particle positions ShareBufferClass *m_RGBABuffer; ///< array of particle color and alpha ShareBufferClass *m_sizeBuffer; ///< array of particle sizes ShareBufferClass *m_angleBuffer; ///< array of particle orientations + + ParticleSystemInfo::ParticleShaderType m_batchShaderType; Bool m_readyToRender; ///< if true, it is OK to render + Bool m_batchBillboard; }; diff --git a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h index 02423a0e867..dc251abc698 100644 --- a/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h +++ b/Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DScorch.h @@ -68,17 +68,24 @@ class W3DScorch : public W3DScorchInterface enum { - MAX_SCORCH_VERTEX = 8194, - MAX_SCORCH_INDEX = 6 * 8194, + MAX_SCORCH_VERTEX = 32768, + MAX_SCORCH_INDEX = 65535, MAX_SCORCH_MARKS = 500, SCORCH_MARKS_IN_TEXTURE = 9, - SCORCH_PER_ROW = 3 + SCORCH_PER_ROW = 3, + }; + + enum WriteScorchResult + { + SCORCH_WRITTEN, + SCORCH_SKIPPED, + SCORCH_BUFFER_FULL, }; Bool isDuplicate(const TScorch& scorch) const; void updateScorches(WorldHeightMap& map); ///< Update m_vertexScorch and m_indexScorch so all scorches will be drawn. - Bool writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, UnsignedInt diffuse, - VertexFormatXYZDUV1* curVb, UnsignedShort* curIb); + WriteScorchResult writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, UnsignedInt diffuse, + VertexFormatXYZDUV1* curVb, UnsignedShort* curIb); DX8VertexBufferClass* m_vertexScorch; ///< Scorch vertex buffer. DX8IndexBufferClass* m_indexScorch; ///< indices defining a triangles for the scorch drawing. diff --git a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp index 7b0d7b73a9b..d9833392f62 100644 --- a/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MilesAudioDevice/MilesAudioManager.cpp @@ -2294,44 +2294,14 @@ void MilesAudioManager::processPlayingList() if (m_volumeHasChanged) { m_volumeHasChanged = false; - } -} - -//Patch for a rare bug (only on about 5% of in-studio machines suffer, and not all the time) . -//The actual mechanics of this problem are still elusive as of the date of this comment. 8/21/03 -//but the cause is clear. Some cinematics do a radical change in the microphone position, which -//calls for a radical 3DSoundVolume adjustment. If this happens while a stereo stream is *ENDING*, -//low-level code gets caught in a tight loop. (Hangs) on some machines. -//To prevent this condition, we just suppress the updating of 3DSoundVolume while one of these -//is on the list. Since the music tracks play continuously, they never *END* during these cinematics. -//so we filter them out as, *NOT SENSITIVE*... we do want to update 3DSoundVolume during music, -//which is almost all of the time. - -Bool MilesAudioManager::has3DSensitiveStreamsPlaying() const -{ - if ( m_playingStreams.empty() ) - return FALSE; - - for ( std::list< PlayingAudio* >::const_iterator it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it ) - { - const PlayingAudio *playing = (*it); - - if ( playing->m_audioEventRTS->getAudioEventInfo()->m_soundType != AT_Music ) - { - return TRUE; - } - - if ( playing->m_audioEventRTS->getEventName().startsWith("Game_") == FALSE ) - { - return TRUE; - } - } - - return FALSE; + // TheSuperHackers @bugfix Push speech volume changes because Bink movie audio bypasses the Miles mixer. + if (TheVideoPlayer) { + TheVideoPlayer->setVolume(getVolume(AudioAffect_Speech)); + } + } } - //------------------------------------------------------------------------------------------------- void MilesAudioManager::processFadingList() { diff --git a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp index 105d1f3b32f..b346ca10424 100644 --- a/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp +++ b/Core/GameEngineDevice/Source/MiniAudioDevice/MiniAudioManager.cpp @@ -1227,8 +1227,14 @@ void MiniAudioManager::processPlayingList(void) ++it; } - if (m_volumeHasChanged) + if (m_volumeHasChanged) { m_volumeHasChanged = false; + + // GeneralsX @bugfix Push speech volume changes because movie audio bypasses the audio mixer + if (TheVideoPlayer) { + TheVideoPlayer->setVolume(getVolume(AudioAffect_Speech)); + } + } } //------------------------------------------------------------------------------------------------- @@ -1351,25 +1357,6 @@ void MiniAudioManager::closeAnySamplesUsingFile(const void *fileToClose) // miniaudio manages file lifecycle internally after decoding } -//------------------------------------------------------------------------------------------------- -Bool MiniAudioManager::has3DSensitiveStreamsPlaying(void) const -{ - if (m_playingSounds.empty()) return FALSE; - - for (auto it = m_playingSounds.begin(); it != m_playingSounds.end(); ++it) { - const PlayingAudio *playing = (*it); - if (!playing || !playing->m_audioEventRTS) continue; - - if (playing->m_type != PAT_Stream) continue; - - const AudioEventInfo *info = playing->m_audioEventRTS->getAudioEventInfo(); - if (!info) continue; - - if (info->m_soundType != AT_Music) return TRUE; - if (playing->m_audioEventRTS->getEventName().startsWith("Game_") == FALSE) return TRUE; - } - return FALSE; -} //------------------------------------------------------------------------------------------------- Bool MiniAudioManager::startNextLoop(PlayingAudio *looping) diff --git a/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp b/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp index f70d02c8b8f..f6a32731a19 100644 --- a/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp +++ b/Core/GameEngineDevice/Source/OpenALAudioDevice/OpenALAudioManager.cpp @@ -2569,55 +2569,16 @@ void OpenALAudioManager::processPlayingList(void) if (m_volumeHasChanged) { m_volumeHasChanged = false; - } -} - -//Patch for a rare bug (only on about 5% of in-studio machines suffer, and not all the time) . -//The actual mechanics of this problem are still elusive as of the date of this comment. 8/21/03 -//but the cause is clear. Some cinematics do a radical change in the microphone position, which -//calls for a radical 3DSoundVolume adjustment. If this happens while a stereo stream is *ENDING*, -//low-level code gets caught in a tight loop. (Hangs) on some machines. -//To prevent this condition, we just suppress the updating of 3DSoundVolume while one of these -//is on the list. Since the music tracks play continuously, they never *END* during these cinematics. -//so we filter them out as, *NOT SENSITIVE*... we do want to update 3DSoundVolume during music, -//which is almost all of the time. - -Bool OpenALAudioManager::has3DSensitiveStreamsPlaying(void) const -{ - if (m_playingStreams.empty()) - return FALSE; - - for (std::list< PlayingAudio* >::const_iterator it = m_playingStreams.begin(); it != m_playingStreams.end(); ++it) - { - const PlayingAudio* playing = (*it); - - if (!playing) - continue; - - // GeneralsX @bugfix BenderAI 11/03/2026 - guard against null audioEventRTS/info - if (!playing->m_audioEventRTS) - continue; - const AudioEventInfo* info = playing->m_audioEventRTS->getAudioEventInfo(); - if (!info) - continue; - - if (info->m_soundType != AT_Music) - { - return TRUE; - } - - if (playing->m_audioEventRTS->getEventName().startsWith("Game_") == FALSE) - { - return TRUE; + // GeneralsX @bugfix Push speech volume changes because movie audio bypasses the audio mixer + if (TheVideoPlayer) { + TheVideoPlayer->setVolume(getVolume(AudioAffect_Speech)); } } - - return FALSE; - } + //------------------------------------------------------------------------------------------------- void OpenALAudioManager::processFadingList(void) { diff --git a/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp b/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp index 8964494ab2c..8d14efdb762 100644 --- a/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp +++ b/Core/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp @@ -207,18 +207,40 @@ VideoStreamInterface* BinkVideoPlayer::createStream( HBINK handle ) stream->m_player = this; m_firstStream = stream; - // never let volume go to 0, as Bink will interpret that as "play at full volume". - Int mod = (Int) ((TheAudio->getVolume(AudioAffect_Speech) * 0.8f) * 100) + 1; - Int volume = (32768*mod)/100; - DEBUG_LOG(("BinkVideoPlayer::createStream() - About to set volume (%g -> %d -> %d", - TheAudio->getVolume(AudioAffect_Speech), mod, volume)); - BinkSetVolume( stream->m_handle,0, volume); - DEBUG_LOG(("BinkVideoPlayer::createStream() - set volume")); + // TheSuperHackers @bugfix BinkWait must run first or Bink ignores the initial volume. + BinkWait( stream->m_handle ); + Int volume = calculateMovieAudioVolume( TheAudio->getVolume(AudioAffect_Speech) ); + BinkSetVolume( stream->m_handle, 0, volume ); } return stream; } +//============================================================================ +// BinkVideoPlayer::calculateMovieAudioVolume +//============================================================================ + +Int BinkVideoPlayer::calculateMovieAudioVolume( Real volume ) +{ + // Never let volume go to 0, as Bink will interpret that as "play at full volume". + Int mod = (Int) ((volume * 0.8f) * 100) + 1; + return (32768*mod)/100; +} + +//============================================================================ +// BinkVideoPlayer::setVolume +//============================================================================ + +void BinkVideoPlayer::setVolume( Real volume ) +{ + // Push the new volume to every open stream's audio output. + Int binkVolume = calculateMovieAudioVolume( volume ); + for ( VideoStreamInterface* stream = firstStream(); stream != nullptr; stream = stream->next() ) + { + BinkSetVolume( static_cast( stream )->m_handle, 0, binkVolume ); + } +} + //============================================================================ // BinkVideoPlayer::open //============================================================================ diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp index 1d2db2be3f8..5f479bc5615 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DModelDraw.cpp @@ -2621,7 +2621,7 @@ void W3DModelDraw::recalcBonesForClientParticleSystems() tmp.Scale(getDrawable()->getScale()); m_renderObject->Set_Transform(tmp); // set to identity transform - const Matrix3D boneTransform = m_renderObject->Get_Bone_Transform(boneIndex); + const Matrix3D& boneTransform = m_renderObject->Get_Bone_Transform(boneIndex); Vector3 vpos = boneTransform.Get_Translation(); rotation = boneTransform.Get_Z_Rotation(); @@ -2692,7 +2692,7 @@ Bool W3DModelDraw::updateBonesForClientParticleSystems() Int boneIndex = (*it).boneIndex; if ( (sys != nullptr) && (boneIndex != 0) ) { - const Matrix3D boneTransform = m_renderObject->Get_Bone_Transform(boneIndex);// just a little worried about state changes + const Matrix3D& boneTransform = m_renderObject->Get_Bone_Transform(boneIndex);// just a little worried about state changes Vector3 vpos = boneTransform.Get_Translation(); @@ -3514,7 +3514,7 @@ Bool W3DModelDraw::clientOnly_getRenderObjBoundBox(OBBoxClass * boundbox) const AABoxClass aabox; m_renderObject->Get_Obj_Space_Bounding_Box(aabox); - Matrix3D tm = m_renderObject->Get_Transform(); + const Matrix3D& tm = m_renderObject->Get_Transform(); // build an OBB for this AAB,transform OBBoxClass box0(aabox.Center,aabox.Extent); @@ -3718,7 +3718,7 @@ Bool W3DModelDraw::handleWeaponFireFX(WeaponSlotType wslot, Int specificBarrelTo if( ! m_renderObject->Is_Hidden() || (logicObject == nullptr) ) { // I can ask the drawable's bone position if I am not hidden (if I have no object I have no choice) - Matrix3D mtx = m_renderObject->Get_Bone_Transform(info.m_fxBone); + const Matrix3D& mtx = m_renderObject->Get_Bone_Transform(info.m_fxBone); Coord3D pos; pos.x = mtx.Get_X_Translation(); pos.y = mtx.Get_Y_Translation(); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/FlatHeightMap.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/FlatHeightMap.cpp index 2d6b8d21559..f794216dc74 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/FlatHeightMap.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/FlatHeightMap.cpp @@ -468,7 +468,6 @@ void FlatHeightMapRenderObjClass::Render(RenderInfoClass & rinfo) W3DShaderManager::updateCloud(); } - Matrix3D tm(Transform); // If there are trees, tell them to draw at the transparent time to draw. if (m_treeBuffer) { m_treeBuffer->setIsTerrain(); @@ -494,8 +493,7 @@ void FlatHeightMapRenderObjClass::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Texture(1,nullptr); ShaderClass::Invalidate(); - // tm.Scale(ObjSpaceExtent); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); DX8Wrapper::Set_Material(m_vertexMaterialClass); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp index b84ea8663ff..f5b5761d526 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/HeightMap.cpp @@ -1884,7 +1884,6 @@ void HeightMapRenderObjClass::Render(RenderInfoClass & rinfo) W3DShaderManager::updateCloud(); } - Matrix3D tm(Transform); #if 0 // There is some weirdness sometimes with the dx8 static buffers. // This usually fixes terrain flashing. jba. static Int delay = 1; @@ -1926,8 +1925,7 @@ void HeightMapRenderObjClass::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Texture(1,nullptr); ShaderClass::Invalidate(); - // tm.Scale(ObjSpaceExtent); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); //Apply the shader and material diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DParticleSys.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DParticleSys.cpp index c0a901ec7e6..9ceadaa2894 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DParticleSys.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DParticleSys.cpp @@ -46,6 +46,9 @@ W3DParticleSystemManager::W3DParticleSystemManager() { + m_batchBillboard = true; + m_batchShaderType = ParticleSystemInfo::INVALID_SHADER; + m_pointGroup = nullptr; m_streakLine = nullptr; m_posBuffer = nullptr; @@ -144,6 +147,9 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) TheSmudgeManager->resetDraw(); } + // Number of particles/points being rendered. + UnsignedInt pointCount = 0; + ParticleSystemManager::ParticleSystemList &particleSysList = TheParticleSystemManager->getAllParticleSystems(); for( ParticleSystemManager::ParticleSystemListIt it = particleSysList.begin(); it != particleSysList.end(); ++it) { @@ -156,6 +162,30 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) if (sys->isUsingDrawables()) continue; + // TheSuperHackers @performance Mauller 16/08/2026 Skip processing particle system if no particles are in view. + UnsignedInt particleCount = 0; + for (Particle* vp = sys->getFirstParticle(); vp; vp = vp->m_systemNext) + { + const Coord3D* pos = vp->getPosition(); + const Real psize = vp->getSize(); + + //Test if particle is at the screen or terrain edges. + if (WWMath::Fabs(pos->x - bcX) > (beX + psize) || + WWMath::Fabs(pos->y - bcY) > (beY + psize) || + WWMath::Fabs(pos->z - bcZ) > (beZ + psize)) + { + vp->setIsCulled(true); + continue; + } + + vp->setIsCulled(false); + particleCount++; + } + + // Particle system has no particles on screen + if (particleCount == 0) + continue; + // Handle smudge type particles if (sys->isUsingSmudge()) { @@ -164,17 +194,7 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) for (Particle *p = sys->getFirstParticle(); p; p = p->m_systemNext) { - const Coord3D *pos = p->getPosition(); - Real psize = p->getSize(); - - //Cull particle to edges of screen and terrain. - if (WWMath::Fabs( pos->x - bcX ) > ( beX + psize ) ) - continue; - - if (WWMath::Fabs( pos->y - bcY ) > ( beY + psize ) ) - continue; - - if (WWMath::Fabs( pos->z - bcZ ) > ( beZ + psize ) ) + if (p->isCulled()) continue; if (Smudge *smudge = TheSmudgeManager->findSmudge(p)) @@ -186,10 +206,28 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) continue; } - /// @todo lorenzen sez: declare these outside the sys loop, and put some in registers - // initialize them here still, of course + // TheSuperHackers @performance Ronin/Mauller 09/08/2026 Implement batched rendering for similar particles. + // Particles with the same properties will now be batched onto a single texture surface before being drawn. + // If a different particle type appears before the batch is filled, the previous batch will be drawn first. + RefCountPtr texture; + texture.Assign_No_Add_Ref(W3DDisplay::m_assetManager->Get_Texture(sys->getParticleTypeName().str())); + + const Bool canBatch = sys->isUsingParticles(); + const Bool batchDone = finishedBatch(*sys, texture); + if (!canBatch || batchDone) + { + flushParticleBatch(rinfo, pointCount); + } + + // setup a new particle batch texture if prior batch was flushed. + if (canBatch && m_batchTexture == nullptr) + { + initializeBatch(*sys, texture); + } + + UnsignedInt startCount = pointCount; + // build W3D particle buffer - Int count = 0; Vector3 *posArray = m_posBuffer->Get_Array(); Real *sizeArray = m_sizeBuffer->Get_Array(); Vector4 *RGBAArray = m_RGBABuffer->Get_Array(); @@ -203,53 +241,58 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) //set-up all the per-particle for (Particle *p = sys->getFirstParticle(); p; p = p->m_systemNext) { - pos = p->getPosition(); - psize = p->getSize(); - - //Cull particle to edges of screen and terrain. - if (WWMath::Fabs(pos->x - bcX) > (beX + psize)) - continue; - - if (WWMath::Fabs(pos->y - bcY) > (beY + psize)) + if (p->isCulled()) continue; - if (WWMath::Fabs(pos->z - bcZ) > (beZ + psize)) - continue; + pos = p->getPosition(); + psize = p->getSize(); m_fieldParticleCount += ( sys->getPriority() == AREA_EFFECT && sys->m_isGroundAligned != FALSE ); //@todo lorenzen sez: use pointer arithmetic for these arrays - personalities[count] = p->getPersonality(); + personalities[pointCount] = p->getPersonality(); - posArray[count].X = pos->x; - posArray[count].Y = pos->y; - posArray[count].Z = pos->z; + posArray[pointCount].X = pos->x; + posArray[pointCount].Y = pos->y; + posArray[pointCount].Z = pos->z; - sizeArray[count] = psize; + sizeArray[pointCount] = psize; color = p->getColor(); - RGBAArray[count].X = color->red; - RGBAArray[count].Y = color->green; - RGBAArray[count].Z = color->blue; - RGBAArray[count].W = p->getAlpha(); + RGBAArray[pointCount].X = color->red; + RGBAArray[pointCount].Y = color->green; + RGBAArray[pointCount].Z = color->blue; + RGBAArray[pointCount].W = p->getAlpha(); - angleArray[count] = (uint8)(p->getAngle() * 255.0f / (2.0f * PI)); + angleArray[pointCount] = (uint8)(p->getAngle() * 255.0f / (2.0f * PI)); + + if (++pointCount == MAX_POINTS_PER_GROUP) + { + if (!canBatch) + { + break; + } - if (++count == MAX_POINTS_PER_GROUP) - break; + // TheSuperHackers @info The Buffer is full mid-system so draw what we have and carry on with the SAME system. + // This prevents particles being dropped. Bank the stats first as the flush resets count to 0. + m_onScreenParticleCount += (pointCount - startCount); + flushParticleBatch(rinfo, pointCount); + initializeBatch(*sys, texture); + startCount = 0; + } } - if ( count == 0 ) + if (pointCount == startCount) + { continue; //this system has no particles to render + } - TextureClass *texture = W3DDisplay::m_assetManager->Get_Texture( sys->getParticleTypeName().str() ); - - if ( m_streakLine && sys->isUsingStreak() && (count >= 2) ) + // Handle drawing streak type particles. + if ( sys->isUsingStreak() && (pointCount >= 2) ) { m_streakLine->Reset_Line(); - m_streakLine->Set_Texture( texture ); - texture->Release_Ref();//release reference since it's held by streakline + m_streakLine->Set_Texture( texture.Peek() ); switch( sys->getShaderType() ) { case ParticleSystemInfo::ADDITIVE: @@ -268,14 +311,14 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) //UPDATE THE STREAK'S ARRAYS m_streakLine->Set_LocsWidthsColors( - count, + pointCount, m_posBuffer->Get_Array(), m_sizeBuffer->Get_Array(), m_RGBABuffer->Get_Array(), &personalities[0] ); - //WWASSERT( m_streakLine->Get_Num_Points() == count ); + //WWASSERT( m_streakLine->Get_Num_Points() == pointCount ); // This is the happy place for this! RGBAArray[0].X = 0;//eliminates the scissor edge on the trailing edge of the streak @@ -286,61 +329,51 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) //RENDER STREAK! m_streakLine->Render( rinfo ); - + m_onScreenParticleCount += (pointCount - startCount); + pointCount = startCount; } - else - { - WWASSERT( m_pointGroup ); + // Handle volumetric type particle systems. + const UnsignedInt volumeParticleDepth = sys->getVolumeParticleDepth(); + if( sys->isUsingVolumeParticles() && volumeParticleDepth > DEFAULT_VOLUME_PARTICLE_DEPTH ) + { + m_pointGroup->Set_Texture( texture.Peek() ); + m_pointGroup->Set_Flag( PointGroupClass::TRANSFORM, true ); // transform to screen space - if ( m_pointGroup ) // this catches the particle and volumeparticle cases + switch( sys->getShaderType() ) { - // render all the systems' particles - m_pointGroup->Set_Texture( texture ); - texture->Release_Ref();//release reference since it's held by pointGroup - m_pointGroup->Set_Flag( PointGroupClass::TRANSFORM, true ); // transform to screen space - - switch( sys->getShaderType() ) - { - case ParticleSystemInfo::ADDITIVE: - m_pointGroup->Set_Shader( ShaderClass::_PresetAdditiveSpriteShader ); - break; - case ParticleSystemInfo::ALPHA: - m_pointGroup->Set_Shader( ShaderClass::_PresetAlphaSpriteShader ); - break; - case ParticleSystemInfo::ALPHA_TEST: - m_pointGroup->Set_Shader( ShaderClass::_PresetATestSpriteShader ); - break; - case ParticleSystemInfo::MULTIPLY: - m_pointGroup->Set_Shader( ShaderClass::_PresetMultiplicativeSpriteShader ); - break; - } - - /// @todo Use both QUADS and TRIS for particles - m_pointGroup->Set_Point_Mode( PointGroupClass::QUADS ); - m_pointGroup->Set_Arrays( m_posBuffer, m_RGBABuffer, nullptr, m_sizeBuffer, m_angleBuffer, nullptr, count ); - m_pointGroup->Set_Billboard(sys->shouldBillboard()); + case ParticleSystemInfo::ADDITIVE: + m_pointGroup->Set_Shader( ShaderClass::_PresetAdditiveSpriteShader ); + break; + case ParticleSystemInfo::ALPHA: + m_pointGroup->Set_Shader( ShaderClass::_PresetAlphaSpriteShader ); + break; + case ParticleSystemInfo::ALPHA_TEST: + m_pointGroup->Set_Shader( ShaderClass::_PresetATestSpriteShader ); + break; + case ParticleSystemInfo::MULTIPLY: + m_pointGroup->Set_Shader( ShaderClass::_PresetMultiplicativeSpriteShader ); + break; + } - /// @todo Support animated texture particles - /// @todo lorenzen sez: unimplemented code wastes cpu cycles - m_pointGroup->Set_Point_Frame( 0 ); + /// @todo Use both QUADS and TRIS for particles + m_pointGroup->Set_Point_Mode( PointGroupClass::QUADS ); + m_pointGroup->Set_Arrays( m_posBuffer, m_RGBABuffer, nullptr, m_sizeBuffer, m_angleBuffer, nullptr, pointCount ); + m_pointGroup->Set_Billboard(sys->shouldBillboard()); - //RENDER IT! - const UnsignedInt volumeParticleDepth = sys->getVolumeParticleDepth(); - if( sys->isUsingVolumeParticles() && volumeParticleDepth > DEFAULT_VOLUME_PARTICLE_DEPTH ) - { - m_pointGroup->RenderVolumeParticle( rinfo, volumeParticleDepth); - } - else - m_pointGroup->Render( rinfo ); + /// @todo Support animated texture particles + /// @todo lorenzen sez: unimplemented code wastes cpu cycles + m_pointGroup->Set_Point_Frame( 0 ); - } + m_pointGroup->RenderVolumeParticle( rinfo, volumeParticleDepth); + m_onScreenParticleCount += (pointCount - startCount); + pointCount = startCount; } /// @todo lorenzen sez: this should be debug only: //add particle count to total - m_onScreenParticleCount += count; + m_onScreenParticleCount += (pointCount - startCount); /* // draw the wind vector for this particle system on the screen @@ -362,6 +395,9 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) } + // TheSuperHackers @info Flush the last batch if one is pending. + flushParticleBatch(rinfo, pointCount); + /// @todo lorenzen sez: this should be debug only: TheParticleSystemManager->setOnScreenParticleCount(m_onScreenParticleCount); @@ -375,3 +411,54 @@ void W3DParticleSystemManager::doParticles(RenderInfoClass &rinfo) ((W3DSmudgeManager *)TheSmudgeManager)->render(rinfo); } } + +Bool W3DParticleSystemManager::finishedBatch(const ParticleSystem& system, const RefCountPtr& texture) +{ + return texture.Peek() != m_batchTexture.Peek() || + system.getShaderType() != m_batchShaderType || + system.shouldBillboard() != m_batchBillboard; +} + +void W3DParticleSystemManager::initializeBatch(const ParticleSystem& system, const RefCountPtr& texture) +{ + m_batchTexture = texture; + m_batchShaderType = system.getShaderType(); + m_batchBillboard = system.shouldBillboard(); +} + +void W3DParticleSystemManager::flushParticleBatch(RenderInfoClass& rinfo, UnsignedInt& pointCount) +{ + if (pointCount > 0) + { + m_pointGroup->Set_Texture(m_batchTexture.Peek()); + + switch (m_batchShaderType) + { + case ParticleSystemInfo::ADDITIVE: + m_pointGroup->Set_Shader(ShaderClass::_PresetAdditiveSpriteShader); + break; + case ParticleSystemInfo::ALPHA: + m_pointGroup->Set_Shader(ShaderClass::_PresetAlphaSpriteShader); + break; + case ParticleSystemInfo::ALPHA_TEST: + m_pointGroup->Set_Shader(ShaderClass::_PresetATestSpriteShader); + break; + case ParticleSystemInfo::MULTIPLY: + m_pointGroup->Set_Shader(ShaderClass::_PresetMultiplicativeSpriteShader); + break; + } + + m_pointGroup->Set_Flag(PointGroupClass::TRANSFORM, true); + m_pointGroup->Set_Point_Mode(PointGroupClass::QUADS); + m_pointGroup->Set_Arrays(m_posBuffer, m_RGBABuffer, nullptr, m_sizeBuffer, m_angleBuffer, nullptr, pointCount); + m_pointGroup->Set_Billboard(m_batchBillboard); + m_pointGroup->Set_Point_Frame(0); + m_pointGroup->Render(rinfo); + + pointCount = 0; + } + + m_batchTexture.Clear(); + m_batchBillboard = false; + m_batchShaderType = ParticleSystemInfo::INVALID_SHADER; +} diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp index f8ff61611d8..1a44e3e8fa4 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DScorch.cpp @@ -162,16 +162,17 @@ void W3DScorch::updateScorches(WorldHeightMap& map) // TheSuperHackers @info Scorches are written in reverse order to ensure that the last added scorches fit in the buffers. for (std::deque::reverse_iterator it = m_scorches.rbegin(); it != m_scorches.rend(); ++it) { - if (!writeScorchToBuffer(*it, map, diffuse, - vb + m_curNumScorchVertices, ib + m_curNumScorchIndices)) + if (writeScorchToBuffer(*it, map, diffuse, + vb + m_curNumScorchVertices, ib + m_curNumScorchIndices) == SCORCH_BUFFER_FULL) { return; } } } -Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, UnsignedInt diffuse, - VertexFormatXYZDUV1* curVb, UnsignedShort* curIb) +W3DScorch::WriteScorchResult W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, + UnsignedInt diffuse, VertexFormatXYZDUV1* curVb, + UnsignedShort* curIb) { Real radius = scorch.radius; Vector3 loc = scorch.location; @@ -196,14 +197,28 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, { maxY = map.getYExtent() - map.getBorderSizeInline(); } + + const Int vertexCountX = maxX - minX; + const Int vertexCountY = maxY - minY; + if (vertexCountX <= 0 || vertexCountY <= 0) + { + return SCORCH_SKIPPED; + } + + const Int requiredVertices = vertexCountX * vertexCountY; + const Int requiredIndices = 6 * (vertexCountX - 1) * (vertexCountY - 1); + if (m_curNumScorchVertices + requiredVertices > MAX_SCORCH_VERTEX || + m_curNumScorchIndices + requiredIndices > MAX_SCORCH_INDEX) + { + return SCORCH_BUFFER_FULL; + } + Int startVertex = m_curNumScorchVertices; Int i, j; for (j = minY; j < maxY; j++) { for (i = minX; i < maxX; i++) { - if (m_curNumScorchVertices >= MAX_SCORCH_VERTEX) - return false; curVb->diffuse = diffuse; Real theZ = amtToFloat + getMapHeight(map, i, j); // The scorchmarks are spaced out by 1.5 in the texture. @@ -225,8 +240,6 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, { for (i = 0; i < maxX - minX - 1; i++) { - if (m_curNumScorchIndices + 6 > MAX_SCORCH_INDEX) - return false; Int xNdx = i + minX + map.getBorderSizeInline(); Int yNdx = j + minY + map.getBorderSizeInline(); Bool flipForBlend = map.getFlipState(xNdx, yNdx); @@ -257,5 +270,5 @@ Bool W3DScorch::writeScorchToBuffer(const TScorch& scorch, WorldHeightMap& map, } } - return true; + return SCORCH_WRITTEN; } diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp index c40ca0c5041..c818bdde884 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTerrainVisual.cpp @@ -991,7 +991,7 @@ void W3DTerrainVisual::addFactionBib(Object *factionBuilding, Bool highlight, Re pos.set(0,0,0); Real exitWidth = factionBuilding->getTemplate()->getFactoryExitWidth(); Real extraWidth = factionBuilding->getTemplate()->getFactoryExtraBibWidth() + extra; - const GeometryInfo info = factionBuilding->getGeometryInfo(); + const GeometryInfo &info = factionBuilding->getGeometryInfo(); Real sizeX = info.getMajorRadius(); Real sizeY = info.getMinorRadius(); if (info.getGeomType() != GEOMETRY_BOX) { diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTreeBuffer.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTreeBuffer.cpp index e184c79865f..0155f26840a 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTreeBuffer.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DTreeBuffer.cpp @@ -299,7 +299,7 @@ void W3DTreeBuffer::cull(const CameraClass * camera) Int curTree; // Calculate the vector direction that the camera is looking at. - Matrix3D camera_matrix = camera->Get_Transform(); + const Matrix3D &camera_matrix = camera->Get_Transform(); float zmod = -1; float x = zmod * camera_matrix[0][2] ; float y = zmod * camera_matrix[1][2] ; @@ -1281,7 +1281,7 @@ Int W3DTreeBuffer::addTreeType(const W3DTreeDrawModuleData *data) if (robj->Class_ID() == RenderObjClass::CLASSID_HLOD) { RenderObjClass *hlod = robj; robj = hlod->Get_Sub_Object(0); - const Matrix3D xfm = robj->Get_Bone_Transform(0); + const Matrix3D& xfm = robj->Get_Bone_Transform(0); xfm.Get_Translation(&offset); REF_PTR_RELEASE(hlod); } @@ -1297,7 +1297,6 @@ Int W3DTreeBuffer::addTreeType(const W3DTreeDrawModuleData *data) Int numVertex = m_treeTypes[m_numTreeTypes].m_mesh->Peek_Model()->Get_Vertex_Count(); Vector3 *pVert = m_treeTypes[m_numTreeTypes].m_mesh->Peek_Model()->Get_Vertex_Array(); - const Matrix3D xfm = m_treeTypes[m_numTreeTypes].m_mesh->Get_Transform(); SphereClass bounds(pVert, numVertex); bounds.Center += offset; m_treeTypes[m_numTreeTypes].m_bounds = bounds; diff --git a/Core/Libraries/Include/Lib/PathUtil.h b/Core/Libraries/Include/Lib/PathUtil.h index cf1ce769d91..683f6fee130 100644 --- a/Core/Libraries/Include/Lib/PathUtil.h +++ b/Core/Libraries/Include/Lib/PathUtil.h @@ -23,6 +23,38 @@ #include "BaseType.h" #include +inline bool isPathSeparator(char ch) +{ +#ifdef _WIN32 + return ch == '\\' || ch == '/'; +#else + return ch == '/'; +#endif +} + +inline bool isAbsolutePath(const char* path) +{ + if (path == nullptr) + { + return false; + } + + if (isPathSeparator(path[0])) + { + return true; + } + +#ifdef _WIN32 + const bool hasDriveLetter = (path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z'); + if (hasDriveLetter && path[1] == ':' && isPathSeparator(path[2])) + { + return true; + } +#endif + + return false; +} + inline const char* getExtension(const char* path) { const char* lastDot = strrchr(path, '.'); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp new file mode 100644 index 00000000000..fac042dc906 --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.cpp @@ -0,0 +1,114 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** 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 3 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, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 DX8Backend adapter and lifecycle owner. +// Rendering methods in this file are one-line trampolines to the existing +// DX8Wrapper static API. Backend construction and destruction own the +// DX8Wrapper lifecycle. + +#include "DX8Backend.h" +#include "RenderBackend.h" + +#include "WW3D2/dx8wrapper.h" +#include "WW3D2/formconv.h" +#include "WWMath/vector3.h" +#include "WW3D2/lightenvironment.h" +#include "WWDebug/wwdebug.h" + +IRenderBackend *Create_Render_Backend(void * window, bool lite) +{ + return DX8Backend::Create(window, lite); +} + +DX8Backend::DX8Backend(bool lite) : Lite(lite) +{ +} + +DX8Backend::~DX8Backend() +{ + if (!Lite) + { + DX8Wrapper::Shutdown(); + } +} + +DX8Backend *DX8Backend::Create(void * window, bool lite) +{ + Init_D3D_To_WW3_Conversion(); + WWDEBUG_SAY(("Init DX8Wrapper")); + if (!DX8Wrapper::Init(window, lite)) + { + return nullptr; + } + + return new DX8Backend(lite); +} + +void DX8Backend::Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) +{ + DX8Wrapper::Set_Gamma(gamma, bright, contrast, calibrate, uselimit); +} + +void DX8Backend::Begin_Scene() +{ + DX8Wrapper::Begin_Scene(); +} + +void DX8Backend::End_Scene(bool flip_frame) +{ + DX8Wrapper::End_Scene(flip_frame); +} + +void DX8Backend::Flip_To_Primary() +{ + DX8Wrapper::Flip_To_Primary(); +} + +void DX8Backend::Clear(bool clear_color, bool clear_z_stencil, + const Vector3 & color, + float dest_alpha, float z, unsigned int stencil) +{ + DX8Wrapper::Clear(clear_color, clear_z_stencil, color, dest_alpha, z, stencil); +} + +void DX8Backend::Set_Viewport(const RenderBackendViewport & viewport) +{ + D3DVIEWPORT8 vp; + vp.X = viewport.x; + vp.Y = viewport.y; + vp.Width = viewport.width; + vp.Height = viewport.height; + vp.MinZ = viewport.min_z; + vp.MaxZ = viewport.max_z; + DX8Wrapper::Set_Viewport(&vp); +} + +void DX8Backend::Invalidate_Cached_Render_States() +{ + DX8Wrapper::Invalidate_Cached_Render_States(); +} + +void DX8Backend::Set_Ambient(const Vector3 & color) +{ + DX8Wrapper::Set_Ambient(color); +} + +void DX8Backend::Set_Light_Environment(LightEnvironmentClass * light_env) +{ + DX8Wrapper::Set_Light_Environment(light_env); +} diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h new file mode 100644 index 00000000000..a5597c9edef --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/DX8Backend.h @@ -0,0 +1,52 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** 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 3 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, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 DX8Backend is the reference +// implementation of IRenderBackend that owns the DX8Wrapper lifecycle and +// forwards rendering methods to the existing DX8Wrapper static facade. + +#pragma once + +#include "WW3D2/IRenderBackend.h" + +class DX8Backend : public IRenderBackend +{ +public: + static DX8Backend *Create(void * window, bool lite); + + virtual ~DX8Backend() override; + + virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate, bool uselimit) override; + + virtual void Begin_Scene() override; + virtual void End_Scene(bool flip_frame) override; + virtual void Flip_To_Primary() override; + virtual void Clear(bool clear_color, bool clear_z_stencil, + const Vector3 & color, + float dest_alpha, float z, unsigned int stencil) override; + virtual void Set_Viewport(const RenderBackendViewport & viewport) override; + virtual void Invalidate_Cached_Render_States() override; + + virtual void Set_Ambient(const Vector3 & color) override; + virtual void Set_Light_Environment(LightEnvironmentClass * light_env) override; + +private: + explicit DX8Backend(bool lite); + + bool Lite; +}; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h new file mode 100644 index 00000000000..e9d67508a88 --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/Backend/RenderBackend.h @@ -0,0 +1,30 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** 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 3 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, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 Backend selection seam. The +// build links exactly one backend implementation, and that implementation +// defines Create_Render_Backend. WW3D owns the instance it returns; use +// WW3D::Get_Render_Backend() to reach the active backend. + +#pragma once + +class IRenderBackend; + +// Construct and initialize the backend selected by the build. Exactly one +// backend implementation must define this function. Returns null on failure. +IRenderBackend *Create_Render_Backend(void * window, bool lite); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt index e942df0e95d..21f2b1be15e 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WW3D2/CMakeLists.txt @@ -13,6 +13,9 @@ set(WW3D2_SRC #assetmgr.h assetstatus.cpp assetstatus.h + Backend/DX8Backend.cpp + Backend/DX8Backend.h + Backend/RenderBackend.h bitmaphandler.cpp bitmaphandler.h bmp2d.cpp @@ -91,6 +94,7 @@ set(WW3D2_SRC htree.h #htreemgr.cpp #htreemgr.h + IRenderBackend.h intersec.cpp intersec.h intersec.inl diff --git a/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h new file mode 100644 index 00000000000..28dd3b14ec8 --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WW3D2/IRenderBackend.h @@ -0,0 +1,68 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** 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 3 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, see . +*/ + +// TheSuperHackers @refactor bobtista 10/04/2026 Abstract W3D-facing rendering +// interface so WW3D2 rendering can be re-targeted to other backends while the +// existing DX8 path stays as the reference implementation. + +#pragma once + +// Forward declarations keep this header includable without pulling in the full +// WW3D2 header graph. All W3D types below are passed by pointer or reference. + +class LightEnvironmentClass; +class Vector3; + +struct RenderBackendViewport +{ + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + float min_z; + float max_z; +}; + +// A method appears here once a caller routes through it, not in anticipation of +// one. The set below is what current callers route through; the rest of the +// DX8Wrapper API stays reachable through DX8Wrapper's static methods until a +// caller migrates, at which point the method it needs moves here. +// +// Method names intentionally match the existing DX8Wrapper names so migrating a +// caller is a mechanical DX8Wrapper::X(...) -> Get_Render_Backend()->X(...) +// rewrite. + +class IRenderBackend +{ +public: + virtual ~IRenderBackend() {} + + virtual void Set_Gamma(float gamma, float bright, float contrast, bool calibrate = true, bool uselimit = true) = 0; + + virtual void Begin_Scene() = 0; + virtual void End_Scene(bool flip_frame = true) = 0; + virtual void Flip_To_Primary() = 0; + virtual void Clear(bool clear_color, bool clear_z_stencil, + const Vector3 & color, + float dest_alpha = 0.0f, float z = 1.0f, unsigned int stencil = 0) = 0; + virtual void Set_Viewport(const RenderBackendViewport & viewport) = 0; + virtual void Invalidate_Cached_Render_States() = 0; + + virtual void Set_Ambient(const Vector3 & color) = 0; + virtual void Set_Light_Environment(LightEnvironmentClass * light_env) = 0; +}; diff --git a/Core/Libraries/Source/WWVegas/WW3D2/htree.cpp b/Core/Libraries/Source/WWVegas/WW3D2/htree.cpp index fc64894f36b..17ed63aa849 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/htree.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/htree.cpp @@ -209,9 +209,10 @@ int HTreeClass::Load_W3D(ChunkLoadClass & cload) */ memcpy(Name,header.Name,W3D_NAME_LEN); NumPivots = header.NumPivots; - if (NumPivots > 0) { - Pivot = MSGW3DNEWARRAY("HTreeClass::Pivot") PivotClass[NumPivots]; + if (NumPivots < 1) { + return LOAD_ERROR; } + Pivot = MSGW3DNEWARRAY("HTreeClass::Pivot") PivotClass[NumPivots]; /* ** Now, read in all of the other chunks for this hierarchy. diff --git a/Core/Libraries/Source/WWVegas/WW3D2/intersec.inl b/Core/Libraries/Source/WWVegas/WW3D2/intersec.inl index b9ca0b9ff41..d21d48db1a7 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/intersec.inl +++ b/Core/Libraries/Source/WWVegas/WW3D2/intersec.inl @@ -87,7 +87,7 @@ inline void IntersectionClass::Get_Screen_Ray(float screen_x, float screen_y, co CameraClass *camera = Layer.Camera; // determine the ray corresponding to the camera and distance to projection plane - Matrix3D camera_matrix = camera->Get_Transform(); + const Matrix3D& camera_matrix = camera->Get_Transform(); Vector3 camera_location = camera->Get_Position(); // the projected ray has the same origin as the camera diff --git a/Core/Libraries/Source/WWVegas/WW3D2/rendobj.cpp b/Core/Libraries/Source/WWVegas/WW3D2/rendobj.cpp index 47954075d76..4b04540bad0 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/rendobj.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/rendobj.cpp @@ -322,7 +322,7 @@ float RenderObjClass::Get_Screen_Size(CameraClass &camera) // accurate (perhaps by using the object-space bounding-box) Vector3 cam = camera.Get_Position(); - ViewportClass viewport = camera.Get_Viewport(); + const ViewportClass &viewport = camera.Get_Viewport(); Vector2 vpr_min, vpr_max; camera.Get_View_Plane(vpr_min, vpr_max); float width_factor = viewport.Width() / (vpr_max.X - vpr_min.X); @@ -1277,7 +1277,7 @@ void RenderObjPersistFactoryClass::Save(ChunkSaveClass & csave,PersistClass * ob { RenderObjClass * robj = (RenderObjClass *)obj; const char * name = robj->Get_Name(); - Matrix3D tm = robj->Get_Transform(); + const Matrix3D& tm = robj->Get_Transform(); csave.Begin_Chunk(RENDOBJFACTORY_CHUNKID_VARIABLES); WRITE_MICRO_CHUNK(csave,RENDOBJFACTORY_VARIABLE_OBJPOINTER,robj); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/ringobj.cpp b/Core/Libraries/Source/WWVegas/WW3D2/ringobj.cpp index 9ee3d934f1a..e82c97476ca 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/ringobj.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/ringobj.cpp @@ -690,8 +690,6 @@ void RingRenderObjClass::Render(RenderInfoClass & rinfo) // Process texture reductions: // if (RingTexture) RingTexture->Process_Reduction(); - Matrix3D temp = Transform; - // Do Time Based Animation animate (); diff --git a/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp b/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp index 9a1c2de806d..a8ecb7372f0 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/shattersystem.cpp @@ -920,7 +920,7 @@ void ShatterSystem::Shatter_Mesh(MeshClass * mesh,const Vector3 & point,const Ve /* ** Object-space to world-space transform */ - Matrix3D Mobj_to_world = mesh->Get_Transform(); + const Matrix3D& Mobj_to_world = mesh->Get_Transform(); /* ** World-space to shatter-space transform diff --git a/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp b/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp index ae718524197..38b5137398d 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/texproject.cpp @@ -931,9 +931,8 @@ bool TexProjectClass::Compute_Perspective_Projection ** Calculate the axis-aligned bounding box of the model in the camera's coordinate system. */ AABoxClass box = obj_box; - Matrix3D obj_to_world = tm; Matrix3D obj_to_texture; - Matrix3D::Multiply(texture_tm_inv,obj_to_world,&obj_to_texture); + Matrix3D::Multiply(texture_tm_inv,tm,&obj_to_texture); box.Transform(obj_to_texture); /* @@ -1060,9 +1059,8 @@ bool TexProjectClass::Compute_Ortho_Projection ** Calculate the axis-aligned bounding box of the model in the camera's coordinate system. */ AABoxClass box = obj_box; - Matrix3D obj_to_world = tm; Matrix3D obj_to_texture; - Matrix3D::Multiply(texture_tm_inv,obj_to_world,&obj_to_texture); + Matrix3D::Multiply(texture_tm_inv,tm,&obj_to_texture); box.Transform(obj_to_texture); /* diff --git a/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp b/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp index 454fc3d48b2..e3c5e64c7bc 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp +++ b/Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp @@ -105,6 +105,8 @@ #include "dazzle.h" #include "meshmdl.h" #include "dx8renderer.h" +#include "Backend/RenderBackend.h" +#include "IRenderBackend.h" #include "render2d.h" #include "WWLib/bound.h" #include "rddesc.h" @@ -115,7 +117,6 @@ #include "WWLib/thread.h" #include "WWLib/cpudetect.h" #include "dx8texman.h" -#include "formconv.h" #include "animatedsoundmgr.h" #include "static_sort_list.h" #include "shdlib.h" @@ -173,6 +174,8 @@ float WW3D::PixelCenterX = 0.0f; float WW3D::PixelCenterY = 0.0f; +IRenderBackend * WW3D::RenderBackend = nullptr; + bool WW3D::IsInitted = false; bool WW3D::IsRendering = false; bool WW3D::IsCapturing = false; @@ -271,14 +274,18 @@ WW3DErrorType WW3D::Init(void *hwnd, char *defaultpal, bool lite) _Hwnd = (HWND)hwnd; Lite = lite; - /* - ** Initialize d3d, this also enumerates the available devices and resolutions. - */ - Init_D3D_To_WW3_Conversion(); - WWDEBUG_SAY(("Init DX8Wrapper")); - if (!DX8Wrapper::Init(_Hwnd, lite)) { + // TheSuperHackers @refactor bobtista 07/08/2026 The backend object is created + // and initialized once here and destroyed in WW3D::Shutdown. + WWASSERT(RenderBackend == nullptr); + if (RenderBackend == nullptr) + { + RenderBackend = Create_Render_Backend(_Hwnd, lite); + } + if (RenderBackend == nullptr) + { return(WW3D_ERROR_INITIALIZATION_FAILED); } + WWDEBUG_SAY(("Allocate Debug Resources")); Allocate_Debug_Resources(); @@ -365,9 +372,9 @@ WW3DErrorType WW3D::Shutdown() } DX8TextureManagerClass::Shutdown(); - if (!Lite) { - DX8Wrapper::Shutdown(); - } + + delete RenderBackend; + RenderBackend = nullptr; /* ** Clear the default static sort lists @@ -854,22 +861,22 @@ WW3DErrorType WW3D::Begin_Render(bool clear,bool clearz,const Vector3 & color, f // If we want to clear the screen, we need to set the viewport to include the entire screen: if (clear || clearz) { - D3DVIEWPORT8 vp; + RenderBackendViewport vp; int width, height, bits; bool windowed; WW3D::Get_Render_Target_Resolution(width, height, bits, windowed); - vp.X = 0; - vp.Y = 0; - vp.Width = width; - vp.Height = height; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - DX8Wrapper::Set_Viewport(&vp); - DX8Wrapper::Clear(clear, clearz, color, dest_alpha); + vp.x = 0; + vp.y = 0; + vp.width = width; + vp.height = height; + vp.min_z = 0.0f; + vp.max_z = 1.0f; + Get_Render_Backend()->Set_Viewport(vp); + Get_Render_Backend()->Clear(clear, clearz, color, dest_alpha); } // Notify D3D that we are beginning to render the frame - DX8Wrapper::Begin_Scene(); + Get_Render_Backend()->Begin_Scene(); return WW3D_ERROR_OK; } @@ -966,7 +973,7 @@ WW3DErrorType WW3D::Render(SceneClass * scene,CameraClass * cam,bool clear,bool // Clear the viewport if (clear || clearz) { - DX8Wrapper::Clear(clear, clearz, color); + Get_Render_Backend()->Clear(clear, clearz, color); } // set the rendering mode @@ -984,7 +991,7 @@ WW3DErrorType WW3D::Render(SceneClass * scene,CameraClass * cam,bool clear,bool // Set the global ambient light value here. If the scene is using the LightEnvironment system // this setting will get overridden. - DX8Wrapper::Set_Ambient(scene->Get_Ambient_Light()); + Get_Render_Backend()->Set_Ambient(scene->Get_Ambient_Light()); // render the scene @@ -1036,7 +1043,7 @@ WW3DErrorType WW3D::Render( // Install the lighting environment if one is supplied if (rinfo.light_environment != nullptr) { - DX8Wrapper::Set_Light_Environment(rinfo.light_environment); + Get_Render_Backend()->Set_Light_Environment(rinfo.light_environment); } // Render the object @@ -1111,8 +1118,8 @@ WW3DErrorType WW3D::End_Render(bool flip_frame) IsRendering = false; { - WWPROFILE("DX8Wrapper::End_Scene"); - DX8Wrapper::End_Scene(flip_frame); + WWPROFILE("IRenderBackend::End_Scene"); + Get_Render_Backend()->End_Scene(flip_frame); } FrameCount++; @@ -1152,7 +1159,7 @@ WW3DErrorType WW3D::End_Render(bool flip_frame) *=============================================================================================*/ void WW3D::Flip_To_Primary() { - DX8Wrapper::Flip_To_Primary(); + Get_Render_Backend()->Flip_To_Primary(); } @@ -2122,5 +2129,5 @@ void WW3D::Reset_Current_Static_Sort_Lists_To_Default() void WW3D::Set_Gamma(float gamma,float bright,float contrast,bool calibrate) { - DX8Wrapper::Set_Gamma(gamma,bright,contrast,calibrate); + Get_Render_Backend()->Set_Gamma(gamma,bright,contrast,calibrate); } diff --git a/Core/Libraries/Source/WWVegas/WW3D2/ww3d.h b/Core/Libraries/Source/WWVegas/WW3D2/ww3d.h index 02207fd8c53..482485c8893 100644 --- a/Core/Libraries/Source/WWVegas/WW3D2/ww3d.h +++ b/Core/Libraries/Source/WWVegas/WW3D2/ww3d.h @@ -46,6 +46,7 @@ class SceneClass; class CameraClass; class ShaderClass; class DX8Wrapper; +class IRenderBackend; struct RenderStatistics; class FrameGrabClass; @@ -111,6 +112,10 @@ class WW3D static WW3DErrorType Shutdown(); static bool Is_Initted() { return IsInitted; } + // The active rendering backend. + // Created in Init and destroyed in Shutdown, so it is never null in between. + static IRenderBackend * Get_Render_Backend() { return RenderBackend; } + static int Get_Render_Device_Count(); static const char * Get_Render_Device_Name(int device_index); static const RenderDeviceDescClass & Get_Render_Device_Desc(int device = -1); @@ -370,6 +375,8 @@ class WW3D static float PixelCenterX; static float PixelCenterY; + static IRenderBackend * RenderBackend; + static bool IsInitted; static bool IsRendering; static bool IsCapturing; diff --git a/Core/Libraries/Source/WWVegas/WWAudio/Sound3D.cpp b/Core/Libraries/Source/WWVegas/WWAudio/Sound3D.cpp index 20e019930c4..b73658dd1f6 100644 --- a/Core/Libraries/Source/WWVegas/WWAudio/Sound3D.cpp +++ b/Core/Libraries/Source/WWVegas/WWAudio/Sound3D.cpp @@ -353,9 +353,8 @@ Sound3DClass::Set_Position (const Vector3 &position) // // Transform the sound's position into 'listener-space' // - Vector3 sound_pos = position; Vector3 listener_space_pos; - Matrix3D::Inverse_Transform_Vector (m_ListenerTransform, sound_pos, &listener_space_pos); + Matrix3D::Inverse_Transform_Vector (m_ListenerTransform, position, &listener_space_pos); // // Update the object's position inside of Miles diff --git a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt index dc704a307fb..d7dc786eb52 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt +++ b/Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt @@ -168,6 +168,10 @@ if(WIN32) MPU.h rcfile.cpp rcfile.h + registry.cpp + registry.h + Usp10Loader.cpp + Usp10Loader.h verchk.cpp verchk.h WWCOMUtil.cpp diff --git a/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.cpp b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.cpp new file mode 100644 index 00000000000..6f09f861dae --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.cpp @@ -0,0 +1,163 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** 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 3 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, see . +*/ + +#include "Usp10Loader.h" + + +CriticalSectionClass Usp10Loader::CriticalSection; +HMODULE Usp10Loader::Module = HMODULE(nullptr); +bool Usp10Loader::LoadAttempted = false; +Usp10Loader::ScriptIsComplex_t Usp10Loader::ScriptIsComplexPtr = nullptr; +Usp10Loader::ScriptItemize_t Usp10Loader::ScriptItemizePtr = nullptr; +Usp10Loader::ScriptBreak_t Usp10Loader::ScriptBreakPtr = nullptr; +Usp10Loader::ScriptLayout_t Usp10Loader::ScriptLayoutPtr = nullptr; +Usp10Loader::ScriptStringAnalyse_t Usp10Loader::ScriptStringAnalysePtr = nullptr; +Usp10Loader::ScriptStringFree_t Usp10Loader::ScriptStringFreePtr = nullptr; +Usp10Loader::ScriptString_pSize_t Usp10Loader::ScriptString_pSizePtr = nullptr; +Usp10Loader::ScriptStringOut_t Usp10Loader::ScriptStringOutPtr = nullptr; + + +bool Usp10Loader::load() +{ + if (LoadAttempted) { + return Module != HMODULE(nullptr); + } + LoadAttempted = true; + + char dll_path[MAX_PATH]; + const char dll_name[] = "\\usp10.dll"; + const UINT path_length = ::GetSystemDirectoryA(dll_path, ARRAY_SIZE(dll_path)); + if (path_length == 0 || path_length + ARRAY_SIZE(dll_name) > ARRAY_SIZE(dll_path)) { + return false; + } + strcpy(dll_path + path_length, dll_name); + + Module = ::LoadLibraryA(dll_path); + if (Module == HMODULE(nullptr)) { + return false; + } + + ScriptIsComplexPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptIsComplex")); + ScriptItemizePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptItemize")); + ScriptBreakPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptBreak")); + ScriptLayoutPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptLayout")); + ScriptStringAnalysePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptStringAnalyse")); + ScriptStringFreePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptStringFree")); + ScriptString_pSizePtr = reinterpret_cast(::GetProcAddress(Module, "ScriptString_pSize")); + ScriptStringOutPtr = reinterpret_cast(::GetProcAddress(Module, "ScriptStringOut")); + + if (ScriptIsComplexPtr == nullptr || ScriptItemizePtr == nullptr || ScriptBreakPtr == nullptr || + ScriptLayoutPtr == nullptr || ScriptStringAnalysePtr == nullptr || ScriptStringFreePtr == nullptr || + ScriptString_pSizePtr == nullptr || ScriptStringOutPtr == nullptr) + { + freeResources(); + return false; + } + + return true; +} + + +void Usp10Loader::unload() +{ + CriticalSectionClass::LockClass lock(CriticalSection); + + freeResources(); + LoadAttempted = false; +} + + +void Usp10Loader::freeResources() +{ + if (Module != HMODULE(nullptr)) { + ::FreeLibrary(Module); + Module = HMODULE(nullptr); + } + + ScriptIsComplexPtr = nullptr; + ScriptItemizePtr = nullptr; + ScriptBreakPtr = nullptr; + ScriptLayoutPtr = nullptr; + ScriptStringAnalysePtr = nullptr; + ScriptStringFreePtr = nullptr; + ScriptString_pSizePtr = nullptr; + ScriptStringOutPtr = nullptr; +} + + +HRESULT Usp10Loader::ScriptIsComplex(const WCHAR *text, int text_length, DWORD flags) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptIsComplexPtr(text, text_length, flags) : E_FAIL; +} + + +HRESULT Usp10Loader::ScriptItemize(const WCHAR *text, int text_length, int item_capacity, + const ScriptControl *control, const ScriptState *state, ScriptItem *items, int *item_count) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptItemizePtr(text, text_length, item_capacity, control, state, items, item_count) : E_FAIL; +} + + +HRESULT Usp10Loader::ScriptBreak(const WCHAR *text, int text_length, const ScriptAnalysis *analysis, + ScriptLogAttr *attributes) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptBreakPtr(text, text_length, analysis, attributes) : E_FAIL; +} + + +HRESULT Usp10Loader::ScriptLayout(int run_count, const BYTE *levels, int *visual_to_logical, + int *logical_to_visual) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptLayoutPtr(run_count, levels, visual_to_logical, logical_to_visual) : E_FAIL; +} + + +HRESULT Usp10Loader::ScriptStringAnalyse(HDC dc, const void *text, int text_length, int glyph_count, + int charset, DWORD flags, int required_width, ScriptControl *control, ScriptState *state, + const int *spacing, ScriptTabDefinition *tabs, const BYTE *character_classes, ScriptStringAnalysis *analysis) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptStringAnalysePtr(dc, text, text_length, glyph_count, charset, flags, required_width, + control, state, spacing, tabs, character_classes, analysis) : E_FAIL; +} + + +HRESULT Usp10Loader::ScriptStringFree(ScriptStringAnalysis *analysis) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptStringFreePtr(analysis) : E_FAIL; +} + + +const SIZE *Usp10Loader::ScriptString_pSize(ScriptStringAnalysis analysis) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptString_pSizePtr(analysis) : nullptr; +} + + +HRESULT Usp10Loader::ScriptStringOut(ScriptStringAnalysis analysis, int x, int y, UINT options, + const RECT *rect, int minimum_selection, int maximum_selection, BOOL disabled) +{ + CriticalSectionClass::LockClass lock(CriticalSection); + return load() ? ScriptStringOutPtr(analysis, x, y, options, rect, minimum_selection, maximum_selection, disabled) : E_FAIL; +} diff --git a/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.h b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.h new file mode 100644 index 00000000000..3b35b03b82b --- /dev/null +++ b/Core/Libraries/Source/WWVegas/WWLib/Usp10Loader.h @@ -0,0 +1,121 @@ +/* +** Command & Conquer Generals Zero Hour(tm) +** Copyright 2026 TheSuperHackers +** +** 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 3 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, see . +*/ + +#pragma once + +#include "mutex.h" +#include "win.h" + + +// This static class loads usp10.dll on first use and unloads it during engine shutdown. + +class Usp10Loader +{ +public: + + typedef void *ScriptStringAnalysis; + struct ScriptControl; + struct ScriptTabDefinition; + + struct ScriptState + { + WORD bidi_level : 5; + WORD reserved : 11; + }; + + struct ScriptAnalysis + { + WORD script : 10; + WORD right_to_left : 1; + WORD layout_right_to_left : 1; + WORD link_before : 1; + WORD link_after : 1; + WORD logical_order : 1; + WORD no_glyph_index : 1; + ScriptState state; + }; + + struct ScriptItem + { + int character_position; + ScriptAnalysis analysis; + }; + + struct ScriptLogAttr + { + BYTE soft_break : 1; + BYTE white_space : 1; + BYTE char_stop : 1; + BYTE word_stop : 1; + BYTE invalid : 1; + BYTE reserved : 3; + }; + + enum + { + SIC_COMPLEX = 0x00000001, + SSA_FALLBACK = 0x00000020, + SSA_GLYPHS = 0x00000080, + SSA_RTL = 0x00000100, + }; + + static HRESULT ScriptIsComplex(const WCHAR *text, int text_length, DWORD flags); + static HRESULT ScriptItemize(const WCHAR *text, int text_length, int item_capacity, + const ScriptControl *control, const ScriptState *state, ScriptItem *items, int *item_count); + static HRESULT ScriptBreak(const WCHAR *text, int text_length, const ScriptAnalysis *analysis, + ScriptLogAttr *attributes); + static HRESULT ScriptLayout(int run_count, const BYTE *levels, int *visual_to_logical, + int *logical_to_visual); + static HRESULT ScriptStringAnalyse(HDC dc, const void *text, int text_length, int glyph_count, + int charset, DWORD flags, int required_width, ScriptControl *control, ScriptState *state, + const int *spacing, ScriptTabDefinition *tabs, const BYTE *character_classes, + ScriptStringAnalysis *analysis); + static HRESULT ScriptStringFree(ScriptStringAnalysis *analysis); + static const SIZE *ScriptString_pSize(ScriptStringAnalysis analysis); + static HRESULT ScriptStringOut(ScriptStringAnalysis analysis, int x, int y, UINT options, + const RECT *rect, int minimum_selection, int maximum_selection, BOOL disabled); + static void unload(); + +private: + + static bool load(); + static void freeResources(); + + typedef HRESULT (WINAPI *ScriptIsComplex_t)(const WCHAR *, int, DWORD); + typedef HRESULT (WINAPI *ScriptItemize_t)(const WCHAR *, int, int, const ScriptControl *, + const ScriptState *, ScriptItem *, int *); + typedef HRESULT (WINAPI *ScriptBreak_t)(const WCHAR *, int, const ScriptAnalysis *, ScriptLogAttr *); + typedef HRESULT (WINAPI *ScriptLayout_t)(int, const BYTE *, int *, int *); + typedef HRESULT (WINAPI *ScriptStringAnalyse_t)(HDC, const void *, int, int, int, DWORD, int, + ScriptControl *, ScriptState *, const int *, ScriptTabDefinition *, const BYTE *, ScriptStringAnalysis *); + typedef HRESULT (WINAPI *ScriptStringFree_t)(ScriptStringAnalysis *); + typedef const SIZE *(WINAPI *ScriptString_pSize_t)(ScriptStringAnalysis); + typedef HRESULT (WINAPI *ScriptStringOut_t)(ScriptStringAnalysis, int, int, UINT, const RECT *, int, int, BOOL); + + static CriticalSectionClass CriticalSection; + static HMODULE Module; + static bool LoadAttempted; + static ScriptIsComplex_t ScriptIsComplexPtr; + static ScriptItemize_t ScriptItemizePtr; + static ScriptBreak_t ScriptBreakPtr; + static ScriptLayout_t ScriptLayoutPtr; + static ScriptStringAnalyse_t ScriptStringAnalysePtr; + static ScriptStringFree_t ScriptStringFreePtr; + static ScriptString_pSize_t ScriptString_pSizePtr; + static ScriptStringOut_t ScriptStringOutPtr; +}; diff --git a/Core/Libraries/Source/WWVegas/WWLib/multilist.h b/Core/Libraries/Source/WWVegas/WWLib/multilist.h index eea610c3074..e2085838676 100644 --- a/Core/Libraries/Source/WWVegas/WWLib/multilist.h +++ b/Core/Libraries/Source/WWVegas/WWLib/multilist.h @@ -218,7 +218,7 @@ class MultiListClass : public GenericMultiListClass MultiListClass() { } - virtual ~MultiListClass() + virtual ~MultiListClass() override { while (!Is_Empty()) { Remove_Head(); @@ -342,7 +342,7 @@ class RefMultiListClass : public GenericMultiListClass { public: - virtual ~RefMultiListClass() + virtual ~RefMultiListClass() override { while (!Is_Empty()) { Release_Head(); diff --git a/Core/Libraries/Source/debug/internal.h b/Core/Libraries/Source/debug/internal.h index 3b5b8efc163..8a7be5aaf2e 100644 --- a/Core/Libraries/Source/debug/internal.h +++ b/Core/Libraries/Source/debug/internal.h @@ -86,9 +86,9 @@ class DebugCmdInterfaceDebug: public DebugCmdInterface { public: virtual bool Execute(class Debug& dbg, const char *cmd, CommandMode cmdmode, - unsigned argn, const char * const * argv); + unsigned argn, const char * const * argv) override; - virtual void Delete() + virtual void Delete() override { this->~DebugCmdInterfaceDebug(); DebugFreeMemory(this); diff --git a/Core/Libraries/Source/debug/internal_io.h b/Core/Libraries/Source/debug/internal_io.h index 7a2ab35b53c..2ddeb266740 100644 --- a/Core/Libraries/Source/debug/internal_io.h +++ b/Core/Libraries/Source/debug/internal_io.h @@ -61,14 +61,14 @@ class DebugIOCon: public DebugIOInterface public: explicit DebugIOCon(); - virtual ~DebugIOCon(); - virtual int Read(char *buf, int maxchar); - virtual void Write(StringType type, const char *src, const char *str); - virtual void EmergencyFlush() {} + virtual ~DebugIOCon() override; + virtual int Read(char *buf, int maxchar) override; + virtual void Write(StringType type, const char *src, const char *str) override; + virtual void EmergencyFlush() override {} virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd, - unsigned argn, const char * const * argv); + unsigned argn, const char * const * argv) override; static DebugIOInterface *Create(); - virtual void Delete(); + virtual void Delete() override; }; /// \internal \brief con flat I/O class @@ -212,14 +212,14 @@ class DebugIOFlat: public DebugIOInterface public: explicit DebugIOFlat(); - virtual ~DebugIOFlat(); - virtual int Read(char *buf, int maxchar) { return 0; } - virtual void Write(StringType type, const char *src, const char *str); - virtual void EmergencyFlush(); + virtual ~DebugIOFlat() override; + virtual int Read(char *buf, int maxchar) override { return 0; } + virtual void Write(StringType type, const char *src, const char *str) override; + virtual void EmergencyFlush() override; virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd, - unsigned argn, const char * const * argv); + unsigned argn, const char * const * argv) override; static DebugIOInterface *Create(); - virtual void Delete(); + virtual void Delete() override; }; /// \internal \brief net debug I/O class @@ -230,14 +230,14 @@ class DebugIONet: public DebugIOInterface public: explicit DebugIONet(); - virtual ~DebugIONet(); - virtual int Read(char *buf, int maxchar); - virtual void Write(StringType type, const char *src, const char *str); - virtual void EmergencyFlush(); + virtual ~DebugIONet() override; + virtual int Read(char *buf, int maxchar) override; + virtual void Write(StringType type, const char *src, const char *str) override; + virtual void EmergencyFlush() override; virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd, - unsigned argn, const char * const * argv); + unsigned argn, const char * const * argv) override; static DebugIOInterface *Create(); - virtual void Delete(); + virtual void Delete() override; }; /// \internal \brief ods debug I/O class @@ -245,11 +245,11 @@ class DebugIOOds: public DebugIOInterface { public: explicit DebugIOOds() {} - virtual int Read(char *buf, int maxchar) { return 0; } - virtual void Write(StringType type, const char *src, const char *str); - virtual void EmergencyFlush() {} + virtual int Read(char *buf, int maxchar) override { return 0; } + virtual void Write(StringType type, const char *src, const char *str) override; + virtual void EmergencyFlush() override {} virtual void Execute(class Debug& dbg, const char *cmd, bool structuredCmd, - unsigned argn, const char * const * argv) {} + unsigned argn, const char * const * argv) override {} static DebugIOInterface *Create(); - virtual void Delete(); + virtual void Delete() override; }; diff --git a/Core/Libraries/Source/profile/internal_cmd.h b/Core/Libraries/Source/profile/internal_cmd.h index a315fc6e2a9..a1d43bf0897 100644 --- a/Core/Libraries/Source/profile/internal_cmd.h +++ b/Core/Libraries/Source/profile/internal_cmd.h @@ -51,6 +51,6 @@ class ProfileCmdInterface: public DebugCmdInterface void RunResultFunctions(); virtual bool Execute(class Debug& dbg, const char *cmd, CommandMode cmdmode, - unsigned argn, const char * const * argv); - virtual void Delete() {} + unsigned argn, const char * const * argv) override; + virtual void Delete() override {} }; diff --git a/Core/Tools/DebugWindow/DebugWindow.h b/Core/Tools/DebugWindow/DebugWindow.h index fb9366810b6..9e11d6e047d 100644 --- a/Core/Tools/DebugWindow/DebugWindow.h +++ b/Core/Tools/DebugWindow/DebugWindow.h @@ -38,7 +38,7 @@ class CDebugWindowApp : public CWinApp { public: CDebugWindowApp(); - ~CDebugWindowApp(); + ~CDebugWindowApp() override; DebugWindowDialog* GetDialogWindow(); void SetDialogWindow(DebugWindowDialog* pWnd); diff --git a/Core/Tools/MapCacheBuilder/Source/WinMain.cpp b/Core/Tools/MapCacheBuilder/Source/WinMain.cpp index 134f1465980..1ba344f7c01 100644 --- a/Core/Tools/MapCacheBuilder/Source/WinMain.cpp +++ b/Core/Tools/MapCacheBuilder/Source/WinMain.cpp @@ -259,7 +259,7 @@ Int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, initSubsystem(TheTerrainRoads, new TerrainRoadCollection(), "Data\\INI\\Default\\Roads", "Data\\INI\\Roads"); initSubsystem(TheScriptEngine, (ScriptEngine*)(new ScriptEngine())); initSubsystem(TheAudio, (AudioManager*)new MilesAudioManager()); - initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new VideoPlayer())); + initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new NullVideoPlayer())); initSubsystem(TheModuleFactory, (ModuleFactory*)(new W3DModuleFactory())); initSubsystem(TheSidesList, new SidesList()); initSubsystem(TheCaveSystem, new CaveSystem()); diff --git a/Core/Tools/ParticleEditor/CButtonShowColor.h b/Core/Tools/ParticleEditor/CButtonShowColor.h index 64238d4585c..f570742769b 100644 --- a/Core/Tools/ParticleEditor/CButtonShowColor.h +++ b/Core/Tools/ParticleEditor/CButtonShowColor.h @@ -29,7 +29,7 @@ class CButtonShowColor : public CButton const RGBColor& getColor() const { return m_color; } void setColor(Int color) { m_color.setFromInt(color); } void setColor(const RGBColor& color) { m_color = color; } - ~CButtonShowColor(); + ~CButtonShowColor() override; static COLORREF RGBtoBGR(Int color); diff --git a/Core/Tools/ParticleEditor/MoreParmsDialog.h b/Core/Tools/ParticleEditor/MoreParmsDialog.h index 6e57198500d..2d1800b2588 100644 --- a/Core/Tools/ParticleEditor/MoreParmsDialog.h +++ b/Core/Tools/ParticleEditor/MoreParmsDialog.h @@ -46,7 +46,7 @@ class MoreParmsDialog : public CDialog public: enum { IDD = IDD_PSEd_EditMoreParms }; MoreParmsDialog(UINT nIDTemplate = MoreParmsDialog::IDD, CWnd* pParentWnd = nullptr); - virtual ~MoreParmsDialog(); + virtual ~MoreParmsDialog() override; void InitPanel(); diff --git a/Core/Tools/ParticleEditor/ParticleEditor.h b/Core/Tools/ParticleEditor/ParticleEditor.h index e498f903e5e..9099fa7a55c 100644 --- a/Core/Tools/ParticleEditor/ParticleEditor.h +++ b/Core/Tools/ParticleEditor/ParticleEditor.h @@ -38,7 +38,7 @@ class CDebugWindowApp : public CWinApp { public: CDebugWindowApp(); - ~CDebugWindowApp(); + ~CDebugWindowApp() override; DebugWindowDialog* GetDialogWindow(); void SetDialogWindow(DebugWindowDialog* pWnd); diff --git a/Core/Tools/ParticleEditor/ParticleEditorDialog.h b/Core/Tools/ParticleEditor/ParticleEditorDialog.h index 69203757a5c..e33ae65606b 100644 --- a/Core/Tools/ParticleEditor/ParticleEditorDialog.h +++ b/Core/Tools/ParticleEditor/ParticleEditorDialog.h @@ -55,7 +55,7 @@ class DebugWindowDialog : public CDialog public: enum {IDD = IDD_PSEd}; DebugWindowDialog(UINT nIDTemplate = DebugWindowDialog::IDD, CWnd* pParentWnd = nullptr); - virtual ~DebugWindowDialog(); + virtual ~DebugWindowDialog() override; void InitPanel(); HWND GetMainWndHWND(); diff --git a/Core/Tools/W3DView/AdvancedAnimSheet.h b/Core/Tools/W3DView/AdvancedAnimSheet.h index 42244a55901..345e3cee940 100644 --- a/Core/Tools/W3DView/AdvancedAnimSheet.h +++ b/Core/Tools/W3DView/AdvancedAnimSheet.h @@ -62,7 +62,7 @@ class CAdvancedAnimSheet : public CPropertySheet // Implementation public: - virtual ~CAdvancedAnimSheet(); + virtual ~CAdvancedAnimSheet() override; // Generated message map functions protected: diff --git a/Core/Tools/W3DView/AnimMixingPage.h b/Core/Tools/W3DView/AnimMixingPage.h index 0a917858dc8..df4314d8838 100644 --- a/Core/Tools/W3DView/AnimMixingPage.h +++ b/Core/Tools/W3DView/AnimMixingPage.h @@ -33,7 +33,7 @@ class CAnimMixingPage : public CPropertyPage // Construction public: CAnimMixingPage(CAdvancedAnimSheet *sheet = nullptr); - ~CAnimMixingPage(); + ~CAnimMixingPage() override; // Dialog Data //{{AFX_DATA(CAnimMixingPage) diff --git a/Core/Tools/W3DView/AnimReportPage.h b/Core/Tools/W3DView/AnimReportPage.h index 591aa82e269..8432b41aa8e 100644 --- a/Core/Tools/W3DView/AnimReportPage.h +++ b/Core/Tools/W3DView/AnimReportPage.h @@ -34,7 +34,7 @@ class CAnimReportPage : public CPropertyPage // Construction public: CAnimReportPage(CAdvancedAnimSheet *sheet = nullptr); - ~CAnimReportPage(); + ~CAnimReportPage() override; // Dialog Data //{{AFX_DATA(CAnimReportPage) diff --git a/Core/Tools/W3DView/AnimationPropPage.h b/Core/Tools/W3DView/AnimationPropPage.h index cd10d5cd399..f31d4e1ad6e 100644 --- a/Core/Tools/W3DView/AnimationPropPage.h +++ b/Core/Tools/W3DView/AnimationPropPage.h @@ -31,7 +31,7 @@ class CAnimationPropPage : public CPropertyPage // Construction public: CAnimationPropPage(); - ~CAnimationPropPage(); + ~CAnimationPropPage() override; // Dialog Data //{{AFX_DATA(CAnimationPropPage) diff --git a/Core/Tools/W3DView/AssetPropertySheet.h b/Core/Tools/W3DView/AssetPropertySheet.h index c770b2f5752..08bd1a295f5 100644 --- a/Core/Tools/W3DView/AssetPropertySheet.h +++ b/Core/Tools/W3DView/AssetPropertySheet.h @@ -45,7 +45,7 @@ class CAssetPropertySheet : public CPropertySheet // Implementation public: - virtual ~CAssetPropertySheet(); + virtual ~CAssetPropertySheet() override; // Generated message map functions protected: diff --git a/Core/Tools/W3DView/ColorBar.h b/Core/Tools/W3DView/ColorBar.h index a66c9a0af46..2c6410e7ba3 100644 --- a/Core/Tools/W3DView/ColorBar.h +++ b/Core/Tools/W3DView/ColorBar.h @@ -108,7 +108,7 @@ class ColorBarClass : public CWnd // Implementation public: - virtual ~ColorBarClass(); + virtual ~ColorBarClass() override; // Generated message map functions protected: diff --git a/Core/Tools/W3DView/ColorPicker.h b/Core/Tools/W3DView/ColorPicker.h index fa6d833158c..3339d11bec6 100644 --- a/Core/Tools/W3DView/ColorPicker.h +++ b/Core/Tools/W3DView/ColorPicker.h @@ -82,7 +82,7 @@ class ColorPickerClass : public CWnd // Implementation public: - virtual ~ColorPickerClass(); + virtual ~ColorPickerClass() override; // Generated message map functions protected: diff --git a/Core/Tools/W3DView/DialogToolbar.h b/Core/Tools/W3DView/DialogToolbar.h index c614a35d13a..e1812168d26 100644 --- a/Core/Tools/W3DView/DialogToolbar.h +++ b/Core/Tools/W3DView/DialogToolbar.h @@ -46,7 +46,7 @@ class DialogToolbarClass : public CToolBar { public: DialogToolbarClass (); - virtual ~DialogToolbarClass () {} + virtual ~DialogToolbarClass () override {} // Form Data public: diff --git a/Core/Tools/W3DView/EmitterColorPropPage.h b/Core/Tools/W3DView/EmitterColorPropPage.h index e928e421fd7..6e64455dd72 100644 --- a/Core/Tools/W3DView/EmitterColorPropPage.h +++ b/Core/Tools/W3DView/EmitterColorPropPage.h @@ -39,7 +39,7 @@ class EmitterColorPropPageClass : public CPropertyPage // Construction public: EmitterColorPropPageClass (EmitterInstanceListClass *pemitter_list = nullptr); - ~EmitterColorPropPageClass (); + ~EmitterColorPropPageClass () override; // Dialog Data //{{AFX_DATA(EmitterColorPropPageClass) diff --git a/Core/Tools/W3DView/EmitterFramePropPage.h b/Core/Tools/W3DView/EmitterFramePropPage.h index f2f80553da2..ace4125c05c 100644 --- a/Core/Tools/W3DView/EmitterFramePropPage.h +++ b/Core/Tools/W3DView/EmitterFramePropPage.h @@ -36,7 +36,7 @@ class EmitterFramePropPageClass : public CPropertyPage // Construction public: EmitterFramePropPageClass(); - ~EmitterFramePropPageClass(); + ~EmitterFramePropPageClass() override; // Dialog Data //{{AFX_DATA(EmitterFramePropPageClass) diff --git a/Core/Tools/W3DView/EmitterGeneralPropPage.h b/Core/Tools/W3DView/EmitterGeneralPropPage.h index 1096611b810..833de0ddb12 100644 --- a/Core/Tools/W3DView/EmitterGeneralPropPage.h +++ b/Core/Tools/W3DView/EmitterGeneralPropPage.h @@ -39,7 +39,7 @@ class EmitterGeneralPropPageClass : public CPropertyPage // Construction public: EmitterGeneralPropPageClass (EmitterInstanceListClass *pemitter_list = nullptr); - ~EmitterGeneralPropPageClass (); + ~EmitterGeneralPropPageClass () override; // Dialog Data //{{AFX_DATA(EmitterGeneralPropPageClass) diff --git a/Core/Tools/W3DView/EmitterInstanceList.h b/Core/Tools/W3DView/EmitterInstanceList.h index dd5453cd057..20cca34c371 100644 --- a/Core/Tools/W3DView/EmitterInstanceList.h +++ b/Core/Tools/W3DView/EmitterInstanceList.h @@ -53,7 +53,7 @@ class EmitterInstanceListClass : public ParticleEmitterDefClass EmitterInstanceListClass (const EmitterInstanceListClass &src) : ParticleEmitterDefClass (src) { } - virtual ~EmitterInstanceListClass (); + virtual ~EmitterInstanceListClass () override; /////////////////////////////////////////////////////// // Public methods @@ -71,30 +71,30 @@ class EmitterInstanceListClass : public ParticleEmitterDefClass // definition and can be used to create a new prototype loader. // - virtual void Set_Velocity (const Vector3 &value); - virtual void Set_Acceleration (const Vector3 &value); - virtual void Set_Burst_Size (unsigned int count); - virtual void Set_Outward_Vel (float value); - virtual void Set_Vel_Inherit (float value); + virtual void Set_Velocity (const Vector3 &value) override; + virtual void Set_Acceleration (const Vector3 &value) override; + virtual void Set_Burst_Size (unsigned int count) override; + virtual void Set_Outward_Vel (float value) override; + virtual void Set_Vel_Inherit (float value) override; // // Randomizer accessors // - virtual void Set_Velocity_Random (Vector3Randomizer *randomizer); + virtual void Set_Velocity_Random (Vector3Randomizer *randomizer) override; // // Keyframe accessors // - virtual void Set_Color_Keyframes (ParticlePropertyStruct &keyframes); - virtual void Set_Opacity_Keyframes (ParticlePropertyStruct &keyframes); - virtual void Set_Size_Keyframes (ParticlePropertyStruct &keyframes); - virtual void Set_Rotation_Keyframes (ParticlePropertyStruct &keyframes, float orient_rnd); - virtual void Set_Frame_Keyframes (ParticlePropertyStruct &keyframes); - virtual void Set_Blur_Time_Keyframes (ParticlePropertyStruct &keyframes); - - virtual void Get_Color_Keyframes (ParticlePropertyStruct &keyframes) const; - virtual void Get_Opacity_Keyframes (ParticlePropertyStruct &keyframes) const; - virtual void Get_Size_Keyframes (ParticlePropertyStruct &keyframes) const; + virtual void Set_Color_Keyframes (ParticlePropertyStruct &keyframes) override; + virtual void Set_Opacity_Keyframes (ParticlePropertyStruct &keyframes) override; + virtual void Set_Size_Keyframes (ParticlePropertyStruct &keyframes) override; + virtual void Set_Rotation_Keyframes (ParticlePropertyStruct &keyframes, float orient_rnd) override; + virtual void Set_Frame_Keyframes (ParticlePropertyStruct &keyframes) override; + virtual void Set_Blur_Time_Keyframes (ParticlePropertyStruct &keyframes) override; + + virtual void Get_Color_Keyframes (ParticlePropertyStruct &keyframes) const override; + virtual void Get_Opacity_Keyframes (ParticlePropertyStruct &keyframes) const override; + virtual void Get_Size_Keyframes (ParticlePropertyStruct &keyframes) const override; private: diff --git a/Core/Tools/W3DView/EmitterLineGroupPropPage.h b/Core/Tools/W3DView/EmitterLineGroupPropPage.h index fd502f7ab1f..637b2ca11dd 100644 --- a/Core/Tools/W3DView/EmitterLineGroupPropPage.h +++ b/Core/Tools/W3DView/EmitterLineGroupPropPage.h @@ -39,7 +39,7 @@ class EmitterLineGroupPropPageClass : public CPropertyPage // Construction public: EmitterLineGroupPropPageClass(); - ~EmitterLineGroupPropPageClass(); + ~EmitterLineGroupPropPageClass() override; // Dialog Data //{{AFX_DATA(EmitterLineGroupPropPageClass) diff --git a/Core/Tools/W3DView/EmitterLinePropPage.h b/Core/Tools/W3DView/EmitterLinePropPage.h index 8e6566b1c0e..e9ada2a5899 100644 --- a/Core/Tools/W3DView/EmitterLinePropPage.h +++ b/Core/Tools/W3DView/EmitterLinePropPage.h @@ -36,7 +36,7 @@ class EmitterLinePropPageClass : public CPropertyPage // Construction public: EmitterLinePropPageClass(); - ~EmitterLinePropPageClass(); + ~EmitterLinePropPageClass() override; // Dialog Data //{{AFX_DATA(EmitterLinePropPageClass) diff --git a/Core/Tools/W3DView/EmitterParticlePropPage.h b/Core/Tools/W3DView/EmitterParticlePropPage.h index b3a084d425c..a92acee4612 100644 --- a/Core/Tools/W3DView/EmitterParticlePropPage.h +++ b/Core/Tools/W3DView/EmitterParticlePropPage.h @@ -39,7 +39,7 @@ class EmitterParticlePropPageClass : public CPropertyPage // Construction public: EmitterParticlePropPageClass (EmitterInstanceListClass *pemitter_list = nullptr); - ~EmitterParticlePropPageClass (); + ~EmitterParticlePropPageClass () override; // Dialog Data //{{AFX_DATA(EmitterParticlePropPageClass) diff --git a/Core/Tools/W3DView/EmitterPhysicsPropPage.h b/Core/Tools/W3DView/EmitterPhysicsPropPage.h index c94a0c44501..3af0f56d21b 100644 --- a/Core/Tools/W3DView/EmitterPhysicsPropPage.h +++ b/Core/Tools/W3DView/EmitterPhysicsPropPage.h @@ -38,7 +38,7 @@ class EmitterPhysicsPropPageClass : public CPropertyPage // Construction public: EmitterPhysicsPropPageClass (EmitterInstanceListClass *pemitter_list = nullptr); - ~EmitterPhysicsPropPageClass (); + ~EmitterPhysicsPropPageClass () override; // Dialog Data //{{AFX_DATA(EmitterPhysicsPropPageClass) diff --git a/Core/Tools/W3DView/EmitterPropertySheet.h b/Core/Tools/W3DView/EmitterPropertySheet.h index 80a9bca7937..361d3e5b46e 100644 --- a/Core/Tools/W3DView/EmitterPropertySheet.h +++ b/Core/Tools/W3DView/EmitterPropertySheet.h @@ -61,12 +61,12 @@ class EmitterPropertySheetClass : public CPropertySheet // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(EmitterPropertySheetClass) protected: - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation public: - virtual ~EmitterPropertySheetClass(); + virtual ~EmitterPropertySheetClass() override; // Generated message map functions protected: diff --git a/Core/Tools/W3DView/EmitterRotationPropPage.h b/Core/Tools/W3DView/EmitterRotationPropPage.h index 977561c66dc..9f2b6d47ac2 100644 --- a/Core/Tools/W3DView/EmitterRotationPropPage.h +++ b/Core/Tools/W3DView/EmitterRotationPropPage.h @@ -38,7 +38,7 @@ class EmitterRotationPropPageClass : public CPropertyPage // Construction public: EmitterRotationPropPageClass(); - ~EmitterRotationPropPageClass(); + ~EmitterRotationPropPageClass() override; // Dialog Data //{{AFX_DATA(EmitterRotationPropPageClass) diff --git a/Core/Tools/W3DView/EmitterSizePropPage.h b/Core/Tools/W3DView/EmitterSizePropPage.h index d53b5975dab..7f357de378d 100644 --- a/Core/Tools/W3DView/EmitterSizePropPage.h +++ b/Core/Tools/W3DView/EmitterSizePropPage.h @@ -39,7 +39,7 @@ class EmitterSizePropPageClass : public CPropertyPage // Construction public: EmitterSizePropPageClass(EmitterInstanceListClass *pemitter = nullptr); - ~EmitterSizePropPageClass(); + ~EmitterSizePropPageClass() override; // Dialog Data //{{AFX_DATA(EmitterSizePropPageClass) diff --git a/Core/Tools/W3DView/EmitterUserPropPage.h b/Core/Tools/W3DView/EmitterUserPropPage.h index accdb6e5324..66db288932f 100644 --- a/Core/Tools/W3DView/EmitterUserPropPage.h +++ b/Core/Tools/W3DView/EmitterUserPropPage.h @@ -36,7 +36,7 @@ class EmitterUserPropPageClass : public CPropertyPage // Construction public: EmitterUserPropPageClass (EmitterInstanceListClass *pemitter_list = nullptr); - ~EmitterUserPropPageClass (); + ~EmitterUserPropPageClass () override; // Dialog Data //{{AFX_DATA(EmitterUserPropPageClass) diff --git a/Core/Tools/W3DView/GammaDialog.h b/Core/Tools/W3DView/GammaDialog.h index 6252b3d024b..05bf15b0913 100644 --- a/Core/Tools/W3DView/GammaDialog.h +++ b/Core/Tools/W3DView/GammaDialog.h @@ -42,7 +42,7 @@ class GammaDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(GammaDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -50,8 +50,8 @@ class GammaDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(GammaDialogClass) - virtual BOOL OnInitDialog(); - virtual void OnOK(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; afx_msg void OnReleasedcaptureGammaSlider(NMHDR* pNMHDR, LRESULT* pResult); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/GraphicView.h b/Core/Tools/W3DView/GraphicView.h index 7175327089c..6b3a2b4519a 100644 --- a/Core/Tools/W3DView/GraphicView.h +++ b/Core/Tools/W3DView/GraphicView.h @@ -66,7 +66,7 @@ class CGraphicView : public CView // Implementation protected: - virtual ~CGraphicView(); + virtual ~CGraphicView() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/Core/Tools/W3DView/HierarchyPropPage.h b/Core/Tools/W3DView/HierarchyPropPage.h index bd70b4f939e..a4776f9a4be 100644 --- a/Core/Tools/W3DView/HierarchyPropPage.h +++ b/Core/Tools/W3DView/HierarchyPropPage.h @@ -31,7 +31,7 @@ class CHierarchyPropPage : public CPropertyPage // Construction public: CHierarchyPropPage (const CString &stringHierarchyName); - ~CHierarchyPropPage (); + ~CHierarchyPropPage () override; // Dialog Data //{{AFX_DATA(CHierarchyPropPage) @@ -44,14 +44,14 @@ class CHierarchyPropPage : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(CHierarchyPropPage) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CHierarchyPropPage) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnDblclkSubObjectList(NMHDR* pNMHDR, LRESULT* pResult); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/MeshPropPage.h b/Core/Tools/W3DView/MeshPropPage.h index 4286b4ea337..08ee399c5fa 100644 --- a/Core/Tools/W3DView/MeshPropPage.h +++ b/Core/Tools/W3DView/MeshPropPage.h @@ -31,7 +31,7 @@ class CMeshPropPage : public CPropertyPage // Construction public: CMeshPropPage (const CString &stringMeshName); - ~CMeshPropPage (); + ~CMeshPropPage () override; // Dialog Data //{{AFX_DATA(CMeshPropPage) @@ -45,14 +45,14 @@ class CMeshPropPage : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(CMeshPropPage) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(CMeshPropPage) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnClose(); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/OpacityVectorDialog.h b/Core/Tools/W3DView/OpacityVectorDialog.h index 0d1a41737aa..bb31b1beecf 100644 --- a/Core/Tools/W3DView/OpacityVectorDialog.h +++ b/Core/Tools/W3DView/OpacityVectorDialog.h @@ -48,8 +48,8 @@ class OpacityVectorDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(OpacityVectorDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation @@ -57,9 +57,9 @@ class OpacityVectorDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(OpacityVectorDialogClass) - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual void OnCancel(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; + virtual void OnCancel() override; afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/ParticleBlurTimeKeyDialog.h b/Core/Tools/W3DView/ParticleBlurTimeKeyDialog.h index acdd78cbb61..db7c368359b 100644 --- a/Core/Tools/W3DView/ParticleBlurTimeKeyDialog.h +++ b/Core/Tools/W3DView/ParticleBlurTimeKeyDialog.h @@ -41,8 +41,8 @@ class ParticleBlurTimeKeyDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(ParticleBlurTimeKeyDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation @@ -50,7 +50,7 @@ class ParticleBlurTimeKeyDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(ParticleBlurTimeKeyDialogClass) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnOk2(); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/ParticleRotationKeyDialog.h b/Core/Tools/W3DView/ParticleRotationKeyDialog.h index d2fa14e3269..aebe5991a51 100644 --- a/Core/Tools/W3DView/ParticleRotationKeyDialog.h +++ b/Core/Tools/W3DView/ParticleRotationKeyDialog.h @@ -41,8 +41,8 @@ class ParticleRotationKeyDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(ParticleRotationKeyDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation @@ -50,8 +50,8 @@ class ParticleRotationKeyDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(ParticleRotationKeyDialogClass) - virtual BOOL OnInitDialog(); - virtual void OnOK(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/ParticleSizeDialog.h b/Core/Tools/W3DView/ParticleSizeDialog.h index 8303479c9c7..2cc06120008 100644 --- a/Core/Tools/W3DView/ParticleSizeDialog.h +++ b/Core/Tools/W3DView/ParticleSizeDialog.h @@ -41,8 +41,8 @@ class ParticleSizeDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(ParticleSizeDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation @@ -50,8 +50,8 @@ class ParticleSizeDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(ParticleSizeDialogClass) - virtual BOOL OnInitDialog(); - virtual void OnOK(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/PlaySoundDialog.h b/Core/Tools/W3DView/PlaySoundDialog.h index 1162955df3b..c0f2d16fe5a 100644 --- a/Core/Tools/W3DView/PlaySoundDialog.h +++ b/Core/Tools/W3DView/PlaySoundDialog.h @@ -44,7 +44,7 @@ class PlaySoundDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(PlaySoundDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -53,8 +53,8 @@ class PlaySoundDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(PlaySoundDialogClass) afx_msg void OnPlaySoundEffect(); - virtual void OnCancel(); - virtual BOOL OnInitDialog(); + virtual void OnCancel() override; + virtual BOOL OnInitDialog() override; afx_msg void OnStopSoundEffect(); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/ResolutionDialog.h b/Core/Tools/W3DView/ResolutionDialog.h index ddb0be63a8f..2080596cbce 100644 --- a/Core/Tools/W3DView/ResolutionDialog.h +++ b/Core/Tools/W3DView/ResolutionDialog.h @@ -43,7 +43,7 @@ class ResolutionDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(ResolutionDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -51,8 +51,8 @@ class ResolutionDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(ResolutionDialogClass) - virtual BOOL OnInitDialog(); - virtual void OnOK(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; afx_msg void OnDblclkResolutionListCtrl(NMHDR* pNMHDR, LRESULT* pResult); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/RingColorPropPage.h b/Core/Tools/W3DView/RingColorPropPage.h index 4d2d6f67a28..5775281ec53 100644 --- a/Core/Tools/W3DView/RingColorPropPage.h +++ b/Core/Tools/W3DView/RingColorPropPage.h @@ -37,7 +37,7 @@ class RingColorPropPageClass : public CPropertyPage // Construction public: RingColorPropPageClass (RingRenderObjClass *ring = nullptr); - ~RingColorPropPageClass (); + ~RingColorPropPageClass () override; // Dialog Data //{{AFX_DATA(RingColorPropPageClass) @@ -51,18 +51,18 @@ class RingColorPropPageClass : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(RingColorPropPageClass) public: - virtual BOOL OnApply(); - virtual void OnCancel(); + virtual BOOL OnApply() override; + virtual void OnCancel() override; protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(RingColorPropPageClass) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnDestroy(); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/RingGeneralPropPage.h b/Core/Tools/W3DView/RingGeneralPropPage.h index 66701ab910f..0d8c286075e 100644 --- a/Core/Tools/W3DView/RingGeneralPropPage.h +++ b/Core/Tools/W3DView/RingGeneralPropPage.h @@ -37,7 +37,7 @@ class RingGeneralPropPageClass : public CPropertyPage // Construction public: RingGeneralPropPageClass (RingRenderObjClass *ring = nullptr); - ~RingGeneralPropPageClass (); + ~RingGeneralPropPageClass () override; // Dialog Data //{{AFX_DATA(RingGeneralPropPageClass) @@ -51,18 +51,18 @@ class RingGeneralPropPageClass : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(RingGeneralPropPageClass) public: - virtual BOOL OnApply(); + virtual BOOL OnApply() override; protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(RingGeneralPropPageClass) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnBrowseButton(); afx_msg void OnChangeFilenameEdit(); afx_msg void OnChangeNameEdit(); diff --git a/Core/Tools/W3DView/RingPropertySheet.h b/Core/Tools/W3DView/RingPropertySheet.h index 4e101da0baf..cd0bdf4e824 100644 --- a/Core/Tools/W3DView/RingPropertySheet.h +++ b/Core/Tools/W3DView/RingPropertySheet.h @@ -71,12 +71,12 @@ class RingPropertySheetClass : public CPropertySheet // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(RingPropertySheetClass) protected: - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation public: - virtual ~RingPropertySheetClass(); + virtual ~RingPropertySheetClass() override; // Generated message map functions protected: diff --git a/Core/Tools/W3DView/RingSizePropPage.h b/Core/Tools/W3DView/RingSizePropPage.h index 820cd11e28d..cfb08a77cde 100644 --- a/Core/Tools/W3DView/RingSizePropPage.h +++ b/Core/Tools/W3DView/RingSizePropPage.h @@ -37,7 +37,7 @@ class RingSizePropPageClass : public CPropertyPage // Construction public: RingSizePropPageClass(RingRenderObjClass *ring = nullptr); - ~RingSizePropPageClass(); + ~RingSizePropPageClass() override; // Dialog Data //{{AFX_DATA(RingSizePropPageClass) @@ -53,19 +53,19 @@ class RingSizePropPageClass : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(RingSizePropPageClass) public: - virtual BOOL OnApply(); - virtual void OnCancel(); + virtual BOOL OnApply() override; + virtual void OnCancel() override; protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(RingSizePropPageClass) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnDestroy(); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/SaveSettingsDialog.h b/Core/Tools/W3DView/SaveSettingsDialog.h index b3d9b8be186..8a8799bbe95 100644 --- a/Core/Tools/W3DView/SaveSettingsDialog.h +++ b/Core/Tools/W3DView/SaveSettingsDialog.h @@ -41,8 +41,8 @@ class CSaveSettingsDialog : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSaveSettingsDialog) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation @@ -50,10 +50,10 @@ class CSaveSettingsDialog : public CDialog // Generated message map functions //{{AFX_MSG(CSaveSettingsDialog) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnBrowseButton(); afx_msg void OnUpdateFilenameEdit(); - virtual void OnOK(); + virtual void OnOK() override; //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/ScaleDialog.h b/Core/Tools/W3DView/ScaleDialog.h index 9872f26e191..207c15605dc 100644 --- a/Core/Tools/W3DView/ScaleDialog.h +++ b/Core/Tools/W3DView/ScaleDialog.h @@ -42,8 +42,8 @@ class ScaleDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(ScaleDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation @@ -51,8 +51,8 @@ class ScaleDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(ScaleDialogClass) - virtual BOOL OnInitDialog(); - virtual void OnOK(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/SceneLightDialog.h b/Core/Tools/W3DView/SceneLightDialog.h index c10dc4d535f..f14c1aba7e1 100644 --- a/Core/Tools/W3DView/SceneLightDialog.h +++ b/Core/Tools/W3DView/SceneLightDialog.h @@ -51,8 +51,8 @@ class CSceneLightDialog : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CSceneLightDialog) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation @@ -60,9 +60,9 @@ class CSceneLightDialog : public CDialog // Generated message map functions //{{AFX_MSG(CSceneLightDialog) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); - virtual void OnCancel(); + virtual void OnCancel() override; afx_msg void OnGrayscaleCheck(); afx_msg void OnChannelBothRadio(); afx_msg void OnChannelDiffuseRadio(); diff --git a/Core/Tools/W3DView/ScreenCursor.h b/Core/Tools/W3DView/ScreenCursor.h index 19f65a6f904..29000220b5b 100644 --- a/Core/Tools/W3DView/ScreenCursor.h +++ b/Core/Tools/W3DView/ScreenCursor.h @@ -53,7 +53,7 @@ class ScreenCursorClass : public RenderObjClass //////////////////////////////////////////////////////////////////////// ScreenCursorClass (); ScreenCursorClass (const ScreenCursorClass &src); - virtual ~ScreenCursorClass (); + virtual ~ScreenCursorClass () override; //////////////////////////////////////////////////////////////////////// // Public operators @@ -69,15 +69,15 @@ class ScreenCursorClass : public RenderObjClass //////////////////////////////////////////////////////////////////////// // Base class overrides //////////////////////////////////////////////////////////////////////// - RenderObjClass * Clone () const { return new ScreenCursorClass (*this); } - virtual int Class_ID() const { return CLASSID_LAST + 103L; } - virtual void Render (RenderInfoClass &rinfo); - virtual void On_Frame_Update (); - virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const; - virtual void Get_Obj_Space_Bounding_Box(AABoxClass & box) const; - - virtual void Notify_Added(SceneClass * scene); - virtual void Notify_Removed(SceneClass * scene); + RenderObjClass * Clone () const override { return new ScreenCursorClass (*this); } + virtual int Class_ID() const override { return CLASSID_LAST + 103L; } + virtual void Render (RenderInfoClass &rinfo) override; + virtual void On_Frame_Update () override; + virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const override; + virtual void Get_Obj_Space_Bounding_Box(AABoxClass & box) const override; + + virtual void Notify_Added(SceneClass * scene) override; + virtual void Notify_Removed(SceneClass * scene) override; protected: diff --git a/Core/Tools/W3DView/SoundEditDialog.h b/Core/Tools/W3DView/SoundEditDialog.h index 6a962164c08..c757b2571bd 100644 --- a/Core/Tools/W3DView/SoundEditDialog.h +++ b/Core/Tools/W3DView/SoundEditDialog.h @@ -37,7 +37,7 @@ class SoundEditDialogClass : public CDialog { public: SoundEditDialogClass (CWnd *parent); - virtual ~SoundEditDialogClass (); + virtual ~SoundEditDialogClass () override; // Form Data public: @@ -57,7 +57,7 @@ class SoundEditDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(SoundEditDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -73,9 +73,9 @@ class SoundEditDialogClass : public CDialog afx_msg void On2DRadio(); afx_msg void On3DRadio(); afx_msg void OnPlay(); - virtual BOOL OnInitDialog(); - virtual void OnOK(); - virtual void OnCancel(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; + virtual void OnCancel() override; //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/SphereColorPropPage.h b/Core/Tools/W3DView/SphereColorPropPage.h index b0df952f9ee..776f74ce391 100644 --- a/Core/Tools/W3DView/SphereColorPropPage.h +++ b/Core/Tools/W3DView/SphereColorPropPage.h @@ -37,7 +37,7 @@ class SphereColorPropPageClass : public CPropertyPage // Construction public: SphereColorPropPageClass (SphereRenderObjClass *sphere = nullptr); - ~SphereColorPropPageClass (); + ~SphereColorPropPageClass () override; // Dialog Data //{{AFX_DATA(SphereColorPropPageClass) @@ -51,18 +51,18 @@ class SphereColorPropPageClass : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(SphereColorPropPageClass) public: - virtual BOOL OnApply(); - virtual void OnCancel(); + virtual BOOL OnApply() override; + virtual void OnCancel() override; protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(SphereColorPropPageClass) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnDestroy(); afx_msg void OnOpacityVectorCheck(); afx_msg void OnInvertVectorCheck(); diff --git a/Core/Tools/W3DView/SphereGeneralPropPage.h b/Core/Tools/W3DView/SphereGeneralPropPage.h index 868f1975b2c..585260ccd37 100644 --- a/Core/Tools/W3DView/SphereGeneralPropPage.h +++ b/Core/Tools/W3DView/SphereGeneralPropPage.h @@ -37,7 +37,7 @@ class SphereGeneralPropPageClass : public CPropertyPage // Construction public: SphereGeneralPropPageClass (SphereRenderObjClass *sphere = nullptr); - ~SphereGeneralPropPageClass (); + ~SphereGeneralPropPageClass () override; // Dialog Data //{{AFX_DATA(SphereGeneralPropPageClass) @@ -50,18 +50,18 @@ class SphereGeneralPropPageClass : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(SphereGeneralPropPageClass) public: - virtual BOOL OnApply(); + virtual BOOL OnApply() override; protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(SphereGeneralPropPageClass) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnBrowseButton(); afx_msg void OnChangeFilenameEdit(); afx_msg void OnChangeNameEdit(); diff --git a/Core/Tools/W3DView/SpherePropertySheet.h b/Core/Tools/W3DView/SpherePropertySheet.h index 2589687b2a3..a34d4723314 100644 --- a/Core/Tools/W3DView/SpherePropertySheet.h +++ b/Core/Tools/W3DView/SpherePropertySheet.h @@ -71,12 +71,12 @@ class SpherePropertySheetClass : public CPropertySheet // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(SpherePropertySheetClass) protected: - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation public: - virtual ~SpherePropertySheetClass(); + virtual ~SpherePropertySheetClass() override; // Generated message map functions protected: diff --git a/Core/Tools/W3DView/SphereSizePropPage.h b/Core/Tools/W3DView/SphereSizePropPage.h index 3bbbe4123b2..7f6eb2bd18c 100644 --- a/Core/Tools/W3DView/SphereSizePropPage.h +++ b/Core/Tools/W3DView/SphereSizePropPage.h @@ -37,7 +37,7 @@ class SphereSizePropPageClass : public CPropertyPage // Construction public: SphereSizePropPageClass(SphereRenderObjClass *sphere = nullptr); - ~SphereSizePropPageClass(); + ~SphereSizePropPageClass() override; // Dialog Data //{{AFX_DATA(SphereSizePropPageClass) @@ -52,19 +52,19 @@ class SphereSizePropPageClass : public CPropertyPage // ClassWizard generate virtual function overrides //{{AFX_VIRTUAL(SphereSizePropPageClass) public: - virtual BOOL OnApply(); - virtual void OnCancel(); + virtual BOOL OnApply() override; + virtual void OnCancel() override; protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam) override; //}}AFX_VIRTUAL // Implementation protected: // Generated message map functions //{{AFX_MSG(SphereSizePropPageClass) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; afx_msg void OnDestroy(); //}}AFX_MSG DECLARE_MESSAGE_MAP() diff --git a/Core/Tools/W3DView/TexturePathDialog.h b/Core/Tools/W3DView/TexturePathDialog.h index 58082664864..960a79d6629 100644 --- a/Core/Tools/W3DView/TexturePathDialog.h +++ b/Core/Tools/W3DView/TexturePathDialog.h @@ -41,7 +41,7 @@ class TexturePathDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(TexturePathDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation @@ -49,8 +49,8 @@ class TexturePathDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(TexturePathDialogClass) - virtual BOOL OnInitDialog(); - virtual void OnOK(); + virtual BOOL OnInitDialog() override; + virtual void OnOK() override; afx_msg void OnBrowse1(); afx_msg void OnBrowse2(); //}}AFX_MSG diff --git a/Core/Tools/W3DView/Toolbar.h b/Core/Tools/W3DView/Toolbar.h index fbab2af7cb9..d79da687ca9 100644 --- a/Core/Tools/W3DView/Toolbar.h +++ b/Core/Tools/W3DView/Toolbar.h @@ -82,7 +82,7 @@ class CFancyToolbar : public CControlBar // Public Contructors // CFancyToolbar (); - virtual ~CFancyToolbar (); + virtual ~CFancyToolbar () override; //////////////////////////////////////////////////////// diff --git a/Core/Tools/W3DView/ViewerScene.cpp b/Core/Tools/W3DView/ViewerScene.cpp index ae9486a097d..911aaed1de1 100644 --- a/Core/Tools/W3DView/ViewerScene.cpp +++ b/Core/Tools/W3DView/ViewerScene.cpp @@ -53,10 +53,10 @@ class ViewerSceneIterator : public SceneIterator { public: - virtual void First(); - virtual void Next(); - virtual bool Is_Done(); - virtual RenderObjClass * Current_Item(); + virtual void First() override; + virtual void Next() override; + virtual bool Is_Done() override; + virtual RenderObjClass * Current_Item() override; protected: diff --git a/Core/Tools/W3DView/VolumeRandomDialog.h b/Core/Tools/W3DView/VolumeRandomDialog.h index 7ff8c1e96f1..b69915cd0e7 100644 --- a/Core/Tools/W3DView/VolumeRandomDialog.h +++ b/Core/Tools/W3DView/VolumeRandomDialog.h @@ -51,8 +51,8 @@ class VolumeRandomDialogClass : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(VolumeRandomDialogClass) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support + virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) override; //}}AFX_VIRTUAL // Implementation @@ -60,8 +60,8 @@ class VolumeRandomDialogClass : public CDialog // Generated message map functions //{{AFX_MSG(VolumeRandomDialogClass) - virtual void OnOK(); - virtual BOOL OnInitDialog(); + virtual void OnOK() override; + virtual BOOL OnInitDialog() override; afx_msg void OnBoxRadio(); afx_msg void OnCylinderRadio(); afx_msg void OnSphereRadio(); diff --git a/Core/Tools/W3DView/W3DView.cpp b/Core/Tools/W3DView/W3DView.cpp index 552740b4937..a4384115689 100644 --- a/Core/Tools/W3DView/W3DView.cpp +++ b/Core/Tools/W3DView/W3DView.cpp @@ -275,13 +275,13 @@ class CAboutDlg : public CDialog // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) - virtual BOOL OnInitDialog(); + virtual BOOL OnInitDialog() override; //}}AFX_MSG DECLARE_MESSAGE_MAP() }; diff --git a/Core/Tools/W3DView/W3DViewDoc.cpp b/Core/Tools/W3DView/W3DViewDoc.cpp index 25213270260..da6d529a0a4 100644 --- a/Core/Tools/W3DView/W3DViewDoc.cpp +++ b/Core/Tools/W3DView/W3DViewDoc.cpp @@ -1506,7 +1506,7 @@ CW3DViewDoc::SaveSettings stringValue, (LPCTSTR)stringCompleteFilename); - Matrix3D transform = m_pCSceneLight->Get_Transform (); + const Matrix3D& transform = m_pCSceneLight->Get_Transform (); Quaternion orientation = ::Build_Quaternion (transform); // Write the x-position out to the file @@ -2379,7 +2379,7 @@ CW3DViewDoc::Make_Movie () if (index != -1) { // Convert the bone's transform into a camera transform - Matrix3D transform = m_pCRenderObj->Get_Bone_Transform (index); + const Matrix3D& transform = m_pCRenderObj->Get_Bone_Transform (index); Matrix3D cam_transform (Vector3 (0, -1, 0), Vector3 (0, 0, 1), Vector3 (-1, 0, 0), Vector3 (0, 0, 0)); #ifdef ALLOW_TEMPORARIES Matrix3D new_transform = transform * cam_transform; @@ -2719,7 +2719,7 @@ CW3DViewDoc::Copy_Assets_To_Dir (LPCTSTR directory) // // Determine the source and destination filenames // - StringClass filename = dependency_list[counter]; + const StringClass &filename = dependency_list[counter]; CString src_filename = src_path + CString (filename); CString dest_filename = dest_path + CString (filename); diff --git a/Core/Tools/W3DView/W3DViewDoc.h b/Core/Tools/W3DView/W3DViewDoc.h index 768af4f6480..28297114cfe 100644 --- a/Core/Tools/W3DView/W3DViewDoc.h +++ b/Core/Tools/W3DView/W3DViewDoc.h @@ -88,7 +88,7 @@ class CW3DViewDoc : public CDocument // Implementation public: - virtual ~CW3DViewDoc(); + virtual ~CW3DViewDoc() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/Core/Tools/W3DView/W3DViewView.h b/Core/Tools/W3DView/W3DViewView.h index c69d133494d..08e1cfda240 100644 --- a/Core/Tools/W3DView/W3DViewView.h +++ b/Core/Tools/W3DView/W3DViewView.h @@ -39,14 +39,14 @@ class CW3DViewView : public CView // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CW3DViewView) public: - virtual void OnDraw(CDC* pDC); // overridden to draw this view - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void OnDraw(CDC* pDC) override; // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs) override; protected: //}}AFX_VIRTUAL // Implementation public: - virtual ~CW3DViewView(); + virtual ~CW3DViewView() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/Core/Tools/textureCompress/textureCompress.cpp b/Core/Tools/textureCompress/textureCompress.cpp index 6080a6e5750..544315620ea 100644 --- a/Core/Tools/textureCompress/textureCompress.cpp +++ b/Core/Tools/textureCompress/textureCompress.cpp @@ -472,7 +472,7 @@ static void scanDir( const std::string& sourceDirName, const std::string& target FileInfoSet::iterator fit = sourceFiles->find(f); if (fit != sourceFiles->end()) { - FileInfo sf = *fit; + const FileInfo &sf = *fit; if (f.modTime < sf.modTime) { /** @@ -563,7 +563,7 @@ static void scanDir( const std::string& sourceDirName, const std::string& target FileInfoSet::iterator fit = cacheFiles->find(f); if (fit != cacheFiles->end()) { - FileInfo cf = *fit; + const FileInfo &cf = *fit; if (cf.modTime < f.modTime) { origFilesToCompress.insert(fname); diff --git a/Generals/Code/GameEngine/CMakeLists.txt b/Generals/Code/GameEngine/CMakeLists.txt index f14b320f7e8..f6148261ed6 100644 --- a/Generals/Code/GameEngine/CMakeLists.txt +++ b/Generals/Code/GameEngine/CMakeLists.txt @@ -129,7 +129,7 @@ set(GAMEENGINE_SRC # Include/Common/XferLoad.h # Include/Common/XferSave.h # Include/GameClient/Anim2D.h - Include/GameClient/AnimateWindowManager.h +# Include/GameClient/AnimateWindowManager.h # Include/GameClient/ChallengeGenerals.h Include/GameClient/CampaignManager.h # Include/GameClient/ClientInstance.h @@ -171,8 +171,8 @@ set(GAMEENGINE_SRC # Include/GameClient/GameText.h # Include/GameClient/GameWindow.h # Include/GameClient/GameWindowGlobal.h - Include/GameClient/GameWindowID.h - Include/GameClient/GameWindowManager.h +# Include/GameClient/GameWindowID.h +# Include/GameClient/GameWindowManager.h # Include/GameClient/GameWindowTransitions.h # Include/GameClient/GlobalLanguage.h # Include/GameClient/GraphDraw.h @@ -653,7 +653,7 @@ set(GAMEENGINE_SRC # Source/GameClient/GameText.cpp # Source/GameClient/GlobalLanguage.cpp # Source/GameClient/GraphDraw.cpp - Source/GameClient/GUI/AnimateWindowManager.cpp +# Source/GameClient/GUI/AnimateWindowManager.cpp # Source/GameClient/GUI/ChallengeGenerals.cpp # Source/GameClient/GUI/ControlBar/ControlBar.cpp # Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp @@ -683,10 +683,10 @@ set(GAMEENGINE_SRC # Source/GameClient/GUI/GameFont.cpp # Source/GameClient/GUI/GameWindow.cpp # Source/GameClient/GUI/GameWindowGlobal.cpp - Source/GameClient/GUI/GameWindowManager.cpp - Source/GameClient/GUI/GameWindowManagerScript.cpp +# Source/GameClient/GUI/GameWindowManager.cpp +# Source/GameClient/GUI/GameWindowManagerScript.cpp # Source/GameClient/GUI/GameWindowTransitions.cpp - Source/GameClient/GUI/GameWindowTransitionsStyles.cpp +# Source/GameClient/GUI/GameWindowTransitionsStyles.cpp # Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp # Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp # Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp diff --git a/Generals/Code/GameEngine/Include/Common/GameState.h b/Generals/Code/GameEngine/Include/Common/GameState.h index 2e292cedee8..84f6db72cdc 100644 --- a/Generals/Code/GameEngine/Include/Common/GameState.h +++ b/Generals/Code/GameEngine/Include/Common/GameState.h @@ -211,6 +211,7 @@ class GameState : public SubsystemInterface, AsciiString getSaveDirectory() const; AsciiString getFilePathInSaveDirectory(const AsciiString& leaf) const; + AsciiString getSaveGamePathForRead(const AsciiString& filenameOrPath) const; Bool isInSaveDirectory(const AsciiString& path) const; AsciiString realMapPathToPortableMapPath(const AsciiString& in) const; diff --git a/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h b/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h index c370ac5b3c0..9089411e091 100644 --- a/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h +++ b/Generals/Code/GameEngine/Include/Common/MapReaderWriterInfo.h @@ -70,7 +70,7 @@ class InputStream { variety of sources, such as FILE* or CFile. */ class ChunkInputStream : public InputStream{ public: - virtual Int read(void *pData, Int numBytes) = 0; + virtual Int read(void *pData, Int numBytes) override = 0; virtual UnsignedInt tell() = 0; virtual Bool absoluteSeek(UnsignedInt pos) = 0; virtual Bool eof() = 0; diff --git a/Generals/Code/GameEngine/Include/Common/TunnelTracker.h b/Generals/Code/GameEngine/Include/Common/TunnelTracker.h index b8d19cb7197..28300f338b9 100644 --- a/Generals/Code/GameEngine/Include/Common/TunnelTracker.h +++ b/Generals/Code/GameEngine/Include/Common/TunnelTracker.h @@ -66,7 +66,11 @@ class TunnelTracker : public MemoryPoolObject, void healObjects(); ///< heal all objects within the tunnel #endif +#if RETAIL_COMPATIBLE_CRC UnsignedInt friend_getTunnelCount() const {return m_tunnelCount;}///< TunnelContains are allowed to ask if they are the last one ahead of deletion time +#else + UnsignedInt friend_getTunnelCount() const { return m_tunnelIDs.size(); }///< TunnelContains are allowed to ask if they are the last one ahead of deletion time +#endif const std::list< ObjectID > *getContainerList() const {return &m_tunnelIDs;} @@ -87,7 +91,9 @@ class TunnelTracker : public MemoryPoolObject, std::list< ObjectID > m_xferContainList;///< for loading of m_containList during post processing Int m_containListSize; ///< size of the contain list UnsignedInt m_heroUnitsContained; ///< cached hero count +#if RETAIL_COMPATIBLE_CRC UnsignedInt m_tunnelCount; ///< How many tunnels have registered so we know when we should kill our contain list +#endif UnsignedInt m_framesForFullHeal; ///< How many frames it takes to fully heal a unit Bool m_needsFullHealTimeUpdate; ///< Set to true when needing to recalc full heal time to batch the operation diff --git a/Generals/Code/GameEngine/Include/GameClient/AnimateWindowManager.h b/Generals/Code/GameEngine/Include/GameClient/AnimateWindowManager.h deleted file mode 100644 index 4452cb3bad3..00000000000 --- a/Generals/Code/GameEngine/Include/GameClient/AnimateWindowManager.h +++ /dev/null @@ -1,235 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: AnimateWindowManager.h ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Mar 2002 -// -// Filename: AnimateWindowManager.h -// -// author: Chris Huybregts -// -// purpose: The Animate Window class will be used by registering a window with -// the manager with stating what kind of animation to do. Then on every -// update, we'll move the windows. -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "Lib/BaseType.h" -#include "Common/SubsystemInterface.h" -#include "Common/GameMemory.h" - -//----------------------------------------------------------------------------- -// FORWARD REFERENCES ///////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -class GameWindow; -class ProcessAnimateWindowSlideFromBottom; -class ProcessAnimateWindowSlideFromBottomTimed; -class ProcessAnimateWindowSlideFromTop; -class ProcessAnimateWindowSlideFromLeft; -class ProcessAnimateWindowSlideFromRight; -class ProcessAnimateWindowSlideFromRightFast; -class ProcessAnimateWindowSpiral; -class ProcessAnimateWindowSlideFromTopFast; -class ProcessAnimateWindowSideSelect; -class ProcessAnimateWindow; - -//----------------------------------------------------------------------------- -// TYPE DEFINES /////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -enum AnimTypes CPP_11(: Int) -{ - WIN_ANIMATION_NONE = 0, - WIN_ANIMATION_SLIDE_RIGHT, - WIN_ANIMATION_SLIDE_RIGHT_FAST, - WIN_ANIMATION_SLIDE_LEFT, - WIN_ANIMATION_SLIDE_TOP, - WIN_ANIMATION_SLIDE_BOTTOM, - WIN_ANIMATION_SPIRAL, - WIN_ANIMATION_SLIDE_BOTTOM_TIMED, - WIN_ANIMATION_SLIDE_TOP_FAST, - WIN_ANIMATION_COUNT -} ; - -//----------------------------------------------------------------------------- -// TheSuperHackers @build xezon 14/03/2025 Puts class into namespace to avoid name collision with AnimateWindow function in WinUser.h -namespace wnd -{ -class AnimateWindow : public MemoryPoolObject -{ - MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(AnimateWindow, "AnimateWindow") -public: - AnimateWindow(); - //~AnimateWindow(); - - static AnimateWindow* createNewInstance() - { - return newInstance(AnimateWindow); - } - - void setAnimData( ICoord2D startPos, ICoord2D endPos, Coord2D curPos, ICoord2D restPos, Coord2D vel, UnsignedInt startTime, UnsignedInt endTime); - - ICoord2D getStartPos(); ///< Get the Start Position 2D coord - Coord2D getCurPos(); ///< Get the Current Position 2D coord - ICoord2D getEndPos(); ///< Get the End Position 2D coord - ICoord2D getRestPos(); ///< Get the Rest Position 2D coord - GameWindow *getGameWindow(); ///< Get the GameWindow that will be animating - AnimTypes getAnimType(); ///< Get the Animation type - UnsignedInt getDelay(); ///< Get the Time Delay - Coord2D getVel(); ///< Get the Velocity Position 2D coord - UnsignedInt getStartTime(); ///< Get the start time of the time-based anim - UnsignedInt getEndTime(); ///< Get the end time of the time-based anim - - void setStartPos( ICoord2D starPos); ///< Set the Start Position 2D coord - void setCurPos( Coord2D curPos); ///< Set the Current Position 2D coord - void setEndPos( ICoord2D endPos); ///< Set the End Position 2D coord - void setRestPos( ICoord2D restPos); ///< Set the Rest Position 2D coord - void setGameWindow( GameWindow *win); ///< Set the GameWindow that will be animating - void setAnimType( AnimTypes animType); ///< Set the Animation type - void setDelay( UnsignedInt delay); ///< Set the Time Delay - void setVel( Coord2D vel); ///< Set the Velocity Position 2D coord - void setStartTime( UnsignedInt t); ///< Set the start time of the time-based anim - void setEndTime( UnsignedInt t); ///< Set the end time of the time-based anim - - void setFinished(Bool finished); ///< Set if the animation has finished - Bool isFinished(); ///< Return if the animation has finished or not. - void setNeedsToFinish( Bool needsToFinish); ///< set if we need this animation to finish for the manager to return true - Bool needsToFinish(); ///< set if the animation has finished - -private: - UnsignedInt m_delay; ///< Holds the delay time in which the animation will start (in milliseconds) - ICoord2D m_startPos; ///< Holds the starting position of the animation - ///<(usually is also the end position of the animation when the animation is reversed) - ICoord2D m_endPos; ///< Holds the target End Position (usually is the same as the rest position) - Coord2D m_curPos; ///< It's Current Position - ICoord2D m_restPos; ///< When the Manager Resets, It sets the window's position to this position - GameWindow *m_win; ///< the window that this animation is happening on - Coord2D m_vel; ///< the Velocity of the animation - UnsignedInt m_startTime; ///< time we started the time-based anim - UnsignedInt m_endTime; ///< time we should end the time-based anim - AnimTypes m_animType; ///< The type of animation that will happen - Bool m_needsToFinish; ///< Flag to tell the manager if we need to finish before it's done with it's animation - Bool m_isFinished; ///< We're finished -}; -} // namespace wnd - - - -//----------------------------------------------------------------------------- -typedef std::list AnimateWindowList; - -//----------------------------------------------------------------------------- -class AnimateWindowManager : public SubsystemInterface -{ -public: - AnimateWindowManager(); - virtual ~AnimateWindowManager() override; - - // Inhertited from subsystem ==================================================================== - virtual void init() override; - virtual void reset() override; - virtual void update() override; - //=============================================================================================== - - void registerGameWindow(GameWindow *win, AnimTypes animType, Bool needsToFinish, UnsignedInt ms = 0, UnsignedInt delayMs = 0); // Registers a new window to animate. - Bool isFinished(); ///< Are all the animations that need to be finished, finished? - void reverseAnimateWindow(); ///< tell each animation type to setup the windows to run in reverse - void resetToRestPosition(); ///< Reset all windows to their rest position - Bool isReversed(); ///< Returns whether or not we're in our reversed state. - Bool isEmpty(); -private: - AnimateWindowList m_winList; ///< A list of AnimationWindows that we don't care if their finished animating - AnimateWindowList m_winMustFinishList; ///< A list of AnimationWindows that we do care about - Bool m_needsUpdate; ///< If we're done animating all our monitored windows, then this will be false - Bool m_reverse; ///< Are we in a reverse state? - ProcessAnimateWindowSlideFromRight *m_slideFromRight; ///< Holds the process in which the windows slide from the right - ProcessAnimateWindowSlideFromRightFast *m_slideFromRightFast; - ProcessAnimateWindowSlideFromTop *m_slideFromTop; ///< Holds the process in which the windows slide from the Top - ProcessAnimateWindowSlideFromLeft *m_slideFromLeft; ///< Holds the process in which the windows slide from the Left - ProcessAnimateWindowSlideFromBottom *m_slideFromBottom; ///< Holds the process in which the windows slide from the Bottom - ProcessAnimateWindowSpiral *m_spiral; ///< Holds the process in which the windows Spiral onto the screen - ProcessAnimateWindowSlideFromBottomTimed *m_slideFromBottomTimed; ///< Holds the process in which the windows slide from the Bottom in a time-based fashion - ProcessAnimateWindowSlideFromTopFast *m_slideFromTopFast; ///< holds the process in wich the windows slide from the top,fast - ProcessAnimateWindow *getProcessAnimate( AnimTypes animType); ///< returns the process for the kind of animation we need. - -}; - -//----------------------------------------------------------------------------- -// INLINING /////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -namespace wnd -{ - inline ICoord2D AnimateWindow::getStartPos() { return m_startPos; }; - inline Coord2D AnimateWindow::getCurPos() { return m_curPos; }; - inline ICoord2D AnimateWindow::getEndPos() { return m_endPos; }; - inline ICoord2D AnimateWindow::getRestPos() { return m_restPos; }; - inline GameWindow *AnimateWindow::getGameWindow(){ return m_win; }; - inline AnimTypes AnimateWindow::getAnimType() { return m_animType; }; - inline UnsignedInt AnimateWindow::getDelay() { return m_delay; }; - inline Coord2D AnimateWindow::getVel() { return m_vel; }; - inline UnsignedInt AnimateWindow::getStartTime() { return m_startTime; }; - inline UnsignedInt AnimateWindow::getEndTime() { return m_endTime; }; - - inline void AnimateWindow::setStartPos( ICoord2D startPos) { m_startPos = startPos; }; - inline void AnimateWindow::setCurPos( Coord2D curPos) { m_curPos = curPos; }; - inline void AnimateWindow::setEndPos( ICoord2D endPos) { m_endPos = endPos; }; - inline void AnimateWindow::setRestPos( ICoord2D restPos) { m_restPos = restPos; }; - inline void AnimateWindow::setGameWindow( GameWindow *win) { m_win = win; }; - inline void AnimateWindow::setAnimType( AnimTypes animType) { m_animType = animType; }; - inline void AnimateWindow::setDelay( UnsignedInt delay) { m_delay = delay; }; - inline void AnimateWindow::setVel( Coord2D vel) { m_vel = vel; }; - inline void AnimateWindow::setStartTime( UnsignedInt t ) { m_startTime = t; } - inline void AnimateWindow::setEndTime( UnsignedInt t ) { m_endTime = t; } - - inline void AnimateWindow::setFinished( Bool finished) { m_isFinished = finished; }; - inline Bool AnimateWindow::isFinished() { return m_isFinished; }; - inline void AnimateWindow::setNeedsToFinish( Bool needsToFinish) { m_needsToFinish = needsToFinish; }; - inline Bool AnimateWindow::needsToFinish() { return m_needsToFinish; }; -} // namespace wnd - - inline Bool AnimateWindowManager::isFinished() { return !m_needsUpdate; }; - inline Bool AnimateWindowManager::isReversed() { return m_reverse; }; - inline Bool AnimateWindowManager::isEmpty(){return (m_winList.empty() && m_winMustFinishList.empty()); } -//----------------------------------------------------------------------------- -// EXTERNALS ////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Include/GameClient/GameWindowID.h b/Generals/Code/GameEngine/Include/GameClient/GameWindowID.h deleted file mode 100644 index 9d5eec2be54..00000000000 --- a/Generals/Code/GameEngine/Include/GameClient/GameWindowID.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameWindowID.h /////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Westwood Studios Pacific. -// -// Confidential Information -// Copyright (C) 2001 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// Project: RTS3 -// -// File name: GameWindowID.h -// -// Created: Colin Day, July 2001 -// -// Desc: Game window ID definitions, this is so we can uniquely -// identify any window in the game and pass messages from -// anywhere to anywhere else instantly -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -#pragma once - -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// - -// USER INCLUDES ////////////////////////////////////////////////////////////// - -// FORWARD REFERENCES ///////////////////////////////////////////////////////// - -// TYPE DEFINES /////////////////////////////////////////////////////////////// -#define GWID_INVALID 0 - -#define GWID_SIDEBAR 100 - -#define GWID_SIDEBAR_1 101 -#define GWID_SIDEBAR_2 102 -#define GWID_SIDEBAR_3 103 -#define GWID_SIDEBAR_4 104 -#define GWID_SIDEBAR_5 105 -#define GWID_SIDEBAR_6 106 -#define GWID_SIDEBAR_7 107 -#define GWID_SIDEBAR_8 108 -#define GWID_SIDEBAR_9 109 -#define GWID_SIDEBAR_10 110 -#define GWID_SIDEBAR_11 111 -#define GWID_SIDEBAR_12 112 - -#define GWID_SIDEBAR_TAB_1 151 -#define GWID_SIDEBAR_TAB_2 152 -#define GWID_SIDEBAR_TAB_3 153 -#define GWID_SIDEBAR_TAB_4 154 - -#define GWID_SIDEBAR_RADAR 175 - -// INLINING /////////////////////////////////////////////////////////////////// - -// EXTERNALS ////////////////////////////////////////////////////////////////// diff --git a/Generals/Code/GameEngine/Include/GameClient/GameWindowManager.h b/Generals/Code/GameEngine/Include/GameClient/GameWindowManager.h deleted file mode 100644 index a3a4f53a4a6..00000000000 --- a/Generals/Code/GameEngine/Include/GameClient/GameWindowManager.h +++ /dev/null @@ -1,414 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameWindowManager.h ////////////////////////////////////////////////////////////////////// -// Created: Colin Day, June 2001 -// Desc: The game window manager is the interface for interacting with -// the windowing system for purposes of any menus, or GUI -// controls. -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#pragma once - -#include "Common/STLTypedefs.h" -#include "Common/SubsystemInterface.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/KeyDefs.h" -#include "GameClient/Gadget.h" - -class GameWindow; - -//------------------------------------------------------------------------------------------------- -/** Window layout info is a structure that can be passed to the load function of - * a window script. After the script is loaded, this parameter (if present) - * will contain information about the script file at a global level such - * as what file version was loaded, global layout callbacks, etc */ -//------------------------------------------------------------------------------------------------- -enum { MAX_LAYOUT_FUNC_LEN = 256 }; - -typedef std::list GameWindowList; - -class WindowLayoutInfo -{ - -public: - WindowLayoutInfo(); - - UnsignedInt version; ///< file version that was loaded - WindowLayoutInitFunc init; ///< init method (if specified) - WindowLayoutUpdateFunc update; ///< update method (if specified) - WindowLayoutShutdownFunc shutdown; ///< shutdown method (if specified) - AsciiString initNameString; ///< init method in flavor of string name - AsciiString updateNameString; ///< update method in string flavor - AsciiString shutdownNameString; ///< shutdown method in string flavor, mmm! - std::list windows; ///< list of top-level windows in the layout -}; - -//------------------------------------------------------------------------------------------------- -/** There exists a singleton GameWindowManager that defines how we can - * interact with the game windowing system */ -//------------------------------------------------------------------------------------------------- -class GameWindowManager : public SubsystemInterface -{ - -friend class GameWindow; - -public: - - GameWindowManager(); - virtual ~GameWindowManager() override; - - //----------------------------------------------------------------------------------------------- - virtual void init() override; ///< initialize function - virtual void reset() override; ///< reset the system - virtual void update() override; ///< update method, called once per frame - - virtual GameWindow *allocateNewWindow() = 0; ///< new game window - - void linkWindow( GameWindow *window ); ///< link into master list - void unlinkWindow( GameWindow *window ); ///< unlink from master list - void unlinkChildWindow( GameWindow *window ); ///< remove child from parent list - void insertWindowAheadOf( GameWindow *window, GameWindow *aheadOf ); ///< add window to list 'ahead of' - - virtual GameWinDrawFunc getPushButtonImageDrawFunc() = 0; - virtual GameWinDrawFunc getPushButtonDrawFunc() = 0; - virtual GameWinDrawFunc getCheckBoxImageDrawFunc() = 0; - virtual GameWinDrawFunc getCheckBoxDrawFunc() = 0; - virtual GameWinDrawFunc getRadioButtonImageDrawFunc() = 0; - virtual GameWinDrawFunc getRadioButtonDrawFunc() = 0; - virtual GameWinDrawFunc getTabControlImageDrawFunc() = 0; - virtual GameWinDrawFunc getTabControlDrawFunc() = 0; - virtual GameWinDrawFunc getListBoxImageDrawFunc() = 0; - virtual GameWinDrawFunc getListBoxDrawFunc() = 0; - virtual GameWinDrawFunc getComboBoxImageDrawFunc() = 0; - virtual GameWinDrawFunc getComboBoxDrawFunc() = 0; - virtual GameWinDrawFunc getHorizontalSliderImageDrawFunc() = 0; - virtual GameWinDrawFunc getHorizontalSliderDrawFunc() = 0; - virtual GameWinDrawFunc getVerticalSliderImageDrawFunc() = 0; - virtual GameWinDrawFunc getVerticalSliderDrawFunc() = 0; - virtual GameWinDrawFunc getProgressBarImageDrawFunc() = 0; - virtual GameWinDrawFunc getProgressBarDrawFunc() = 0; - virtual GameWinDrawFunc getStaticTextImageDrawFunc() = 0; - virtual GameWinDrawFunc getStaticTextDrawFunc() = 0; - virtual GameWinDrawFunc getTextEntryImageDrawFunc() = 0; - virtual GameWinDrawFunc getTextEntryDrawFunc() = 0; - - //--------------------------------------------------------------------------- - - virtual GameWinDrawFunc getDefaultDraw(); ///< return default draw func - virtual GameWinSystemFunc getDefaultSystem(); ///< return default system func - virtual GameWinInputFunc getDefaultInput(); ///< return default input func - virtual GameWinTooltipFunc getDefaultTooltip(); ///< return default tooltip func - - //--------------------------------------------------------------------------- - // MessageBox creation - virtual GameWindow *gogoMessageBox(Int x, Int y, Int width, Int height, UnsignedShort buttonFlags, - UnicodeString titleString, UnicodeString bodyString, - GameWinMsgBoxFunc yesCallback, - GameWinMsgBoxFunc noCallback, - GameWinMsgBoxFunc okCallback, - GameWinMsgBoxFunc cancelCallback ); - - virtual GameWindow *gogoMessageBox(Int x, Int y, Int width, Int height, UnsignedShort buttonFlags, - UnicodeString titleString, UnicodeString bodyString, - GameWinMsgBoxFunc yesCallback, - GameWinMsgBoxFunc noCallback, - GameWinMsgBoxFunc okCallback, - GameWinMsgBoxFunc cancelCallback, Bool useLogo ); - - - //--------------------------------------------------------------------------- - // gadget creation - virtual GameWindow *gogoGadgetPushButton( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetCheckbox( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetRadioButton( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - RadioButtonData *rData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetTabControl( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - TabControlData *rData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetListBox( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - ListboxData *listboxData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetSlider( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - SliderData *sliderData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetProgressBar( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetStaticText( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - TextData *textData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetTextEntry( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - EntryData *entryData, - GameFont *defaultFont, Bool defaultVisual ); - virtual GameWindow *gogoGadgetComboBox( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - WinInstanceData *instData, - ComboBoxData *comboBoxDataTemplate, - GameFont *defaultFont, Bool defaultVisual ); - - /** Use this method to assign the default images to gadgets as - * they area created */ - virtual void assignDefaultGadgetLook( GameWindow *gadget, - GameFont *defaultFont, - Bool assignVisual ); - - //--------------------------------------------------------------------------- - // Creating windows - /// create new window(s) from .wnd file ... see definition for what is returned - virtual GameWindow *winCreateFromScript( AsciiString filename, WindowLayoutInfo *info = nullptr ); - - /// create new window(s) from .wnd file and wrap in a WindowLayout - virtual WindowLayout *winCreateLayout( AsciiString filename ); - - /// free temporary strings to make the memory leak manager happy. - virtual void freeStaticStrings(); - - /// create a new window by setting up parameters and callbacks - virtual GameWindow *winCreate( GameWindow *parent, UnsignedInt status, - Int x, Int y, Int width, Int height, - GameWinSystemFunc system, - WinInstanceData *instData = nullptr ); - - //--------------------------------------------------------------------------- - // Manipulating windows in the system - virtual Int winDestroy( GameWindow *window ); ///< destroy this window - virtual Int winDestroyAll(); ///< destroy all windows in the system - virtual GameWindow *winGetWindowList(); ///< get head of master list - - /// hide all windows in a certain range of id's (inclusive ); - virtual void hideWindowsInRange( GameWindow *baseWindow, Int first, Int last, - Bool hideFlag ); - /// enable all windows in a range of id's (inclusive) - virtual void enableWindowsInRange( GameWindow *baseWindow, Int first, Int last, - Bool enableFlag ); - - /// this gets called from winHide() when a window hides itself - virtual void windowHiding( GameWindow *window ); - - virtual void winRepaint(); ///< draw GUI in reverse order - - virtual void winNextTab( GameWindow *window ); ///< give keyboard focus to the next window in the tab list - - virtual void winPrevTab( GameWindow *window ); ///< give keyboard focus to the previous window in the tab list - - virtual void registerTabList( GameWindowList tabList ); ///< we have to register a Tab List - virtual void clearTabList(); ///< we's gotz ta clear the tab list yo! - - // -------------------------------------------------------------------------- - /// process a single mouse event - virtual WinInputReturnCode winProcessMouseEvent( GameWindowMessage msg, - ICoord2D *mousePos, - void *data ); - /// process a singke key event - virtual WinInputReturnCode winProcessKey( UnsignedByte key, - UnsignedByte state ); - // -------------------------------------------------------------------------- - - virtual GameWindow *winGetFocus(); ///< return window that has the focus - virtual Int winSetFocus( GameWindow *window ); ///< set this window as has focus - virtual void winSetGrabWindow( GameWindow *window ); ///< set the grab window - virtual GameWindow *winGetGrabWindow(); ///< who is currently 'held' by mouse - virtual void winSetLoneWindow( GameWindow *window ); ///< set the open window - - // Finds the top-level window at the mouse position that matches the required and forbidden status masks. - virtual GameWindow* findWindowUnderMouse(GameWindow*& toolTipWindow, const ICoord2D* mousePos, unsigned int requiredStatusMask, unsigned int forbiddenStatusMask); - static bool isMouseWithinWindow(GameWindow* window, const ICoord2D* mousePos, unsigned int requiredStatusMask, unsigned int forbiddenStatusMask); - - virtual Bool isEnabled( GameWindow *win ); ///< is window or parents enabled - virtual Bool isHidden( GameWindow *win ); ///< is parent or parents hidden - virtual void addWindowToParent( GameWindow *window, GameWindow *parent ); - virtual void addWindowToParentAtEnd( GameWindow *window, GameWindow *parent ); - - /// sends a system message to specified window - virtual WindowMsgHandledType winSendSystemMsg( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ); - - /// sends an input message to the specified window - virtual WindowMsgHandledType winSendInputMsg( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ); - - /** get the window pointer from id, starting at 'window' and searching - down the hierarchy. If 'window' is nullptr then all windows will - be searched */ - virtual GameWindow *winGetWindowFromId( GameWindow *window, Int id ); - virtual Int winCapture( GameWindow *window ); ///< captures the mouse - virtual Int winRelease( GameWindow *window ); ///< release mouse capture - virtual GameWindow *winGetCapture(); ///< current mouse capture settings - - virtual Int winSetModal( GameWindow *window ); ///< put at top of modal stack - virtual Int winUnsetModal( GameWindow *window ); /**< take window off modal stack, if window is - not at top of stack and error will occur */ - - //--------------------------------------------------------------------------- - ///////////////////////////////////////////////////////////////////////////// - //--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- - // The following public functions you should implement change the guts - // for to work with your application. Rather than draw images, or do string - // operations with native methods, the game window system will always call - // these methods to get the work done it needs - //--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- - ///////////////////////////////////////////////////////////////////////////// - //--------------------------------------------------------------------------- - - /// draw image, coord are in screen and should be kepth within that box specified - virtual void winDrawImage( const Image *image, Int startX, Int startY, Int endX, Int endY, Color color = 0xFFFFFFFF ); - /// draw filled rect, coords are absolute screen coords - virtual void winFillRect( Color color, Real width, Int startX, Int startY, Int endX, Int endY ); - /// draw rect outline, coords are absolute screen coords - virtual void winOpenRect( Color color, Real width, Int startX, Int startY, Int endX, Int endY ); - /// draw line, coords are absolute screen coords - virtual void winDrawLine( Color color, Real width, Int startX, Int startY, Int endX, Int endY ); - /// Make a color representation out of RGBA components - virtual Color winMakeColor( UnsignedByte red, UnsignedByte green, UnsignedByte blue, UnsignedByte alpha ); - /** Find an image reference and return a pointer to its image, you may - recreate all Image structs to suit your project */ - virtual const Image *winFindImage( const char *name ); - virtual Int winFontHeight( GameFont *font ); ///< get height of font in pixels - virtual Int winIsDigit( Int c ); ///< is character a digit - virtual Int winIsAscii( Int c ); ///< is character a digit - virtual Int winIsAlNum( Int c ); ///< is character alpha-numeric - virtual void winFormatText( GameFont *font, UnicodeString text, Color color, - Int x, Int y, Int width, Int height ); - virtual void winGetTextSize( GameFont *font, UnicodeString text, - Int *width, Int *height, Int maxWidth ); - virtual UnicodeString winTextLabelToText( AsciiString label ); ///< convert localizable text label to real text - virtual GameFont *winFindFont( AsciiString fontName, Int pointSize, Bool bold ); ///< get a font given a name - - /// @todo just for testing, remov this - Bool initTestGUI(); - - virtual GameWindow *getWindowUnderCursor( Int x, Int y, Bool ignoreEnabled = FALSE ); ///< find the top window at the given coordinates - - //--------------------------------------------------------------------------- - ///////////////////////////////////////////////////////////////////////////// - //--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- - //--------------------------------------------------------------------------- - ///////////////////////////////////////////////////////////////////////////// - //--------------------------------------------------------------------------- - -protected: - - void processDestroyList(); ///< process windows waiting to be killed - - Int drawWindow( GameWindow *window ); ///< draw this window - - void dumpWindow( GameWindow *window ); ///< for debugging - - GameWindow *m_windowList; // list of all top level windows - GameWindow *m_windowTail; // last in windowList - - GameWindow *m_destroyList; // list of windows to destroy - - GameWindow *m_currMouseRgn; // window that mouse is over - GameWindow *m_mouseCaptor; // window that captured mouse - GameWindow *m_keyboardFocus; // window that has input focus - ModalWindow *m_modalHead; // top of windows in the modal stack - GameWindow *m_grabWindow; // window that grabbed the last down event - GameWindow *m_loneWindow; // Set if we just opened a Lone Window - GameWindowList m_tabList; // we have to register a tab list to make a tab list. - const Image *m_cursorBitmap; - UnsignedInt m_captureFlags; - -}; - -// INLINE ///////////////////////////////////////////////////////////////////////////////////////// -inline GameWinDrawFunc GameWindowManager::getDefaultDraw() { return GameWinDefaultDraw; } -inline GameWinSystemFunc GameWindowManager::getDefaultSystem() { return GameWinDefaultSystem; } -inline GameWinInputFunc GameWindowManager::getDefaultInput() { return GameWinDefaultInput; } -inline GameWinTooltipFunc GameWindowManager::getDefaultTooltip() { return GameWinDefaultTooltip; } - -// EXTERN ///////////////////////////////////////////////////////////////////////////////////////// -extern GameWindowManager *TheWindowManager; ///< singleton extern definition -extern UnsignedInt WindowLayoutCurrentVersion; ///< current version of our window layouts - -// this function lets us generically pass button selections to our parent, we may -// frequently want to do this because we want windows grouped on child windows for -// convenience, but only want one logical system procedure responding to them all -extern WindowMsgHandledType PassSelectedButtonsToParentSystem( GameWindow *window, - UnsignedInt msg, - WindowMsgData mData1, - WindowMsgData mData2 ); -extern WindowMsgHandledType PassMessagesToParentSystem( GameWindow *window, - UnsignedInt msg, - WindowMsgData mData1, - WindowMsgData mData2 ); - -// TheSuperHackers @feature helmutbuhler 24/04/2025 -// GameWindowManager that does nothing. Used for Headless Mode. -class GameWindowManagerDummy : public GameWindowManager -{ -public: - virtual GameWindow *winGetWindowFromId(GameWindow *window, Int id) override; - virtual GameWindow *winCreateFromScript(AsciiString filenameString, WindowLayoutInfo *info) override; - - virtual GameWindow *allocateNewWindow() override { return newInstance(GameWindowDummy); } - - virtual GameWinDrawFunc getPushButtonImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getPushButtonDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getCheckBoxImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getCheckBoxDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getRadioButtonImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getRadioButtonDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getTabControlImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getTabControlDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getListBoxImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getListBoxDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getComboBoxImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getComboBoxDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getHorizontalSliderImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getHorizontalSliderDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getVerticalSliderImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getVerticalSliderDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getProgressBarImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getProgressBarDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getStaticTextImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getStaticTextDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getTextEntryImageDrawFunc() override { return nullptr; } - virtual GameWinDrawFunc getTextEntryDrawFunc() override { return nullptr; } -}; diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h b/Generals/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h index 3bcfe1b13c1..3860bfc4349 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h @@ -158,7 +158,7 @@ class ProductionUpdateInterface virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0; virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) = 0; - virtual void cancelUnitCreate( ProductionID productionID ) = 0; + virtual Bool cancelUnitCreate( ProductionID productionID ) = 0; virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) = 0; virtual void cancelAndRefundAllProduction() = 0; @@ -214,7 +214,7 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface, virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const override; ///< count number of units with matching unit type in the production queue virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) override; ///< queue unit to be produced - virtual void cancelUnitCreate( ProductionID productionID ) override; ///< cancel construction of unit with matching production ID + virtual Bool cancelUnitCreate( ProductionID productionID ) override; ///< cancel construction of unit with matching production ID virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) override; ///< cancel all production of type unitType virtual void cancelAndRefundAllProduction() override; ///< cancel and refund anything in the production queue diff --git a/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h b/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h index 8d20de4e80c..f95930d830a 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h @@ -94,7 +94,9 @@ class TunnelContain : public OpenContain, public CreateModuleInterface virtual void onContaining( Object *obj ) override; ///< object now contains 'obj' virtual void onRemoving( Object *obj ) override; ///< object no longer contains 'obj' virtual void onSelling() override;///< Container is being sold. Tunnel responds by kicking people out if this is the last tunnel. +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) virtual void onCapture( Player *oldOwner, Player *newOwner ) override; // Need to change who we are registered with. +#endif virtual void orderAllPassengersToExit( CommandSourceType commandSource ) override; ///< All of the smarts of exiting are in the passenger's AIExit. removeAllFrommContain is a last ditch system call, this is the game Evacuate diff --git a/Generals/Code/GameEngine/Include/GameLogic/Object.h b/Generals/Code/GameEngine/Include/GameLogic/Object.h index 7a1a25260a9..54ca8613dc8 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/Object.h +++ b/Generals/Code/GameEngine/Include/GameLogic/Object.h @@ -428,10 +428,6 @@ class Object : public Thing, public Snapshot const Object* getEnclosingContainedBy() const; ///< Find the first enclosing container in the containment chain. const Object* getOuterObject() const; ///< Get the top-level object -#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC - void friend_setContainedByID(ObjectID id) { m_containedByID = id; } -#endif - // Special Powers ------------------------------------------------------------------------------- SpecialPowerModuleInterface *getSpecialPowerModule( const SpecialPowerTemplate *specialPowerTemplate ) const; void doSpecialPower( const SpecialPowerTemplate *specialPowerTemplate, UnsignedInt commandOptions, Bool forced = false ); ///< execute power @@ -721,7 +717,7 @@ class Object : public Thing, public Snapshot Object* m_containedBy; /**< an object can only be contained by at most one other object, this is that object (if present) */ - ObjectID m_containedByID; ///< ID of the object we're contained by; only to be used when m_containedBy cannot be used + ObjectID m_xferContainedByID; ///< xfer uses IDs to store pointers and looks them up after UnsignedInt m_containedByFrame; ///< frame we were contained by m_containedBy Real m_constructionPercent; ///< for objects being built ... this is the amount completed (0.0 to 100.0) diff --git a/Generals/Code/GameEngine/Include/GameLogic/VictoryConditions.h b/Generals/Code/GameEngine/Include/GameLogic/VictoryConditions.h index 59d54c40113..423012829b4 100644 --- a/Generals/Code/GameEngine/Include/GameLogic/VictoryConditions.h +++ b/Generals/Code/GameEngine/Include/GameLogic/VictoryConditions.h @@ -51,9 +51,9 @@ class VictoryConditionsInterface : public SubsystemInterface public: VictoryConditionsInterface() { m_victoryConditions = 0; } - virtual void init() = 0; - virtual void reset() = 0; - virtual void update() = 0; + virtual void init() override = 0; + virtual void reset() override = 0; + virtual void update() override = 0; void setVictoryConditions( Int victoryConditions ) { m_victoryConditions = victoryConditions; } Int getVictoryConditions() { return m_victoryConditions; } diff --git a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp index 479c724c7f9..ee026656d94 100644 --- a/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/Generals/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -3542,7 +3542,7 @@ void Player::processSelectTeamGameMessage(Int hotkeyNum) { m_currentSelection->clearSquad(); - VecObjectPtr objectList = m_squads[hotkeyNum]->getLiveObjects(); + const VecObjectPtr& objectList = m_squads[hotkeyNum]->getLiveObjects(); Int numObjs = objectList.size(); for (Int i = 0; i < numObjs; ++i) { @@ -3567,7 +3567,7 @@ void Player::processAddTeamGameMessage(Int hotkeyNum) { m_currentSelection = newInstance( Squad ); } - VecObjectPtr objectList = m_squads[hotkeyNum]->getLiveObjects(); + const VecObjectPtr& objectList = m_squads[hotkeyNum]->getLiveObjects(); Int numObjs = objectList.size(); for (Int i = 0; i < numObjs; ++i) { diff --git a/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp b/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp index 385d1bf20c7..f9fd0171ad5 100644 --- a/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp +++ b/Generals/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp @@ -50,7 +50,9 @@ // ------------------------------------------------------------------------ TunnelTracker::TunnelTracker() { +#if RETAIL_COMPATIBLE_CRC m_tunnelCount = 0; +#endif m_containListSize = 0; m_heroUnitsContained = 0; m_curNemesisID = INVALID_ID; @@ -223,7 +225,12 @@ Bool TunnelTracker::isInContainer( Object *obj ) // ------------------------------------------------------------------------ void TunnelTracker::onTunnelCreated( const Object *newTunnel ) { + DEBUG_ASSERTCRASH(std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), newTunnel->getID()) == m_tunnelIDs.end(), + ("TunnelTracker::onTunnelCreated - New tunnel was already added; this shouldn't happen")); + +#if RETAIL_COMPATIBLE_CRC m_tunnelCount++; +#endif m_tunnelIDs.push_back( newTunnel->getID() ); m_needsFullHealTimeUpdate = true; } @@ -231,20 +238,61 @@ void TunnelTracker::onTunnelCreated( const Object *newTunnel ) // ------------------------------------------------------------------------ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) { +#if RETAIL_COMPATIBLE_CRC + + DEBUG_ASSERTLOG(static_cast(m_tunnelCount) > 0 && m_tunnelCount == m_tunnelIDs.size(), + ("TunnelTracker::onTunnelDestroyed - Tunnel count is unexpected")); + + const size_t oldSize = m_tunnelIDs.size(); + m_tunnelIDs.remove(deadTunnel->getID()); + + (void)oldSize; + DEBUG_ASSERTLOG(oldSize != m_tunnelIDs.size(), + ("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", deadTunnel->getName().str())); + + m_tunnelCount--; + + if( m_tunnelCount == 0 ) + { + // Kill everyone in our contain list. Cave in! + iterateContained( destroyObject, nullptr, FALSE ); + m_containList.clear(); + m_containListSize = 0; + } + else { - std::list::iterator it = std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), deadTunnel->getID()); - if (it == m_tunnelIDs.end()) + // TheSuperHackers @bugfix Caball009 01/09/2026 Check if container is empty before accessing it. + // The tunnel count may diverge from the container size, because of bugs that cannot be fixed with + // retail compatibility enabled. Expected retail behavior: empty container access results in a nullptr. + Object *tunnel = m_tunnelIDs.empty() ? nullptr : TheGameLogic->findObjectByID( m_tunnelIDs.front() ); + + // Otherwise, make sure nobody inside remembers the dead tunnel as the one they entered + // (scripts need to use so there must be something valid here) + for(ContainedItemsList::iterator it = m_containList.begin(); it != m_containList.end(); ) { - DEBUG_CRASH(("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", deadTunnel->getName().str())); - return; + Object* obj = *it; + ++it; + if( obj->getContainedBy() == deadTunnel ) + obj->onContainedBy( tunnel ); } + } - m_tunnelCount--; +#else + + const std::list::iterator it = std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), deadTunnel->getID()); + if (it != m_tunnelIDs.end()) + { m_tunnelIDs.erase(it); + m_needsFullHealTimeUpdate = true; } + else + { + DEBUG_CRASH(("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", + deadTunnel->getName().str())); + } - if( m_tunnelCount == 0 ) + if( m_tunnelIDs.empty() ) { // Kill everyone in our contain list. Cave in! iterateContained( destroyObject, nullptr, FALSE ); @@ -254,6 +302,7 @@ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) else { Object *validTunnel = TheGameLogic->findObjectByID( m_tunnelIDs.front() ); + // Otherwise, make sure nobody inside remembers the dead tunnel as the one they entered // (scripts need to use so there must be something valid here) for(ContainedItemsList::iterator it = m_containList.begin(); it != m_containList.end(); ) @@ -264,6 +313,8 @@ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) obj->onContainedBy( validTunnel ); } } + +#endif // RETAIL_COMPATIBLE_CRC } // ------------------------------------------------------------------------ @@ -378,13 +429,19 @@ void TunnelTracker::crc( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ /** Xfer method * Version Info: - * 1: Initial version */ + * 1: Initial version + * 2: TheSuperHackers @tweak Removed m_tunnelCount (should always be equal to m_tunnelIDs.size()) + */ // ------------------------------------------------------------------------------------------------ void TunnelTracker::xfer( Xfer *xfer ) { // version +#if RETAIL_COMPATIBLE_XFER_SAVE XferVersion currentVersion = 1; +#else + XferVersion currentVersion = 2; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -423,8 +480,25 @@ void TunnelTracker::xfer( Xfer *xfer ) m_needsFullHealTimeUpdate = true; } - // tunnel count - xfer->xferUnsignedInt( &m_tunnelCount ); +#if RETAIL_COMPATIBLE_CRC + if (version <= 1) + { + xfer->xferUnsignedInt(&m_tunnelCount); + } + else + { + if (xfer->getXferMode() == XFER_LOAD) + { + m_tunnelCount = m_tunnelIDs.size(); + } + } +#else + if (version <= 1) + { + UnsignedInt tunnelCount = m_tunnelIDs.size(); + xfer->xferUnsignedInt(&tunnelCount); + } +#endif } diff --git a/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp b/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp index 17aed6d00f9..4f82c26d234 100644 --- a/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp +++ b/Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp @@ -53,6 +53,7 @@ #include "GameClient/GameClient.h" #include "GameClient/GameText.h" #include "GameClient/MapUtil.h" +#include "GameClient/MessageBox.h" #include "GameClient/InGameUI.h" #include "GameClient/ParticleSys.h" #include "GameClient/TerrainVisual.h" @@ -62,6 +63,7 @@ #include "GameLogic/ScriptEngine.h" #include "GameLogic/SidesList.h" #include "GameLogic/TerrainLogic.h" +#include "Lib/PathUtil.h" // PUBLIC DATA //////////////////////////////////////////////////////////////////////////////////// @@ -678,8 +680,7 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo ) // TheGameStateMap->clearScratchPadMaps(); - // construct path to file - AsciiString filepath = getFilePathInSaveDirectory(gameInfo.filename); + AsciiString filepath = getSaveGamePathForRead(gameInfo.filename); // open the save file XferLoad xferLoad; @@ -762,6 +763,15 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo ) } +//------------------------------------------------------------------------------------------------- +static void showQueuedSaveGameLoadFailure( void ) +{ + UnicodeString title = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailedTitle", L"CANNOT LOAD SAVE"); + UnicodeString body = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailed", L"The saved game file could not be opened or is invalid."); + + MessageBoxOk(title, body, nullptr); +} + // ------------------------------------------------------------------------------------------------ /** Load the save game requested on startup, after the shell has been initialized */ // ------------------------------------------------------------------------------------------------ @@ -776,26 +786,32 @@ void GameState::loadQueuedSaveGame() TheWritableGlobalData->m_loadSaveGame.clear(); + if( gameInfo.filename.endsWithNoCase( SAVE_GAME_EXTENSION ) == FALSE ) + { + DEBUG_LOG(("Save game '%s' is not a save game file", gameInfo.filename.str())); + showQueuedSaveGameLoadFailure(); + return; + } + // getSaveGameInfoFromFile throws when the file is missing, so check before reading it if( doesSaveGameExist( gameInfo.filename ) == FALSE ) { std::fprintf(stderr, "Save game '%s' was not found\n", gameInfo.filename.str()); std::fflush(stderr); - TheGameEngine->setQuitting( TRUE ); + showQueuedSaveGameLoadFailure(); return; } // getSaveGameInfoFromFile throws on a malformed file instead of returning a SaveCode try { - AsciiString filepath = getFilePathInSaveDirectory( gameInfo.filename ); - getSaveGameInfoFromFile( filepath, &gameInfo.saveGameInfo ); + getSaveGameInfoFromFile( gameInfo.filename, &gameInfo.saveGameInfo ); } catch( ... ) { std::fprintf(stderr, "Save game '%s' could not be read\n", gameInfo.filename.str()); std::fflush(stderr); - TheGameEngine->setQuitting( TRUE ); + showQueuedSaveGameLoadFailure(); return; } @@ -834,6 +850,17 @@ AsciiString GameState::getFilePathInSaveDirectory(const AsciiString& leaf) const return tmp; } +//------------------------------------------------------------------------------------------------- +AsciiString GameState::getSaveGamePathForRead(const AsciiString& filenameOrPath) const +{ + if (isAbsolutePath(filenameOrPath.str())) + { + return filenameOrPath; + } + + return getFilePathInSaveDirectory(filenameOrPath); +} + //------------------------------------------------------------------------------------------------- Bool GameState::isInSaveDirectory(const AsciiString& path) const { @@ -1000,8 +1027,7 @@ AsciiString GameState::portableMapPathToRealMapPath(const AsciiString& in) const Bool GameState::doesSaveGameExist( AsciiString filename ) { - // construct full path to file - AsciiString filepath = getFilePathInSaveDirectory(filename); + AsciiString filepath = getSaveGamePathForRead(filename); // open file XferLoad xfer; @@ -1046,6 +1072,8 @@ void GameState::getSaveGameInfoFromFile( AsciiString filename, SaveGameInfo *sav } + filename = getSaveGamePathForRead( filename ); + // open file for partial loading XferLoad xferLoad; xferLoad.open( filename ); diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp deleted file mode 100644 index 2dd828857d1..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp +++ /dev/null @@ -1,426 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: AnimateWindowManager.cpp ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Mar 2002 -// -// Filename: AnimateWindowManager.cpp -// -// author: Chris Huybregts -// -// purpose: This will contain the logic behind the different animations that -// can happen to a window. -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "GameClient/AnimateWindowManager.h" -#include "GameClient/GameWindow.h" -#include "GameClient/Display.h" -#include "GameClient/ProcessAnimateWindow.h" -#include "Common/FramePacer.h" -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- -// AnimateWindow PUBLIC FUNCTIONS ///////////////////////////////////////////// -//----------------------------------------------------------------------------- -namespace wnd -{ -AnimateWindow::AnimateWindow() -{ - m_delay = 0; - m_startPos.x = m_startPos.y = 0; - m_endPos.x = m_endPos.y = 0; - m_curPos.x = m_curPos.y = 0.0f; - m_win = nullptr; - m_animType = WIN_ANIMATION_NONE; - - m_restPos.x = m_restPos.y = 0; - m_vel.x = m_vel.y = 0.0f; - m_needsToFinish = FALSE; - m_isFinished = FALSE; - m_endTime = 0; - m_startTime = 0; -} -AnimateWindow::~AnimateWindow() -{ - m_win = nullptr; -} - -void AnimateWindow::setAnimData( ICoord2D startPos, ICoord2D endPos, - Coord2D curPos, ICoord2D restPos, - Coord2D vel, UnsignedInt startTime, - UnsignedInt endTime ) - -{ - m_startPos = startPos; - m_endPos = endPos; - m_curPos = curPos; - m_restPos = restPos; - m_vel = vel; - m_startTime = startTime; - m_endTime = endTime; - -} - -} // namespace wnd - -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -static void clearWinList(AnimateWindowList &winList) -{ - while (!winList.empty()) - { - wnd::AnimateWindow *win = *(winList.begin()); - winList.pop_front(); - deleteInstance(win); - } -} - -AnimateWindowManager::AnimateWindowManager() -{ -// we don't allocate many of these, so no MemoryPools used - m_slideFromRight = NEW ProcessAnimateWindowSlideFromRight; - m_slideFromRightFast = NEW ProcessAnimateWindowSlideFromRightFast; - m_slideFromLeft = NEW ProcessAnimateWindowSlideFromLeft; - m_slideFromTop = NEW ProcessAnimateWindowSlideFromTop; - m_slideFromTopFast = NEW ProcessAnimateWindowSlideFromTopFast; - m_slideFromBottom = NEW ProcessAnimateWindowSlideFromBottom; - m_spiral = NEW ProcessAnimateWindowSpiral; - m_slideFromBottomTimed = NEW ProcessAnimateWindowSlideFromBottomTimed; - m_winList.clear(); - m_needsUpdate = FALSE; - m_reverse = FALSE; - m_winMustFinishList.clear(); -} -AnimateWindowManager::~AnimateWindowManager() -{ - delete m_slideFromRight; - delete m_slideFromRightFast; - delete m_slideFromLeft; - delete m_slideFromTop; - delete m_slideFromTopFast; - delete m_slideFromBottom; - delete m_spiral; - delete m_slideFromBottomTimed; - - m_slideFromRight = nullptr; - resetToRestPosition(); - clearWinList(m_winList); - clearWinList(m_winMustFinishList); -} - - -void AnimateWindowManager::init() -{ - clearWinList(m_winList); - clearWinList(m_winMustFinishList); - m_needsUpdate = FALSE; - m_reverse = FALSE; -} - -void AnimateWindowManager::reset() -{ - resetToRestPosition(); - clearWinList(m_winList); - clearWinList(m_winMustFinishList); - m_needsUpdate = FALSE; - m_reverse = FALSE; -} - -// TheSuperHackers @tweak bobtista 04/08/2026 Advances the animations by a fractional base rate frame -// so that they move fluently on high render frame rates. -void AnimateWindowManager::update() -{ - const Real deltaFrames = TheFramePacer->getBaseOverUpdateFpsRatio(); - - ProcessAnimateWindow *processAnim = nullptr; - - // if we need to update the windows that need to finish, update that list - if(m_needsUpdate) - { - AnimateWindowList::iterator it = m_winMustFinishList.begin(); - m_needsUpdate = FALSE; - - while (it != m_winMustFinishList.end()) - { - wnd::AnimateWindow *animWin = *it; - if (!animWin) - { - DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List")); - return; - } - processAnim = getProcessAnimate( animWin->getAnimType() ); - if(processAnim) - { - if(m_reverse) - { - if(!processAnim->reverseAnimateWindow(animWin, deltaFrames)) - m_needsUpdate = TRUE; - } - else - { - if(!processAnim->updateAnimateWindow(animWin, deltaFrames)) - m_needsUpdate = TRUE; - } - } - - it ++; - } - } - - AnimateWindowList::iterator it = m_winList.begin(); - - while (it != m_winList.end()) - { - wnd::AnimateWindow *animWin = *it; - if (!animWin) - { - DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List")); - return; - } - processAnim = getProcessAnimate( animWin->getAnimType() ); - if(m_reverse) - { - if(processAnim) - processAnim->reverseAnimateWindow(animWin, deltaFrames); - } - else - { - if(processAnim) - processAnim->updateAnimateWindow(animWin, deltaFrames); - } - it ++; - } -} - - -void AnimateWindowManager::registerGameWindow(GameWindow *win, AnimTypes animType, Bool needsToFinish, UnsignedInt ms, UnsignedInt delayMs) -{ - if(!win) - { - DEBUG_CRASH(("Win was null as it was passed into registerGameWindow... not good indeed")); - return; - } - if(animType <= WIN_ANIMATION_NONE || animType >= WIN_ANIMATION_COUNT ) - { - DEBUG_CRASH(("an Invalid WIN_ANIMATION type was passed into registerGameWindow... please fix me ")); - return; - } - - // Create a new AnimateWindow class and fill in it's data. - wnd::AnimateWindow *animWin = wnd::AnimateWindow::createNewInstance(); - animWin->setGameWindow(win); - animWin->setAnimType(animType); - animWin->setNeedsToFinish(needsToFinish); - animWin->setDelay(delayMs); - - // Run the window through the processAnim's init function. - ProcessAnimateWindow *processAnim = getProcessAnimate( animType ); - if(processAnim) - { - processAnim->setMaxDuration(ms); - processAnim->initAnimateWindow( animWin ); - } - - // Add the Window to the proper list - if(needsToFinish) - { - m_winMustFinishList.push_back(animWin); - m_needsUpdate = TRUE; - } - else - m_winList.push_back(animWin); -} - -ProcessAnimateWindow *AnimateWindowManager::getProcessAnimate( AnimTypes animType ) -{ - switch (animType) { - case WIN_ANIMATION_SLIDE_RIGHT: - { - return m_slideFromRight; - } - case WIN_ANIMATION_SLIDE_RIGHT_FAST: - { - return m_slideFromRightFast; - } - case WIN_ANIMATION_SLIDE_LEFT: - { - return m_slideFromLeft; - } - case WIN_ANIMATION_SLIDE_TOP: - { - return m_slideFromTop; - } - case WIN_ANIMATION_SLIDE_BOTTOM: - { - return m_slideFromBottom; - } - case WIN_ANIMATION_SPIRAL: - { - return m_spiral; - } - case WIN_ANIMATION_SLIDE_BOTTOM_TIMED: - { - return m_slideFromBottomTimed; - } - case WIN_ANIMATION_SLIDE_TOP_FAST: - { - return m_slideFromTopFast; - } - default: - return nullptr; - } -} - -void AnimateWindowManager::reverseAnimateWindow() -{ - - m_reverse = TRUE; - m_needsUpdate = TRUE; - ProcessAnimateWindow *processAnim = nullptr; - - UnsignedInt maxDelay = 0; - AnimateWindowList::iterator it = m_winMustFinishList.begin(); - while (it != m_winMustFinishList.end()) - { - wnd::AnimateWindow *animWin = *it; - if (!animWin) - { - DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List")); - return; - } - if(animWin->getDelay() > maxDelay) - maxDelay = animWin->getDelay(); - it ++; - } - - it = m_winMustFinishList.begin(); - while (it != m_winMustFinishList.end()) - { - wnd::AnimateWindow *animWin = *it; - if (!animWin) - { - DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List")); - return; - } - // Run the window through the processAnim's init function. - processAnim = getProcessAnimate( animWin->getAnimType() ); - if(processAnim) - { - processAnim->initReverseAnimateWindow( animWin, maxDelay ); - } - - animWin->setFinished(FALSE); - it ++; - } - - it = m_winList.begin(); - - while (it != m_winList.end()) - { - wnd::AnimateWindow *animWin = *it; - if (!animWin) - { - DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List")); - return; - } - processAnim = getProcessAnimate( animWin->getAnimType() ); - - if(processAnim) - processAnim->initReverseAnimateWindow(animWin); - animWin->setFinished(FALSE); - it ++; - } - -} - -void AnimateWindowManager::resetToRestPosition() -{ - - m_reverse = TRUE; - m_needsUpdate = TRUE; - - AnimateWindowList::iterator it = m_winMustFinishList.begin(); - while (it != m_winMustFinishList.end()) - { - wnd::AnimateWindow *animWin = *it; - if (!animWin) - { - DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List")); - return; - } - ICoord2D restPos = animWin->getRestPos(); - GameWindow *win = animWin->getGameWindow(); - if(win) - win->winSetPosition(restPos.x, restPos.y); - it ++; - } - it = m_winList.begin(); - while (it != m_winList.end()) - { - wnd::AnimateWindow *animWin = *it; - if (!animWin) - { - DEBUG_CRASH(("There's No AnimateWindow in the AnimateWindow List")); - return; - } - ICoord2D restPos = animWin->getRestPos(); - GameWindow *win = animWin->getGameWindow(); - if(win) - win->winSetPosition(restPos.x, restPos.y); - it ++; - } - - -} - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - - - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp index 2c403eaa7c3..34fe50b17ff 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp @@ -698,7 +698,7 @@ void PopulateOldBuddyMessages() BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); for (BuddyMessageList::iterator mIt = messages->begin(); mIt != messages->end(); ++mIt) { - BuddyMessage message = *mIt; + const BuddyMessage &message = *mIt; insertChat(message); } } diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp index 772f7e20232..20c85d39c95 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp @@ -592,7 +592,7 @@ static void populateQuickMatchMapSelectListbox( QuickMatchPreferences& pref ) GadgetListBoxReset(listboxMapSelect); for (std::list::const_iterator it = maps.begin(); it != maps.end(); ++it) { - AsciiString theMap = *it; + const AsciiString &theMap = *it; const MapMetaData *md = TheMapCache->findMap(theMap); if (md && md->m_numPlayers >= numPlayers) { @@ -1670,7 +1670,7 @@ WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt ms if (cit != ladderInfo->validFactions.end()) { Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); - AsciiString sideStr = *cit; + const AsciiString &sideStr = *cit; DEBUG_LOG(("Chose %s as our side... finding", sideStr.str())); for (Int c=0; c. -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameWindowManager.cpp //////////////////////////////////////////////////////////////////// -// Created: Colin Day, June 2001 -// Dean Iverson, March 1998 (Original window code) -// Desc: The game window manager is the singleton class that we interface -// with to interact with the game windowing system. -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -#include "Common/Debug.h" -#include "Common/Language.h" -#include "GameClient/Display.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GameWindow.h" -#include "GameClient/Mouse.h" -#include "GameClient/DisplayStringManager.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameWindowGlobal.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetTabControl.h" -#include "GameClient/GadgetProgressBar.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetSlider.h" -#include "GameClient/GadgetRadioButton.h" -#include "GameClient/GadgetCheckBox.h" -#include "GameClient/GlobalLanguage.h" -#include "GameClient/GameWindowTransitions.h" -#include "Common/NameKeyGenerator.h" - -// PUBLIC DATA //////////////////////////////////////////////////////////////////////////////////// -GameWindowManager *TheWindowManager = nullptr; -UnsignedInt WindowLayoutCurrentVersion = 2; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -// -// with this status set to true, the window system will propagate mouse position -// messages to windows. You may want to disable this if you feel the mouse position -// messages are "spamming" your window and making a particular debugging situation -// difficult. Make sure you do enable this before you check in again tho because -// it is necessary for any code that needs to look at objects or anything under -// the radar cursor -// -static Bool sendMousePosMessages = TRUE; - -//------------------------------------------------------------------------------------------------- -/** Process windows waiting to be destroyed */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::processDestroyList() -{ - GameWindow *next; - GameWindow *doDestroy; - - // - // we need to pass the ownership of the destroy list so - // if, while destroying a window, we need to add other windows - // to the destroy list it won't cause problems. - // - doDestroy = m_destroyList; - - // set the list to empty - m_destroyList = nullptr; - - // do the destroys - for( ; doDestroy; doDestroy = next ) - { - - next = doDestroy->m_next; - - // Check to see if this window is "special" - if( m_mouseCaptor == doDestroy ) - winRelease( doDestroy ); - - if( m_keyboardFocus == doDestroy ) - winSetFocus( nullptr ); - - if( (m_modalHead != nullptr) && (doDestroy == m_modalHead->window) ) - winUnsetModal( m_modalHead->window ); - - if( m_currMouseRgn == doDestroy ) - m_currMouseRgn = nullptr; - - if( m_grabWindow == doDestroy ) - m_grabWindow = nullptr; - - // send the destroy message to the window we're about to kill - winSendSystemMsg( doDestroy, GWM_DESTROY, 0, 0 ); - - DEBUG_ASSERTCRASH(doDestroy->winGetUserData() == nullptr, ("Win user data is expected to be deleted now")); - - // free the memory - deleteInstance(doDestroy); - - } - -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -/** Generic function to simply propagate only button press messages to parent and let it deal with it */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType PassSelectedButtonsToParentSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - // sanity - if( window == nullptr ) - return MSG_IGNORED; - - if( (msg == GBM_SELECTED) || (msg == GBM_SELECTED_RIGHT) || (msg == GBM_MOUSE_ENTERING) || (msg == GBM_MOUSE_LEAVING) || (msg == GEM_EDIT_DONE)) - { - GameWindow *parent = window->winGetParent(); - - if( parent ) - return TheWindowManager->winSendSystemMsg( parent, msg, mData1, mData2 ); - - } - - return MSG_IGNORED; - -} - -//------------------------------------------------------------------------------------------------- -/** Generic function to simply propagate only button press messages to parent and let it deal with it */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType PassMessagesToParentSystem( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - // sanity - if( window == nullptr ) - return MSG_IGNORED; - - - GameWindow *parent = window->winGetParent(); - - if( parent ) - return TheWindowManager->winSendSystemMsg( parent, msg, mData1, mData2 ); - - return MSG_IGNORED; - -} - - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -GameWindowManager::GameWindowManager() -{ - - m_windowList = nullptr; // list of all top level windows - m_windowTail = nullptr; // last in windowList - - m_destroyList = nullptr; // list of windows to destroy - - m_currMouseRgn = nullptr; // window that mouse is over - m_mouseCaptor = nullptr; // window that captured mouse - m_keyboardFocus = nullptr; // window that has input focus - m_modalHead = nullptr; // top of windows in the modal stack - m_grabWindow = nullptr; // window that grabbed the last down event - m_loneWindow = nullptr; // Set if we just opened a combo box - - m_cursorBitmap = nullptr; - m_captureFlags = 0; - -} - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -GameWindowManager::~GameWindowManager() -{ - - // destroy all windows - winDestroyAll(); - freeStaticStrings(); - - delete TheTransitionHandler; - TheTransitionHandler = nullptr; -} - -//------------------------------------------------------------------------------------------------- -/** Initialize the game window manager system */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::init() -{ - if(!TheTransitionHandler) - TheTransitionHandler = NEW GameWindowTransitionsHandler; - TheTransitionHandler->load(); - TheTransitionHandler->init(); -} - -//------------------------------------------------------------------------------------------------- -/** Reset window system */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::reset() -{ - - // destroy all windows left - winDestroyAll(); - if(TheTransitionHandler) - TheTransitionHandler->reset(); - -} - -//------------------------------------------------------------------------------------------------- -/** Update cycle for game window manager */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::update() -{ - - // Process windows waiting to be destroyed - processDestroyList(); - if(TheTransitionHandler) - TheTransitionHandler->update(); -} - -//------------------------------------------------------------------------------------------------- -/** Puts a window at the head of the window list */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::linkWindow( GameWindow *window ) -{ - GameWindow *lastModalWindow = nullptr; - GameWindow *tmp = m_windowList; - while (tmp) - { - const ModalWindow *modal = m_modalHead; - while (modal) - { - if (modal->window == tmp && modal->window != window) - { - lastModalWindow = tmp; - } - modal = modal->next; - } - tmp = tmp->m_next; - } - - if (!lastModalWindow) - { - - // Add to head of the top level window list - window->m_prev = nullptr; - window->m_next = m_windowList; - - if( m_windowList ) - m_windowList->m_prev = window; - else - { - // first on list is also the tail - m_windowTail = window; - } - - m_windowList = window; - } - else - { - // lastModalWindow points to a modal window - add behind it - window->m_prev = lastModalWindow; - window->m_next = lastModalWindow->m_next; - lastModalWindow->m_next = window; - if (window->m_next) - { - window->m_next->m_prev = window; - } - } - -} - -//------------------------------------------------------------------------------------------------- -/** Insert the window ahead of the the 'aheadOf' window. 'aheadOf' can - * be a window in the master list or a child of any window in that master - * list */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::insertWindowAheadOf( GameWindow *window, - GameWindow *aheadOf ) -{ - - // sanity - if( window == nullptr ) - return; - - // we'll say that an aheadOf window means at the head of the list - if( aheadOf == nullptr ) - { - - linkWindow( window ); - return; - - } - - // get parent of aheadOf - GameWindow *aheadOfParent = aheadOf->winGetParent(); - - // - // if ahead of has no parent insert it in the master list just before - // ahead of - // - if( aheadOfParent == nullptr ) - { - - window->m_prev = aheadOf->m_prev; - - if( aheadOf->m_prev ) - aheadOf->m_prev->m_next = window; - else - m_windowList = window; - - aheadOf->m_prev = window; - window->m_next = aheadOf; - - } - else - { - - window->m_prev = aheadOf->m_prev; - - if( aheadOf->m_prev ) - aheadOf->m_prev->m_next = window; - else - aheadOfParent->m_child = window; - - aheadOf->m_prev = window; - window->m_next = aheadOf; - - window->m_parent = aheadOfParent; - - } - -} - -//------------------------------------------------------------------------------------------------- -/** Takes a window off the window list */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::unlinkWindow( GameWindow *window ) -{ - - if( window->m_next ) - window->m_next->m_prev = window->m_prev; - else - { - // no next means this is the tail - m_windowTail = window->m_prev; - } - - if( window->m_prev ) - window->m_prev->m_next = window->m_next; - else - m_windowList = window->m_next; - -} - -//------------------------------------------------------------------------------------------------- -/** Takes a child window off its parent's window list */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::unlinkChildWindow( GameWindow *window ) -{ - - if( window->m_prev ) - { - - window->m_prev->m_next = window->m_next; - - if( window->m_next ) - window->m_next->m_prev = window->m_prev; - - } - else - { - - if( window->m_next ) - { - - window->m_parent->m_child = window->m_next; - - window->m_next->m_prev = window->m_prev; - - window->m_next = nullptr; - - } - else - { - - window->m_parent->m_child = nullptr; - - } - - } - - // remove the parent reference from this window - window->m_parent = nullptr; - -} - -//------------------------------------------------------------------------------------------------- -/** Check window and parents to see if this window is enabled */ -//------------------------------------------------------------------------------------------------- -Bool GameWindowManager::isEnabled( GameWindow *win ) -{ - - // sanity - if( win == nullptr ) - return FALSE; - - if( BitIsSet( win->m_status, WIN_STATUS_ENABLED ) == FALSE ) - { - return FALSE; - } - - while( win->m_parent ) - { - win = win->m_parent; - if( BitIsSet( win->m_status, WIN_STATUS_ENABLED ) == FALSE ) - { - return FALSE; - } - } - - return TRUE; - -} - -//------------------------------------------------------------------------------------------------- -/** Check window and parents to see if this window is hidden */ -//------------------------------------------------------------------------------------------------- -Bool GameWindowManager::isHidden( GameWindow *win ) -{ - - // we'll allow for the idea that if a window doesn't exist it is hidden - if( win == nullptr ) - return TRUE; - - if( BitIsSet( win->m_status, WIN_STATUS_HIDDEN )) - { - return TRUE; - } - - while( win->m_parent ) - { - win = win->m_parent; - if( BitIsSet( win->m_status, WIN_STATUS_HIDDEN )) - { - return TRUE; - } - } - - return FALSE; - -} - -//------------------------------------------------------------------------------------------------- -// Adds a child window to its parent. -//------------------------------------------------------------------------------------------------- -void GameWindowManager::addWindowToParent( GameWindow *window, - GameWindow *parent ) -{ - if( parent ) - { - - // add to parent's list of children - window->m_prev = nullptr; - window->m_next = parent->m_child; - - if( parent->m_child ) - parent->m_child->m_prev = window; - - parent->m_child = window; - - window->m_parent = parent; - - } - -} - -//------------------------------------------------------------------------------------------------- -/** Add a child window to the parent, put place it at the end of the - * parent window child list */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::addWindowToParentAtEnd( GameWindow *window, - GameWindow *parent ) -{ - - if( parent ) - { - - window->m_prev = nullptr; - window->m_next = nullptr; - if( parent->m_child ) - { - GameWindow *last; - - // wind down to last child in list - last = parent->m_child; - while( last->m_next != nullptr ) - last = last->m_next; - - // tie to list - last->m_next = window; - window->m_prev = last; - - } - else - parent->m_child = window; - - // assign the parent to the window - window->m_parent = parent; - - } - -} - -//------------------------------------------------------------------------------------------------- -/** this gets called from winHide() when a window hides itself */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::windowHiding( GameWindow *window ) -{ - - // if this window has keyboard focus remove it - if( m_keyboardFocus == window ) - m_keyboardFocus = nullptr; - - // if this is the modal head, unset it - if( m_modalHead && m_modalHead->window == window ) - winUnsetModal( window ); - - // if this is the captor, it shall no longer be - if( m_mouseCaptor == window ) - winCapture( nullptr ); - - // - // since hiding a parent will also hide the children, when a parent - // hides we must call this same method for all the children so they - // each have a chance to go through this logic - // - GameWindow *child; - for( child = window->winGetChild(); child; child = child->winGetNext() ) - windowHiding( child ); - -} - -//------------------------------------------------------------------------------------------------- -/** Hide all windows in a certain range of id's (inclusive) */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::hideWindowsInRange( GameWindow *baseWindow, - Int first, Int last, - Bool hideFlag ) -{ - Int i; - GameWindow *window; - - for( i = first; i <= last; i++ ) - { - - window = winGetWindowFromId( baseWindow, i ); - if( window ) - window->winHide( hideFlag ); - - } - -} - -//------------------------------------------------------------------------------------------------- -// Enable all windows in a certain range of id's (inclusive) -//------------------------------------------------------------------------------------------------- -void GameWindowManager::enableWindowsInRange( GameWindow *baseWindow, - Int first, Int last, - Bool enableFlag ) -{ - Int i; - GameWindow *window; - - for( i =first; i <= last; i++ ) - { - - window = winGetWindowFromId( baseWindow, i ); - if( window ) - window->winEnable( enableFlag ); - - } - -} - -//------------------------------------------------------------------------------------------------- -/** Captures the mouse capture. */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::winCapture( GameWindow *window ) -{ - - if( m_mouseCaptor != nullptr) - return WIN_ERR_MOUSE_CAPTURED; - - m_mouseCaptor = window; - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** Releases the mouse capture. */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::winRelease( GameWindow *window ) -{ - - if( window == m_mouseCaptor ) - m_mouseCaptor = nullptr; - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** Returns the current mouse captor. */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::winGetCapture() -{ - - return m_mouseCaptor; - -} - -//------------------------------------------------------------------------------------------------- -/** Gets the window pointer from its id */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::winGetWindowFromId( GameWindow *window, Int id ) -{ - - if( window == nullptr ) - window = m_windowList; - - for( ; window; window = window->m_next ) - { - - if( window->winGetWindowId() == id) - return window; - else if( window->m_child ) - { - GameWindow *child = winGetWindowFromId( window->m_child, id ); - - if( child ) - return child; - - } - - } - - return nullptr; - -} - -//------------------------------------------------------------------------------------------------- -/** Gets the Window List Pointer */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::winGetWindowList() -{ - - return m_windowList; - -} - -//------------------------------------------------------------------------------------------------- -/** Send a system message to the specified window */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType GameWindowManager::winSendSystemMsg( GameWindow *window, - UnsignedInt msg, - WindowMsgData mData1, - WindowMsgData mData2 ) -{ - - if( window == nullptr) - return MSG_IGNORED; - - if( msg != GWM_DESTROY && BitIsSet( window->m_status, WIN_STATUS_DESTROYED ) ) - return MSG_IGNORED; - - return window->m_system( window, msg, mData1, mData2 ); - -} - -//------------------------------------------------------------------------------------------------- -/** Send a system message to the specified window */ -//------------------------------------------------------------------------------------------------- -WindowMsgHandledType GameWindowManager::winSendInputMsg( GameWindow *window, - UnsignedInt msg, - WindowMsgData mData1, - WindowMsgData mData2 ) -{ - - if( window == nullptr ) - return MSG_IGNORED; - - if( msg != GWM_DESTROY && BitIsSet( window->m_status, WIN_STATUS_DESTROYED ) ) - return MSG_IGNORED; - - return window->m_input( window, msg, mData1, mData2 ); - -} - -//------------------------------------------------------------------------------------------------- -/** Get the current input focus */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::winGetFocus() -{ - - return m_keyboardFocus; - -} - -//------------------------------------------------------------------------------------------------- -/** Set the current input focus */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::winSetFocus( GameWindow *window ) -{ - Bool wantsFocus = FALSE; - - // if a window doesn't want keyboard focus don't give it - if( window ) - if( BitIsSet( window->winGetStatus(), WIN_STATUS_NO_FOCUS) ) - return 0; - - // - // Tell current focus window that it's losing focus - // unless we are trying to give focus to the current focus window - // - if( (m_keyboardFocus) && (m_keyboardFocus != window) ) - { - Bool wf; // dummy var, ignored, but must be passed - winSendSystemMsg( m_keyboardFocus, GWM_INPUT_FOCUS, FALSE, (WindowMsgData)&wf ); - } - - // Set focus to new window - m_keyboardFocus = window; - - // Tell new focus window that it has focus - if( m_keyboardFocus ) - { - - for (;;) - { - winSendSystemMsg( window, GWM_INPUT_FOCUS, TRUE, (WindowMsgData)&wantsFocus ); - if (wantsFocus) - break; - - window = window->winGetParent(); - if( window == nullptr ) - break; - } - - } - - // If new window doesn't want focus, set focus to nullptr - if( wantsFocus == FALSE ) - m_keyboardFocus = nullptr; - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** Process key press through the GUI. */ -//------------------------------------------------------------------------------------------------- -WinInputReturnCode GameWindowManager::winProcessKey( UnsignedByte key, - UnsignedByte state ) -{ - WinInputReturnCode returnCode = WIN_INPUT_NOT_USED; - - // Check for keyboard focus and a legal key for sanity - if( m_keyboardFocus && (key != KEY_NONE) ) - { - GameWindow *win = m_keyboardFocus; - - returnCode = WIN_INPUT_USED; // assume input will be used - - // - // Pass the keystroke up the window hierarchy until it is - // processed or we reach the top level window - // - while( winSendInputMsg( win, GWM_CHAR, key, state ) == MSG_IGNORED ) - { - - win = win->winGetParent(); - if( win == nullptr ) - { - - returnCode = WIN_INPUT_NOT_USED; // oops, it wasn't used after all - break; - - } - - } - - } - - return returnCode; - -} - -//------------------------------------------------------------------------------------------------- -/** Process a single mouse event through the window system */ -//------------------------------------------------------------------------------------------------- -WinInputReturnCode GameWindowManager::winProcessMouseEvent( GameWindowMessage msg, - ICoord2D *mousePos, - void *data ) -{ - WinInputReturnCode returnCode = WIN_INPUT_NOT_USED; - Bool objectTooltip = FALSE; - UnsignedInt packedMouseCoords; - GameWindow *window = nullptr; - GameWindow *toolTipWindow = nullptr; - Int dx, dy; - Bool clearGrabWindow = FALSE; - - // pack mouse coords into one entity for message passing - packedMouseCoords = SHORTTOLONG( mousePos->x, mousePos->y ); - - // clear tooltip ... it will be reset if necessary - TheMouse->setCursorTooltip( UnicodeString::TheEmptyString ); - - // Check for mouse capture - if( m_mouseCaptor ) - { - - // no window grabbed as of yet - m_grabWindow = nullptr; - - // what what window within the captured window are we in - window = m_mouseCaptor->winPointInChild( mousePos->x, mousePos->y ); - - // - // send buttons, drags, wheels to the windows, we don't continually - // send mouse positions - // - if( sendMousePosMessages == TRUE || msg != GWM_MOUSE_POS ) - { - GameWindow *win = window; - - if( win ) - { - while( win != nullptr ) - { - - if( winSendInputMsg( win, msg, packedMouseCoords, 0 ) == MSG_HANDLED ) - { - - // if used clear the event - returnCode = WIN_INPUT_USED; - break; - - } - - // if we just tested mouseCaptor don't go any higher in the chain - if( win == m_mouseCaptor ) - break; - - win = win->winGetParent(); - - } - - } - else - { - - // if used clear the event - if( winSendInputMsg( m_mouseCaptor, msg, packedMouseCoords, 0 ) == MSG_HANDLED ) - returnCode = WIN_INPUT_USED; - - } - - } - - } - else - { - - if( m_grabWindow ) - { - GameWindow *parent; - - switch( msg ) - { - - // -------------------------------------------------------------------- - case GWM_LEFT_UP: - { - //Play a beep sound if the window is disabled. - m_grabWindow->winPointInChild( mousePos->x, mousePos->y, FALSE, TRUE ); - - BitClear( m_grabWindow->m_status, WIN_STATUS_ACTIVE ); - if( m_grabWindow->winPointInWindow( mousePos->x, mousePos->y ) ) - winSendInputMsg( m_grabWindow, GWM_LEFT_UP, packedMouseCoords, 0 ); - else if( BitIsSet( m_grabWindow->m_status, WIN_STATUS_DRAGGABLE )) - { - winSendInputMsg( m_grabWindow, GWM_LEFT_UP, packedMouseCoords, 0 ); - } - - clearGrabWindow = TRUE; - break; - - } - - // -------------------------------------------------------------------- - case MOUSE_EVENT_NONE: - case GWM_LEFT_DRAG: - { - - if( BitIsSet( m_grabWindow->m_status, WIN_STATUS_DRAGGABLE ) ) - { - ICoord2D *mouseDelta = (ICoord2D *)data; - dx = mouseDelta->x; - dy = mouseDelta->y; - - // Clip window to parent - if( m_grabWindow->winGetParent() ) - { - - parent = m_grabWindow->winGetParent(); - - if( m_grabWindow->m_region.lo.x + dx < 0 ) - dx = 0 - m_grabWindow->m_region.lo.x; - else if( m_grabWindow->m_region.hi.x + dx > parent->m_size.x ) - dx = parent->m_size.x - m_grabWindow->m_region.hi.x; - - if( m_grabWindow->m_region.lo.y + dy < 0 ) - dy = 0 - m_grabWindow->m_region.lo.y; - else if( m_grabWindow->m_region.hi.y + dy > parent->m_size.y ) - dy = parent->m_size.y - m_grabWindow->m_region.hi.y; - } - - // Move the window, but keep it completely visible within screen boundaries - IRegion2D newRegion; - ICoord2D grabSize; - - m_grabWindow->winGetPosition( &newRegion.lo.x, &newRegion.lo.y ); - m_grabWindow->winGetSize( &grabSize.x, &grabSize.y ); - - newRegion.lo.x += dx; - newRegion.lo.y += dy; - if( newRegion.lo.x < 0 ) - newRegion.lo.x = 0; - if( newRegion.lo.y < 0 ) - newRegion.lo.y = 0; - - newRegion.hi.x = newRegion.lo.x + grabSize.x; - newRegion.hi.y = newRegion.lo.y + grabSize.y; - if( newRegion.hi.x > (Int)TheDisplay->getWidth() ) - newRegion.hi.x = (Int)TheDisplay->getWidth(); - if( newRegion.hi.y > (Int)TheDisplay->getHeight() ) - newRegion.hi.y = (Int)TheDisplay->getHeight(); - - newRegion.lo.x = newRegion.hi.x - grabSize.x; - newRegion.lo.y = newRegion.hi.y - grabSize.y; - - m_grabWindow->winSetPosition( newRegion.lo.x, newRegion.lo.y ); - - } - - // Send mouse drag message - winSendInputMsg( m_grabWindow, msg, packedMouseCoords, 0 ); - break; - - } - - } - - // mark event handled - returnCode = WIN_INPUT_USED; - - } - else - { - - if( m_modalHead && m_modalHead->window ) - { - window = m_modalHead->window->winPointInChild( mousePos->x, mousePos->y ); - } - else - { - // search for top-level window which contains pointer - window = findWindowUnderMouse(toolTipWindow, mousePos, WIN_STATUS_ABOVE, WIN_STATUS_HIDDEN); - - // check !above, below and hidden - if( window == nullptr ) - window = findWindowUnderMouse(toolTipWindow, mousePos, WIN_STATUS_NONE, WIN_STATUS_ABOVE | WIN_STATUS_BELOW | WIN_STATUS_HIDDEN); - - // check below and !hidden - if( window == nullptr ) - window = findWindowUnderMouse(toolTipWindow, mousePos, WIN_STATUS_BELOW, WIN_STATUS_HIDDEN); - } - - if( window ) - if( BitIsSet( window->m_status, WIN_STATUS_NO_INPUT ) ) - { - if(window->winGetParent() && BitIsSet( window->winGetParent()->winGetInstanceData()->getStyle(), GWS_COMBO_BOX )) - window = window->winGetParent(); - else - window = nullptr; - } - - if( window ) - { - GameWindow *tempWin; - - // - // only send messages for button states, wheel states, we do not - // continually send messages for mouse positions - // - if( sendMousePosMessages == TRUE || msg != GWM_MOUSE_POS ) - { - - tempWin = window; - - // Give everyone a chance to do something with the clicks - GameWindow *oldLoneWindow = m_loneWindow; - while( winSendInputMsg( tempWin, msg, packedMouseCoords, 0 ) == MSG_IGNORED ) - { - - tempWin = tempWin->m_parent; - if( tempWin == nullptr ) - break; - - } - - - // First check to see if m_loneWindow is set if so, close the window - if( m_loneWindow && m_loneWindow == oldLoneWindow - &&( msg == GWM_LEFT_UP || msg == GWM_MIDDLE_UP || msg == GWM_RIGHT_UP || tempWin)) - { - if(!m_loneWindow->winIsChild(tempWin)) - winSetLoneWindow( nullptr ); - /* - ComboBoxData *cData = (ComboBoxData *)m_comboBoxOpen->winGetUserData(); - // verify that the window that ate the message wasn't one of our own - if(cData->dropDownButton != tempWin && - cData->editBox != tempWin && - cData->listBox != tempWin && - cData->listboxData->upButton != tempWin && - cData->listboxData->downButton != tempWin && - cData->listboxData->slider != tempWin && - cData->listboxData->slider != tempWin->winGetParent()) - winSetOpenComboBoxWindow( nullptr );*/ - - } - if( tempWin ) - { - - // - // Someone cares, if this is a left button down event - // it should get "grabbed" - /// @todo should allow for left handed mouse configs here? - // - if( msg == GWM_LEFT_DOWN ) - { - -// if( tempWin != windowList ) -// WinActivate( tempWin ); - m_grabWindow = tempWin; - - } - - // event is used - returnCode = WIN_INPUT_USED; - - } - - } - - } - - if( toolTipWindow == nullptr ) - { - - if( isHidden( window ) == FALSE ) - toolTipWindow = window; - - } - - // if tooltips are on set them into the window - Bool tooltipsOn = TRUE; - if( tooltipsOn ) - { -// if( toolTipWindow && toolTipWindow->winGetParent() && BitIsSet( toolTipWindow->winGetParent()->winGetInstanceData()->getStyle(), GWS_COMBO_BOX )) -// toolTipWindow = toolTipWindow->winGetParent(); - if( toolTipWindow ) - { - // do we have a callback to call for the tooltip - if( toolTipWindow->m_tooltip ) - toolTipWindow->m_tooltip( toolTipWindow, - &toolTipWindow->m_instData, - packedMouseCoords ); - - // else, do we have a normal tooltip to set - else if( toolTipWindow->m_instData.getTooltipTextLength() ) - TheMouse->setCursorTooltip( toolTipWindow->m_instData.getTooltipText(), toolTipWindow->m_instData.m_tooltipDelay ); - - } - else - { - - // - // not pointing at a window... perhaps we are pointing at a valid - // tooltip-able object in the game world ... let's set a flag so - // during the object testing we can set the tooltip, we can do - // whatever we like now that we know no other tooltip was set from - // a window - // - objectTooltip = TRUE; - - } - - } - - } - - } - - // - // check if new current window is different from the last - // but only if both windows fall within the mouseCaptor if one exists - // - if( (m_grabWindow == nullptr) && (window != m_currMouseRgn) ) - { - if( m_mouseCaptor ) - { - if( m_mouseCaptor->winIsChild( m_currMouseRgn ) ) - winSendInputMsg( m_currMouseRgn, GWM_MOUSE_LEAVING, packedMouseCoords, 0 ); - } - else if( m_currMouseRgn ) - winSendInputMsg( m_currMouseRgn, GWM_MOUSE_LEAVING, packedMouseCoords, 0 ); - - if( window ) - winSendInputMsg( window, GWM_MOUSE_ENTERING, packedMouseCoords, 0 ); - - m_currMouseRgn = window; - - } - - // clear grabWindow if necessary - if( clearGrabWindow == TRUE ) - { - - m_grabWindow = nullptr; - clearGrabWindow = FALSE; - - } - - return returnCode; - -} - -bool GameWindowManager::isMouseWithinWindow(GameWindow* window, const ICoord2D* mousePos, unsigned int requiredStatusMask, unsigned int forbiddenStatusMask) -{ - return ((BitIsSet(window->m_status, requiredStatusMask) || requiredStatusMask == 0) && - !BitIsSet(window->m_status, forbiddenStatusMask) && - mousePos->x >= window->m_region.lo.x && - mousePos->x <= window->m_region.hi.x && - mousePos->y >= window->m_region.lo.y && - mousePos->y <= window->m_region.hi.y); -} - -GameWindow* GameWindowManager::findWindowUnderMouse(GameWindow*& toolTipWindow, const ICoord2D* mousePos, unsigned int requiredStatusMask, unsigned int forbiddenStatusMask) -{ - for (GameWindow* window = m_windowList; window; window = window->m_next) - { - if (!isMouseWithinWindow(window, mousePos, requiredStatusMask, forbiddenStatusMask)) - continue; - - if (toolTipWindow == nullptr) - { - GameWindow* childWindow = window->winPointInAnyChild(mousePos->x, mousePos->y, TRUE, TRUE); - - if (childWindow->m_tooltip || childWindow->m_instData.getTooltipTextLength()) - toolTipWindow = childWindow; - } - - if (BitIsSet(window->m_status, WIN_STATUS_ENABLED)) - { - // determine which child window the mouse is in - return window->winPointInChild(mousePos->x, mousePos->y); - } - } - - return nullptr; -} - -//------------------------------------------------------------------------------------------------- -/** Draw a window and its children, in parent-first order. - * Children's coordinates are relative to their parents. - * Note that hidden windows automatically will not draw any - * of their children ... but see-thru windows only will not - * draw themselves, but will give their children an - * opportunity to draw */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::drawWindow( GameWindow *window ) -{ - GameWindow *child; - - if( window == nullptr ) - return WIN_ERR_INVALID_WINDOW; - - if( BitIsSet( window->m_status, WIN_STATUS_HIDDEN ) == FALSE ) - { - - if( !BitIsSet( window->m_status, WIN_STATUS_SEE_THRU ) && window->m_draw ) - window->m_draw( window, &window->m_instData ); - - /// @todo visit list boxes and borders, this is stupid! - // for list boxes only draw the borders BEFORE the children - if( BitIsSet( window->winGetStyle(), GWS_SCROLL_LISTBOX ) ) - if( BitIsSet( window->m_status, WIN_STATUS_BORDER ) == TRUE && - !BitIsSet( window->m_status, WIN_STATUS_SEE_THRU ) ) - window->winDrawBorder(); - - // draw children in reverse order just like the window list - child = window->m_child; - while( child && child->m_next ) - child = child->m_next; - - for( ; child; child = child->m_prev ) - drawWindow( child ); - - // - // draw the border for the window AFTER the window contents AND the - // children contents have drawn - // - if( !BitIsSet( window->winGetStyle(), GWS_SCROLL_LISTBOX ) ) - if( BitIsSet( window->m_status, WIN_STATUS_BORDER ) == TRUE && - !BitIsSet( window->m_status, WIN_STATUS_SEE_THRU ) ) - window->winDrawBorder(); - - } - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** Draw the GUI in reverse order to correlate with clicking priority */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::winRepaint() -{ - GameWindow *window, *next; - - // draw below windows - for( window = m_windowTail; window; window = next ) - { - next = window->m_prev; - - if( BitIsSet( window->m_status, WIN_STATUS_BELOW ) ) - drawWindow( window ); - } - - // draw non-above and non-below windows - for( window = m_windowTail; window; window = next ) - { - next = window->m_prev; - - if (BitIsSet( window->m_status, WIN_STATUS_ABOVE | - WIN_STATUS_BELOW ) == FALSE) - drawWindow( window ); - } - - // draw above windows - for( window = m_windowTail; window; window = next ) - { - next = window->m_prev; - - if( BitIsSet( window->m_status, WIN_STATUS_ABOVE ) ) - drawWindow( window ); - } - - if(TheTransitionHandler) - TheTransitionHandler->draw(); -} - -//------------------------------------------------------------------------------------------------- -/** Dump information about all the windows for resource problems */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::dumpWindow( GameWindow *window ) -{ -#ifndef FINAL - GameWindow *child; - - if( window == nullptr ) - return; - - DEBUG_LOG(( "ID: %d\tRedraw: 0x%08X\tUser Data: %d", - window->winGetWindowId(), window->m_draw, window->m_userData )); - - for( child = window->m_child; child; child = child->m_next ) - dumpWindow( child ); - - return; -#endif -} - -//------------------------------------------------------------------------------------------------- -/** Create a new window by setting up its parameters and callbacks. */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::winCreate( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - GameWinSystemFunc system, - WinInstanceData *instData ) -{ - GameWindow *window; - - // allocate new window - window = allocateNewWindow(); - if( window == nullptr ) - { - - DEBUG_LOG(( "WinCreate error: Could not allocate new window" )); -#ifndef FINAL - { - GameWindow *win; - - for( win = m_windowList; win; win = win->m_next ) - dumpWindow( win ); - } -#endif - - return nullptr; - - } - - // If this is a child window add it to the parent's window list - if( parent ) - addWindowToParent( window, parent ); - else - linkWindow( window ); - - window->m_status = status; - window->m_size.x = width; - window->m_size.y = height; - - window->m_region.lo.x = x; - window->m_region.lo.y = y; - window->m_region.hi.x = x + width; - window->m_region.hi.y = y + height; - - window->normalizeWindowRegion(); - - // set the system function and send a create message to window - window->winSetSystemFunc( system ); - winSendSystemMsg( window, GWM_CREATE, 0, 0 ); - - // copy over instance data if present - if( instData ) - window->winSetInstanceData( instData ); - - // set default font - if (TheGlobalLanguageData && TheGlobalLanguageData->m_defaultWindowFont.name.isNotEmpty()) - { window->winSetFont( winFindFont( - TheGlobalLanguageData->m_defaultWindowFont.name, - TheGlobalLanguageData->m_defaultWindowFont.size, - TheGlobalLanguageData->m_defaultWindowFont.bold) ); - } - else - window->winSetFont( winFindFont( "Times New Roman", 14, FALSE ) ); - - return window; - -} - -//------------------------------------------------------------------------------------------------- -/** Take a window and its children off the top level list and free - * their allocation class data. */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::winDestroy( GameWindow *window ) -{ - GameWindow *child, *next; - - if( window == nullptr ) - return WIN_ERR_INVALID_WINDOW; - - // - // we should never have edit data allocated in the window code, it's - // completely handled by the editor ONLY - // - DEBUG_ASSERTCRASH( window->winGetEditData() == nullptr, - ("winDestroy(): edit data should NOT be present!") ); - - if( BitIsSet( window->m_status, WIN_STATUS_DESTROYED ) ) - return WIN_ERR_OK; - - BitSet( window->m_status, WIN_STATUS_DESTROYED ); - window->freeImages(); - - if( m_mouseCaptor == window ) - winRelease( window ); - - if( m_keyboardFocus == window ) - winSetFocus( nullptr ); - - if( (m_modalHead != nullptr) && (window == m_modalHead->window) ) - winUnsetModal( m_modalHead->window ); - - if( m_currMouseRgn == window ) - m_currMouseRgn = nullptr; - - if( m_grabWindow == window ) - m_grabWindow = nullptr; - - for( child = window->m_child; child; child = next ) - { - next = child->m_next; - winDestroy( child ); - } - - // Remove the top level window from list - if( window->m_parent == nullptr ) - unlinkWindow( window ); - else - unlinkChildWindow( window ); - - // Add to head of the destroy list - window->m_prev = nullptr; - window->m_next = m_destroyList; - - m_destroyList = window; - - // - // if this window is part of a layout screen, notify the screen that - // this window is going away - // - if( window->m_layout ) - window->m_layout->removeWindow( window ); - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** Destroy all windows on the window list IMMEDIATELY */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::winDestroyAll() -{ - GameWindow *win, *next; - - // - // NOTE that it is CRITICAL that the windows be destroyed this way, - // the editor has windows that are not on this main list that must - // exist throughout a reset of the system (copy/paste for instance) - // so DO NOT ever change this to a clever pool of memory for the - // windows and reset the _pool_ ... I will have to kill you! CBD - // - - for( next = win = m_windowList; next; win = next) - { - next = win->m_next; - - winDestroy( win ); - - } - - // Destroy All Windows just added to destroy list - processDestroyList(); - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** Sets selected window into a modal state. This window will get - * put at the top of a modal stack */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::winSetModal( GameWindow *window ) -{ - ModalWindow *modal; - - if( window == nullptr ) - return WIN_ERR_INVALID_WINDOW; - - // verify requesting window is a root window - if( window->m_parent != nullptr ) - { - DEBUG_LOG(( "WinSetModal: Non Root window attempted to go modal." )); - return WIN_ERR_INVALID_PARAMETER; // return error if not - } - // Allocate new Modal Window Entry - modal = newInstance(ModalWindow); - if( modal == nullptr ) - { - DEBUG_LOG(( "WinSetModal: Unable to allocate space for Modal Entry." )); - return WIN_ERR_GENERAL_FAILURE; - } - - // Put new entry at top of list - modal->window = window; - modal->next = m_modalHead; - m_modalHead = modal; - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** pops window off of the modal stack. If this window is not the top - * of the modal stack an error will occur. */ -//------------------------------------------------------------------------------------------------- -Int GameWindowManager::winUnsetModal( GameWindow *window ) -{ - ModalWindow *next; - - if( window == nullptr ) - return WIN_ERR_INVALID_WINDOW; - - // verify entry is at top of list - if( (m_modalHead == nullptr) || (m_modalHead->window != window) ) - { - - // return error if not - DEBUG_LOG(( "WinUnsetModal: Invalid window attempting to unset modal (%d)", - window->winGetWindowId() )); - return WIN_ERR_GENERAL_FAILURE; - - } - - // remove from top of list - next = m_modalHead->next; - deleteInstance(m_modalHead); - m_modalHead = next; - - return WIN_ERR_OK; - -} - -//------------------------------------------------------------------------------------------------- -/** Get the grabbed window */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::winGetGrabWindow() -{ - - return m_grabWindow; - -} - -//------------------------------------------------------------------------------------------------- -/** Explicitly set the grab window */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::winSetGrabWindow( GameWindow *window ) -{ - - m_grabWindow = window; - -} - -//------------------------------------------------------------------------------------------------- -/** Explicitly set the grab window */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::winSetLoneWindow( GameWindow *window ) -{ - // ignore if we're trying to set the same window - if( m_loneWindow == window ) - return; - if( m_loneWindow ) - winSendSystemMsg( m_loneWindow, GGM_CLOSE, 0, 0 ); - m_loneWindow = window; - -} - -//------------------------------------------------------------------------------------------------- -/** Create a Modal Message Box */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoMessageBox(Int x, Int y, Int width, Int height, UnsignedShort buttonFlags, - UnicodeString titleString, UnicodeString bodyString, - GameWinMsgBoxFunc yesCallback, - GameWinMsgBoxFunc noCallback, - GameWinMsgBoxFunc okCallback, - GameWinMsgBoxFunc cancelCallback ) -{ - return gogoMessageBox(x,y, width,height,buttonFlags,titleString,bodyString,yesCallback,noCallback,okCallback,cancelCallback, FALSE); -} - -GameWindow *GameWindowManager::gogoMessageBox(Int x, Int y, Int width, Int height, UnsignedShort buttonFlags, - UnicodeString titleString, UnicodeString bodyString, - GameWinMsgBoxFunc yesCallback, - GameWinMsgBoxFunc noCallback, - GameWinMsgBoxFunc okCallback, - GameWinMsgBoxFunc cancelCallback, Bool useLogo ) - -{ - // first check to make sure we have some buttons to display - if(buttonFlags == 0 ) - { - return nullptr; - } - GameWindow *trueParent = nullptr; - //Changed by Chris - if(useLogo) - trueParent = winCreateFromScript( "Menus/QuitMessageBox.wnd" ); - else - trueParent = winCreateFromScript( "Menus/MessageBox.wnd" ); - //Added By Chris - AsciiString menuName; - if(useLogo) - menuName.set("QuitMessageBox.wnd:"); - else - menuName.set("MessageBox.wnd:"); - - AsciiString tempName; - GameWindow *parent = nullptr; - - tempName = menuName; - tempName.concat("MessageBoxParent"); - parent = winGetWindowFromId(trueParent, TheNameKeyGenerator->nameToKey( tempName )); - winSetModal( trueParent ); - winSetFocus( nullptr ); // make sure we lose focus from other windows even if we refuse focus ourselves - winSetFocus( parent ); - - // If the user wants the size to be different then the default - float ratioX, ratioY = 1; - - if( width > 0 && height > 0 ) - { - ICoord2D temp; - //First grab the percent increase/decrease compared to the default size - parent->winGetSize( &temp.x, &temp.y); - ratioX = (float)width / (float)temp.x; - ratioY = (float)height / (float)temp.y; - //Set the window's new size - parent->winSetSize( width, height); - - //Resize/reposition all the children windows based off the ratio - GameWindow *child; - for( child = parent->winGetChild(); child; child = child->winGetNext() ) - { - child->winGetSize(&temp.x, &temp.y); - temp.x =Int(temp.x * ratioX); - temp.y =Int(temp.y * ratioY); - child->winSetSize(temp.x, temp.y); - - child->winGetPosition(&temp.x, &temp.y); - temp.x =Int(temp.x * ratioX); - temp.y =Int(temp.y * ratioY); - child->winSetPosition(temp.x, temp.y); - } - } - - // If the user wants to position the message box somewhere other then default - if( x >= 0 && y >= 0) - parent->winSetPosition(x, y); - - // Reposition the buttons - Int buttonX[3], buttonY[3]; - - //In the layout, buttonOk will be in the first button position - NameKeyType buttonOkID = NAMEKEY_INVALID; - - tempName = menuName; - tempName.concat("ButtonOk"); - buttonOkID = TheNameKeyGenerator->nameToKey( tempName ); - GameWindow *buttonOk = winGetWindowFromId(parent, buttonOkID); - buttonOk->winGetPosition(&buttonX[0], &buttonY[0]); - - tempName = menuName; - tempName.concat("ButtonYes"); - NameKeyType buttonYesID = TheNameKeyGenerator->nameToKey( tempName ); - GameWindow *buttonYes = winGetWindowFromId(parent, buttonYesID); - //buttonNo in the second position - tempName = menuName; - tempName.concat("ButtonNo"); - NameKeyType buttonNoID = TheNameKeyGenerator->nameToKey(tempName); - GameWindow *buttonNo = winGetWindowFromId(parent, buttonNoID); - buttonNo->winGetPosition(&buttonX[1], &buttonY[1]); - - //and buttonCancel in the third - tempName = menuName; - tempName.concat("ButtonCancel"); - NameKeyType buttonCancelID = TheNameKeyGenerator->nameToKey( tempName ); - GameWindow *buttonCancel = winGetWindowFromId(parent, buttonCancelID); - buttonCancel->winGetPosition(&buttonX[2], &buttonY[2]); - - //we shouldn't have button OK and Yes on the same dialog - if((buttonFlags & (MSG_BOX_OK | MSG_BOX_YES)) == (MSG_BOX_OK | MSG_BOX_YES) ) - { - DEBUG_CRASH(("Passed in MSG_BOX_OK and MSG_BOX_YES. Big No No.")); - } - - //Position the OK button if we have one - if( (buttonFlags & MSG_BOX_OK) == MSG_BOX_OK) - { - buttonOk->winSetPosition(buttonX[0], buttonY[0]); - buttonOk->winHide(FALSE); - } - else if( (buttonFlags & MSG_BOX_YES) == MSG_BOX_YES) - { - //Position the Yes if we have one - buttonYes->winSetPosition(buttonX[0], buttonY[0]); - buttonYes->winHide(FALSE); - } - - if((buttonFlags & (MSG_BOX_NO | MSG_BOX_CANCEL)) == (MSG_BOX_NO | MSG_BOX_CANCEL) ) - { - //If we have both the No and Cancel button, then the no should go in the middle position - buttonNo->winSetPosition(buttonX[1], buttonY[1]); - buttonCancel->winSetPosition(buttonX[2], buttonY[2]); - buttonNo->winHide(FALSE); - buttonCancel->winHide(FALSE); - } - else if( (buttonFlags & MSG_BOX_NO) == MSG_BOX_NO) - { - //if we just have the no button, then position it in the right most spot - buttonNo->winSetPosition(buttonX[2], buttonY[2]); - buttonNo->winHide(FALSE); - } - else if( (buttonFlags & MSG_BOX_CANCEL) == MSG_BOX_CANCEL) - { - //else if we just have the Cancel button, well, it should always go in the right spot - buttonCancel->winSetPosition(buttonX[2], buttonY[2]); - buttonCancel->winHide(FALSE); - } - - // Fill the text into the text boxes - tempName = menuName; - tempName.concat("StaticTextTitle"); - NameKeyType staticTextTitleID = TheNameKeyGenerator->nameToKey( tempName ); - GameWindow *staticTextTitle = winGetWindowFromId(parent, staticTextTitleID); - GadgetStaticTextSetText(staticTextTitle,titleString); - tempName = menuName; - tempName.concat("StaticTextMessage"); - NameKeyType staticTextMessageID = TheNameKeyGenerator->nameToKey( tempName ); - GameWindow *staticTextMessage = winGetWindowFromId(parent, staticTextMessageID); - GadgetStaticTextSetText(staticTextMessage,bodyString); - - // create a structure that will pass the functions to - WindowMessageBoxData *MsgBoxCallbacks = NEW WindowMessageBoxData; - MsgBoxCallbacks->cancelCallback = cancelCallback; - MsgBoxCallbacks->noCallback = noCallback; - MsgBoxCallbacks->okCallback = okCallback; - MsgBoxCallbacks->yesCallback = yesCallback; - //pass the structure to the dialog - trueParent->winSetUserData( MsgBoxCallbacks ); - - //make sure the dialog is showing and bring it to the top - parent->winHide(FALSE); - parent->winBringToTop(); - - //Changed By Chris - return trueParent; -} - -//------------------------------------------------------------------------------------------------- -/** Create a button GUI control */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetPushButton( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - GameFont *defaultFont, - Bool defaultVisual ) -{ - GameWindow *button; - - // we MUST have a push button style window to do this - if( BitIsSet( instData->getStyle(), GWS_PUSH_BUTTON ) == FALSE ) - { - - DEBUG_LOG(( "Can't create button gadget, instance data not button type" )); - assert( 0 ); - return nullptr; - - } - - // create the button window - button = winCreate( parent, status, - x, y, width, height, - GadgetPushButtonSystem, - instData ); - if( button == nullptr ) - { - - DEBUG_LOG(( "Unable to create button for push button gadget" )); - assert( 0 ); - return nullptr; - - } - - // assign input function - button->winSetInputFunc( GadgetPushButtonInput ); - - // - // assign draw function, the draw functions must actually be implemented - // on the device level of the engine - // - if( BitIsSet( button->winGetStatus(), WIN_STATUS_IMAGE ) ) - button->winSetDrawFunc( getPushButtonImageDrawFunc() ); - else - button->winSetDrawFunc( getPushButtonDrawFunc() ); - - // set the owner to the parent, or if no parent it will be itself - button->winSetOwner( parent ); - - // Init the userdata to null - button->winSetUserData(nullptr); - - // assign the default images/colors - assignDefaultGadgetLook( button, defaultFont, defaultVisual ); - - // assign text from label - UnicodeString text = winTextLabelToText( instData->m_textLabelString ); - if( text.getLength() ) - GadgetButtonSetText( button, text ); - - return button; - -} - -//------------------------------------------------------------------------------------------------- -/** Create a checkbox UI element */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetCheckbox( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *checkbox; - - // we MUST have a push button style window to do this - if( BitIsSet( instData->getStyle(), GWS_CHECK_BOX ) == FALSE ) - { - - DEBUG_LOG(( "Can't create checkbox gadget, instance data not checkbox type" )); - assert( 0 ); - return nullptr; - - } - - // create the button window - checkbox = winCreate( parent, status, - x, y, width, height, - GadgetCheckBoxSystem, - instData ); - if( checkbox == nullptr ) - { - - DEBUG_LOG(( "Unable to create checkbox window" )); - assert( 0 ); - return nullptr; - - } - - // assign input function - checkbox->winSetInputFunc( GadgetCheckBoxInput ); - - // - // assign draw function, the draw functions must actually be implemented - // on the device level of the engine - // - if( BitIsSet( checkbox->winGetStatus(), WIN_STATUS_IMAGE ) ) - checkbox->winSetDrawFunc( getCheckBoxImageDrawFunc() ); - else - checkbox->winSetDrawFunc( getCheckBoxDrawFunc() ); - - // set the owner to the parent, or if no parent it will be itself - checkbox->winSetOwner( parent ); - - // assign the default images/colors - assignDefaultGadgetLook( checkbox, defaultFont, defaultVisual ); - - // assign text from label - UnicodeString text = winTextLabelToText( instData->m_textLabelString ); - if( text.getLength() ) - GadgetCheckBoxSetText( checkbox, text ); - - return checkbox; - -} - -//------------------------------------------------------------------------------------------------- -/** Create a radio button GUI element */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetRadioButton( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - RadioButtonData *rData, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *radioButton; - RadioButtonData *radioData; - - // we MUST have a push button style window to do this - if( BitIsSet( instData->getStyle(), GWS_RADIO_BUTTON ) == FALSE ) - { - - DEBUG_LOG(( "Can't create radioButton gadget, instance data not radioButton type" )); - assert( 0 ); - return nullptr; - - } - - // create the button window - radioButton = winCreate( parent, status, - x, y, width, height, - GadgetRadioButtonSystem, - instData ); - if( radioButton == nullptr ) - { - - DEBUG_LOG(( "Unable to create radio button window" )); - assert( 0 ); - return nullptr; - - } - - // allocate and store the radio button user data - radioData = NEW RadioButtonData; - memcpy( radioData, rData, sizeof( RadioButtonData ) ); - radioButton->winSetUserData( radioData ); - - // assign input function - radioButton->winSetInputFunc( GadgetRadioButtonInput ); - - // - // assign draw function, the draw functions must actually be implemented - // on the device level of the engine - // - if( BitIsSet( radioButton->winGetStatus(), WIN_STATUS_IMAGE ) ) - radioButton->winSetDrawFunc( getRadioButtonImageDrawFunc() ); - else - radioButton->winSetDrawFunc( getRadioButtonDrawFunc() ); - - // set the owner to the parent, or if no parent it will be itself - radioButton->winSetOwner( parent ); - - // assign the default images/colors - assignDefaultGadgetLook( radioButton, defaultFont, defaultVisual ); - - // assign text from label - UnicodeString text = winTextLabelToText( instData->m_textLabelString ); - if( text.getLength() ) - GadgetRadioSetText( radioButton, text ); - - return radioButton; - -} - -//------------------------------------------------------------------------------------------------- -/** Create a tab control GUI element */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetTabControl( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - TabControlData *tData, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *tabControl; - TabControlData *tabData; - - // we MUST have a tab control style window to do this - if( BitIsSet( instData->getStyle(), GWS_TAB_CONTROL ) == FALSE ) - { - - DEBUG_LOG(( "Can't create tabControl gadget, instance data not tabControl type" )); - assert( 0 ); - return nullptr; - - } - - // create the tab control window - tabControl = winCreate( parent, status, - x, y, width, height, - GadgetTabControlSystem, - instData ); - if( tabControl == nullptr ) - { - - DEBUG_LOG(( "Unable to create tab control window" )); - assert( 0 ); - return nullptr; - - } - - // allocate and store the tab control user data - tabData = NEW TabControlData; - memcpy( tabData, tData, sizeof( TabControlData ) ); - tabControl->winSetUserData( tabData ); - - GadgetTabControlComputeTabRegion( tabControl ); - GadgetTabControlCreateSubPanes( tabControl ); - GadgetTabControlShowSubPane( tabControl, 0 ); - - // assign input function - tabControl->winSetInputFunc( GadgetTabControlInput ); - - // - // assign draw function, the draw functions must actually be implemented - // on the device level of the engine - // - if( BitIsSet( tabControl->winGetStatus(), WIN_STATUS_IMAGE ) ) - tabControl->winSetDrawFunc( getTabControlImageDrawFunc() ); - else - tabControl->winSetDrawFunc( getTabControlDrawFunc() ); - - // set the owner to the parent, or if no parent it will be itself - tabControl->winSetOwner( parent ); - - // assign the default images/colors - assignDefaultGadgetLook( tabControl, defaultFont, defaultVisual ); - - return tabControl; - -} - -//------------------------------------------------------------------------------------------------- -/** Create a list box GUI control */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetListBox( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - ListboxData *listboxDataTemplate, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *listbox; - ListboxData *listboxData; - Bool title = FALSE; - - // we MUST have a push button style window to do this - if( BitIsSet( instData->getStyle(), GWS_SCROLL_LISTBOX ) == FALSE ) - { - - DEBUG_LOG(( "Can't create listbox gadget, instance data not listbox type" )); - assert( 0 ); - return nullptr; - - } - - // create the listbox - listbox = winCreate( parent, status, x, y, width, height, - GadgetListBoxSystem, instData ); - - if( listbox == nullptr ) - { - - DEBUG_LOG(( "Unable to create listbox window" )); - assert( 0 ); - return nullptr; - - } - - // allocate the listbox data, copy template data over and set it into box - listboxData = NEW ListboxData; - DEBUG_ASSERTCRASH(listboxDataTemplate, ("listboxDataTemplate not initialized")); - memcpy( listboxData, listboxDataTemplate, sizeof( ListboxData ) ); - - // Add the list box data struct to the window's class data - listbox->winSetUserData( listboxData ); - - // set the owner to the parent, or if no parent it will be itself - listbox->winSetOwner( parent ); - - // Adjust for list title if present - if( instData->getTextLength() ) - title = TRUE; - - // Set up list box redraw callbacks - if( BitIsSet( listbox->winGetStatus(), WIN_STATUS_IMAGE )) - listbox->winSetDrawFunc( getListBoxImageDrawFunc() ); - else - listbox->winSetDrawFunc( getListBoxDrawFunc() ); - - // Set up list box input callbacks - if( listboxData->multiSelect ) - listbox->winSetInputFunc( GadgetListBoxMultiInput ); - else - listbox->winSetInputFunc( GadgetListBoxInput ); - - - - // - // allocate and set the list length, note that setting the list length will - // automatically allocate the selection entries that are needed for multi - // select list boxes etc. - // - Int length = listboxData->listLength; - listboxData->listLength = 0; // hacky! - GadgetListBoxSetListLength( listbox, length ); - - // store display height - listboxData->displayHeight = height; - - if( title ) - listboxData->displayHeight -= winFontHeight( instData->getFont() ); - - // Set display position to the top of the list - listboxData->displayPos = 0; - listboxData->selectPos = -1; - listboxData->doubleClickTime = 0; - listboxData->insertPos = 0; - listboxData->endPos = 0; - listboxData->totalHeight = 0; - - // if this listbox has multiple selections prep it - //if( listboxData->multiSelect ) - // GadgetListBoxAddMultiSelect( listbox ); - - // If ScrollBar was requested ... create it. - if( listboxData->scrollBar ) - GadgetListboxCreateScrollbar( listbox ); - // - // Setup listbox Columns - // - if( listboxData->columns == 1 ) - { - listboxData->columnWidth = NEW Int[listboxData->columns]; - listboxData->columnWidth[0] = width; - if( listboxData->slider ) - { - ICoord2D sliderSize; - - listboxData->slider->winGetSize( &sliderSize.x, &sliderSize.y ); - listboxData->columnWidth[0] -= (sliderSize.x + 2); - - } - } - else - { - if( !listboxData->columnWidthPercentage ) - return nullptr; - listboxData->columnWidth = NEW Int[listboxData->columns]; - if(!listboxData->columnWidth) - return nullptr; - - Int totalWidth = width; - if( listboxData->slider ) - { - ICoord2D sliderSize; - - listboxData->slider->winGetSize( &sliderSize.x, &sliderSize.y ); - totalWidth -= (sliderSize.x + 2); - - } - for(Int i = 0; i < listboxData->columns; i++ ) - { - listboxData->columnWidth[i] = listboxData->columnWidthPercentage[i] * totalWidth / 100; - } - } - // assign the default images/colors - assignDefaultGadgetLook( listbox, defaultFont, defaultVisual ); - - return listbox; - -} - -//------------------------------------------------------------------------------------------------- -/** Does all generic window creation, calls appropriate slider create - * function to set up slider-specific data */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetSlider( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - SliderData *sliderData, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *slider; - GameWindow *button; - SliderData *data; - - // - // All sliders need to have the tab stop status in order for - // the focus chain to work correctly. - // - BitSet( status, WIN_STATUS_TAB_STOP ); - - if( BitIsSet( instData->getStyle(), GWS_HORZ_SLIDER ) ) - { - - slider = winCreate( parent, status, x, y, width, height, - GadgetHorizontalSliderSystem, instData ); - - // Set up horizontal slider callbacks - slider->winSetInputFunc( GadgetHorizontalSliderInput ); - if( BitIsSet( slider->winGetStatus(), WIN_STATUS_IMAGE ) ) - slider->winSetDrawFunc( getHorizontalSliderImageDrawFunc() ); - else - slider->winSetDrawFunc( getHorizontalSliderDrawFunc() ); - - } - else if ( BitIsSet( instData->getStyle(), GWS_VERT_SLIDER ) ) - { - - slider = winCreate( parent, status, x, y, width, height, - GadgetVerticalSliderSystem, instData ); - - // Set up vertical slider callbacks - slider->winSetInputFunc( GadgetVerticalSliderInput ); - - if( BitIsSet( slider->winGetStatus(), WIN_STATUS_IMAGE ) && !(parent && BitIsSet(parent->winGetStyle(), GWS_SCROLL_LISTBOX))) - slider->winSetDrawFunc( getVerticalSliderImageDrawFunc() ); - else - slider->winSetDrawFunc( getVerticalSliderDrawFunc() ); - - } - else - { - - DEBUG_LOG(( "gogoGadgetSlider warning: unrecognized slider style." )); - assert( 0 ); - return nullptr; - - } - - // sanity - if( slider == nullptr ) - { - - DEBUG_LOG(( "Unable to create slider control window" )); - assert( 0 ); - return nullptr; - - } - - // set the owner to the parent, or if no parent it will be itself - slider->winSetOwner( parent ); - - // create the slider thumb button - WinInstanceData buttonInstData; - UnsignedInt statusFlags = status | WIN_STATUS_ENABLED | WIN_STATUS_DRAGGABLE; - - buttonInstData.init(); - - // if parent is hidden we don't need to be. - BitClear( statusFlags, WIN_STATUS_HIDDEN ); - - buttonInstData.m_owner = slider; - buttonInstData.m_style = GWS_PUSH_BUTTON; - - // if slider tracks, so will this sub control - if( BitIsSet( instData->getStyle(), GWS_MOUSE_TRACK ) ) - BitSet( buttonInstData.m_style, GWS_MOUSE_TRACK ); - - if( BitIsSet( instData->getStyle(), GWS_HORZ_SLIDER ) ) - button = gogoGadgetPushButton( slider, statusFlags, 0, HORIZONTAL_SLIDER_THUMB_POSITION, - HORIZONTAL_SLIDER_THUMB_WIDTH, HORIZONTAL_SLIDER_THUMB_HEIGHT, &buttonInstData, nullptr, TRUE ); - else - button = gogoGadgetPushButton( slider, statusFlags, 0, 0, - width, width+1, &buttonInstData, nullptr, TRUE ); - - // Protect against divide by zero - if( sliderData->maxVal == sliderData->minVal ) - sliderData->maxVal = sliderData->minVal + 1; - - if( BitIsSet( instData->getStyle(), GWS_HORZ_SLIDER ) ) - { - sliderData->numTicks = (float)(width - HORIZONTAL_SLIDER_THUMB_WIDTH) / - (float)(sliderData->maxVal - sliderData->minVal); - } else - { - sliderData->numTicks = (float)(height - GADGET_SIZE) / - (float)(sliderData->maxVal - sliderData->minVal); - } - - data = NEW SliderData; - memcpy( data, sliderData, sizeof(SliderData) ); - - // Add the slider data struct to the window's class data - slider->winSetUserData( data ); - - // assign the default images/colors - assignDefaultGadgetLook( slider, defaultFont, defaultVisual ); - - return slider; - -} - -//------------------------------------------------------------------------------------------------- -/** Create a Combo Box GUI element */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetComboBox( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - ComboBoxData *comboBoxDataTemplate, - GameFont *defaultFont, - Bool defaultVisual ) -{ - GameWindow *comboBox; - ComboBoxData *comboBoxData; - Bool title = FALSE; - - // we MUST have a push button style window to do this - if( BitIsSet( instData->getStyle(), GWS_COMBO_BOX) == FALSE ) - { - - DEBUG_LOG(( "Can't create ComboBox gadget, instance data not ComboBox type" )); - assert( 0 ); - return nullptr; - - } - - // create the listbox - comboBox = winCreate( parent, status, x, y, width, height, - GadgetComboBoxSystem, instData ); - - if( comboBox == nullptr ) - { - - DEBUG_LOG(( "Unable to create ComboBox window" )); - assert( 0 ); - return nullptr; - - } - - -// begin here - // allocate the listbox data, copy template data over and set it into box - comboBoxData = NEW ComboBoxData; - memcpy( comboBoxData, comboBoxDataTemplate, sizeof( ComboBoxData ) ); - - // Add the list box data struct to the window's class data - comboBox->winSetUserData( comboBoxData ); - - // set the owner to the parent, or if no parent it will be itself - comboBox->winSetOwner( parent ); - - // Adjust for list title if present - if( instData->getTextLength() ) - title = TRUE; - - // Set up list box redraw callbacks - if( BitIsSet( comboBox->winGetStatus(), WIN_STATUS_IMAGE )) - comboBox->winSetDrawFunc( getComboBoxImageDrawFunc() ); - else - comboBox->winSetDrawFunc( getComboBoxDrawFunc() ); - - // Set up list box input callbacks - comboBox->winSetInputFunc( GadgetComboBoxInput ); - - //Create the windows that make up - - - WinInstanceData winInstData; - Int buttonWidth, buttonHeight; - Int fontHeight; - Int top; - Int bottom; - - - // do we have a title - if( comboBox->winGetTextLength() ) - title = TRUE; - - // remove unwanted status bits. - status &= ~(WIN_STATUS_BORDER | WIN_STATUS_HIDDEN); - - fontHeight = winFontHeight( comboBox->winGetFont() ); - top = title ? (fontHeight + 1):0; - bottom = title ? (height - (fontHeight + 1)):height; - - // initialize instData - winInstData.init(); - - // size of button - buttonWidth = 21; - buttonHeight = 22; - - // ---------------------------------------------------------------------- - // Create Drop Down Button - // ---------------------------------------------------------------------- - - winInstData.m_owner = comboBox; - winInstData.m_style = GWS_PUSH_BUTTON; - - // if listbox tracks, so will this sub control - if( BitIsSet( comboBox->winGetStyle(), GWS_MOUSE_TRACK ) ) - BitSet( winInstData.m_style, GWS_MOUSE_TRACK ); - - comboBoxData->dropDownButton = - gogoGadgetPushButton( comboBox, - status | WIN_STATUS_ACTIVE | WIN_STATUS_ENABLED, - width - buttonWidth, 0, - buttonWidth, height, - &winInstData, nullptr, TRUE ); - comboBoxData->dropDownButton->winSetTooltipFunc(comboBox->winGetTooltipFunc()); - comboBoxData->dropDownButton->winSetTooltip(instData->getTooltipText()); - comboBoxData->dropDownButton->setTooltipDelay(comboBox->getTooltipDelay()); - // ---------------------------------------------------------------------- - // Create text entry - // ---------------------------------------------------------------------- - UnsignedInt statusTextEntry; - winInstData.init(); - - winInstData.m_owner = comboBox; - winInstData.m_style |= GWS_ENTRY_FIELD; - winInstData.m_textLabelString = "Entry"; - if( BitIsSet( comboBox->winGetStyle(), GWS_MOUSE_TRACK ) ) - BitSet( winInstData.m_style, GWS_MOUSE_TRACK ); - if( comboBoxData->isEditable) - { - statusTextEntry = status; - } - else - { - statusTextEntry = status | WIN_STATUS_NO_INPUT ;//| WIN_STATUS_NO_FOCUS; - comboBoxData->entryData->drawTextFromStart = TRUE; - } - comboBoxData->editBox = gogoGadgetTextEntry( comboBox, statusTextEntry , - 0,0 , - width - buttonWidth , height , - &winInstData, comboBoxData->entryData, - winInstData.m_font, FALSE ); - comboBoxData->editBox->winSetTooltipFunc(comboBox->winGetTooltipFunc()); - comboBoxData->editBox->winSetTooltip(instData->getTooltipText()); - comboBoxData->editBox->setTooltipDelay(comboBox->getTooltipDelay()); - - delete (comboBoxData->entryData); - comboBoxData->entryData = (EntryData *)comboBoxData->editBox->winGetUserData(); - // ---------------------------------------------------------------------- - // Create list box - // ---------------------------------------------------------------------- - winInstData.init(); - - winInstData.m_owner = comboBox; - if( BitIsSet( comboBox->winGetStyle(), GWS_MOUSE_TRACK ) ) - BitSet( winInstData.m_style, GWS_MOUSE_TRACK ); - BitSet( winInstData.m_style, WIN_STATUS_HIDDEN ); - winInstData.m_style |= GWS_SCROLL_LISTBOX; - status &= ~(WIN_STATUS_IMAGE); - comboBoxData->listBox = gogoGadgetListBox( comboBox, status | WIN_STATUS_ABOVE | WIN_STATUS_ONE_LINE, 0, height, - width, height, - &winInstData, comboBoxData->listboxData, - winInstData.m_font, FALSE ); - comboBoxData->listBox->winHide(TRUE); - delete(comboBoxData->listboxData); - comboBoxData->listboxData = (ListboxData *)comboBoxData->listBox->winGetUserData(); - - comboBoxData->listBox->winSetTooltipFunc(comboBox->winGetTooltipFunc()); - comboBoxData->listBox->winSetTooltip(instData->getTooltipText()); - comboBoxData->listBox->setTooltipDelay(comboBox->getTooltipDelay()); - GadgetListBoxSetAudioFeedback(comboBoxData->listBox, TRUE); - - // Initialize the ComboBox's variables and the controls with them - GadgetComboBoxSetIsEditable(comboBox, comboBoxData->isEditable); - GadgetComboBoxSetMaxChars( comboBox, comboBoxData->maxChars ); - GadgetComboBoxSetMaxDisplay( comboBox, comboBoxData->maxDisplay ); - - //Initialize the control's text colors - Color color, border; - - color = comboBox->winGetEnabledTextColor(); - border = comboBox->winGetEnabledTextBorderColor(); - if(comboBoxData->listBox) - comboBoxData->listBox->winSetEnabledTextColors( color,border); - if(comboBoxData->editBox) - comboBoxData->editBox->winSetEnabledTextColors(color,border); - - color = comboBox->winGetDisabledTextColor(); - border = comboBox->winGetDisabledTextBorderColor(); - if(comboBoxData->listBox) - comboBoxData->listBox->winSetDisabledTextColors( color,border); - if(comboBoxData->editBox) - comboBoxData->editBox->winSetDisabledTextColors(color,border); - - - color = comboBox->winGetHiliteTextColor(); - border = comboBox->winGetHiliteTextBorderColor(); - if(comboBoxData->listBox) - comboBoxData->listBox->winSetHiliteTextColors( color,border); - if(comboBoxData->editBox) - comboBoxData->editBox->winSetHiliteTextColors(color,border); - - comboBoxData->dontHide = FALSE; - - // assign the default images/colors - assignDefaultGadgetLook( comboBox, defaultFont, defaultVisual ); - - return comboBox; - -} - -//------------------------------------------------------------------------------------------------- -/** Create a progress bar GUI element */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetProgressBar( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *progressBar; - - // we MUST have a push button style window to do this - if( BitIsSet( instData->getStyle(), GWS_PROGRESS_BAR ) == FALSE ) - { - - DEBUG_LOG(( "Can't create progressBar gadget, instance data not progressBar type" )); - assert( 0 ); - return nullptr; - - } - - // create the button window - progressBar = winCreate( parent, status, - x, y, width, height, - GadgetProgressBarSystem, - instData ); - if( progressBar == nullptr ) - { - - DEBUG_LOG(( "Unable to create progress bar control" )); - assert( 0 ); - return nullptr; - - } - - // - // assign draw function, the draw functions must actually be implemented - // on the device level of the engine - // - if( BitIsSet( progressBar->winGetStatus(), WIN_STATUS_IMAGE ) ) - progressBar->winSetDrawFunc( getProgressBarImageDrawFunc() ); - else - progressBar->winSetDrawFunc( getProgressBarDrawFunc() ); - - // set the owner to the parent, or if no parent it will be itself - progressBar->winSetOwner( parent ); - - // assign the default images/colors - assignDefaultGadgetLook( progressBar, defaultFont, defaultVisual ); - - return progressBar; - -} - -//------------------------------------------------------------------------------------------------- -/** Does all generic window creation, calls appropriate text field create - * function to set up specific data */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetStaticText( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - TextData *textData, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *textWin; - TextData *data; - - // Static Text can not be a Tab Stop - BitClear( instData->m_style, GWS_TAB_STOP ); - - if( BitIsSet( instData->getStyle(), GWS_STATIC_TEXT ) ) - { - textWin = winCreate( parent, status, x, y, width, height, - GadgetStaticTextSystem, instData ); - } - else - { - DEBUG_LOG(( "gogoGadgetText warning: unrecognized text style." )); - return nullptr; - } - - if( textWin != nullptr ) - { - - // set the owner to the parent, or if no parent it will be itself - textWin->winSetOwner( parent ); - - // assign callbacks - textWin->winSetInputFunc( GadgetStaticTextInput ); - if( BitIsSet( textWin->winGetStatus(), WIN_STATUS_IMAGE ) ) - textWin->winSetDrawFunc( getStaticTextImageDrawFunc() ); - else - textWin->winSetDrawFunc( getStaticTextDrawFunc() ); - - data = NEW TextData; - assert( textData != nullptr ); - memcpy( data, textData, sizeof(TextData) ); - - // allocate a display string for the tet - data->text = TheDisplayStringManager->newDisplayString(); - // set whether or not we center the wrapped text - data->text->setWordWrapCentered( BitIsSet( instData->getStatus(), WIN_STATUS_WRAP_CENTERED )); - // Add the entry field data struct to the window's class data - textWin->winSetUserData( data ); - - // assign the default images/colors - assignDefaultGadgetLook( textWin, defaultFont, defaultVisual ); - - // assign text from label - UnicodeString text = winTextLabelToText( instData->m_textLabelString ); - if( text.getLength() ) - GadgetStaticTextSetText( textWin, text ); - - } - - return textWin; - -} - -//------------------------------------------------------------------------------------------------- -/** Does all generic window creation, calls appropriate entry field create - * function to set up specific data */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::gogoGadgetTextEntry( GameWindow *parent, - UnsignedInt status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - EntryData *entryData, - GameFont *defaultFont, - Bool defaultVisual ) - -{ - GameWindow *entry; - EntryData *data; - - if( BitIsSet( instData->getStyle(), GWS_ENTRY_FIELD ) == FALSE ) - { - - DEBUG_LOG(( "Unable to create text entry, style not entry type" )); - assert( 0 ); - return nullptr; - - } - - // create the window - entry = winCreate( parent, status, x, y, width, height, - GadgetTextEntrySystem, instData ); - if( entry == nullptr ) - { - - DEBUG_LOG(( "Unable to create text entry window" )); - assert( 0 ); - return nullptr; - - } - - // set owner of this control - entry->winSetOwner( parent ); - - // assign callbacks - entry->winSetInputFunc( GadgetTextEntryInput ); - if( BitIsSet( entry->winGetStatus(), WIN_STATUS_IMAGE ) ) - entry->winSetDrawFunc( getTextEntryImageDrawFunc() ); - else - entry->winSetDrawFunc( getTextEntryDrawFunc() ); - - // zero entry data -// memset( entryData->text, 0, ENTRY_TEXT_LEN ); -// memset( entryData->constructText, 0, ENTRY_TEXT_LEN ); - - // initialize character positions, lengths etc - if( entryData->text ) - entryData->charPos = entryData->text->getTextLength(); - else - entryData->charPos = 0; - entryData->conCharPos = 0; - entryData->receivedUnichar = FALSE; - if( entryData->maxTextLen > ENTRY_TEXT_LEN ) - entryData->maxTextLen = ENTRY_TEXT_LEN; - - // allocate entry data - data = NEW EntryData; - - // copy over data control - memcpy( data, entryData, sizeof(EntryData) ); - - // allocate new text display string - data->text = TheDisplayStringManager->newDisplayString(); - data->sText = TheDisplayStringManager->newDisplayString(); - data->constructText = TheDisplayStringManager->newDisplayString(); - - // set the max for the text lengths -// data->text->allocateFixed( ENTRY_TEXT_LEN ); -// data->sText->allocateFixed( ENTRY_TEXT_LEN ); - - // do any real display string copies - if( entryData->text ) - data->text->setText( entryData->text->getText() ); - if( entryData->sText ) - data->sText->setText( entryData->sText->getText() ); - - // set data into window - entry->winSetUserData( data ); - - // asian languages get to have list box kanji character completion - data->constructList = nullptr; - if( OurLanguage == LANGUAGE_ID_KOREAN || - OurLanguage == LANGUAGE_ID_JAPANESE ) - { - // we need to create the construct listbox - WinInstanceData boxInstData; - ListboxData lData; - - // initialize instData - boxInstData.init(); - - // define display region - memset( &lData, 0, sizeof(ListboxData) ); - lData.listLength = 128; - lData.autoScroll = FALSE; - lData.scrollIfAtEnd = FALSE; - lData.autoPurge = TRUE; - lData.scrollBar = TRUE; - lData.multiSelect = FALSE; - lData.columns = 1; - lData.columnWidth = nullptr; - - boxInstData.m_style = GWS_SCROLL_LISTBOX | GWS_MOUSE_TRACK; - - data->constructList = gogoGadgetListBox( nullptr, - WIN_STATUS_ABOVE | - WIN_STATUS_HIDDEN | - WIN_STATUS_NO_FOCUS | - WIN_STATUS_ONE_LINE, - 0, height, - 110, 119, - &boxInstData, - &lData, - nullptr, - TRUE ); - - if( data->constructList == nullptr ) - { - - DEBUG_LOG(( "gogoGadgetEntry warning: Failed to create listbox." )); - assert( 0 ); - winDestroy( entry ); - return nullptr; - - } - - } - - // assign the default images/colors - assignDefaultGadgetLook( entry, defaultFont, defaultVisual ); - - // assign text from label - UnicodeString text = winTextLabelToText( instData->m_textLabelString ); - if( text.getLength() ) - GadgetTextEntrySetText( entry, text ); - - return entry; - -} - -//------------------------------------------------------------------------------------------------- -/** Use this method to assign the default images/colors to gadgets as - * they area created */ -//------------------------------------------------------------------------------------------------- -void GameWindowManager::assignDefaultGadgetLook( GameWindow *gadget, - GameFont *defaultFont, - Bool assignVisual ) -{ - UnsignedByte alpha = 255; - static Color red = winMakeColor( 255, 0, 0, alpha ); - static Color darkRed = winMakeColor( 128, 0, 0, alpha ); - static Color lightRed = winMakeColor( 255, 128, 128, alpha ); - static Color green = winMakeColor( 0, 255, 0, alpha ); - static Color darkGreen = winMakeColor( 0, 128, 0, alpha ); - static Color lightGreen = winMakeColor( 128, 255, 128, alpha ); - static Color blue = winMakeColor( 0, 0, 255, alpha ); - static Color darkBlue = winMakeColor( 0, 0, 128, alpha ); - static Color lightBlue = winMakeColor( 128, 128, 255, alpha ); - static Color purple = winMakeColor( 255, 0, 255, alpha ); - static Color darkPurple = winMakeColor( 128, 0, 128, alpha ); - static Color lightPurple= winMakeColor( 255, 128, 255, alpha ); - static Color yellow = winMakeColor( 255, 255, 0, alpha ); - static Color darkYellow = winMakeColor( 128, 128, 0, alpha ); - static Color lightYellow= winMakeColor( 255, 255, 128, alpha ); - static Color cyan = winMakeColor( 0, 255, 255, alpha ); - static Color darkCyan = winMakeColor( 64, 128, 128, alpha ); - static Color lightCyan = winMakeColor( 128, 255, 255, alpha ); - static Color gray = winMakeColor( 128, 128, 128, alpha ); - static Color darkGray = winMakeColor( 64, 64, 64, alpha ); - static Color lightGray = winMakeColor( 192, 192, 192, alpha ); - static Color black = winMakeColor( 0, 0, 0, alpha ); - static Color white = winMakeColor( 254, 254, 254, alpha ); - static Color enabledText = white; - static Color enabledTextBorder = darkGray; - static Color disabledText = darkGray; - static Color disabledTextBorder = black; - static Color hiliteText = lightBlue; - static Color hiliteTextBorder = blue; - static Color imeCompositeText = green; - static Color imeCompositeTextBorder = blue; - WinInstanceData *instData; - - // sanity - if( gadget == nullptr ) - return; - - // get instance data - instData = gadget->winGetInstanceData(); - - // set default font - if( defaultFont ) - gadget->winSetFont( defaultFont ); - else - { - if (TheGlobalLanguageData && TheGlobalLanguageData->m_defaultWindowFont.name.isNotEmpty()) - { gadget->winSetFont( winFindFont( - TheGlobalLanguageData->m_defaultWindowFont.name, - TheGlobalLanguageData->m_defaultWindowFont.size, - TheGlobalLanguageData->m_defaultWindowFont.bold) ); - } - else - gadget->winSetFont( winFindFont( "Times New Roman", 14, FALSE ) ); - } - - // if we don't want to assign default colors/images get out of here - if( assignVisual == FALSE ) - return; - - // create images for the correct gadget type - if( BitIsSet( instData->getStyle(), GWS_PUSH_BUTTON ) ) - { - - // enabled background - GadgetButtonSetEnabledImage( gadget, winFindImage( "PushButtonEnabled" ) ); - GadgetButtonSetEnabledColor( gadget, red ); - GadgetButtonSetEnabledBorderColor( gadget, lightRed ); - // enabled selected button - GadgetButtonSetEnabledSelectedImage( gadget, winFindImage( "PushButtonEnabledSelected" ) ); - GadgetButtonSetEnabledSelectedColor( gadget, yellow ); - GadgetButtonSetEnabledSelectedBorderColor( gadget, white ); - - // Disabled background - GadgetButtonSetDisabledImage( gadget, winFindImage( "PushButtonDisabled" ) ); - GadgetButtonSetDisabledColor( gadget, gray ); - GadgetButtonSetDisabledBorderColor( gadget, lightGray ); - // Disabled selected button - GadgetButtonSetDisabledSelectedImage( gadget, winFindImage( "PushButtonDisabledSelected" ) ); - GadgetButtonSetDisabledSelectedColor( gadget, lightGray ); - GadgetButtonSetDisabledSelectedBorderColor( gadget, gray ); - - // Hilite background - GadgetButtonSetHiliteImage( gadget, winFindImage( "PushButtonHilite" ) ); - GadgetButtonSetHiliteColor( gadget, green ); - GadgetButtonSetHiliteBorderColor( gadget, darkGreen ); - // Hilite selected button - GadgetButtonSetHiliteSelectedImage( gadget, winFindImage( "PushButtonHiliteSelected" ) ); - GadgetButtonSetHiliteSelectedColor( gadget, yellow ); - GadgetButtonSetHiliteSelectedBorderColor( gadget, white ); - - // set default text colors for the gadget - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - } - else if( BitIsSet( instData->getStyle(), GWS_CHECK_BOX ) ) - { - - // enabled background - GadgetCheckBoxSetEnabledImage( gadget, winFindImage( "CheckBoxEnabled" ) ); - GadgetCheckBoxSetEnabledColor( gadget, red ); - GadgetCheckBoxSetEnabledBorderColor( gadget, lightRed ); - // enabled CheckBox unselected - GadgetCheckBoxSetEnabledUncheckedBoxImage( gadget, winFindImage( "CheckBoxEnabledBoxUnselected" ) ); - GadgetCheckBoxSetEnabledUncheckedBoxColor( gadget, WIN_COLOR_UNDEFINED ); - GadgetCheckBoxSetEnabledUncheckedBoxBorderColor( gadget, lightBlue ); - // enabled CheckBox selected - GadgetCheckBoxSetEnabledCheckedBoxImage( gadget, winFindImage( "CheckBoxEnabledBoxSelected" ) ); - GadgetCheckBoxSetEnabledCheckedBoxColor( gadget, blue ); - GadgetCheckBoxSetEnabledCheckedBoxBorderColor( gadget, lightBlue ); - - // disabled background - GadgetCheckBoxSetDisabledImage( gadget, winFindImage( "CheckBoxDisabled" ) ); - GadgetCheckBoxSetDisabledColor( gadget, gray ); - GadgetCheckBoxSetDisabledBorderColor( gadget, lightGray ); - // Disabled CheckBox unselected - GadgetCheckBoxSetDisabledUncheckedBoxImage( gadget, winFindImage( "CheckBoxDisabledBoxUnselected" ) ); - GadgetCheckBoxSetDisabledUncheckedBoxColor( gadget, WIN_COLOR_UNDEFINED ); - GadgetCheckBoxSetDisabledUncheckedBoxBorderColor( gadget, lightGray ); - // Disabled CheckBox selected - GadgetCheckBoxSetDisabledCheckedBoxImage( gadget, winFindImage( "CheckBoxDisabledBoxSelected" ) ); - GadgetCheckBoxSetDisabledCheckedBoxColor( gadget, darkGray ); - GadgetCheckBoxSetDisabledCheckedBoxBorderColor( gadget, white ); - - // Hilite background - GadgetCheckBoxSetHiliteImage( gadget, winFindImage( "CheckBoxHilite" ) ); - GadgetCheckBoxSetHiliteColor( gadget, green ); - GadgetCheckBoxSetHiliteBorderColor( gadget, lightGreen ); - // Hilite CheckBox unselected - GadgetCheckBoxSetHiliteUncheckedBoxImage( gadget, winFindImage( "CheckBoxHiliteBoxUnselected" ) ); - GadgetCheckBoxSetHiliteUncheckedBoxColor( gadget, WIN_COLOR_UNDEFINED ); - GadgetCheckBoxSetHiliteUncheckedBoxBorderColor( gadget, lightBlue ); - // Hilite CheckBox selected - GadgetCheckBoxSetHiliteCheckedBoxImage( gadget, winFindImage( "CheckBoxHiliteBoxSelected" ) ); - GadgetCheckBoxSetHiliteCheckedBoxColor( gadget, yellow ); - GadgetCheckBoxSetHiliteCheckedBoxBorderColor( gadget, white ); - - // set default text colors for the gadget - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - } - else if( BitIsSet( instData->getStyle(), GWS_RADIO_BUTTON ) ) - { - - // enabled background - GadgetRadioSetEnabledImage( gadget, winFindImage( "RadioButtonEnabled" ) ); - GadgetRadioSetEnabledColor( gadget, red ); - GadgetRadioSetEnabledBorderColor( gadget, lightRed ); - // enabled radio unselected - GadgetRadioSetEnabledUncheckedBoxImage( gadget, winFindImage( "RadioButtonEnabledBoxUnselected" ) ); - GadgetRadioSetEnabledUncheckedBoxColor( gadget, darkRed ); - GadgetRadioSetEnabledUncheckedBoxBorderColor( gadget, black ); - // enabled radio selected - GadgetRadioSetEnabledCheckedBoxImage( gadget, winFindImage( "RadioButtonEnabledBoxSelected" ) ); - GadgetRadioSetEnabledCheckedBoxColor( gadget, blue ); - GadgetRadioSetEnabledCheckedBoxBorderColor( gadget, lightBlue ); - - // disabled background - GadgetRadioSetDisabledImage( gadget, winFindImage( "RadioButtonDisabled" ) ); - GadgetRadioSetDisabledColor( gadget, gray ); - GadgetRadioSetDisabledBorderColor( gadget, lightGray ); - // Disabled radio unselected - GadgetRadioSetDisabledUncheckedBoxImage( gadget, winFindImage( "RadioButtonDisabledBoxUnselected" ) ); - GadgetRadioSetDisabledUncheckedBoxColor( gadget, gray ); - GadgetRadioSetDisabledUncheckedBoxBorderColor( gadget, lightGray ); - // Disabled radio selected - GadgetRadioSetDisabledCheckedBoxImage( gadget, winFindImage( "RadioButtonDisabledBoxSelected" ) ); - GadgetRadioSetDisabledCheckedBoxColor( gadget, darkGray ); - GadgetRadioSetDisabledCheckedBoxBorderColor( gadget, white ); - - // Hilite background - GadgetRadioSetHiliteImage( gadget, winFindImage( "RadioButtonHilite" ) ); - GadgetRadioSetHiliteColor( gadget, green ); - GadgetRadioSetHiliteBorderColor( gadget, lightGreen ); - // Hilite radio unselected - GadgetRadioSetHiliteUncheckedBoxImage( gadget, winFindImage( "RadioButtonHiliteBoxUnselected" ) ); - GadgetRadioSetHiliteUncheckedBoxColor( gadget, darkGreen ); - GadgetRadioSetHiliteUncheckedBoxBorderColor( gadget, lightGreen ); - // Hilite radio selected - GadgetRadioSetHiliteCheckedBoxImage( gadget, winFindImage( "RadioButtonHiliteBoxSelected" ) ); - GadgetRadioSetHiliteCheckedBoxColor( gadget, yellow ); - GadgetRadioSetHiliteCheckedBoxBorderColor( gadget, white ); - - // set default text colors for the gadget - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - } - else if( BitIsSet( instData->getStyle(), GWS_HORZ_SLIDER ) ) - { - - // enabled - GadgetSliderSetEnabledImageLeft( gadget, winFindImage( "HSliderEnabledLeftEnd" ) ); - GadgetSliderSetEnabledImageRight( gadget, winFindImage( "HSliderEnabledRightEnd" ) ); - GadgetSliderSetEnabledImageCenter( gadget, winFindImage( "HSliderEnabledRepeatingCenter" ) ); - GadgetSliderSetEnabledImageSmallCenter( gadget, winFindImage( "HSliderEnabledSmallRepeatingCenter" ) ); - GadgetSliderSetEnabledColor( gadget, red ); - GadgetSliderSetEnabledBorderColor( gadget, lightRed ); - - // disabled - GadgetSliderSetDisabledImageLeft( gadget, winFindImage( "HSliderDisabledLeftEnd" ) ); - GadgetSliderSetDisabledImageRight( gadget, winFindImage( "HSliderDisabledRightEnd" ) ); - GadgetSliderSetDisabledImageCenter( gadget, winFindImage( "HSliderDisabledRepeatingCenter" ) ); - GadgetSliderSetDisabledImageSmallCenter( gadget, winFindImage( "HSliderDisabledSmallRepeatingCenter" ) ); - GadgetSliderSetDisabledColor( gadget, red ); - GadgetSliderSetDisabledBorderColor( gadget, lightRed ); - - // hilite - GadgetSliderSetHiliteImageLeft( gadget, winFindImage( "HSliderHiliteLeftEnd" ) ); - GadgetSliderSetHiliteImageRight( gadget, winFindImage( "HSliderHiliteRightEnd" ) ); - GadgetSliderSetHiliteImageCenter( gadget, winFindImage( "HSliderHiliteRepeatingCenter" ) ); - GadgetSliderSetHiliteImageSmallCenter( gadget, winFindImage( "HSliderHiliteSmallRepeatingCenter" ) ); - GadgetSliderSetHiliteColor( gadget, red ); - GadgetSliderSetHiliteBorderColor( gadget, lightRed ); - - // set default text colors for the gadget - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - // - // set the default colors and images for the slider thumb - // - // enabled - GadgetSliderSetEnabledThumbImage( gadget, winFindImage( "HSliderThumbEnabled" ) ); - GadgetSliderSetEnabledThumbColor( gadget, GadgetSliderGetEnabledColor( gadget ) ); - GadgetSliderSetEnabledThumbBorderColor( gadget, GadgetSliderGetEnabledBorderColor( gadget ) ); - GadgetSliderSetEnabledSelectedThumbImage( gadget, winFindImage( "HSliderThumbEnabled" ) ); - GadgetSliderSetEnabledSelectedThumbColor( gadget, GadgetSliderGetEnabledBorderColor( gadget ) ); - GadgetSliderSetEnabledSelectedThumbBorderColor( gadget, GadgetSliderGetEnabledColor( gadget ) ); - - // disabled - GadgetSliderSetDisabledThumbImage( gadget, winFindImage( "HSliderThumbDisabled" ) ); - GadgetSliderSetDisabledThumbColor( gadget, GadgetSliderGetDisabledColor( gadget ) ); - GadgetSliderSetDisabledThumbBorderColor( gadget, GadgetSliderGetDisabledBorderColor( gadget ) ); - GadgetSliderSetDisabledSelectedThumbImage( gadget, winFindImage( "HSliderThumbDisabled" ) ); - GadgetSliderSetDisabledSelectedThumbColor( gadget, GadgetSliderGetDisabledBorderColor( gadget ) ); - GadgetSliderSetDisabledSelectedThumbBorderColor( gadget, GadgetSliderGetDisabledColor( gadget ) ); - - // hilite - GadgetSliderSetHiliteThumbImage( gadget, winFindImage( "HSliderThumbHilite" ) ); - GadgetSliderSetHiliteThumbColor( gadget, GadgetSliderGetHiliteColor( gadget ) ); - GadgetSliderSetHiliteThumbBorderColor( gadget, GadgetSliderGetHiliteBorderColor( gadget ) ); - GadgetSliderSetHiliteSelectedThumbImage( gadget, winFindImage( "HSliderThumbHiliteSelected" ) ); - GadgetSliderSetHiliteSelectedThumbColor( gadget, GadgetSliderGetHiliteBorderColor( gadget ) ); - GadgetSliderSetHiliteSelectedThumbBorderColor( gadget, GadgetSliderGetHiliteColor( gadget ) ); - - - } - else if( BitIsSet( instData->getStyle(), GWS_VERT_SLIDER ) ) - { - // enabled - GadgetSliderSetEnabledImageTop( gadget, winFindImage( "VSliderEnabledTopEnd" ) ); - GadgetSliderSetEnabledImageBottom( gadget, winFindImage( "VSliderEnabledBottomEnd" ) ); - GadgetSliderSetEnabledImageCenter( gadget, winFindImage( "VSliderEnabledRepeatingCenter" ) ); - GadgetSliderSetEnabledImageSmallCenter( gadget, winFindImage( "VSliderEnabledSmallRepeatingCenter" ) ); - GadgetSliderSetEnabledColor( gadget, red ); - GadgetSliderSetEnabledBorderColor( gadget, lightRed ); - - // disabled - GadgetSliderSetDisabledImageTop( gadget, winFindImage( "VSliderDisabledTopEnd" ) ); - GadgetSliderSetDisabledImageBottom( gadget, winFindImage( "VSliderDisabledBottomEnd" ) ); - GadgetSliderSetDisabledImageCenter( gadget, winFindImage( "VSliderDisabledRepeatingCenter" ) ); - GadgetSliderSetDisabledImageSmallCenter( gadget, winFindImage( "VSliderDisabledSmallRepeatingCenter" ) ); - GadgetSliderSetDisabledColor( gadget, red ); - GadgetSliderSetDisabledBorderColor( gadget, lightRed ); - - // hilite - GadgetSliderSetHiliteImageTop( gadget, winFindImage( "VSliderHiliteTopEnd" ) ); - GadgetSliderSetHiliteImageBottom( gadget, winFindImage( "VSliderHiliteBottomEnd" ) ); - GadgetSliderSetHiliteImageCenter( gadget, winFindImage( "VSliderHiliteRepeatingCenter" ) ); - GadgetSliderSetHiliteImageSmallCenter( gadget, winFindImage( "VSliderHiliteSmallRepeatingCenter" ) ); - GadgetSliderSetHiliteColor( gadget, red ); - GadgetSliderSetHiliteBorderColor( gadget, lightRed ); - - // set default text colors for the gadget - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - // - // set the default colors and images for the slider thumb - // - // enabled - GadgetSliderSetEnabledThumbImage( gadget, winFindImage( "VSliderThumbEnabled" ) ); - GadgetSliderSetEnabledThumbColor( gadget, GadgetSliderGetEnabledColor( gadget ) ); - GadgetSliderSetEnabledThumbBorderColor( gadget, GadgetSliderGetEnabledBorderColor( gadget ) ); - GadgetSliderSetEnabledSelectedThumbImage( gadget, winFindImage( "VSliderThumbEnabled" ) ); - GadgetSliderSetEnabledSelectedThumbColor( gadget, GadgetSliderGetEnabledBorderColor( gadget ) ); - GadgetSliderSetEnabledSelectedThumbBorderColor( gadget, GadgetSliderGetEnabledColor( gadget ) ); - - // disabled - GadgetSliderSetDisabledThumbImage( gadget, winFindImage( "VSliderThumbDisabled" ) ); - GadgetSliderSetDisabledThumbColor( gadget, GadgetSliderGetDisabledColor( gadget ) ); - GadgetSliderSetDisabledThumbBorderColor( gadget, GadgetSliderGetDisabledBorderColor( gadget ) ); - GadgetSliderSetDisabledSelectedThumbImage( gadget, winFindImage( "VSliderThumbDisabled" ) ); - GadgetSliderSetDisabledSelectedThumbColor( gadget, GadgetSliderGetDisabledBorderColor( gadget ) ); - GadgetSliderSetDisabledSelectedThumbBorderColor( gadget, GadgetSliderGetDisabledColor( gadget ) ); - - // hilite - GadgetSliderSetHiliteThumbImage( gadget, winFindImage( "VSliderThumbHilite" ) ); - GadgetSliderSetHiliteThumbColor( gadget, GadgetSliderGetHiliteColor( gadget ) ); - GadgetSliderSetHiliteThumbBorderColor( gadget, GadgetSliderGetHiliteBorderColor( gadget ) ); - GadgetSliderSetHiliteSelectedThumbImage( gadget, winFindImage( "VSliderThumbHiliteSelected" ) ); - GadgetSliderSetHiliteSelectedThumbColor( gadget, GadgetSliderGetHiliteBorderColor( gadget ) ); - GadgetSliderSetHiliteSelectedThumbBorderColor( gadget, GadgetSliderGetHiliteColor( gadget ) ); - - } - else if( BitIsSet( instData->getStyle(), GWS_SCROLL_LISTBOX ) ) - { - ListboxData *listboxData = (ListboxData *)gadget->winGetUserData(); - - // set the colors - GadgetListBoxSetColors( gadget, - red, // enabled - lightRed, // enabled border - yellow, // enabled selected item - white, // enabled selected item border - gray, // disabled - lightGray, // disabled border - lightGray, // disabled selected item - white, // disabled selected item border - green, // hilite - darkGreen, // hilite border - white, // hilite selected item - darkGreen ); // hilite selected item border - - // now set the images - - // enabled - GadgetListBoxSetEnabledImage( gadget, winFindImage( "ListBoxEnabled" ) ); - GadgetListBoxSetEnabledSelectedItemImageLeft( gadget, winFindImage( "ListBoxEnabledSelectedItemLeftEnd" ) ); - GadgetListBoxSetEnabledSelectedItemImageRight( gadget, winFindImage( "ListBoxEnabledSelectedItemRightEnd" ) ); - GadgetListBoxSetEnabledSelectedItemImageCenter( gadget, winFindImage( "ListBoxEnabledSelectedItemRepeatingCenter" ) ); - GadgetListBoxSetEnabledSelectedItemImageSmallCenter( gadget, winFindImage( "ListBoxEnabledSelectedItemSmallRepeatingCenter" ) ); - - // disabled - GadgetListBoxSetDisabledImage( gadget, winFindImage( "ListBoxDisabled" ) ); - GadgetListBoxSetDisabledSelectedItemImageLeft( gadget, winFindImage( "ListBoxDisabledSelectedItemLeftEnd" ) ); - GadgetListBoxSetDisabledSelectedItemImageRight( gadget, winFindImage( "ListBoxDisabledSelectedItemRightEnd" ) ); - GadgetListBoxSetDisabledSelectedItemImageCenter( gadget, winFindImage( "ListBoxDisabledSelectedItemRepeatingCenter" ) ); - GadgetListBoxSetDisabledSelectedItemImageSmallCenter( gadget, winFindImage( "ListBoxDisabledSelectedItemSmallRepeatingCenter" ) ); - - - // hilited - GadgetListBoxSetHiliteImage( gadget, winFindImage( "ListBoxHilite" ) ); - GadgetListBoxSetHiliteSelectedItemImageLeft( gadget, winFindImage( "ListBoxHiliteSelectedItemLeftEnd" ) ); - GadgetListBoxSetHiliteSelectedItemImageRight( gadget, winFindImage( "ListBoxHiliteSelectedItemRightEnd" ) ); - GadgetListBoxSetHiliteSelectedItemImageCenter( gadget, winFindImage( "ListBoxHiliteSelectedItemRepeatingCenter" ) ); - GadgetListBoxSetHiliteSelectedItemImageSmallCenter( gadget, winFindImage( "ListBoxHiliteSelectedItemSmallRepeatingCenter" ) ); - - // assign default slider colors and images as part of the list box - GameWindow *slider = listboxData->slider; - if( slider ) - { - GameWindow *upButton = listboxData->upButton; - GameWindow *downButton = listboxData->downButton; - - // slider and slider thumb ---------------------------------------------- - - // enabled - GadgetSliderSetEnabledImageTop( slider, winFindImage( "VSliderLargeEnabledTopEnd" ) ); - GadgetSliderSetEnabledImageBottom( slider, winFindImage( "VSliderLargeEnabledBottomEnd" ) ); - GadgetSliderSetEnabledImageCenter( slider, winFindImage( "VSliderLargeEnabledRepeatingCenter" ) ); - GadgetSliderSetEnabledImageSmallCenter( slider, winFindImage( "VSliderLargeEnabledSmallRepeatingCenter" ) ); - GadgetSliderSetEnabledThumbImage( slider, winFindImage( "VSliderLargeThumbEnabled" ) ); - GadgetSliderSetEnabledSelectedThumbImage( slider, winFindImage( "VSliderLargeThumbEnabled" ) ); - - // disabled - GadgetSliderSetDisabledImageTop( slider, winFindImage( "VSliderLargeDisabledTopEnd" ) ); - GadgetSliderSetDisabledImageBottom( slider, winFindImage( "VSliderLargeDisabledBottomEnd" ) ); - GadgetSliderSetDisabledImageCenter( slider, winFindImage( "VSliderLargeDisabledRepeatingCenter" ) ); - GadgetSliderSetDisabledImageSmallCenter( slider, winFindImage( "VSliderLargeDisabledSmallRepeatingCenter" ) ); - GadgetSliderSetDisabledThumbImage( slider, winFindImage( "VSliderLargeThumbDisabled" ) ); - GadgetSliderSetDisabledSelectedThumbImage( slider, winFindImage( "VSliderLargeThumbDisabled" ) ); - - // hilite - GadgetSliderSetHiliteImageTop( slider, winFindImage( "VSliderLargeHiliteTopEnd" ) ); - GadgetSliderSetHiliteImageBottom( slider, winFindImage( "VSliderLargeHiliteBottomEnd" ) ); - GadgetSliderSetHiliteImageCenter( slider, winFindImage( "VSliderLargeHiliteRepeatingCenter" ) ); - GadgetSliderSetHiliteImageSmallCenter( slider, winFindImage( "VSliderLargeHiliteSmallRepeatingCenter" ) ); - GadgetSliderSetHiliteThumbImage( slider, winFindImage( "VSliderLargeThumbHilite" ) ); - GadgetSliderSetHiliteSelectedThumbImage( slider, winFindImage( "VSliderLargeThumbHilite" ) ); - - // up button ------------------------------------------------------------ - - // enabled - GadgetButtonSetEnabledImage( upButton, winFindImage( "VSliderLargeUpButtonEnabled" ) ); - GadgetButtonSetEnabledSelectedImage( upButton, winFindImage( "VSliderLargeUpButtonEnabled" ) ); - - // disabled - GadgetButtonSetDisabledImage( upButton, winFindImage( "VSliderLargeUpButtonDisabled" ) ); - GadgetButtonSetDisabledSelectedImage( upButton, winFindImage( "VSliderLargeUpButtonDisabled" ) ); - - // hilite - GadgetButtonSetHiliteImage( upButton, winFindImage( "VSliderLargeUpButtonHilite" ) ); - GadgetButtonSetHiliteSelectedImage( upButton, winFindImage( "VSliderLargeUpButtonHiliteSelected" ) ); - - // down button ---------------------------------------------------------- - - // enabled - GadgetButtonSetEnabledImage( downButton, winFindImage( "VSliderLargeDownButtonEnabled" ) ); - GadgetButtonSetEnabledSelectedImage( downButton, winFindImage( "VSliderLargeDownButtonEnabled" ) ); - - // disabled - GadgetButtonSetDisabledImage( downButton, winFindImage( "VSliderLargeDownButtonDisabled" ) ); - GadgetButtonSetDisabledSelectedImage( downButton, winFindImage( "VSliderLargeDownButtonDisabled" ) ); - - // hilite - GadgetButtonSetHiliteImage( downButton, winFindImage( "VSliderLargeDownButtonHilite" ) ); - GadgetButtonSetHiliteSelectedImage( downButton, winFindImage( "VSliderLargeDownButtonHiliteSelected" ) ); - - } - - } - else if( BitIsSet( instData->getStyle(), GWS_COMBO_BOX ) ) - { -// ComboBoxData *comboBoxData = (ComboBoxData *)gadget->winGetUserData(); - - GadgetComboBoxSetColors( gadget, - red, // enabled - lightRed, // enabled border - yellow, // enabled selected item - white, // enabled selected item border - gray, // disabled - lightGray, // disabled border - lightGray, // disabled selected item - white, // disabled selected item border - green, // hilite - darkGreen, // hilite border - white, // hilite selected item - darkGreen ); // hilite selected item border - - // enabled - GadgetComboBoxSetEnabledImage( gadget, winFindImage( "ListBoxEnabled" ) ); - GadgetComboBoxSetEnabledSelectedItemImageLeft( gadget, winFindImage( "ListBoxEnabledSelectedItemLeftEnd" ) ); - GadgetComboBoxSetEnabledSelectedItemImageRight( gadget, winFindImage( "ListBoxEnabledSelectedItemRightEnd" ) ); - GadgetComboBoxSetEnabledSelectedItemImageCenter( gadget, winFindImage( "ListBoxEnabledSelectedItemRepeatingCenter" ) ); - GadgetComboBoxSetEnabledSelectedItemImageSmallCenter( gadget, winFindImage( "ListBoxEnabledSelectedItemSmallRepeatingCenter" ) ); - - // disabled - GadgetComboBoxSetDisabledImage( gadget, winFindImage( "ListBoxDisabled" ) ); - GadgetComboBoxSetDisabledSelectedItemImageLeft( gadget, winFindImage( "ListBoxDisabledSelectedItemLeftEnd" ) ); - GadgetComboBoxSetDisabledSelectedItemImageRight( gadget, winFindImage( "ListBoxDisabledSelectedItemRightEnd" ) ); - GadgetComboBoxSetDisabledSelectedItemImageCenter( gadget, winFindImage( "ListBoxDisabledSelectedItemRepeatingCenter" ) ); - GadgetComboBoxSetDisabledSelectedItemImageSmallCenter( gadget, winFindImage( "ListBoxDisabledSelectedItemSmallRepeatingCenter" ) ); - - - // hilited - GadgetComboBoxSetHiliteImage( gadget, winFindImage( "ListBoxHilite" ) ); - GadgetComboBoxSetHiliteSelectedItemImageLeft( gadget, winFindImage( "ListBoxHiliteSelectedItemLeftEnd" ) ); - GadgetComboBoxSetHiliteSelectedItemImageRight( gadget, winFindImage( "ListBoxHiliteSelectedItemRightEnd" ) ); - GadgetComboBoxSetHiliteSelectedItemImageCenter( gadget, winFindImage( "ListBoxHiliteSelectedItemRepeatingCenter" ) ); - GadgetComboBoxSetHiliteSelectedItemImageSmallCenter( gadget, winFindImage( "ListBoxHiliteSelectedItemSmallRepeatingCenter" ) ); - - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - GameWindow *dropDownButton = GadgetComboBoxGetDropDownButton( gadget ); - if ( dropDownButton ) - { - // enabled background - GadgetButtonSetEnabledImage( dropDownButton, winFindImage( "PushButtonEnabled" ) ); - // enabled selected button - GadgetButtonSetEnabledSelectedImage( dropDownButton, winFindImage( "PushButtonEnabledSelected" ) ); - - // Disabled background - GadgetButtonSetDisabledImage( dropDownButton, winFindImage( "PushButtonDisabled" ) ); - // Disabled selected button - GadgetButtonSetDisabledSelectedImage( dropDownButton, winFindImage( "PushButtonDisabledSelected" ) ); - - // Hilite background - GadgetButtonSetHiliteImage( dropDownButton, winFindImage( "PushButtonHilite" ) ); - // Hilite selected button - GadgetButtonSetHiliteSelectedImage( dropDownButton, winFindImage( "PushButtonHiliteSelected" ) ); - - } - - GameWindow *editBox = GadgetComboBoxGetEditBox( gadget ); - if ( editBox ) - { - // enabled - GadgetTextEntrySetEnabledImageLeft( editBox, winFindImage( "TextEntryEnabledLeftEnd" ) ); - GadgetTextEntrySetEnabledImageRight( editBox, winFindImage( "TextEntryEnabledRightEnd" ) ); - GadgetTextEntrySetEnabledImageCenter( editBox, winFindImage( "TextEntryEnabledRepeatingCenter" ) ); - GadgetTextEntrySetEnabledImageSmallCenter( editBox, winFindImage( "TextEntryEnabledSmallRepeatingCenter" ) ); - - // disabled - GadgetTextEntrySetDisabledImageLeft( editBox, winFindImage( "TextEntryDisabledLeftEnd" ) ); - GadgetTextEntrySetDisabledImageRight( editBox, winFindImage( "TextEntryDisabledRightEnd" ) ); - GadgetTextEntrySetDisabledImageCenter( editBox, winFindImage( "TextEntryDisabledRepeatingCenter" ) ); - GadgetTextEntrySetDisabledImageSmallCenter( editBox, winFindImage( "TextEntryDisabledSmallRepeatingCenter" ) ); - - // hilited - GadgetTextEntrySetHiliteImageLeft( editBox, winFindImage( "TextEntryHiliteLeftEnd" ) ); - GadgetTextEntrySetHiliteImageRight( editBox, winFindImage( "TextEntryHiliteRightEnd" ) ); - GadgetTextEntrySetHiliteImageCenter( editBox, winFindImage( "TextEntryHiliteRepeatingCenter" ) ); - GadgetTextEntrySetHiliteImageSmallCenter( editBox, winFindImage( "TextEntryHiliteSmallRepeatingCenter" ) ); - - } - - GameWindow * listBox = GadgetComboBoxGetListBox( gadget ); - if ( listBox ) - { - - // now set the images - - // enabled - GadgetListBoxSetEnabledImage( listBox, winFindImage( "ListBoxEnabled" ) ); - GadgetListBoxSetEnabledSelectedItemImageLeft( listBox, winFindImage( "ListBoxEnabledSelectedItemLeftEnd" ) ); - GadgetListBoxSetEnabledSelectedItemImageRight( listBox, winFindImage( "ListBoxEnabledSelectedItemRightEnd" ) ); - GadgetListBoxSetEnabledSelectedItemImageCenter( listBox, winFindImage( "ListBoxEnabledSelectedItemRepeatingCenter" ) ); - GadgetListBoxSetEnabledSelectedItemImageSmallCenter( listBox, winFindImage( "ListBoxEnabledSelectedItemSmallRepeatingCenter" ) ); - - // disabled - GadgetListBoxSetDisabledImage( listBox, winFindImage( "ListBoxDisabled" ) ); - GadgetListBoxSetDisabledSelectedItemImageLeft( listBox, winFindImage( "ListBoxDisabledSelectedItemLeftEnd" ) ); - GadgetListBoxSetDisabledSelectedItemImageRight( listBox, winFindImage( "ListBoxDisabledSelectedItemRightEnd" ) ); - GadgetListBoxSetDisabledSelectedItemImageCenter( listBox, winFindImage( "ListBoxDisabledSelectedItemRepeatingCenter" ) ); - GadgetListBoxSetDisabledSelectedItemImageSmallCenter( listBox, winFindImage( "ListBoxDisabledSelectedItemSmallRepeatingCenter" ) ); - - - // hilited - GadgetListBoxSetHiliteImage( listBox, winFindImage( "ListBoxHilite" ) ); - GadgetListBoxSetHiliteSelectedItemImageLeft( listBox, winFindImage( "ListBoxHiliteSelectedItemLeftEnd" ) ); - GadgetListBoxSetHiliteSelectedItemImageRight( listBox, winFindImage( "ListBoxHiliteSelectedItemRightEnd" ) ); - GadgetListBoxSetHiliteSelectedItemImageCenter( listBox, winFindImage( "ListBoxHiliteSelectedItemRepeatingCenter" ) ); - GadgetListBoxSetHiliteSelectedItemImageSmallCenter( listBox, winFindImage( "ListBoxHiliteSelectedItemSmallRepeatingCenter" ) ); - - // assign default slider colors and images as part of the list box - GameWindow *slider = GadgetListBoxGetSlider( listBox ); - if( slider ) - { - GameWindow *upButton = GadgetListBoxGetUpButton( listBox ); - GameWindow *downButton = GadgetListBoxGetDownButton( listBox ); - - // slider and slider thumb ---------------------------------------------- - - // enabled - GadgetSliderSetEnabledImageTop( slider, winFindImage( "VSliderLargeEnabledTopEnd" ) ); - GadgetSliderSetEnabledImageBottom( slider, winFindImage( "VSliderLargeEnabledBottomEnd" ) ); - GadgetSliderSetEnabledImageCenter( slider, winFindImage( "VSliderLargeEnabledRepeatingCenter" ) ); - GadgetSliderSetEnabledImageSmallCenter( slider, winFindImage( "VSliderLargeEnabledSmallRepeatingCenter" ) ); - GadgetSliderSetEnabledThumbImage( slider, winFindImage( "VSliderLargeThumbEnabled" ) ); - GadgetSliderSetEnabledSelectedThumbImage( slider, winFindImage( "VSliderLargeThumbEnabled" ) ); - - // disabled - GadgetSliderSetDisabledImageTop( slider, winFindImage( "VSliderLargeDisabledTopEnd" ) ); - GadgetSliderSetDisabledImageBottom( slider, winFindImage( "VSliderLargeDisabledBottomEnd" ) ); - GadgetSliderSetDisabledImageCenter( slider, winFindImage( "VSliderLargeDisabledRepeatingCenter" ) ); - GadgetSliderSetDisabledImageSmallCenter( slider, winFindImage( "VSliderLargeDisabledSmallRepeatingCenter" ) ); - GadgetSliderSetDisabledThumbImage( slider, winFindImage( "VSliderLargeThumbDisabled" ) ); - GadgetSliderSetDisabledSelectedThumbImage( slider, winFindImage( "VSliderLargeThumbDisabled" ) ); - - // hilite - GadgetSliderSetHiliteImageTop( slider, winFindImage( "VSliderLargeHiliteTopEnd" ) ); - GadgetSliderSetHiliteImageBottom( slider, winFindImage( "VSliderLargeHiliteBottomEnd" ) ); - GadgetSliderSetHiliteImageCenter( slider, winFindImage( "VSliderLargeHiliteRepeatingCenter" ) ); - GadgetSliderSetHiliteImageSmallCenter( slider, winFindImage( "VSliderLargeHiliteSmallRepeatingCenter" ) ); - GadgetSliderSetHiliteThumbImage( slider, winFindImage( "VSliderLargeThumbHilite" ) ); - GadgetSliderSetHiliteSelectedThumbImage( slider, winFindImage( "VSliderLargeThumbHilite" ) ); - - // up button ------------------------------------------------------------ - - // enabled - GadgetButtonSetEnabledImage( upButton, winFindImage( "VSliderLargeUpButtonEnabled" ) ); - GadgetButtonSetEnabledSelectedImage( upButton, winFindImage( "VSliderLargeUpButtonEnabled" ) ); - - // disabled - GadgetButtonSetDisabledImage( upButton, winFindImage( "VSliderLargeUpButtonDisabled" ) ); - GadgetButtonSetDisabledSelectedImage( upButton, winFindImage( "VSliderLargeUpButtonDisabled" ) ); - - // hilite - GadgetButtonSetHiliteImage( upButton, winFindImage( "VSliderLargeUpButtonHilite" ) ); - GadgetButtonSetHiliteSelectedImage( upButton, winFindImage( "VSliderLargeUpButtonHiliteSelected" ) ); - - // down button ---------------------------------------------------------- - - // enabled - GadgetButtonSetEnabledImage( downButton, winFindImage( "VSliderLargeDownButtonEnabled" ) ); - GadgetButtonSetEnabledSelectedImage( downButton, winFindImage( "VSliderLargeDownButtonEnabled" ) ); - - // disabled - GadgetButtonSetDisabledImage( downButton, winFindImage( "VSliderLargeDownButtonDisabled" ) ); - GadgetButtonSetDisabledSelectedImage( downButton, winFindImage( "VSliderLargeDownButtonDisabled" ) ); - - // hilite - GadgetButtonSetHiliteImage( downButton, winFindImage( "VSliderLargeDownButtonHilite" ) ); - GadgetButtonSetHiliteSelectedImage( downButton, winFindImage( "VSliderLargeDownButtonHiliteSelected" ) ); - - } - } - } - else if( BitIsSet( instData->getStyle(), GWS_PROGRESS_BAR ) ) - { - - // enabled - GadgetProgressBarSetEnabledColor( gadget, red ); - GadgetProgressBarSetEnabledBorderColor( gadget, lightRed ); - GadgetProgressBarSetEnabledImageLeft( gadget, winFindImage( "ProgressBarEnabledLeftEnd" ) ); - GadgetProgressBarSetEnabledImageRight( gadget, winFindImage( "ProgressBarEnabledRightEnd" ) ); - GadgetProgressBarSetEnabledImageCenter( gadget, winFindImage( "ProgressBarEnabledRepeatingCenter" ) ); - GadgetProgressBarSetEnabledImageSmallCenter( gadget, winFindImage( "ProgressBarEnabledSmallRepeatingCenter" ) ); - GadgetProgressBarSetEnabledBarColor( gadget, yellow ); - GadgetProgressBarSetEnabledBarBorderColor( gadget, white ); - GadgetProgressBarSetEnabledBarImageLeft( gadget, winFindImage( "ProgressBarEnabledBarLeftEnd" ) ); - GadgetProgressBarSetEnabledBarImageRight( gadget, winFindImage( "ProgressBarEnabledBarRightEnd" ) ); - GadgetProgressBarSetEnabledBarImageCenter( gadget, winFindImage( "ProgressBarEnabledBarRepeatingCenter" ) ); - GadgetProgressBarSetEnabledBarImageSmallCenter( gadget, winFindImage( "ProgressBarEnabledBarSmallRepeatingCenter" ) ); - - // disabled - GadgetProgressBarSetDisabledColor( gadget, darkGray ); - GadgetProgressBarSetDisabledBorderColor( gadget, lightGray ); - GadgetProgressBarSetDisabledImageLeft( gadget, winFindImage( "ProgressBarDisabledLeftEnd" ) ); - GadgetProgressBarSetDisabledImageRight( gadget, winFindImage( "ProgressBarDisabledRightEnd" ) ); - GadgetProgressBarSetDisabledImageCenter( gadget, winFindImage( "ProgressBarDisabledRepeatingCenter" ) ); - GadgetProgressBarSetDisabledImageSmallCenter( gadget, winFindImage( "ProgressBarDisabledSmallRepeatingCenter" ) ); - GadgetProgressBarSetDisabledBarColor( gadget, lightGray ); - GadgetProgressBarSetDisabledBarBorderColor( gadget, white ); - GadgetProgressBarSetDisabledBarImageLeft( gadget, winFindImage( "ProgressBarDisabledBarLeftEnd" ) ); - GadgetProgressBarSetDisabledBarImageRight( gadget, winFindImage( "ProgressBarDisabledBarRightEnd" ) ); - GadgetProgressBarSetDisabledBarImageCenter( gadget, winFindImage( "ProgressBarDisabledBarRepeatingCenter" ) ); - GadgetProgressBarSetDisabledBarImageSmallCenter( gadget, winFindImage( "ProgressBarDisabledBarSmallRepeatingCenter" ) ); - - // Hilite - GadgetProgressBarSetHiliteColor( gadget, green ); - GadgetProgressBarSetHiliteBorderColor( gadget, darkGreen ); - GadgetProgressBarSetHiliteImageLeft( gadget, winFindImage( "ProgressBarHiliteLeftEnd" ) ); - GadgetProgressBarSetHiliteImageRight( gadget, winFindImage( "ProgressBarHiliteRightEnd" ) ); - GadgetProgressBarSetHiliteImageCenter( gadget, winFindImage( "ProgressBarHiliteRepeatingCenter" ) ); - GadgetProgressBarSetHiliteImageSmallCenter( gadget, winFindImage( "ProgressBarHiliteSmallRepeatingCenter" ) ); - GadgetProgressBarSetHiliteBarColor( gadget, yellow ); - GadgetProgressBarSetHiliteBarBorderColor( gadget, white ); - GadgetProgressBarSetHiliteBarImageLeft( gadget, winFindImage( "ProgressBarHiliteBarLeftEnd" ) ); - GadgetProgressBarSetHiliteBarImageRight( gadget, winFindImage( "ProgressBarHiliteBarRightEnd" ) ); - GadgetProgressBarSetHiliteBarImageCenter( gadget, winFindImage( "ProgressBarHiliteBarRepeatingCenter" ) ); - GadgetProgressBarSetHiliteBarImageSmallCenter( gadget, winFindImage( "ProgressBarHiliteBarSmallRepeatingCenter" ) ); - - } - else if( BitIsSet( instData->getStyle(), GWS_STATIC_TEXT ) ) - { - - // enabled - GadgetStaticTextSetEnabledImage( gadget, winFindImage( "StaticTextEnabled" ) ); - GadgetStaticTextSetEnabledColor( gadget, red ); - GadgetStaticTextSetEnabledBorderColor( gadget, lightRed ); - - // disabled - GadgetStaticTextSetDisabledImage( gadget, winFindImage( "StaticTextDisabled" ) ); - GadgetStaticTextSetDisabledColor( gadget, darkGray ); - GadgetStaticTextSetDisabledBorderColor( gadget, lightGray ); - - // hilite - GadgetStaticTextSetHiliteImage( gadget, winFindImage( "StaticTextHilite" ) ); - GadgetStaticTextSetHiliteColor( gadget, darkGreen ); - GadgetStaticTextSetHiliteBorderColor( gadget, lightGreen ); - - // set default text colors for the gadget - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - } - else if( BitIsSet( instData->getStyle(), GWS_ENTRY_FIELD ) ) - { - - // enabled - GadgetTextEntrySetEnabledImageLeft( gadget, winFindImage( "TextEntryEnabledLeftEnd" ) ); - GadgetTextEntrySetEnabledImageRight( gadget, winFindImage( "TextEntryEnabledRightEnd" ) ); - GadgetTextEntrySetEnabledImageCenter( gadget, winFindImage( "TextEntryEnabledRepeatingCenter" ) ); - GadgetTextEntrySetEnabledImageSmallCenter( gadget, winFindImage( "TextEntryEnabledSmallRepeatingCenter" ) ); - GadgetTextEntrySetEnabledColor( gadget, red ); - GadgetTextEntrySetEnabledBorderColor( gadget, lightRed ); - - // disabled - GadgetTextEntrySetDisabledImageLeft( gadget, winFindImage( "TextEntryDisabledLeftEnd" ) ); - GadgetTextEntrySetDisabledImageRight( gadget, winFindImage( "TextEntryDisabledRightEnd" ) ); - GadgetTextEntrySetDisabledImageCenter( gadget, winFindImage( "TextEntryDisabledRepeatingCenter" ) ); - GadgetTextEntrySetDisabledImageSmallCenter( gadget, winFindImage( "TextEntryDisabledSmallRepeatingCenter" ) ); - GadgetTextEntrySetDisabledColor( gadget, gray ); - GadgetTextEntrySetDisabledBorderColor( gadget, black ); - - // hilited - GadgetTextEntrySetHiliteImageLeft( gadget, winFindImage( "TextEntryHiliteLeftEnd" ) ); - GadgetTextEntrySetHiliteImageRight( gadget, winFindImage( "TextEntryHiliteRightEnd" ) ); - GadgetTextEntrySetHiliteImageCenter( gadget, winFindImage( "TextEntryHiliteRepeatingCenter" ) ); - GadgetTextEntrySetHiliteImageSmallCenter( gadget, winFindImage( "TextEntryHiliteSmallRepeatingCenter" ) ); - GadgetTextEntrySetHiliteColor( gadget, green ); - GadgetTextEntrySetHiliteBorderColor( gadget, darkGreen ); - - // set default text colors for the gadget - gadget->winSetEnabledTextColors( enabledText, enabledTextBorder ); - gadget->winSetDisabledTextColors( disabledText, disabledTextBorder ); - gadget->winSetHiliteTextColors( hiliteText, hiliteTextBorder ); - gadget->winSetIMECompositeTextColors( imeCompositeText, imeCompositeTextBorder ); - - } - -} - -//------------------------------------------------------------------------------------------------- -/** Given a text label, retreive the real localized text associated - * with that label */ -//------------------------------------------------------------------------------------------------- -UnicodeString GameWindowManager::winTextLabelToText( AsciiString label ) -{ - - // sanity - if( label.isEmpty() ) - return UnicodeString::TheEmptyString; - - /// @todo we need to write the string manager here, this is TEMPORARY!!! - UnicodeString tmp; - tmp.translate(label); - return tmp; - -} - -//------------------------------------------------------------------------------------------------- -/** find the top window at the given coordinates */ -//------------------------------------------------------------------------------------------------- -GameWindow *GameWindowManager::getWindowUnderCursor( Int x, Int y, Bool ignoreEnabled ) -{ - if( m_mouseCaptor ) - { - // in what what window within the captured window are we? - return m_mouseCaptor->winPointInChild( x, y, ignoreEnabled ); - } - - if( m_grabWindow ) - { - // in what what window within the grabbed window are we? - return m_grabWindow->winPointInChild( x, y, ignoreEnabled ); - } - - GameWindow *window = nullptr; - if( m_modalHead && m_modalHead->window ) - { - return m_modalHead->window->winPointInChild( x, y, ignoreEnabled ); - } - else - { - // search for top-level window which contains pointer - for( window = m_windowList; window; window = window->m_next ) - { - - if( BitIsSet( window->m_status, WIN_STATUS_ABOVE ) && - !BitIsSet( window->m_status, WIN_STATUS_HIDDEN ) && - x >= window->m_region.lo.x && - x <= window->m_region.hi.x && - y >= window->m_region.lo.y && - y <= window->m_region.hi.y) - { - if( BitIsSet( window->m_status, WIN_STATUS_ENABLED ) || ignoreEnabled ) - { - // determine which child window the mouse is in - window = window->winPointInChild( x, y, ignoreEnabled ); - break; // exit for - } - } - } - - // check !above, below and hidden - if( window == nullptr ) - { - for( window = m_windowList; window; window = window->m_next ) - { - if( !BitIsSet( window->m_status, WIN_STATUS_ABOVE | - WIN_STATUS_BELOW | - WIN_STATUS_HIDDEN ) && - x >= window->m_region.lo.x && - x <= window->m_region.hi.x && - y >= window->m_region.lo.y && - y <= window->m_region.hi.y) - { - if( BitIsSet( window->m_status, WIN_STATUS_ENABLED )|| ignoreEnabled) - { - // determine which child window the mouse is in - window = window->winPointInChild( x, y, ignoreEnabled ); - break; // exit for - } - } - } - } - - // check below and !hidden - if( window == nullptr ) - { - for( window = m_windowList; window; window = window->m_next ) - { - if( BitIsSet( window->m_status, WIN_STATUS_BELOW ) && - !BitIsSet( window->m_status, WIN_STATUS_HIDDEN ) && - x >= window->m_region.lo.x && - x <= window->m_region.hi.x && - y >= window->m_region.lo.y && - y <= window->m_region.hi.y) - { - if( BitIsSet( window->m_status, WIN_STATUS_ENABLED )|| ignoreEnabled) - { - // determine which child window the mouse is in - window = window->winPointInChild( x, y, ignoreEnabled ); - break; // exit for - } - } - } - } - } - - if( window ) - { - if( BitIsSet( window->m_status, WIN_STATUS_NO_INPUT )) - { - // this window does not accept input, discard - window = nullptr; - } - else if( ignoreEnabled && !( BitIsSet( window->m_status, WIN_STATUS_ENABLED ) )) - { - window = nullptr; - } - } - - return window; -} - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -//------------------------------------------------------------------------------------------------- -//------------------------------------------------------------------------------------------------- -static WindowMsgHandledType testGrab( GameWindow *window, UnsignedInt msg, - WindowMsgData mData1, WindowMsgData mData2 ) -{ - - switch( msg ) - { - - case GWM_LEFT_DOWN: return MSG_HANDLED; // use it - - } - - return MSG_IGNORED; - -} - -//------------------------------------------------------------------------------------------------- -/** Just for testing */ -//------------------------------------------------------------------------------------------------- -Bool GameWindowManager::initTestGUI() -{ - -// winCreateFromScript( "_ATest.wnd" ); - return TRUE; - -// UnsignedByte alpha = 200; - GameWindow *window; - UnsignedInt statusFlags = WIN_STATUS_ENABLED | WIN_STATUS_DRAGGABLE | WIN_STATUS_IMAGE; - WinInstanceData instData; - - // make some windows inside each other in the upper left - window = winCreate( nullptr, statusFlags, 0, 0, 100, 100, nullptr, nullptr ); - window->winSetInputFunc( testGrab ); - window->winSetEnabledColor( 0, winMakeColor( 255, 254, 255, 255 ) ); - window->winSetEnabledBorderColor( 0 , winMakeColor( 0, 0, 0, 255 ) ); - window = winCreate( window, statusFlags, 10, 10, 50, 50, nullptr, nullptr ); - window->winSetInputFunc( testGrab ); - window->winSetEnabledColor( 0, winMakeColor( 128, 128, 128, 255 ) ); - window->winSetEnabledBorderColor( 0 , winMakeColor( 0, 0, 0, 255 ) ); - - // make a push button - instData.init(); - BitSet( instData.m_style, GWS_PUSH_BUTTON | GWS_MOUSE_TRACK ); - instData.m_textLabelString = "What Up?"; - window = gogoGadgetPushButton( nullptr, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 200, 100, - 100, 30, - &instData, nullptr, TRUE ); - - // make a push button - instData.init(); - BitSet( instData.m_style, GWS_PUSH_BUTTON | GWS_MOUSE_TRACK ); - instData.m_textLabelString = "Enabled"; - window = gogoGadgetPushButton( nullptr, - WIN_STATUS_ENABLED, - 330, 100, - 100, 30, - &instData, nullptr, TRUE ); - - // make a push button - instData.init(); - BitSet( instData.m_style, GWS_PUSH_BUTTON | GWS_MOUSE_TRACK ); - instData.m_textLabelString = "Disabled"; - window = gogoGadgetPushButton( nullptr, - 0, - 450, 100, - 100, 30, - &instData, nullptr, TRUE ); - - // make a check box - instData.init(); - instData.m_style = GWS_CHECK_BOX | GWS_MOUSE_TRACK; - instData.m_textLabelString = "Check"; - window = gogoGadgetCheckbox( nullptr, - WIN_STATUS_ENABLED | - WIN_STATUS_IMAGE, - 200, 150, - 100, 30, - &instData, nullptr, TRUE ); - - // make a check box - instData.init(); - instData.m_style = GWS_CHECK_BOX | GWS_MOUSE_TRACK; - instData.m_textLabelString = "Check"; - window = gogoGadgetCheckbox( nullptr, - WIN_STATUS_ENABLED, - 330, 150, - 100, 30, - &instData, nullptr, TRUE ); - - // make window to hold radio buttons - window = winCreate( nullptr, WIN_STATUS_ENABLED | WIN_STATUS_DRAGGABLE, - 200, 200, 250, 45, nullptr ); - window->winSetInputFunc( testGrab ); - window->winSetEnabledColor( 0, winMakeColor( 50, 50, 50, 200 ) ); - window->winSetEnabledBorderColor( 0, winMakeColor( 254, 254, 254, 255 ) ); - - // make a radio button - GameWindow *radio; - RadioButtonData rData; - instData.init(); - instData.m_style = GWS_RADIO_BUTTON | GWS_MOUSE_TRACK; - instData.m_textLabelString = "Mama Said!"; - rData.group = 1; - radio = gogoGadgetRadioButton( window, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 10, 10, - 100, 30, - &instData, - &rData, nullptr, TRUE ); - - // make a radio button - instData.init(); - instData.m_style = GWS_RADIO_BUTTON | GWS_MOUSE_TRACK; - instData.m_textLabelString = "On the Run"; - radio = gogoGadgetRadioButton( window, - WIN_STATUS_ENABLED, - 130, 10, - 100, 30, - &instData, - &rData, nullptr, TRUE ); - GadgetRadioSetEnabledColor( radio, GameMakeColor( 0, 0, 255, 255 ) ); - GadgetRadioSetEnabledBorderColor( radio, GameMakeColor( 0, 0, 255, 255 ) ); - - // make a listbox - ListboxData listData; - memset( &listData, 0, sizeof( ListboxData ) ); - listData.listLength = 8; - listData.autoScroll = 1; - listData.scrollIfAtEnd = FALSE; - listData.autoPurge = 1; - listData.scrollBar = 1; - listData.multiSelect = 1; - listData.forceSelect = 0; - listData.columns = 1; - listData.columnWidth = nullptr; - instData.init(); - instData.m_style = GWS_SCROLL_LISTBOX | GWS_MOUSE_TRACK; - window = gogoGadgetListBox( nullptr, - WIN_STATUS_ENABLED, - 200, 250, - 100, 100, - &instData, - &listData, nullptr, TRUE ); - GadgetListBoxAddEntryText( window, L"Listbox text", - winMakeColor( 255, 255, 255, 255 ), -1, 0 ); - GadgetListBoxAddEntryText( window, L"More text", - winMakeColor( 105, 105, 255, 255 ), -1, 0 ); - GadgetListBoxAddEntryText( window, L"Nothing", - winMakeColor( 105, 105, 255, 255 ), -1, 0 ); - GadgetListBoxAddEntryText( window, L"Seasons", - winMakeColor( 105, 205, 255, 255 ), -1, 0 ); - GadgetListBoxAddEntryText( window, L"Misery", - winMakeColor( 235, 105, 255, 255 ), -1, 0 ); - GadgetListBoxAddEntryText( window, L"Natural", - winMakeColor( 105, 205, 45, 255 ), -1, 0 ); - window->winSetFont( TheFontLibrary->getFont( "Times New Roman", 12, FALSE ) ); - - // make a listbox - memset( &listData, 0, sizeof( ListboxData ) ); - listData.listLength = 8; - listData.autoScroll = 1; - listData.scrollIfAtEnd = FALSE; - listData.autoPurge = 1; - listData.scrollBar = 1; - listData.multiSelect = 0; - listData.forceSelect = 0; - listData.columns = 1; - listData.columnWidth = nullptr; - instData.init(); - instData.m_style = GWS_SCROLL_LISTBOX | GWS_MOUSE_TRACK; - window = gogoGadgetListBox( nullptr, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 75, 250, - 100, 100, - &instData, - &listData, nullptr, TRUE ); - GadgetListBoxAddEntryText( window, L"Listbox text", - winMakeColor( 255, 255, 255, 255 ), -1, -1 ); - GadgetListBoxAddEntryText( window, L"More text", - winMakeColor( 105, 105, 255, 255 ), -1, -1 ); - GadgetListBoxAddEntryText( window, L"Nothing", - winMakeColor( 105, 105, 255, 255 ), -1, -1 ); - GadgetListBoxAddEntryText( window, L"Seasons", - winMakeColor( 105, 205, 255, 255 ), -1, -1 ); - GadgetListBoxAddEntryText( window, L"Misery", - winMakeColor( 235, 105, 255, 255 ), -1, -1 ); - GadgetListBoxAddEntryText( window, L"Natural", - winMakeColor( 105, 205, 45, 255 ), -1, -1 ); - - // make a vert slider - SliderData sliderData; - memset( &sliderData, 0, sizeof( sliderData ) ); - sliderData.maxVal = 100; - sliderData.minVal = 0; - sliderData.numTicks = 100; - sliderData.position = 0; - instData.init(); - instData.m_style = GWS_VERT_SLIDER | GWS_MOUSE_TRACK; - window = gogoGadgetSlider( nullptr, - WIN_STATUS_ENABLED, - 360, 250, - 11, 100, - &instData, - &sliderData, nullptr, TRUE ); - - // make a vert slider - memset( &sliderData, 0, sizeof( sliderData ) ); - sliderData.maxVal = 100; - sliderData.minVal = 0; - sliderData.numTicks = 100; - sliderData.position = 0; - instData.init(); - instData.m_style = GWS_VERT_SLIDER | GWS_MOUSE_TRACK; - window = gogoGadgetSlider( nullptr, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 400, 250, - 11, 100, - &instData, - &sliderData, nullptr, TRUE ); - - // make a horizontal slider - memset( &sliderData, 0, sizeof( sliderData ) ); - sliderData.maxVal = 100; - sliderData.minVal = 0; - sliderData.numTicks = 100; - sliderData.position = 0; - instData.init(); - instData.m_style = GWS_HORZ_SLIDER | GWS_MOUSE_TRACK; - window = gogoGadgetSlider( nullptr, - WIN_STATUS_ENABLED, - 200, 400, - 200, 11, - &instData, - &sliderData, nullptr, TRUE ); - - // make a horizontal slider - memset( &sliderData, 0, sizeof( sliderData ) ); - sliderData.maxVal = 100; - sliderData.minVal = 0; - sliderData.numTicks = 100; - sliderData.position = 0; - instData.init(); - instData.m_style = GWS_HORZ_SLIDER | GWS_MOUSE_TRACK; - window = gogoGadgetSlider( nullptr, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 200, 420, - 200, 11, - &instData, - &sliderData, nullptr, TRUE ); - - // make a progress bar - instData.init(); - instData.m_style = GWS_PROGRESS_BAR | GWS_MOUSE_TRACK; - window = gogoGadgetProgressBar( nullptr, - WIN_STATUS_ENABLED, - 200, 450, - 250, 15, - &instData, nullptr, TRUE ); - - // make a progress bar - instData.init(); - instData.m_style = GWS_PROGRESS_BAR | GWS_MOUSE_TRACK; - window = gogoGadgetProgressBar( nullptr, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 200, 470, - 250, 15, - &instData, nullptr, TRUE ); - - // make some static text - TextData textData; - textData.centered = 1; - instData.init(); - instData.m_style = GWS_STATIC_TEXT | GWS_MOUSE_TRACK; - instData.m_textLabelString = "Centered Static Text"; - window = gogoGadgetStaticText( nullptr, - WIN_STATUS_ENABLED, - 200, 490, - 300, 25, - &instData, - &textData, nullptr, TRUE ); - - // make some static text - textData.centered = 0; - instData.init(); - instData.m_style = GWS_STATIC_TEXT | GWS_MOUSE_TRACK; - instData.m_textLabelString = "Not Centered Static Text"; - window = gogoGadgetStaticText( nullptr, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 200, 520, - 300, 25, - &instData, - &textData, nullptr, TRUE ); - window->winSetEnabledTextColors( winMakeColor( 128, 128, 255, 255 ), - winMakeColor( 255, 255, 255, 255 ) ); - - // make some entry text - EntryData entryData; - memset( &entryData, 0, sizeof( entryData ) ); - entryData.maxTextLen = 30; - instData.init(); - instData.m_style = GWS_ENTRY_FIELD | GWS_MOUSE_TRACK; - instData.m_textLabelString = "Entry"; - window = gogoGadgetTextEntry( nullptr, - WIN_STATUS_ENABLED, - 450, 270, - 400, 30, - &instData, - &entryData, nullptr, TRUE ); - - // make some entry text - memset( &entryData, 0, sizeof( entryData ) ); - entryData.maxTextLen = 30; - instData.init(); - instData.m_style = GWS_ENTRY_FIELD | GWS_MOUSE_TRACK; - instData.m_textLabelString = "Entry"; - window = gogoGadgetTextEntry( nullptr, - WIN_STATUS_ENABLED | WIN_STATUS_IMAGE, - 450, 310, - 400, 30, - &instData, - &entryData, nullptr, TRUE ); - - return TRUE; - -} - - -void GameWindowManager::winNextTab( GameWindow *window ) -{ - if(m_tabList.empty()|| m_modalHead) - return; - - GameWindowList::iterator it = m_tabList.begin(); - while( it != m_tabList.end()) - { - if(*it == window) - { - it++; - break; - } - it++; - } - if(it != m_tabList.end()) - winSetFocus(*it); - else - { - winSetFocus(*m_tabList.begin()); - } - winSetLoneWindow(nullptr); -} - -void GameWindowManager::winPrevTab( GameWindow *window ) -{ - if(m_tabList.empty() || m_modalHead) - return; - - GameWindowList::reverse_iterator it = m_tabList.rbegin(); - while( it != m_tabList.rend()) - { - if(*it == window) - { - it++; - break; - } - it++; - } - if(it != m_tabList.rend()) - winSetFocus(*it); - else - { - winSetFocus(*m_tabList.rbegin()); - } - winSetLoneWindow(nullptr); -} - -void GameWindowManager::registerTabList( GameWindowList tabList ) -{ - m_tabList.clear(); - m_tabList = tabList; -} - -void GameWindowManager::clearTabList() -{ - m_tabList.clear(); -} - - -GameWindow *GameWindowManagerDummy::winGetWindowFromId(GameWindow *window, Int id) -{ - window = GameWindowManager::winGetWindowFromId(window, id); - if (window != nullptr) - return window; - - // Just return any window, callers expect this to be non-null - return m_windowList; -} - -WindowMsgHandledType DummyWindowSystem(GameWindow *window, UnsignedInt msg, WindowMsgData mData1, WindowMsgData mData2) -{ - return MSG_IGNORED; -} - -GameWindow *GameWindowManagerDummy::winCreateFromScript(AsciiString filenameString, WindowLayoutInfo *info) -{ - WindowLayoutInfo scriptInfo; - GameWindow* dummyWindow = winCreate(nullptr, 0, 0, 0, 100, 100, DummyWindowSystem, nullptr); - scriptInfo.windows.push_back(dummyWindow); - if (info) - *info = scriptInfo; - return dummyWindow; -} - -GameWindowDummy::~GameWindowDummy() -{ -} diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp deleted file mode 100644 index a3a9ffdae41..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp +++ /dev/null @@ -1,2881 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameWindowManagerScript.cpp ////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Westwood Studios Pacific. -// -// Confidential Information -// Copyright (C) 2001 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// Project: RTS3 -// -// File name: GameWindowManagerScript.cpp -// -// Created: Colin Day, June 2001 -// Dean Iverson, May 1998 -// -// Desc: Reading window definition files from disk for the window manager -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -// USER INCLUDES ////////////////////////////////////////////////////////////// -#include "Lib/BaseType.h" -#include "Common/Debug.h" -#include "Common/file.h" -#include "Common/FileSystem.h" -#include "Common/GameMemory.h" -#include "Common/NameKeyGenerator.h" -#include "Common/FunctionLexicon.h" -#include "GameClient/Display.h" -#include "GameClient/WindowLayout.h" -#include "GameClient/Gadget.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/GameWindowGlobal.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/GadgetTabControl.h" -#include "GameClient/GadgetTextEntry.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetRadioButton.h" -#include "GameClient/GadgetCheckBox.h" -#include "GameClient/GadgetListBox.h" -#include "GameClient/GadgetComboBox.h" -#include "GameClient/GadgetSlider.h" -#include "GameClient/GameText.h" -#include "GameClient/HeaderTemplate.h" - - - -// DEFINES //////////////////////////////////////////////////////////////////// - -/////////////////////////////////////////////////////////////////////////////// -// PRIVATE TYPES ////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -enum -{ - WIN_BUFFER_LENGTH = 2048, - WIN_STACK_DEPTH = 10, -}; - -//------------------------------------------------------------------------------------------------- -/** Layout parse structure ... these data items apply to the window file itself, - * they are not associated with any window, but rather just a block of data in - * every file */ -//------------------------------------------------------------------------------------------------- -struct LayoutScriptParse -{ - - const char *name; - Bool (*parse)( const char *token, char *buffer, UnsignedInt version, WindowLayoutInfo *info ); - -}; - -// GameWindowParse ------------------------------------------------------------ -/** used to match database fields to parsing functions */ -//----------------------------------------------------------------------------- -struct GameWindowParse -{ - - const char *name; - Bool (*parse)( const char *token, WinInstanceData *, char *, void * ); - -}; - -/////////////////////////////////////////////////////////////////////////////// -// PRIVATE DATA /////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -// window methods and their string representations -static GameWinSystemFunc systemFunc = nullptr; -static GameWinInputFunc inputFunc = nullptr; -static GameWinTooltipFunc tooltipFunc = nullptr; -static GameWinDrawFunc drawFunc = nullptr; -static AsciiString theSystemString; -static AsciiString theInputString; -static AsciiString theTooltipString; -static AsciiString theDrawString; - -// default visual properties -static Color defEnabledColor = 0; -static Color defDisabledColor = 0; -static Color defBackgroundColor = 0; -static Color defHiliteColor = 0; -static Color defSelectedColor = 0; -static Color defTextColor = 0; -static GameFont *defFont = nullptr; - -// -// These strings must be in the same order as they are in their definitions -// (see WIN_STATUS_* enums and GWS_* enums). -// -const char *const WindowStatusNames[] = { "ACTIVE", "TOGGLE", "DRAGABLE", "ENABLED", "HIDDEN", - "ABOVE", "BELOW", "IMAGE", "TABSTOP", "NOINPUT", - "NOFOCUS", "DESTROYED", "BORDER", - "SMOOTH_TEXT", "ONE_LINE", "NO_FLUSH", "SEE_THRU", - "RIGHT_CLICK", "WRAP_CENTERED", "CHECK_LIKE","HOTKEY_TEXT", - "USE_OVERLAY_STATES", "NOT_READY", "FLASHING", "ALWAYS_COLOR", - nullptr }; - -const char *const WindowStyleNames[] = { "PUSHBUTTON", "RADIOBUTTON", "CHECKBOX", - "VERTSLIDER", "HORZSLIDER", "SCROLLLISTBOX", - "ENTRYFIELD", "STATICTEXT", "PROGRESSBAR", - "USER", "MOUSETRACK", "ANIMATED", - "TABSTOP", "TABCONTROL", "TABPANE", - "COMBOBOX", - nullptr }; - -// Implement a stack to keep track of parent/child nested window descriptions. -static GameWindow *windowStack[ WIN_STACK_DEPTH ]; -static GameWindow **stackPtr; - -// for parsing -static const char *seps = " =;\n\r\t"; -WinDrawData enabledDropDownButtonDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes -WinDrawData disabledDropDownButtonDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes -WinDrawData hiliteDropDownButtonDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes - -WinDrawData enabledEditBoxDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes -WinDrawData disabledEditBoxDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes -WinDrawData hiliteEditBoxDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes - -WinDrawData enabledListBoxDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes -WinDrawData disabledListBoxDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes -WinDrawData hiliteListBoxDrawData[ MAX_DRAW_DATA ]; ///< for combo boxes - -WinDrawData enabledUpButtonDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData disabledUpButtonDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData hiliteUpButtonDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData enabledDownButtonDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData disabledDownButtonDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData hiliteDownButtonDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData enabledSliderDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData disabledSliderDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData hiliteSliderDrawData[ MAX_DRAW_DATA ]; ///< for list boxes and combo boxes -WinDrawData enabledSliderThumbDrawData[ MAX_DRAW_DATA ]; ///< for sliders and list boxes and combo boxes -WinDrawData disabledSliderThumbDrawData[ MAX_DRAW_DATA ]; ///< for sliders and list boxes and combo boxes -WinDrawData hiliteSliderThumbDrawData[ MAX_DRAW_DATA ]; ///< for sliders and list boxes and combo boxes - -// PUBLIC DATA //////////////////////////////////////////////////////////////// - -// PRIVATE PROTOTYPES ///////////////////////////////////////////////////////// -static GameWindow *parseWindow( File *inFile, char *buffer ); - -/////////////////////////////////////////////////////////////////////////////// -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -// parseBitFlag =============================================================== -/** Parse one of the "flags" referred to below in the header comment - * for ParseBitString(). Sets the appropriate bit in the 'bits' arg, - * if successful. Returns TRUE on success, else FALSE. */ -//============================================================================= -static Bool parseBitFlag( const char *flagString, UnsignedInt *bits, - ConstCharPtrArray flagList ) -{ - ConstCharPtrArray c; - int i; - - for( i = 0, c = flagList; *c; i++, c++ ) - { - - if( stricmp( *c, flagString ) == 0 ) - { - *bits |= (1 << i); - return TRUE; - } - - } - - return FALSE; - -} - -// parseBitString ============================================================= -/** Given a character string of the form 'A+B+C+D', parse the - * flags separated by the '+' symbols into a bitfield stored in the 'bits' - * argument. - * Note that this routine does not clear any bits, only sets them. */ -//============================================================================= -static void parseBitString( const char *inBuffer, UnsignedInt *bits, ConstCharPtrArray flagList ) -{ - char buffer[256]; - char *tok; - - // do not modify the inBuffer argument - strlcpy(buffer, inBuffer, ARRAY_SIZE(buffer)); - - if( strncmp( buffer, "NULL", 4 ) != 0 ) - { - for( tok = strtok( buffer, "+" ); tok; tok = strtok( nullptr, "+" ) ) - { - if ( !parseBitFlag( tok, bits, flagList ) ) - { - DEBUG_LOG(( "ParseBitString: Invalid flag '%s'.", tok )); - } - } - } - -} - -// readUntilSemicolon ========================================================= -//============================================================================= -static void readUntilSemicolon( File *fp, char *buffer, int maxBufLen ) -{ - int i = 0; - Bool start = TRUE; - - while( i < maxBufLen ) - { - - // get next character - fp->read(buffer + i, 1); - - // make all whitespace characters spaces - if( isspace( buffer[ i ] ) ) - { - - if( start == FALSE ) - buffer[ i++ ] = ' '; - - } - else - { - - start = FALSE; - - if( buffer[ i ] == ';' ) - { - - // found end of data chunk - buffer[ i ] = '\000'; - return; - - } - - i++; - } - - } - - DEBUG_LOG(( "ReadUntilSemicolon: ERROR - Read buffer overflow - input truncated." )); - - buffer[ maxBufLen - 1 ] = '\000'; - -} - -// scanBool =================================================================== -//============================================================================= -static Int scanBool( const char *source, Bool& val ) -{ - Int temp = 0; - Int ret = sscanf( source, "%d", &temp ); - val = (Bool)temp; - - return ret; -} - -// scanShort ================================================================== -//============================================================================= -static Int scanShort( const char *source, Short& val ) -{ - Int temp = 0; - Int ret = sscanf( source, "%d", &temp ); - val = (Short)temp; - - return ret; -} - -// scanInt ==================================================================== -//============================================================================= -static Int scanInt( const char *source, Int& val ) -{ - Int ret = sscanf( source, "%d", &val ); // not strictly necessary to wrap this, but it's more consistent - - return ret; -} - -// scanUnsignedInt ============================================================ -//============================================================================= -static Int scanUnsignedInt( const char *source, UnsignedInt& val ) -{ - Int ret = sscanf( source, "%d", &val ); // not strictly necessary to wrap this, but it's more consistent - - return ret; -} - -// resetWindowStack =========================================================== -//============================================================================= -static void resetWindowStack() -{ - - memset( windowStack, 0, sizeof( windowStack ) ); - stackPtr = windowStack; - -} - -// resetWindowDefaults ======================================================== -//============================================================================= -static void resetWindowDefaults() -{ - - defEnabledColor = 0; - defDisabledColor = 0; - defBackgroundColor = 0; - defHiliteColor = 0; - defSelectedColor = 0; - defTextColor = 0; - defFont = nullptr; - -} - -// peekWindow ================================================================= -//============================================================================= -static GameWindow *peekWindow() -{ - if (stackPtr == windowStack) - return nullptr; - - return *(stackPtr - 1); - -} - -// popWindow ================================================================== -//============================================================================= -static GameWindow *popWindow() -{ - - if( stackPtr == windowStack ) - return nullptr; - stackPtr--; - - return *stackPtr; - -} - -// pushWindow ================================================================= -//============================================================================= -static void pushWindow( GameWindow *window ) -{ - - if( stackPtr == &windowStack[ WIN_STACK_DEPTH - 1 ] ) - { - - DEBUG_LOG(( "pushWindow: Warning, stack overflow" )); - return; - - } - - *stackPtr++ = window; - -} - -// parseColor ================================================================= -/** Parse a color entry and store it in the value pointed to by the - * 'color' parm. */ -//============================================================================= -static Bool parseColor( Color *color, char *buffer ) -{ - char *c; - Byte red, green, blue; - - c = strtok( buffer, " \t\n\r" ); - red = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - green = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - blue = atoi(c); - - *color = TheWindowManager->winMakeColor( red, green, blue, 255 ); - - return TRUE; - -} - -// parseDefaultColor ========================================================== -/** Parse a default color entry and store it in the value pointed to by - * the 'color' parm. */ -//============================================================================= -static Bool parseDefaultColor( Color *color, File *inFile, char *buffer ) -{ - // eat '=' -// fscanf( inFile, "%*s" ); - AsciiString str; - inFile->scanString(str); - - // Read the rest of the color definition - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - - if (strcmp( buffer, "TRANSPARENT" ) == 0) - { - - *color = WIN_COLOR_UNDEFINED; - - } - else - parseColor( color, buffer ); - - return TRUE; - -} - -// parseDefaultFont =========================================================== -/** Parse the default font */ -//============================================================================= -static Bool parseDefaultFont( GameFont *font, File *inFile, char *buffer ) -{ - - // eat '=' -// fscanf( inFile, "%*s" ); - AsciiString str; - inFile->scanString(str); - - // Read the rest of the color definition - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - - /// @todo font parsing for window files work needed here -// *font = GetFont( buffer ); -// if( *font == nullptr ) -// return FALSE; - - return TRUE; - -} - -// parseTooltip =============================================================== -/** Parse the tooltip field */ -//============================================================================= -static Bool parseTooltip( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - UnicodeString tooltip; - tooltip.set(L"Need tooltip translation"); - /// @todo need to parse the tooltip in multibyte here - - instData->setTooltipText( tooltip ); - return TRUE; - -} - -// parseScreenRect ============================================================ -/** Parse the screen rect entry which tells us the position and size - * of window. Note we scale for the current resolution if needed - * and adjust to make the screen rect coords relative to any parent - * if present */ -//============================================================================= -static Bool parseScreenRect( const char *token, char *buffer, - Int *x, Int *y, Int *width, Int *height ) -{ - GameWindow *parent = peekWindow(); - IRegion2D screenRegion; - ICoord2D createRes; // creation resolution - const char *seps = " ,:=\n\r\t"; - char *c; - - c = strtok( nullptr, seps ); // UPPERLEFT token - c = strtok( nullptr, seps ); // x position - scanInt( c, screenRegion.lo.x ); - c = strtok( nullptr, seps ); // y posotion - scanInt( c, screenRegion.lo.y ); - - c = strtok( nullptr, seps ); // BOTTOMRIGHT token - c = strtok( nullptr, seps ); // x position - scanInt( c, screenRegion.hi.x ); - c = strtok( nullptr, seps ); // y posotion - scanInt( c, screenRegion.hi.y ); - - c = strtok( nullptr, seps ); // CREATIONRESOLUTION token - c = strtok( nullptr, seps ); // x creation resolution - scanInt( c, createRes.x ); - c = strtok( nullptr, seps ); // y creation resolution - scanInt( c, createRes.y ); - - // - // shrink or expand the screen region by the ratio of the current - // resolution divided by the creation resolution - // - Real xScale = (Real)TheDisplay->getWidth() / (Real)createRes.x; - Real yScale = (Real)TheDisplay->getHeight() / (Real)createRes.y; - screenRegion.lo.x = (Int)((Real)screenRegion.lo.x * xScale); - screenRegion.lo.y = (Int)((Real)screenRegion.lo.y * yScale); - screenRegion.hi.x = (Int)((Real)screenRegion.hi.x * xScale); - screenRegion.hi.y = (Int)((Real)screenRegion.hi.y * yScale); - - // - // given the screen region upper left compute the upper left that we - // will give this window, if we have a parent note that the position - // is relative to the parent client area, if no parent is present - // we're talking about the screen - // - if( parent ) - { - ICoord2D parentScreenPos; - - // get parent position on screen - parent->winGetScreenPosition( &parentScreenPos.x, &parentScreenPos.y ); - - // save x and y with parent position as relative (0,0) location - *x = screenRegion.lo.x - parentScreenPos.x; - *y = screenRegion.lo.y - parentScreenPos.y; - - } - else - { - - *x = screenRegion.lo.x; - *y = screenRegion.lo.y; - - } - - // save our width and height from the adjusted screen region locations - *width = screenRegion.hi.x - screenRegion.lo.x; - *height = screenRegion.hi.y - screenRegion.lo.y; - - return TRUE; - -} - -// parseImageOffset =========================================================== -/** Parse the image draw offset */ -//============================================================================= -static Bool parseImageOffset( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c; - - c = strtok( buffer, " \t\n\r" ); - instData->m_imageOffset.x = atoi( c ); - - c = strtok( nullptr, " \t\n\r" ); - instData->m_imageOffset.y = atoi( c ); - - return TRUE; - -} - -// parseFont ================================================================== -/** Parse the font field */ -//============================================================================= -static Bool parseFont( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c, *ptr; - const char *seps = " ,\n\r\t"; - const char *stringSeps = ":,\n\r\t\""; - char fontName[ 256 ]; - Int fontSize; - Int fontBold; - - // "NAME" - c = strtok( buffer, seps ); // label - // scan to the first " mark - ptr = buffer; - while( *ptr != '"' ) - ptr++; - ptr++; // skip the " - c = strtok( ptr, stringSeps ); // value - strlcpy(fontName, c, ARRAY_SIZE(fontName)); - - // "SIZE" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, fontSize ); - - // "BOLD" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, fontBold ); - - if( TheFontLibrary ) - { - GameFont *font = TheFontLibrary->getFont( AsciiString(fontName), fontSize, fontBold ); - if( font ) - instData->m_font = font; - } - - return TRUE; - -} - -// parseName ================================================================= -/** Parse the NAME field */ -//============================================================================= -static Bool parseName( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c, *ptr; -// const char *seps = " ,\n\r\t"; - const char *stringSeps = "\""; - - // scan to the first " mark - ptr = buffer; - while( *ptr != '"' ) - ptr++; - ptr++; // skip the first " - c = strtok( ptr, stringSeps ); // name value - instData->m_decoratedNameString = c; - - // given the name assign a window ID from the - assert( TheNameKeyGenerator ); - if( TheNameKeyGenerator ) - instData->m_id = (Int)TheNameKeyGenerator->nameToKey( instData->m_decoratedNameString ); - - return TRUE; - -} - -// parseStatus ================================================================ -/** Parse the STATUS field */ -//============================================================================= -static Bool parseStatus( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - - instData->m_status = 0; - parseBitString( buffer, &instData->m_status, WindowStatusNames ); - - return TRUE; - -} - -// parseStyle ================================================================= -/** Parse the STYLE field */ -//============================================================================= -static Bool parseStyle( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - - instData->m_style = 0; - parseBitString( buffer, &instData->m_style, WindowStyleNames ); - - return TRUE; - -} - -// parseSystemCallback ======================================================== -/** Parse the system method callback for a window */ -//============================================================================= -static Bool parseSystemCallback( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c, *ptr; -// const char *seps = " ,\n\r\t"; - const char *stringSeps = "\""; - - // scan to the first " mark - ptr = buffer; - while( *ptr != '"' ) - ptr++; - ptr++; // skip the first " - c = strtok( ptr, stringSeps ); // name value - - // save a pointer of the function address - DEBUG_ASSERTCRASH( TheNameKeyGenerator && TheFunctionLexicon, ("Invalid singletons") ); - theSystemString = c; - NameKeyType key = TheNameKeyGenerator->nameToKey( theSystemString ); - systemFunc = TheFunctionLexicon->gameWinSystemFunc( key ); - - return TRUE; - -} - -// parseInputCallback ========================================================= -/** Parse the Input method callback for a window */ -//============================================================================= -static Bool parseInputCallback( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c, *ptr; -// const char *seps = " ,\n\r\t"; - const char *stringSeps = "\""; - - // scan to the first " mark - ptr = buffer; - while( *ptr != '"' ) - ptr++; - ptr++; // skip the first " - c = strtok( ptr, stringSeps ); // name value - - // save a pointer of the function address - DEBUG_ASSERTCRASH( TheNameKeyGenerator && TheFunctionLexicon, ("Invalid singletons") ); - theInputString = c; - NameKeyType key = TheNameKeyGenerator->nameToKey( theInputString ); - inputFunc = TheFunctionLexicon->gameWinInputFunc( key ); - - return TRUE; - -} - -// parseTooltipCallback ======================================================= -/** Parse the Tooltip method callback for a window */ -//============================================================================= -static Bool parseTooltipCallback( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c, *ptr; -// const char *seps = " ,\n\r\t"; - const char *stringSeps = "\""; - - // scan to the first " mark - ptr = buffer; - while( *ptr != '"' ) - ptr++; - ptr++; // skip the first " - c = strtok( ptr, stringSeps ); // name value - - // save a pointer of the function address - DEBUG_ASSERTCRASH( TheNameKeyGenerator && TheFunctionLexicon, ("Invalid singletons") ); - theTooltipString = c; - NameKeyType key = TheNameKeyGenerator->nameToKey( theTooltipString ); - tooltipFunc = TheFunctionLexicon->gameWinTooltipFunc( key ); - - return TRUE; - -} - -// parseDrawCallback ========================================================== -/** Parse the Draw method callback for a window */ -//============================================================================= -static Bool parseDrawCallback( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c, *ptr; -// const char *seps = " ,\n\r\t"; - const char *stringSeps = "\""; - - // scan to the first " mark - ptr = buffer; - while( *ptr != '"' ) - ptr++; - ptr++; // skip the first " - c = strtok( ptr, stringSeps ); // name value - - // save a pointer of the function address - DEBUG_ASSERTCRASH( TheNameKeyGenerator && TheFunctionLexicon, ("Invalid singletons") ); - theDrawString = c; - NameKeyType key = TheNameKeyGenerator->nameToKey( theDrawString ); - drawFunc = TheFunctionLexicon->gameWinDrawFunc( key ); - - return TRUE; - -} - -// parseHeaderTemplate ========================================================== -/** Parse the Draw method callback for a window */ -//============================================================================= -static Bool parseHeaderTemplate( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c, *ptr; -// const char *seps = " ,\n\r\t"; - const char *stringSeps = "\""; - - // scan to the first " mark - ptr = buffer; - while( *ptr != '"' ) - ptr++; - ptr++; // skip the first " - c = strtok( ptr, stringSeps ); // name value - - // save a pointer of the function address - DEBUG_ASSERTCRASH( TheNameKeyGenerator && TheFunctionLexicon, ("Invalid singletons") ); - - instData->m_headerTemplateName = c; - - return TRUE; - -} - -// parseListboxData =========================================================== -/** Parse listbox data entry */ -//============================================================================= -static Bool parseListboxData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - ListboxData *listData = (ListboxData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - // "LENGTH" - c = strtok( buffer, seps ); // label - c = strtok( nullptr, seps ); - scanShort( c, listData->listLength ); - - // "AUTOSCROLL" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, listData->autoScroll ); - - // "SCROLLIFATEND" (optional) - c = strtok( nullptr, seps ); // label - if ( stricmp(c, "ScrollIfAtEnd") == 0 ) - { - c = strtok( nullptr, seps ); // value - scanBool( c, listData->scrollIfAtEnd ); - c = strtok( nullptr, seps ); // label - } - else - { - listData->scrollIfAtEnd = FALSE; - } - - // "AUTOPURGE" - c = strtok( nullptr, seps ); // value - scanBool( c, listData->autoPurge ); - - // "SCROLLBAR" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, listData->scrollBar ); - - // "MULTISELECT" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, listData->multiSelect ); - - // "COLUMNS" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanShort( c, listData->columns ); - if(listData->columns > 1) - { - listData->columnWidthPercentage = NEW Int[listData->columns]; - for(Int i = 0; i < listData->columns; i++ ) - { - // "COLUMNS" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, listData->columnWidthPercentage[i] ); - } - } - else - listData->columnWidthPercentage = nullptr; - listData->columnWidth = nullptr; - // "FORCESELECT" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, listData->forceSelect ); - - - // " - return TRUE; - -} - -// parseComboBoxData =========================================================== -/** Parse Combo Box data entry */ -//============================================================================= -static Bool parseComboBoxData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - ComboBoxData *comboData = (ComboBoxData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - c = strtok( buffer, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, comboData->isEditable ); - - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, comboData->maxChars ); - - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, comboData->maxDisplay ); - - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, comboData->asciiOnly ); - - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, comboData->lettersAndNumbersOnly ); - - - return TRUE; -} - -// parseSliderData ============================================================ -/** Parse slider data entry */ -//============================================================================= -static Bool parseSliderData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - SliderData *sliderData = (SliderData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - // "MINVALUE" - c = strtok( buffer, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, sliderData->minVal ); - - // "MAXVALUE" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, sliderData->maxVal ); - - return TRUE; - -} - -// parseRadioButtonData ======================================================= -/** Parse radio button data entry */ -//============================================================================= -static Bool parseRadioButtonData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - RadioButtonData *radioData = (RadioButtonData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - // "GROUP" - c = strtok( buffer, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, radioData->group ); - - return TRUE; - -} - - -// parseTooltipText =========================================================== -/** Parse the TOOLTIPTEXT field */ -//============================================================================= -static Bool parseTooltipText( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *ptr = buffer; - char *c; - const char *stringSeps = "\n\r\t\""; - - // scan to the first " mark - while( *ptr != '"' ) - ptr++; - ptr++; // skip the " - if(strlen( ptr ) == 1 ) - return TRUE; - c = strtok( ptr, stringSeps ); // value - if( strlen( c ) >= MAX_TEXT_LABEL ) - { - - DEBUG_LOG(( "TextTooltip label '%s' is too long, max is '%d'", c, MAX_TEXT_LABEL )); - assert( 0 ); - return FALSE; - - } - instData->m_tooltipString.set(c); - instData->setTooltipText(TheGameText->fetch(c)); - - - return TRUE; - -} - -// parseTooltipDelay ======================================================= -/** Parse the tooltip delay */ -//============================================================================= -static Bool parseTooltipDelay( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - //RadioButtonData *radioData = (RadioButtonData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - // "getvalue" - c = strtok( buffer, seps ); // value - scanInt( c, instData->m_tooltipDelay ); - - return TRUE; - -} - - -// parseText ================================================================== -/** Parse the TEXT field */ -//============================================================================= -static Bool parseText( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *ptr = buffer; - char *c; - const char *stringSeps = "\n\r\t\""; - - // scan to the first " mark - while( *ptr != '"' ) - ptr++; - ptr++; // skip the " - c = strtok( ptr, stringSeps ); // value - if( strlen( c ) >= MAX_TEXT_LABEL ) - { - - DEBUG_LOG(( "Text label '%s' is too long, max is '%d'", c, MAX_TEXT_LABEL )); - assert( 0 ); - return FALSE; - - } - instData->m_textLabelString = c; - - - return TRUE; - -} - -// parseTextColor ============================================================= -/** Parse text color entries for enabled, disabled, and hilite with - * drop shadow colors */ -//============================================================================= -static Bool parseTextColor( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - char *c; - const char *seps = " :,\n\r\t"; - UnsignedInt r, g, b, a; - Int i, states = 3; - TextDrawData *textData; - Bool first = TRUE; - - - for( i = 0; i < states; i++ ) - { - - if( i == 0 ) - textData = &instData->m_enabledText; - else if( i == 1 ) - textData = &instData->m_disabledText; - else if( i == 2 ) - textData = &instData->m_hiliteText; - else - { - - DEBUG_LOG(( "Undefined state for text color" )); - assert( 0 ); - return FALSE; - - } - - // color - if( first == TRUE ) - c = strtok( buffer, seps ); // label - else - c = strtok( nullptr, seps ); // label - first = FALSE; - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, r ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, g ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, b ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, a ); - textData->color = GameMakeColor( r, g, b, a ); - - // border color - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, r ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, g ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, b ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, a ); - textData->borderColor = GameMakeColor( r, g, b, a ); - - } - - return TRUE; - -} - -// parseStaticTextData ======================================================== -/** Parse static text data entry */ -//============================================================================= -static Bool parseStaticTextData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - TextData *textData = (TextData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - // "CENTERED" - c = strtok( buffer, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, textData->centered ); - - // @todo: add these to GUIEdit options and output - // These are initialized here because any TextData constructor would never get called. - // The behavior with these defaults is the same as it was before these members were added. - textData->centeredVertically = TRUE; - textData->leftMargin = 7; - textData->topMargin = 7; - - return TRUE; - -} - -// parseTextEntryData ========================================================= -/** Parse text entry data entry */ -//============================================================================= -static Bool parseTextEntryData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - EntryData *entryData = (EntryData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - // "MAXLEN" - c = strtok( buffer, seps ); // label - c = strtok( nullptr, seps ); // value - scanShort( c, entryData->maxTextLen ); - - // "SECRETTEXT" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, entryData->secretText ); - - // "NUMERICALONLY" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, entryData->numericalOnly ); - - // "ALPHANUMERICALONLY" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, entryData->alphaNumericalOnly ); - - // "ASCIIONLY" - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanBool( c, entryData->aSCIIOnly ); - - return TRUE; - -} - -// parseTabControlData ========================================================= -/** Parse tab control data entry */ -//============================================================================= -static Bool parseTabControlData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - TabControlData *tabControlData = (TabControlData *)data; - char *c; - const char *seps = " :,\n\r\t"; - - //TABORIENTATION - c = strtok( buffer, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, tabControlData->tabOrientation ); - - //TABEDGE - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, tabControlData->tabEdge ); - - //TABWIDTH - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, tabControlData->tabWidth ); - - //TABHEIGHT - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, tabControlData->tabHeight ); - - //TABCOUNT - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, tabControlData->tabCount ); - - //PANEBORDER - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, tabControlData->paneBorder ); - - //PANEDISABLED - Int entryCount = 0; - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanInt( c, entryCount ); - - for( Int paneIndex = 0; paneIndex < entryCount; paneIndex ++ ) - { - c = strtok( nullptr, seps ); // value - scanBool( c, tabControlData->subPaneDisabled[paneIndex] ); - } - - return TRUE; -} - -// parseDrawData ============================================================== -/** Parse set of draw data elements */ -//============================================================================= -static Bool parseDrawData( const char *token, WinInstanceData *instData, - char *buffer, void *data ) -{ - Int i; - UnsignedInt r, g, b, a; - WinDrawData *drawData; - Bool first = TRUE; - char *c; - const char *seps = " :,\n\r\t"; - - for( i = 0; i < MAX_DRAW_DATA; i++ ) - { - - // get the right draw data - if( strcmp( token, "ENABLEDDRAWDATA" ) == 0 ) - drawData = &instData->m_enabledDrawData[ i ]; - else if( strcmp( token, "DISABLEDDRAWDATA" ) == 0 ) - drawData = &instData->m_disabledDrawData[ i ]; - else if( strcmp( token, "HILITEDRAWDATA" ) == 0 ) - drawData = &instData->m_hiliteDrawData[ i ]; - else if( strcmp( token, "LISTBOXENABLEDUPBUTTONDRAWDATA" ) == 0 ) - drawData = &enabledUpButtonDrawData[ i ]; - else if( strcmp( token, "LISTBOXDISABLEDUPBUTTONDRAWDATA" ) == 0 ) - drawData = &disabledUpButtonDrawData[ i ]; - else if( strcmp( token, "LISTBOXHILITEUPBUTTONDRAWDATA" ) == 0 ) - drawData = &hiliteUpButtonDrawData[ i ]; - else if( strcmp( token, "LISTBOXENABLEDDOWNBUTTONDRAWDATA" ) == 0 ) - drawData = &enabledDownButtonDrawData[ i ]; - else if( strcmp( token, "LISTBOXDISABLEDDOWNBUTTONDRAWDATA" ) == 0 ) - drawData = &disabledDownButtonDrawData[ i ]; - else if( strcmp( token, "LISTBOXHILITEDOWNBUTTONDRAWDATA" ) == 0 ) - drawData = &hiliteDownButtonDrawData[ i ]; - else if( strcmp( token, "LISTBOXENABLEDSLIDERDRAWDATA" ) == 0 ) - drawData = &enabledSliderDrawData[ i ]; - else if( strcmp( token, "LISTBOXDISABLEDSLIDERDRAWDATA" ) == 0 ) - drawData = &disabledSliderDrawData[ i ]; - else if( strcmp( token, "LISTBOXHILITESLIDERDRAWDATA" ) == 0 ) - drawData = &hiliteSliderDrawData[ i ]; - else if( strcmp( token, "SLIDERTHUMBENABLEDDRAWDATA" ) == 0 ) - drawData = &enabledSliderThumbDrawData[ i ]; - else if( strcmp( token, "SLIDERTHUMBDISABLEDDRAWDATA" ) == 0 ) - drawData = &disabledSliderThumbDrawData[ i ]; - else if( strcmp( token, "SLIDERTHUMBHILITEDRAWDATA" ) == 0 ) - drawData = &hiliteSliderThumbDrawData[ i ]; - else if( strcmp( token, "COMBOBOXDROPDOWNBUTTONENABLEDDRAWDATA" ) == 0 ) - drawData = &enabledDropDownButtonDrawData[ i ]; - else if( strcmp( token, "COMBOBOXDROPDOWNBUTTONDISABLEDDRAWDATA" ) == 0 ) - drawData = &disabledDropDownButtonDrawData[ i ]; - else if( strcmp( token, "COMBOBOXDROPDOWNBUTTONHILITEDRAWDATA" ) == 0 ) - drawData = &hiliteDropDownButtonDrawData[ i ]; - else if( strcmp( token, "COMBOBOXEDITBOXENABLEDDRAWDATA" ) == 0 ) - drawData = &enabledEditBoxDrawData[ i ]; - else if( strcmp( token, "COMBOBOXEDITBOXDISABLEDDRAWDATA" ) == 0 ) - drawData = &disabledEditBoxDrawData[ i ]; - else if( strcmp( token, "COMBOBOXEDITBOXHILITEDRAWDATA" ) == 0 ) - drawData = &hiliteEditBoxDrawData[ i ]; - else if( strcmp( token, "COMBOBOXLISTBOXENABLEDDRAWDATA" ) == 0 ) - drawData = &enabledListBoxDrawData[ i ]; - else if( strcmp( token, "COMBOBOXLISTBOXDISABLEDDRAWDATA" ) == 0 ) - drawData = &disabledListBoxDrawData[ i ]; - else if( strcmp( token, "COMBOBOXLISTBOXHILITEDRAWDATA" ) == 0 ) - drawData = &hiliteListBoxDrawData[ i ]; - else - { - - DEBUG_LOG(( "ParseDrawData, undefined token '%s'", token )); - assert( 0 ); - return FALSE; - - } - - // IMAGE: X - if( first == TRUE ) - c = strtok( buffer, seps ); // label - else - c = strtok( nullptr, seps ); // label - first = FALSE; - - c = strtok( nullptr, seps ); // value - if( strcmp( c, "NoImage" ) != 0 ) - drawData->image = TheMappedImageCollection->findImageByName( AsciiString( c ) ); - else - drawData->image = nullptr; - // COLOR: R G B A - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, r ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, g ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, b ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, a ); - drawData->color = GameMakeColor( r, g, b, a ); - - // BORDERCOLOR: R G B A - c = strtok( nullptr, seps ); // label - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, r ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, g ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, b ); - c = strtok( nullptr, seps ); // value - scanUnsignedInt( c, a ); - drawData->borderColor = GameMakeColor( r, g, b, a ); - - } - - return TRUE; - -} - -// getDataTemplate ============================================================ -/** Given a window type style string return the address of a static - * gadget data type used for the generic data pointers in the - * GUI gadget controls */ -//============================================================================= -void *getDataTemplate( char *type ) -{ - static EntryData eData; - static SliderData sData; - static ListboxData lData; - static TextData tData; - static RadioButtonData rData; - static TabControlData tcData; - static ComboBoxData cData; - void *data; - - if( strcmp( type, "VERTSLIDER" ) == 0 || strcmp( type, "HORZSLIDER" ) == 0 ) - { - - memset( &sData, 0, sizeof( SliderData ) ); - data = &sData; - - } - else if( strcmp( type, "SCROLLLISTBOX" ) == 0 ) - { - - memset( &lData, 0, sizeof( ListboxData ) ); - data = &lData; - - } - else if( strcmp( type, "TABCONTROL" ) == 0 ) - { - memset( &tcData, 0, sizeof( TabControlData ) ); - data = &tcData; - } - else if( strcmp( type, "ENTRYFIELD" ) == 0 ) - { - - memset( &eData, 0, sizeof( EntryData ) ); - data = &eData; - - } - else if( strcmp( type, "STATICTEXT" ) == 0 ) - { - - memset( &tData, 0, sizeof( TextData ) ); - data = &tData; - - } - else if( strcmp( type, "RADIOBUTTON" ) == 0 ) - { - - memset( &rData, 0, sizeof( RadioButtonData ) ); - data = &rData; - } - else if( strcmp( type, "COMBOBOX" ) == 0 ) - { - - memset( &cData, 0, sizeof( ComboBoxData ) ); - data = &cData; - } - else - data = nullptr; - - return data; - -} - -// parseData ================================================================== -// -// Parse the data for gadgets. For sliders the data is in the format: -// -// -// For listboxes the data is formatted as: -// -// -// For Combo Boxes the data is formatted as: -// -// -// For entry fields the data is as follows: -// <1 = NumericalOnly, 2 = AlphaNumericOnly> -// -// For text the data is as follows: -// -// -// 1/2/2003: THIS FUNCTION IS NEVER REACHED; IT IS OBSOLETE -MDC -// -//============================================================================= -static Bool parseData( void **data, char *type, char *buffer ) -{ - char *c; - static EntryData eData; - static SliderData sData; - static ListboxData lData; - static TextData tData; - static RadioButtonData rData; - static ComboBoxData cData; - - if( strcmp( type, "VERTSLIDER" ) == 0 || strcmp( type, "HORZSLIDER" ) == 0 ) - { - - memset( &sData, 0, sizeof( SliderData ) ); - - c = strtok( buffer, " \t\n\r" ); - sData.minVal = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - sData.maxVal = atoi(c); - - *data = &sData; - - } - else if( strcmp( type, "SCROLLLISTBOX" ) == 0 ) - { - - memset( &lData, 0, sizeof( ListboxData ) ); - - c = strtok( buffer, " \t\n\r" ); - lData.listLength = atoi(c); - -// c = strtok( nullptr, " \t\n\r" ); -// lData.entryHeight = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - lData.autoScroll = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - lData.autoPurge = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - lData.scrollBar = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - lData.multiSelect = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); - lData.forceSelect = atoi(c); - - *data = &lData; - - } - else if( strcmp( type, "ENTRYFIELD" ) == 0 ) - { - - memset( &eData, 0, sizeof( EntryData ) ); - - c = strtok( buffer, " \t\n\r" ); - eData.maxTextLen = atoi(c); - - c = strtok( nullptr, " \t\n\r" ); -// if (c) -// eData.entryWidth = atoi(c); -// else -// eData.entryWidth = -1; - - c = strtok( nullptr, " \t\n\r" ); - if (c) - { - eData.secretText = atoi(c); - - if( eData.secretText != FALSE ) - eData.secretText = TRUE; - } - else - eData.secretText = FALSE; - - c = strtok( nullptr, " \t\n\r" ); - if (c) - { - eData.numericalOnly = ( atoi(c) == 1 ); - eData.alphaNumericalOnly = ( atoi(c) == 2 ); - eData.aSCIIOnly = ( atoi(c) == 3 ); - } - else - { - eData.numericalOnly = FALSE; - eData.alphaNumericalOnly = FALSE; - eData.aSCIIOnly = FALSE; - } - *data = &eData; - - } - else if( strcmp( type, "STATICTEXT" ) == 0 ) - { - - c = strtok( buffer, " \t\n\r" ); - tData.centered = atoi(c); - - if( tData.centered != FALSE ) - tData.centered = TRUE; - - c = strtok( nullptr, " \t\n\r" ); - - /** @todo need to get a label from the translation manager, uncomment - the following line and remove the WideChar assignment when - we have it */ -// text = StringManagerFetch( c ); -// text = L"Need StrManager, Remove me!"; -// TheWindowManager->winStrcpy( tData.text, text ); - - *data = &tData; - - } - else if( strcmp( type, "RADIOBUTTON" ) == 0 ) - { - - c = strtok( buffer, " \t\n\r" ); - rData.group = atoi(c); -/// @todo Colin: Why was this here??? -// if( tData.centered != FALSE ) -// { -// tData.centered = TRUE; -// } - *data = &rData; - } - else - *data = nullptr; - - return TRUE; - -} - -// setWindowText ============================================================== -/** Set the default text for a window or gadget control */ -//============================================================================= -static void setWindowText( GameWindow *window, AsciiString textLabel ) -{ - - // sanity - if (textLabel.isEmpty()) - return; - - UnicodeString theText, entryText; - //Translate the text - theText = TheGameText->fetch( (char *)textLabel.str()); - // set the text in the window based on what it is - if( BitIsSet( window->winGetStyle(), GWS_PUSH_BUTTON ) ) - GadgetButtonSetText( window, theText ); - else if( BitIsSet( window->winGetStyle(), GWS_RADIO_BUTTON ) ) - GadgetRadioSetText( window, theText ); - else if( BitIsSet( window->winGetStyle(), GWS_CHECK_BOX ) ) - GadgetCheckBoxSetText( window, theText ); - else if( BitIsSet( window->winGetStyle(), GWS_STATIC_TEXT ) ) - GadgetStaticTextSetText( window, theText ); - else if( BitIsSet( window->winGetStyle(), GWS_ENTRY_FIELD ) ) - { - entryText.translate(textLabel); - GadgetTextEntrySetText( window, entryText ); - } - else - window->winSetText( theText ); - -} - -// createGadget =============================================================== -/** Create a gadget based on the 'type' parm */ -//============================================================================= -static GameWindow *createGadget( char *type, - GameWindow *parent, - Int status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - void *data ) -{ - GameWindow *window = nullptr; - - instData->m_owner = parent; - - if( strcmp( type, "PUSHBUTTON" ) == 0 ) - { - - instData->m_style |= GWS_PUSH_BUTTON; - window = TheWindowManager->gogoGadgetPushButton( parent, status, x, y, - width, height, - instData, - instData->m_font, FALSE ); - - } - else if( strcmp( type, "RADIOBUTTON" ) == 0 ) - { - RadioButtonData *rData = (RadioButtonData *)data; - char filename[ MAX_WINDOW_NAME_LEN ]; - char *c; - - // - // assign a screen identifier to the radio button based on the - // filename the radio button was saved in - // - - strlcpy(filename, instData->m_decoratedNameString.str(), ARRAY_SIZE(filename)); - c = strchr( filename, ':' ); - if( c ) - *c = 0; // terminate after filename (format is filename:gadgetname) - assert( TheNameKeyGenerator ); - if( TheNameKeyGenerator ) - rData->screen = (Int)(TheNameKeyGenerator->nameToKey( filename )); - - instData->m_style |= GWS_RADIO_BUTTON; - window = TheWindowManager->gogoGadgetRadioButton( parent, status, x, y, - width, height, - instData, rData, - instData->m_font, FALSE ); - - } - else if( strcmp( type, "CHECKBOX" ) == 0 ) - { - - instData->m_style |= GWS_CHECK_BOX; - window = TheWindowManager->gogoGadgetCheckbox( parent, status, x, y, - width, height, - instData, - instData->m_font, FALSE ); - - } - else if( strcmp( type, "TABCONTROL" ) == 0 ) - { - TabControlData *tcData = (TabControlData *)data; - instData->m_style |= GWS_TAB_CONTROL; - window = TheWindowManager->gogoGadgetTabControl( parent, status, x, y, - width, height, - instData, tcData, - instData->m_font, FALSE ); - } - else if( strcmp( type, "VERTSLIDER" ) == 0 ) - { - SliderData *sData = (SliderData *)data; - - instData->m_style |= GWS_VERT_SLIDER; - window = TheWindowManager->gogoGadgetSlider( parent, status, x, y, - width, height, - instData, sData, - instData->m_font, FALSE ); - - // - // we know we've read in the slider thumb data in the definition file - // (it's guaranteed to be generated by the editor) so place that - // draw data into the thumb of the slider - // - GameWindow *thumb = window->winGetChild(); - if( thumb ) - { - WinInstanceData *instData = thumb->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledSliderThumbDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledSliderThumbDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteSliderThumbDrawData[ i ]; - - } - - } - - } - else if( strcmp( type, "HORZSLIDER" ) == 0 ) - { - SliderData *sData = (SliderData *)data; - - instData->m_style |= GWS_HORZ_SLIDER; - window = TheWindowManager->gogoGadgetSlider( parent, status, x, y, - width, height, - instData, sData, - instData->m_font, FALSE ); - - // - // we know we've read in the slider thumb data in the definition file - // (it's guaranteed to be generated by the editor) so place that - // draw data into the thumb of the slider - // - GameWindow *thumb = window->winGetChild(); - if( thumb ) - { - WinInstanceData *instData = thumb->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledSliderThumbDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledSliderThumbDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteSliderThumbDrawData[ i ]; - - } - - } - - } - else if( strcmp( type, "SCROLLLISTBOX" ) == 0 ) - { - - ListboxData *lData = (ListboxData *)data; - - instData->m_style |= GWS_SCROLL_LISTBOX; - window = TheWindowManager->gogoGadgetListBox( parent, status, x, y, - width, height, - instData, lData, - instData->m_font, FALSE ); - - // - // we know that in the file we have read the draw data for the listbox - // parts (up button, down button, and slider), now that we have those - // parts actually created we must assign that data to them - // - GameWindow *upButton = GadgetListBoxGetUpButton( window ); - if( upButton ) - { - WinInstanceData *instData = upButton->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledUpButtonDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledUpButtonDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteUpButtonDrawData[ i ]; - - } - - } - - GameWindow *downButton = GadgetListBoxGetDownButton( window ); - if( downButton ) - { - WinInstanceData *instData = downButton->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledDownButtonDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledDownButtonDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteDownButtonDrawData[ i ]; - - } - - } - - GameWindow *slider = GadgetListBoxGetSlider( window ); - if( slider ) - { - WinInstanceData *instData = slider->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledSliderDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledSliderDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteSliderDrawData[ i ]; - - } - - // do the slider thumb - GameWindow *thumb = slider->winGetChild(); - if( thumb ) - { - WinInstanceData *instData = thumb->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledSliderThumbDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledSliderThumbDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteSliderThumbDrawData[ i ]; - - } - - } - - } - - } - else if( strcmp( type, "COMBOBOX" ) == 0 ) - { - ComboBoxData *cData = (ComboBoxData *)data; - cData->entryData = NEW EntryData; - memset ( cData->entryData, 0, sizeof(EntryData)); - cData->listboxData = NEW ListboxData; - memset ( cData->listboxData, 0, sizeof(ListboxData)); - - //initialize combo box data - //cData->isEditable = TRUE; - //cData->maxChars = 16; - //cData->maxDisplay = 5; - cData->entryCount = 0; - //initialize entry data - cData->entryData->aSCIIOnly = cData->asciiOnly; - cData->entryData->alphaNumericalOnly = cData->lettersAndNumbersOnly; - cData->entryData->maxTextLen = cData->maxChars; - - //initialize listbox data - cData->listboxData->listLength = 10; - cData->listboxData->autoScroll = 0; - cData->listboxData->scrollIfAtEnd = FALSE; - cData->listboxData->autoPurge = 0; - cData->listboxData->scrollBar = 1; - cData->listboxData->multiSelect = 0; - cData->listboxData->forceSelect = 1; - cData->listboxData->columns = 1; - cData->listboxData->columnWidth = nullptr; - cData->listboxData->columnWidthPercentage = nullptr; - - instData->m_style |= GWS_COMBO_BOX; - window = TheWindowManager->gogoGadgetComboBox( parent, status, x, y, - width, height, - instData, cData, - instData->m_font, FALSE ); - - GameWindow *dropDownButton = GadgetComboBoxGetDropDownButton( window ); - if( dropDownButton ) - { - WinInstanceData *instData = dropDownButton->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledDropDownButtonDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledDropDownButtonDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteDropDownButtonDrawData[ i ]; - - } - } - - GameWindow *editBox = GadgetComboBoxGetEditBox( window ); - if( editBox ) - { - WinInstanceData *instData = editBox->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledEditBoxDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledEditBoxDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteEditBoxDrawData[ i ]; - - } - } - - - GameWindow *listBox = GadgetComboBoxGetListBox( window ); - if( listBox ) - { - WinInstanceData *instData = listBox->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledListBoxDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledListBoxDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteListBoxDrawData[ i ]; - - } - - - GameWindow *upButton = GadgetListBoxGetUpButton( listBox ); - if( upButton ) - { - WinInstanceData *instData = upButton->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledUpButtonDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledUpButtonDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteUpButtonDrawData[ i ]; - - } - - } - - GameWindow *downButton = GadgetListBoxGetDownButton( listBox ); - if( downButton ) - { - WinInstanceData *instData = downButton->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledDownButtonDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledDownButtonDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteDownButtonDrawData[ i ]; - - } - - } - - GameWindow *slider = GadgetListBoxGetSlider( listBox ); - if( slider ) - { - WinInstanceData *instData = slider->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledSliderDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledSliderDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteSliderDrawData[ i ]; - - } - - // do the slider thumb - GameWindow *thumb = slider->winGetChild(); - if( thumb ) - { - WinInstanceData *instData = thumb->winGetInstanceData(); - - for( Int i = 0; i < MAX_DRAW_DATA; i++ ) - { - - instData->m_enabledDrawData[ i ] = enabledSliderThumbDrawData[ i ]; - instData->m_disabledDrawData[ i ] = disabledSliderThumbDrawData[ i ]; - instData->m_hiliteDrawData[ i ] = hiliteSliderThumbDrawData[ i ]; - - } - - } - - } - } - } - else if( strcmp( type, "ENTRYFIELD" ) == 0 ) - { - EntryData *eData = (EntryData *)data; - - instData->m_style |= GWS_ENTRY_FIELD; - window = TheWindowManager->gogoGadgetTextEntry( parent, status, x, y, - width, height, - instData, eData, - instData->m_font, FALSE ); - - } - else if( strcmp( type, "STATICTEXT" ) == 0 ) - { - TextData *tData = (TextData *)data; - - instData->m_style |= GWS_STATIC_TEXT; - window = TheWindowManager->gogoGadgetStaticText( parent, status, x, y, - width, height, - instData, tData, - instData->m_font, FALSE ); - - - } - else if( strcmp( type, "PROGRESSBAR" ) == 0 ) - { - - instData->m_style |= GWS_PROGRESS_BAR; - window = TheWindowManager->gogoGadgetProgressBar( parent, status, x, y, - width, height, - instData, - instData->m_font, FALSE ); - - } - - return window; - -} - -// createWindow =============================================================== -// Create a user window or a gadget depending on the 'type' parm -//============================================================================= -static GameWindow *createWindow( char *type, - Int id, - Int status, - Int x, Int y, - Int width, Int height, - WinInstanceData *instData, - void *data, - GameWinSystemFunc system, - GameWinInputFunc input, - GameWinTooltipFunc tooltip, - GameWinDrawFunc draw ) -{ - GameWindow *window, *parent; - - // Check to see if this window has a parent - parent = peekWindow(); - - // If this is a regular window just create it - if( strcmp( type, "USER" ) == 0 ) - { - - window = TheWindowManager->winCreate( parent, - status, x, y, - width, height, - system ); - if( window ) - { - - instData->m_style |= GWS_USER_WINDOW; - window->winSetInstanceData( instData ); - window->winSetWindowId( id ); - - } - - } - else if( strcmp( type, "TABPANE" ) == 0 ) - { - - window = TheWindowManager->winCreate( parent, - status, x, y, - width, height, - system ); - if( window ) - { - - instData->m_style |= GWS_TAB_PANE; - window->winSetInstanceData( instData ); - window->winSetWindowId( id ); - - } - - } - - else - { - - // Else parse the type and create the gadget - window = createGadget( type, - parent, - status, - x, y, - width, height, - instData, - data ); - if( window ) - { - - // set id - window->winSetWindowId( id ); - - } - - } - - // assign the callbacks if they are not empty/nullptr, that means they were read - // in and parsed from the window definition file - if( window ) - { - - if( system ) - window->winSetSystemFunc( system ); - if( input ) - window->winSetInputFunc( input ); - if( tooltip ) - window->winSetTooltipFunc( tooltip ); - if( draw ) - window->winSetDrawFunc( draw ); - - // save strings for edit data if present - GameWindowEditData *editData = window->winGetEditData(); - if( editData ) - { - - editData->systemCallbackString = theSystemString; - editData->inputCallbackString = theInputString; - editData->tooltipCallbackString = theTooltipString; - editData->drawCallbackString = theDrawString; - - } - - } - - if( window ) - { - - // set any text read from the textLabel - setWindowText( window, instData->m_textLabelString ); - - } - - // If there is a parent window, send it the SCRIPT_CREATE message - if( window && parent ) - TheWindowManager->winSendInputMsg( parent, GWM_SCRIPT_CREATE, id, 0 ); - - return window; - -} - -// parseChildWindows ========================================================== -/** Parse window descriptions until an extra end is encountered indicating - * the end of this block of child window descriptions. */ -//============================================================================= -static Bool parseChildWindows( GameWindow *window, - File *inFile, - char *buffer ) -{ - GameWindow *lastWindow; - AsciiString asciibuf; - - //The gadget with children needs to delete its default created children in favor - //of the ones from the script file. So kill them before reading. - if( BitIsSet( window->winGetStyle(), GWS_TAB_CONTROL ) ) - { - GameWindow *nextWindow = nullptr; - for( GameWindow *myChild = window->winGetChild(); myChild; myChild = nextWindow ) - { - nextWindow = myChild->winGetNext(); - TheWindowManager->winDestroy( myChild ); - } - } - - // Push the current window onto the stack so we know it's the parent - pushWindow( window ); - - while( TRUE ) - { - - if (inFile->scanString(asciibuf) == FALSE) { - break; - } - - if (asciibuf.compare("ENDALLCHILDREN") == 0) { - break; - } - - if (asciibuf.compare("END") == 0) { - break; - } - - if (asciibuf.compare("ENABLEDCOLOR") == 0) - { - - if( parseDefaultColor( &defEnabledColor, inFile, buffer ) == FALSE ) - { - return FALSE; - } - - } - else if (asciibuf.compare("DISABLEDCOLOR") == 0) - { - - if( parseDefaultColor( &defDisabledColor, inFile, buffer ) == FALSE ) - { - return FALSE; - } - - } - else if (asciibuf.compare("HILITECOLOR") == 0) - { - - if( parseDefaultColor( &defHiliteColor, inFile, buffer ) == FALSE ) - { - return FALSE; - } - - } - else if (asciibuf.compare("SELECTEDCOLOR") == 0) - { - - if( parseDefaultColor( &defSelectedColor, inFile, buffer ) == FALSE ) - { - return FALSE; - } - - } - else if (asciibuf.compare("TEXTCOLOR") == 0) - { - - if( parseDefaultColor( &defTextColor, inFile, buffer ) == FALSE ) - { - return FALSE; - } - - } - else if (asciibuf.compare("WINDOW") == 0) - { - - // Parse window descriptions until the last END is read - if( parseWindow( inFile, buffer ) == nullptr ) - { - return FALSE; - } - - } - - } - - // Pop the current window off the stack - lastWindow = popWindow(); - - if( lastWindow != window ) - { - - DEBUG_LOG(( "parseChildWindows: unmatched window on stack. Corrupt stack or bad source" )); - return FALSE; - - } - - if( BitIsSet( window->winGetStyle(), GWS_TAB_CONTROL ) ) - GadgetTabControlFixupSubPaneList( window );//all children created, so re-fill SubPane array with children - - return TRUE; - -} - -// lookup table for parsing functions -static GameWindowParse gameWindowFieldList[] = -{ - { "NAME", parseName }, - { "STATUS", parseStatus }, - { "STYLE", parseStyle }, - { "SYSTEMCALLBACK", parseSystemCallback }, - { "INPUTCALLBACK", parseInputCallback }, - { "TOOLTIPCALLBACK", parseTooltipCallback }, - { "DRAWCALLBACK", parseDrawCallback }, - { "FONT", parseFont }, - { "HEADERTEMPLATE", parseHeaderTemplate }, - { "LISTBOXDATA", parseListboxData }, - { "COMBOBOXDATA", parseComboBoxData }, - { "SLIDERDATA", parseSliderData }, - { "RADIOBUTTONDATA", parseRadioButtonData }, - { "TOOLTIPTEXT", parseTooltipText }, - { "TOOLTIPDELAY", parseTooltipDelay }, - { "TEXT", parseText }, - { "TEXTCOLOR", parseTextColor }, - { "STATICTEXTDATA", parseStaticTextData }, - { "TEXTENTRYDATA", parseTextEntryData }, - { "TABCONTROLDATA", parseTabControlData }, - - { "ENABLEDDRAWDATA", parseDrawData }, - { "DISABLEDDRAWDATA", parseDrawData }, - { "HILITEDRAWDATA", parseDrawData }, - { "LISTBOXENABLEDUPBUTTONDRAWDATA", parseDrawData }, - { "LISTBOXENABLEDDOWNBUTTONDRAWDATA", parseDrawData }, - { "LISTBOXENABLEDSLIDERDRAWDATA", parseDrawData }, - { "LISTBOXDISABLEDUPBUTTONDRAWDATA", parseDrawData }, - { "LISTBOXDISABLEDDOWNBUTTONDRAWDATA", parseDrawData }, - { "LISTBOXDISABLEDSLIDERDRAWDATA", parseDrawData }, - { "LISTBOXHILITEUPBUTTONDRAWDATA", parseDrawData }, - { "LISTBOXHILITEDOWNBUTTONDRAWDATA", parseDrawData }, - { "LISTBOXHILITESLIDERDRAWDATA", parseDrawData }, - { "SLIDERTHUMBENABLEDDRAWDATA", parseDrawData }, - { "SLIDERTHUMBDISABLEDDRAWDATA", parseDrawData }, - { "SLIDERTHUMBHILITEDRAWDATA", parseDrawData }, - - { "COMBOBOXDROPDOWNBUTTONENABLEDDRAWDATA", parseDrawData }, - { "COMBOBOXDROPDOWNBUTTONDISABLEDDRAWDATA", parseDrawData }, - { "COMBOBOXDROPDOWNBUTTONHILITEDRAWDATA", parseDrawData }, - { "COMBOBOXEDITBOXENABLEDDRAWDATA", parseDrawData }, - { "COMBOBOXEDITBOXDISABLEDDRAWDATA", parseDrawData }, - { "COMBOBOXEDITBOXHILITEDRAWDATA", parseDrawData }, - { "COMBOBOXLISTBOXENABLEDDRAWDATA", parseDrawData }, - { "COMBOBOXLISTBOXDISABLEDDRAWDATA", parseDrawData }, - { "COMBOBOXLISTBOXHILITEDRAWDATA", parseDrawData }, - - { "IMAGEOFFSET", parseImageOffset }, - { "TOOLTIP", parseTooltip }, - - { nullptr, nullptr } -}; - -// parseWindow ================================================================ -/** Parse a WINDOW entry in the script. */ -//============================================================================= -static GameWindow *parseWindow( File *inFile, char *buffer ) -{ - GameWindowParse *parse; - GameWindow *window = nullptr; - GameWindow *parent = peekWindow(); - WinInstanceData instData; - char type[64]; - char token[ 256 ]; - char *c; - Int x, y, width, height; - void *data = nullptr; - ICoord2D parentSize; - AsciiString asciibuf; - - // - // reset our 'static globals' that house the current parsed window callback - // definitions to empty - // - systemFunc = nullptr; - inputFunc = nullptr; - tooltipFunc = nullptr; - drawFunc = nullptr; - theSystemString.clear(); - theInputString.clear(); - theTooltipString.clear(); - theDrawString.clear(); - - // get the size of the parent, or if no parent present the screen - if( parent ) - { - parent->winGetSize( &parentSize.x, &parentSize.y ); - } - else - { - parentSize.x = TheDisplay->getWidth(); - parentSize.y = TheDisplay->getHeight(); - } - - // Initialize the instance data to the defaults - /// @todo need to support enabled/disabled/hilite text colors here - instData.init(); - instData.m_enabledText.color = defTextColor; - instData.m_enabledText.borderColor = defTextColor; - instData.m_disabledText.color = defTextColor; - instData.m_disabledText.borderColor = defTextColor; - instData.m_hiliteText.color = defTextColor; - instData.m_hiliteText.borderColor = defTextColor; - - /// @todo need real font support here - instData.m_font = defFont; - - // - // read the first few lines that are required to be first in a - // window definition file including position, size, type, and id - // - - // window type - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - c = strtok( buffer, seps ); - assert( strcmp( c, "WINDOWTYPE" ) == 0 ); - c = strtok( nullptr, seps ); // get data to right of = sign - strlcpy(type, c, ARRAY_SIZE(type)); - - // - // based on the window type get a pointer for any specific data - // for the gadget controls needed - // - data = getDataTemplate( type ); - - // position - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - c = strtok( buffer, seps ); - assert( strcmp( c, "SCREENRECT" ) == 0 ); - if( parseScreenRect( c, buffer, &x, &y, &width, &height ) == FALSE ) - goto cleanupAndExit; - - // parse all the field definitions - while( TRUE ) - { - - // get token - inFile->scanString(asciibuf); - - // parse field - for( parse = gameWindowFieldList; parse->parse; parse++ ) - { - - if (asciibuf.compare(parse->name) == 0) - { - - strlcpy(token, asciibuf.str(), ARRAY_SIZE(token)); - - // eat '=' - inFile->scanString(asciibuf); - - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - - if (parse->parse( token, &instData, buffer, data ) == FALSE ) - { - DEBUG_LOG(( "parseGameObject: Error parsing %s", parse->name )); - goto cleanupAndExit; - } - - break; - } - - } - - if( parse->parse == nullptr ) - { - - // If it's the END keyword - if (asciibuf.compare("DATA") == 0) - { - - // eat '=' - inFile->scanString(asciibuf); - - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - - if( parseData( &data, type, buffer ) == FALSE ) - { - DEBUG_LOG(( "parseGameWindow: Error parsing %s", parse->name )); - goto cleanupAndExit; - } - - } - else if (asciibuf.compare("END") == 0) - { - // Check to see if we have a header template, if so, set the font equal to that. - if(TheHeaderTemplateManager->getFontFromTemplate(instData.m_headerTemplateName)) - instData.m_font = TheHeaderTemplateManager->getFontFromTemplate(instData.m_headerTemplateName); - - // Create a window using the current description - if( window == nullptr ) - window = createWindow( type, instData.m_id, instData.getStatus(), x, y, - width, height, &instData, data, - systemFunc, inputFunc, tooltipFunc, drawFunc ); - - - goto cleanupAndExit; - - } - else if (asciibuf.compare("CHILD") == 0) - { - - // Create a window using the current description - window = createWindow( type, instData.m_id, instData.getStatus(), x, y, - width, height, &instData, data, - systemFunc, inputFunc, tooltipFunc, drawFunc ); - - if (window == nullptr) - goto cleanupAndExit; - - // Parses the CHILD's window info. - if( parseChildWindows( window, inFile, buffer ) == FALSE ) - { - - TheWindowManager->winDestroy( window ); - window = nullptr; - goto cleanupAndExit; - - } - - } - else - { - - // Else it is unrecognized so eat associated data - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - - } - - } - - } - -cleanupAndExit: - - // - // this should be true since we should never set the text in - // display strings in a instance data that is not inside a - // window ... it's for sanity checking - // - // I am commenting this out to get tooltips working, If for - // some reason we start having displayString problems... CLH -// assert( instData.m_text == nullptr && instData.m_tooltip == nullptr ); - - return window; - -} - -//================================================================================================= -//================================================================================================= -//================================================================================================= - -//------------------------------------------------------------------------------------------------- -/** Parse init for layout file */ -//------------------------------------------------------------------------------------------------- -Bool parseInit( const char *token, char *buffer, UnsignedInt version, WindowLayoutInfo *info ) -{ - char *c; - const char *seps = " \n\r\t"; - - // get string - c = strtok( buffer, seps ); - - // translate string to function address - info->initNameString = c; - info->init = TheFunctionLexicon->winLayoutInitFunc( TheNameKeyGenerator->nameToKey( info->initNameString ) ); - - return TRUE; // success - -} - -//------------------------------------------------------------------------------------------------- -/** Parse update for layout file */ -//------------------------------------------------------------------------------------------------- -Bool parseUpdate( const char *token, char *buffer, UnsignedInt version, WindowLayoutInfo *info ) -{ - char *c; - const char *seps = " \n\r\t"; - - // get string - c = strtok( buffer, seps ); - - // translate string to function address - info->updateNameString = c; - info->update = TheFunctionLexicon->winLayoutUpdateFunc( TheNameKeyGenerator->nameToKey( info->updateNameString ) ); - - return TRUE; // success - -} - -//------------------------------------------------------------------------------------------------- -/** Parse shutdown for layout file */ -//------------------------------------------------------------------------------------------------- -Bool parseShutdown( const char *token, char *buffer, UnsignedInt version, WindowLayoutInfo *info ) -{ - char *c; - const char *seps = " \n\r\t"; - - // get string - c = strtok( buffer, seps ); - - // translate string to function address - info->shutdownNameString = c; - info->shutdown = TheFunctionLexicon->winLayoutShutdownFunc( TheNameKeyGenerator->nameToKey( info->shutdownNameString ) ); - - return TRUE; // success - -} - -static LayoutScriptParse layoutScriptTable[] = -{ - { "LAYOUTINIT", parseInit }, - { "LAYOUTUPDATE", parseUpdate }, - { "LAYOUTSHUTDOWN", parseShutdown }, - - { nullptr, nullptr }, - -}; - -//------------------------------------------------------------------------------------------------- -/** Parse the layout block which MUST be present in every window file */ -//------------------------------------------------------------------------------------------------- -Bool parseLayoutBlock( File *inFile, char *buffer, UnsignedInt version, WindowLayoutInfo *info ) -{ - LayoutScriptParse *parse; - char token[ 256 ]; - - AsciiString asciitoken; - if (inFile->scanString(asciitoken) == FALSE) { - return FALSE; - } - - // better be the layout block - if (asciitoken.compare("STARTLAYOUTBLOCK") != 0) { - return FALSE; - } - - while( TRUE ) - { - - // get next token - inFile->scanString(asciitoken); - - // check for end - if (asciitoken.compare("ENDLAYOUTBLOCK") == 0) { - break; - } - - // search for token in the table - for( parse = layoutScriptTable; parse && parse->name; parse++ ) - { - - if (asciitoken.compare(parse->name) == 0) - { - char *c; - - // read from file - readUntilSemicolon( inFile, buffer, WIN_BUFFER_LENGTH ); - - // eat equals separator " = " - c = strtok( buffer, " =" ); - - strlcpy(token, asciitoken.str(), ARRAY_SIZE(token)); - - // parse it - if( parse->parse( token, c, version, info ) == FALSE ) - return FALSE; - - break; // exit for - - } - - } - - } - - return TRUE; - -} - -/////////////////////////////////////////////////////////////////////////////// -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -// GameWindowManager::winCreateLayout ========================================= -/** Load window(s) from a .wnd definition file and wrap within a - * new window layout */ -//============================================================================= -WindowLayout *GameWindowManager::winCreateLayout( AsciiString filename ) -{ - WindowLayout *layout; - - // allocate a new window layout - layout = newInstance(WindowLayout); - - // load windows into layout - if( layout->load( filename ) == FALSE ) - { - - deleteInstance(layout); - return nullptr; - - } - - // return loaded layout - return layout; - -} - -/** Free up the memory used by static strings. Normally this memory -is freed by the string destructor but we do it here to make the -memory leak detection code happy.*/ -void GameWindowManager::freeStaticStrings() -{ - theSystemString.clear(); - theInputString.clear(); - theTooltipString.clear(); - theDrawString.clear(); -} - -WindowLayoutInfo::WindowLayoutInfo() : - version(0), - init(nullptr), - update(nullptr), - shutdown(nullptr), - initNameString(AsciiString::TheEmptyString), - updateNameString(AsciiString::TheEmptyString), - shutdownNameString(AsciiString::TheEmptyString) -{ - windows.clear(); -} - -// GameWindowManager::winCreateFromScript ===================================== -/** Parse through a window .wnd file and create all the windows - * within it. - * - * NOTE: The FIRST window created from the script is returned, this - * way if you want to know ALL of the windows created from this - * layout file you must iterate over info->windows, since the windows will - * not be at the head of the window list if there is a modal window active. - */ -//============================================================================= -GameWindow *GameWindowManager::winCreateFromScript( AsciiString filenameString, - WindowLayoutInfo *info ) -{ - const char* filename = filenameString.str(); - static char buffer[ WIN_BUFFER_LENGTH ]; // input buffer for reading - GameWindow *firstWindow = nullptr; - GameWindow *window; - char filepath[ _MAX_PATH ] = "Window\\"; - File *inFile; - WindowLayoutInfo scriptInfo; - AsciiString asciibuf; - - // zero info struct - //memset( &scriptInfo, 0, sizeof( WindowLayoutInfo ) ); // it's a class - use a constructor - - // Reset the window stack - resetWindowStack(); - resetWindowDefaults(); - - // - // get the filename from the parameter, if it doesn't contain a '\' it is - // a it is assumed to be a filename only, which we will prefix a "window\" - // directory to, otherwise it is assumed to be an absolute path. When using - // a filename only make sure the current directory is set to the right - // place for the window files subdirectory - // - if( strchr( filename, '\\' ) == nullptr ) - snprintf( filepath, ARRAY_SIZE(filepath), "Window\\%s", filename ); - else - strlcpy(filepath, filename, ARRAY_SIZE(filepath)); - - // Open the input file - inFile = TheFileSystem->openFile(filepath, File::READ); - if (inFile == nullptr) - { - DEBUG_LOG(( "WinCreateFromScript: Cannot access file '%s'.", filename )); - return nullptr; - } - - // read the file version - Int version; - inFile->read(nullptr, strlen("FILE_VERSION = ")); - inFile->scanInt(version); - inFile->nextLine(); - - // version 2+ have a special block called the layout block - if( version >= 2 ) - { - - if( parseLayoutBlock( inFile, buffer, version, &scriptInfo ) == FALSE ) - { - - DEBUG_LOG(( "WinCreateFromScript: Error parsing layout block" )); - return FALSE; - - } - - } - else - { - - // default none names - scriptInfo.initNameString = "[None]"; - scriptInfo.updateNameString = "[None]"; - scriptInfo.shutdownNameString = "[None]"; - - } - - while( TRUE ) - { - - if (inFile->scanString(asciibuf) == FALSE) { - break; - } - - if (asciibuf.compare("END") == 0) { - continue; - } - - if (asciibuf.compare("ENABLEDCOLOR") == 0) - { - - if( parseDefaultColor( &defEnabledColor, inFile, buffer ) == FALSE ) - { - inFile->close(); - inFile = nullptr; - return nullptr; - } - - } - else if (asciibuf.compare("DISABLEDCOLOR") == 0) - { - - if( parseDefaultColor( &defDisabledColor, inFile, buffer ) == FALSE ) - { - inFile->close(); - inFile = nullptr; - return nullptr; - } - - } - else if (asciibuf.compare("HILITECOLOR") == 0) - { - - if( parseDefaultColor( &defHiliteColor, inFile, buffer ) == FALSE ) - { - inFile->close(); - inFile = nullptr; - return nullptr; - } - - } - else if (asciibuf.compare("SELECTEDCOLOR") == 0) - { - - if( parseDefaultColor( &defSelectedColor, inFile, buffer ) == FALSE ) - { - inFile->close(); - inFile = nullptr; - return nullptr; - } - - } - else if (asciibuf.compare("TEXTCOLOR") == 0) - { - - if( parseDefaultColor( &defTextColor, inFile, buffer ) == FALSE ) - { - inFile->close(); - inFile = nullptr; - return nullptr; - } - - } - else if (asciibuf.compare("BACKGROUNDCOLOR") == 0) - { - - if( parseDefaultColor( &defBackgroundColor, inFile, buffer ) == FALSE ) - { - inFile->close(); - inFile = nullptr; - return nullptr; - } - - } - else if (asciibuf.compare("FONT") == 0) - { - - if( parseDefaultFont( defFont, inFile, buffer ) == FALSE ) - { - inFile->close(); - inFile = nullptr; - return nullptr; - } - - } - else if (asciibuf.compare("WINDOW") == 0) - { - - // Parse window descriptions until the last END is read - window = parseWindow( inFile, buffer ); - - // save first window created - if( firstWindow == nullptr ) - firstWindow = window; - - scriptInfo.windows.push_back(window); - - } - - } - - // close the file - inFile->close(); - inFile = nullptr; - - // if info parameter is provided, copy info to the param - if( info ) - *info = scriptInfo; - - // return the first window created - return firstWindow; - -} - diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp deleted file mode 100644 index 9ea44f2d90b..00000000000 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp +++ /dev/null @@ -1,2247 +0,0 @@ -/* -** Command & Conquer Generals(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -// FILE: GameWindowTransitionsStyles.cpp ///////////////////////////////////////////////// -//----------------------------------------------------------------------------- -// -// Electronic Arts Pacific. -// -// Confidential Information -// Copyright (C) 2002 - All Rights Reserved -// -//----------------------------------------------------------------------------- -// -// created: Dec 2002 -// -// Filename: GameWindowTransitionsStyles.cpp -// -// author: Chris Huybregts -// -// purpose: The Actual Styles that can fire off. -// -//----------------------------------------------------------------------------- -/////////////////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------------- -// SYSTEM INCLUDES //////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "PreRTS.h" // This must go first in EVERY cpp file in the GameEngine - -//----------------------------------------------------------------------------- -// USER INCLUDES ////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -#include "Common/AudioEventRTS.h" -#include "Common/GameAudio.h" -#include "GameClient/GameWindowTransitions.h" -#include "GameClient/GameWindow.h" -#include "GameClient/GameWindowManager.h" -#include "GameClient/Display.h" -#include "GameClient/DisplayStringManager.h" -#include "GameClient/GadgetPushButton.h" -#include "GameClient/GadgetStaticText.h" -#include "GameClient/ControlBar.h" - -//----------------------------------------------------------------------------- -// DEFINES //////////////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -static void drawTypeText( GameWindow *window, DisplayString *str); -//----------------------------------------------------------------------------- -// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- -Transition::Transition () -{ - -} - -Transition::~Transition() -{ - -} -//----------------------------------------------------------------------------- - -FlashTransition::FlashTransition () -{ - m_frameLength = FLASHTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -FlashTransition::~FlashTransition() -{ - m_win = nullptr; -} - -void FlashTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - m_isForward = FALSE; - update(FLASHTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - -} - -void FlashTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < FLASHTRANSITION_START || frame > FLASHTRANSITION_END) - { - DEBUG_CRASH(("FlashTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case FLASHTRANSITION_START: - { - - if(m_isForward || !m_win) - break; - m_win->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case FLASHTRANSITION_FADE_IN_1: - if(m_isForward) - { - AudioEventRTS buttonClick("GUIBoarderFadeIn"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - - } - FALLTHROUGH; - - case FLASHTRANSITION_FADE_IN_2: - case FLASHTRANSITION_FADE_IN_3: - { - if(!m_win) - break; - m_win->winHide(TRUE); - m_drawState = frame; - } - break; - case FLASHTRANSITION_FADE_TO_BACKGROUND_1: - case FLASHTRANSITION_FADE_TO_BACKGROUND_2: - case FLASHTRANSITION_FADE_TO_BACKGROUND_3: - case FLASHTRANSITION_FADE_TO_BACKGROUND_4: - { - if(!m_win) - break; - m_win->winHide(FALSE); - m_drawState = frame; - } - break; - case FLASHTRANSITION_END: - { - if(!m_isForward || !m_win) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - } - break; - } - - -} - -void FlashTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void FlashTransition::draw() -{ - switch (m_drawState) - { - case FLASHTRANSITION_FADE_IN_1: - { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 203, 45,100)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 203, 45, 33)); - } - break; - case FLASHTRANSITION_FADE_IN_2: - { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 203, 45,150)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 203, 45, 66)); - } - break; - case FLASHTRANSITION_FADE_IN_3: - { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 203, 45,200)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 203, 45, 99)); - } - break; - case FLASHTRANSITION_FADE_TO_BACKGROUND_1: - { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 203, 45, 75)); - } - break; - case FLASHTRANSITION_FADE_TO_BACKGROUND_2: - { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 203, 45,50)); - } - break; - case FLASHTRANSITION_FADE_TO_BACKGROUND_3: - { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 203, 45, 25)); - } - break; - case FLASHTRANSITION_FADE_TO_BACKGROUND_4: - { - TheDisplay->drawOpenRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x+1, m_pos.y+1,m_size.x-2, m_size.y, GameMakeColor(255, 203, 45, 10)); - } - break; - } -} - -void FlashTransition::skip() -{ - update(FLASHTRANSITION_END); -} - -//----------------------------------------------------------------------------- - - -ButtonFlashTransition::ButtonFlashTransition () -{ - m_frameLength = BUTTONFLASHTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -ButtonFlashTransition::~ButtonFlashTransition() -{ - m_win = nullptr; -} - -void ButtonFlashTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - m_isForward = FALSE; - update(BUTTONFLASHTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - m_gradient = (Image *)TheMappedImageCollection->findImageByName("Gradient"); -} - -void ButtonFlashTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < BUTTONFLASHTRANSITION_START || frame > BUTTONFLASHTRANSITION_END) - { - DEBUG_CRASH(("ButtonFlashTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case BUTTONFLASHTRANSITION_START: - { - - if(m_isForward || !m_win) - break; - m_win->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case BUTTONFLASHTRANSITION_FADE_IN_1: - { - if(!m_win) - break; - m_win->winHide(TRUE); - if(m_isForward) - { - AudioEventRTS buttonClick("GUIButtonsFadeIn"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - - m_drawState = frame; - } - else - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_4; - } - break; - case BUTTONFLASHTRANSITION_FADE_IN_2: - { - if(!m_win) - break; - m_win->winHide(TRUE); - if(m_isForward) - m_drawState = frame; - else - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_3; - } - break; - case BUTTONFLASHTRANSITION_FADE_IN_3: - { - if(!m_win) - break; - m_win->winHide(TRUE); - if(m_isForward) - m_drawState = frame; - else - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_2; - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_1: - { - if(!m_win) - break; - m_win->winHide(TRUE); - if(m_isForward) - m_drawState = frame; - else - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_1; - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_2: - { - if(!m_win) - break; - m_win->winHide(TRUE); - if(m_isForward) - m_drawState = frame; - else - m_drawState = BUTTONFLASHTRANSITION_FADE_IN_3; - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_3: - { - if(!m_win) - break; - m_win->winHide(TRUE); - if(m_isForward) - m_drawState = frame; - else - m_drawState = BUTTONFLASHTRANSITION_FADE_IN_2; - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_4: - { - if(!m_win) - break; - m_win->winHide(TRUE); - if(m_isForward) - m_drawState = frame; - else - m_drawState = BUTTONFLASHTRANSITION_FADE_IN_1; - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_1: - { - if(!m_win) - break; - if(m_isForward) - { -// AudioEventRTS buttonClick("GUIBlip"); -// -// if( TheAudio ) -// { -// TheAudio->addAudioEvent( &buttonClick ); -// } // end if - - m_win->winHide(FALSE); - m_drawState = frame; - } - else - { - - m_win->winHide(TRUE); - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_4; - } - - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_2: - { - if(!m_win) - break; - if(m_isForward) - { - m_win->winHide(FALSE); - m_drawState = frame; - } - else - { - m_win->winHide(TRUE); - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_3; - } - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_1: - { - if(!m_win) - break; - if(m_isForward) - { - m_win->winHide(FALSE); - m_drawState = frame; - } - else - { - m_win->winHide(TRUE); - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_2; - } - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_2: - { - if(!m_win) - break; - if(m_isForward) - { - m_win->winHide(FALSE); - m_drawState = frame; - } - else - { - m_win->winHide(TRUE); - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_1; - } - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_3: - { - if(!m_win) - break; - if(m_isForward) - { - m_win->winHide(FALSE); - m_drawState = frame; - } - else - { - m_win->winHide(FALSE); - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_2; - } - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_4: - { - - if(!m_win) - break; - if(m_isForward) - { - m_win->winHide(FALSE); - m_drawState = frame; - } - else - { - m_win->winHide(FALSE); - m_drawState = BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_1; - } - - } - break; - case BUTTONFLASHTRANSITION_END: - { - if(!m_isForward || !m_win) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - } - break; - } - if(frame > BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_4 && frame < BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_1) - m_drawState = BUTTONFLASHTRANSITION_SHOW_BACKGROUND; - -} - -void ButtonFlashTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void ButtonFlashTransition::draw() -{ - switch (m_drawState) - { - case BUTTONFLASHTRANSITION_FADE_IN_1: - { - //PushButtonImageDrawThree(m_win, 100); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 203, 45,100)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 203, 45, 75)); - } - break; - case BUTTONFLASHTRANSITION_FADE_IN_2: - { - //PushButtonImageDrawThree(m_win, 150); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 203, 45,150)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 203, 45, 150)); - } - break; - case BUTTONFLASHTRANSITION_FADE_IN_3: - { - //PushButtonImageDrawThree(m_win, 200); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 203, 45,200)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 203, 45, 200)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_1: - { - PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 203, 45, 150)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_2: - { - PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 203, 45,100)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_3: - { - PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 203, 45, 50)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_BACKGROUND_4: - { - PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y,m_size.x, m_size.y, 1, GameMakeColor(255, 203, 45,250)); - TheDisplay->drawFillRect(m_pos.x, m_pos.y,m_size.x, m_size.y, GameMakeColor(255, 203, 45, 15)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_1: - { - if(m_isForward) - PushButtonImageDrawThree(m_win, 255); - TheDisplay->drawImage(m_gradient, m_pos.x, m_pos.y, m_pos.x +m_size.x, m_pos.y + m_size.y,GameMakeColor(255,255,255,100)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_IN_2: - { - TheDisplay->drawImage(m_gradient, m_pos.x, m_pos.y, m_pos.x +m_size.x, m_pos.y + m_size.y,GameMakeColor(255,255,255,200)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_1: - { - if(!m_isForward) - PushButtonImageDrawThree(m_win, 255); - - TheDisplay->drawImage(m_gradient, m_pos.x, m_pos.y, m_pos.x +m_size.x, m_pos.y + m_size.y,GameMakeColor(255,255,255,150)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_2: - { - if(!m_isForward) - PushButtonImageDrawThree(m_win, 255); - - TheDisplay->drawImage(m_gradient, m_pos.x, m_pos.y, m_pos.x +m_size.x, m_pos.y + m_size.y,GameMakeColor(255,255,255,100)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_3: - { - if(!m_isForward) - PushButtonImageDrawThree(m_win, 255); - - TheDisplay->drawImage(m_gradient, m_pos.x, m_pos.y, m_pos.x +m_size.x, m_pos.y + m_size.y,GameMakeColor(255,255,255,50)); - } - break; - case BUTTONFLASHTRANSITION_FADE_TO_GRADE_OUT_4: - { - if(!m_isForward) - PushButtonImageDrawThree(m_win, 255); - - TheDisplay->drawImage(m_gradient, m_pos.x, m_pos.y, m_pos.x +m_size.x, m_pos.y + m_size.y,GameMakeColor(255,255,255,17)); - } - break; - case BUTTONFLASHTRANSITION_SHOW_BACKGROUND: - { - PushButtonImageDrawThree(m_win, 255); - } - break; - - } -} - -void ButtonFlashTransition::skip() -{ - update(BUTTONFLASHTRANSITION_END); -} - - -//----------------------------------------------------------------------------- - -FadeTransition::FadeTransition () -{ - m_frameLength = FADETRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -FadeTransition::~FadeTransition() -{ - m_win = nullptr; -} - -void FadeTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - m_isForward = FALSE; - update(FADETRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; -} - -void FadeTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < FADETRANSITION_START || frame > FADETRANSITION_END) - { - DEBUG_CRASH(("FadeTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case FADETRANSITION_START: - { - - if(m_isForward || !m_win) - break; - m_win->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case FADETRANSITION_FADE_IN_1: - case FADETRANSITION_FADE_IN_2: - case FADETRANSITION_FADE_IN_3: - case FADETRANSITION_FADE_IN_4: - case FADETRANSITION_FADE_IN_5: - case FADETRANSITION_FADE_IN_6: - case FADETRANSITION_FADE_IN_7: - case FADETRANSITION_FADE_IN_8: - case FADETRANSITION_FADE_IN_9: - m_win->winHide(TRUE); - - m_drawState = frame; - break; - case FADETRANSITION_END: - { - if(!m_isForward || !m_win) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - } - } -} - -void FadeTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void FadeTransition::draw() -{ - if(!m_win) - return; - if(m_drawState <= FADETRANSITION_START || m_drawState >= FADETRANSITION_END) - return; - const Image *image = m_win->winGetEnabledImage(0); - switch (m_drawState) - { - case FADETRANSITION_FADE_IN_1: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 25)); - } - break; - case FADETRANSITION_FADE_IN_2: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 50)); - } - break; - case FADETRANSITION_FADE_IN_3: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 75)); - } - break; - case FADETRANSITION_FADE_IN_4: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 100)); - } - break; - case FADETRANSITION_FADE_IN_5: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 125)); - } - break; - case FADETRANSITION_FADE_IN_6: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 150)); - } - break; - case FADETRANSITION_FADE_IN_7: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 175)); - } - break; - case FADETRANSITION_FADE_IN_8: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 200)); - } - break; - case FADETRANSITION_FADE_IN_9: - { - TheDisplay->drawImage(image, m_pos.x, m_pos.y, m_pos.x + m_size.x, m_pos.y + m_size.y, GameMakeColor(255, 255, 255, 225)); - } - } -} - -void FadeTransition::skip() -{ - update(FADETRANSITION_END); -} -//----------------------------------------------------------------------------- - -ScaleUpTransition::ScaleUpTransition () -{ - m_frameLength = SCALEUPTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -ScaleUpTransition::~ScaleUpTransition() -{ - m_win = nullptr; -} - -void ScaleUpTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - m_isForward = FALSE; - update(SCALEUPTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - m_centerPos.x = m_pos.x + m_size.x / 2; - m_centerPos.y = m_pos.y + m_size.y / 2; - m_incrementSize.x = m_size.x / SCALEUPTRANSITION_END; - m_incrementSize.y = m_size.y / SCALEUPTRANSITION_END; - -} - -void ScaleUpTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < SCALEUPTRANSITION_START || frame > SCALEUPTRANSITION_END) - { - DEBUG_CRASH(("ScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case SCALEUPTRANSITION_START: - { - if(m_isForward || !m_win) - break; - m_win->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case SCALEUPTRANSITION_1: - if(m_isForward) - { - AudioEventRTS buttonClick("GUILogoMouseOver"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - - } - FALLTHROUGH; - - case SCALEUPTRANSITION_2: - case SCALEUPTRANSITION_3: - case SCALEUPTRANSITION_4: - case SCALEUPTRANSITION_5: -// case SCALEUPTRANSITION_6: -// case SCALEUPTRANSITION_7: -// case SCALEUPTRANSITION_8: -// case SCALEUPTRANSITION_9: -// case SCALEUPTRANSITION_10: -// case SCALEUPTRANSITION_11: -// case SCALEUPTRANSITION_12: -// case SCALEUPTRANSITION_13: -// case SCALEUPTRANSITION_14: -// case SCALEUPTRANSITION_15: -// case SCALEUPTRANSITION_16: -// case SCALEUPTRANSITION_17: -// case SCALEUPTRANSITION_18: -// case SCALEUPTRANSITION_19: - if(m_win) - m_win->winHide(TRUE); - m_drawState = frame; - break; - case SCALEUPTRANSITION_END: - { - if(!m_isForward || !m_win) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - } - } -} - -void ScaleUpTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void ScaleUpTransition::draw() -{ - if(!m_win) - return; - if(m_drawState <= SCALEUPTRANSITION_START || m_drawState >= SCALEUPTRANSITION_END) - return; - const Image *image = m_win->winGetEnabledImage(0); - Int x = m_centerPos.x - ((m_incrementSize.x * m_drawState) / 2); - Int y = m_centerPos.y - ((m_incrementSize.y * m_drawState) / 2); - Int x1 = x + m_incrementSize.x * m_drawState; - Int y1 = y + m_incrementSize.y * m_drawState; - TheDisplay->drawImage(image, x,y, x1, y1); -} - -void ScaleUpTransition::skip() -{ - update(SCALEUPTRANSITION_END); -} - -//----------------------------------------------------------------------------- - -ScoreScaleUpTransition::ScoreScaleUpTransition () -{ - m_frameLength = SCORESCALEUPTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -ScoreScaleUpTransition::~ScoreScaleUpTransition() -{ - m_win = nullptr; -} - -void ScoreScaleUpTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - m_isForward = FALSE; - update(SCORESCALEUPTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - m_centerPos.x = m_pos.x + m_size.x / 2; - m_centerPos.y = m_pos.y + m_size.y / 2; - m_incrementSize.x = m_size.x / SCORESCALEUPTRANSITION_END; - m_incrementSize.y = m_size.y / SCORESCALEUPTRANSITION_END; - -} - -void ScoreScaleUpTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < SCORESCALEUPTRANSITION_START || frame > SCORESCALEUPTRANSITION_END) - { - DEBUG_CRASH(("ScoreScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case SCORESCALEUPTRANSITION_START: - { - if(m_isForward || !m_win) - break; - m_win->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case SCORESCALEUPTRANSITION_1: - if(m_isForward) - { - AudioEventRTS buttonClick("GUIScoreScreenPictures"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - - } - FALLTHROUGH; - - case SCORESCALEUPTRANSITION_2: - case SCORESCALEUPTRANSITION_3: - case SCORESCALEUPTRANSITION_4: - case SCORESCALEUPTRANSITION_5: -// case SCORESCALEUPTRANSITION_6: -// case SCORESCALEUPTRANSITION_7: -// case SCORESCALEUPTRANSITION_8: -// case SCORESCALEUPTRANSITION_9: -// case SCORESCALEUPTRANSITION_10: -// case SCORESCALEUPTRANSITION_11: -// case SCORESCALEUPTRANSITION_12: -// case SCORESCALEUPTRANSITION_13: -// case SCORESCALEUPTRANSITION_14: -// case SCORESCALEUPTRANSITION_15: -// case SCORESCALEUPTRANSITION_16: -// case SCORESCALEUPTRANSITION_17: -// case SCORESCALEUPTRANSITION_18: -// case SCORESCALEUPTRANSITION_19: - if(m_win) - m_win->winHide(TRUE); - m_drawState = frame; - break; - case SCORESCALEUPTRANSITION_END: - { - if(!m_isForward || !m_win) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - } - } -} - -void ScoreScaleUpTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void ScoreScaleUpTransition::draw() -{ - if(!m_win) - return; - if(m_drawState <= SCORESCALEUPTRANSITION_START || m_drawState >= SCORESCALEUPTRANSITION_END) - return; - const Image *image = m_win->winGetEnabledImage(0); - Int x = m_centerPos.x - ((m_incrementSize.x * m_drawState) / 2); - Int y = m_centerPos.y - ((m_incrementSize.y * m_drawState) / 2); - Int x1 = x + m_incrementSize.x * m_drawState; - Int y1 = y + m_incrementSize.y * m_drawState; - TheDisplay->drawImage(image, x,y, x1, y1); -} - -void ScoreScaleUpTransition::skip() -{ - update(SCORESCALEUPTRANSITION_END); -} - -//----------------------------------------------------------------------------- - -MainMenuScaleUpTransition::MainMenuScaleUpTransition () -{ - m_frameLength = MAINMENUSCALEUPTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -MainMenuScaleUpTransition::~MainMenuScaleUpTransition() -{ - m_win = nullptr; -} - -void MainMenuScaleUpTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - m_growWin = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("MainMenu.wnd:WinGrowMarker")); - if(!m_growWin) - return; - - m_growWin->winGetSize(&m_growSize.x, &m_growSize.y); - m_growWin->winGetScreenPosition(&m_growPos.x, &m_growPos.y ); - - m_isForward = FALSE; - update(MAINMENUSCALEUPTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - m_incrementPos.x = (m_growPos.x - m_pos.x) / MAINMENUSCALEUPTRANSITION_END; - m_incrementPos.y = (m_growPos.y - m_pos.y) / MAINMENUSCALEUPTRANSITION_END; - m_incrementSize.x = (m_growSize.x - m_size.x) / MAINMENUSCALEUPTRANSITION_END; - m_incrementSize.y = (m_growSize.y - m_size.y) / MAINMENUSCALEUPTRANSITION_END; - const Image *image = m_win->winGetDisabledImage(0); - m_growWin->winSetEnabledImage(0, image); - -} - -void MainMenuScaleUpTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < MAINMENUSCALEUPTRANSITION_START || frame > MAINMENUSCALEUPTRANSITION_END) - { - DEBUG_CRASH(("MainMenuScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case MAINMENUSCALEUPTRANSITION_START: - { - - if(m_isForward || !m_win || !m_growWin) - break; -// m_win->winHide(TRUE); - m_growWin->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case MAINMENUSCALEUPTRANSITION_END: - { - if(!m_isForward || !m_win || !m_growWin) - break; - m_win->winHide(TRUE); - m_growWin->winHide(FALSE); - m_isFinished = TRUE; - } - } - if(frame == 1) - { - AudioEventRTS buttonClick("GUILogoSelect"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - } - if(frame > MAINMENUSCALEUPTRANSITION_START && frame < MAINMENUSCALEUPTRANSITION_END) - { - if(m_win) - m_win->winHide(TRUE); - if(m_growWin) - m_growWin->winHide(TRUE); - m_drawState = frame; - } - -} - -void MainMenuScaleUpTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void MainMenuScaleUpTransition::draw() -{ - if(!m_win) - return; - if(m_drawState <= MAINMENUSCALEUPTRANSITION_START || m_drawState >= MAINMENUSCALEUPTRANSITION_END) - return; - const Image *image = m_growWin->winGetEnabledImage(0); - Int x = m_pos.x + ((m_incrementPos.x * m_drawState)); - Int y = m_pos.y + ((m_incrementPos.y * m_drawState)); - Int x1 = x + m_size.x + ((m_incrementSize.x * m_drawState)); - Int y1 = y + m_size.y + ((m_incrementSize.y * m_drawState)); - TheDisplay->drawImage(image, x,y, x1, y1); -} - -void MainMenuScaleUpTransition::skip() -{ - update(MAINMENUSCALEUPTRANSITION_END); -} - -//----------------------------------------------------------------------------- - -MainMenuMediumScaleUpTransition::MainMenuMediumScaleUpTransition () -{ - m_frameLength = MAINMENUMEDIUMSCALEUPTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -MainMenuMediumScaleUpTransition::~MainMenuMediumScaleUpTransition() -{ - m_win = nullptr; -} - -void MainMenuMediumScaleUpTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - AsciiString growWinName; - growWinName = m_win->winGetInstanceData()->m_decoratedNameString; - growWinName.concat("Medium"); - m_growWin = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey(growWinName)); - if(!m_growWin) - return; - - m_growWin->winGetSize(&m_growSize.x, &m_growSize.y); - m_growWin->winGetScreenPosition(&m_growPos.x, &m_growPos.y ); - - m_isForward = FALSE; - update(MAINMENUMEDIUMSCALEUPTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - m_incrementSize.x = (m_growSize.x - m_size.x) / MAINMENUMEDIUMSCALEUPTRANSITION_END; - m_incrementSize.y = (m_growSize.y - m_size.y) / MAINMENUMEDIUMSCALEUPTRANSITION_END; -// const Image *image = m_win->winGetEnabledImage(0); - //m_growWin->winSetEnabledImage(0, image); - -} - -void MainMenuMediumScaleUpTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < MAINMENUMEDIUMSCALEUPTRANSITION_START || frame > MAINMENUMEDIUMSCALEUPTRANSITION_END) - { - DEBUG_CRASH(("MainMenuMediumScaleUpTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case MAINMENUMEDIUMSCALEUPTRANSITION_START: - { - - if(m_isForward || !m_win || !m_growWin) - break; - m_win->winHide(FALSE); - m_growWin->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case MAINMENUMEDIUMSCALEUPTRANSITION_END: - { - if(!m_isForward || !m_win || !m_growWin) - break; - m_win->winHide(TRUE); - m_growWin->winHide(FALSE); - m_isFinished = TRUE; - } - } - if(frame > MAINMENUMEDIUMSCALEUPTRANSITION_START && frame < MAINMENUMEDIUMSCALEUPTRANSITION_END) - { - if(frame == 1 && m_isForward) - { - AudioEventRTS buttonClick("GUILogoMouseOver"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - } - if(m_win) - m_win->winHide(TRUE); - if(m_growWin) - m_growWin->winHide(TRUE); - m_drawState = frame; - } -} - -void MainMenuMediumScaleUpTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - m_win->winHide(TRUE); - m_growWin->winHide(TRUE); - -} - -void MainMenuMediumScaleUpTransition::draw() -{ - if(!m_win) - return; - if(m_drawState <= MAINMENUMEDIUMSCALEUPTRANSITION_START || m_drawState >= MAINMENUMEDIUMSCALEUPTRANSITION_END) - return; - const Image *image = m_win->winGetEnabledImage(0); - Int x = m_pos.x - ((m_incrementSize.x * m_drawState) /2); - Int y = m_pos.y - ((m_incrementSize.y * m_drawState) / 2); - Int x1 = m_pos.x + m_size.x + ((m_incrementSize.x * m_drawState) / 2); - Int y1 = m_pos.y + m_size.y + ((m_incrementSize.y * m_drawState) / 2); - TheDisplay->drawImage(image, x,y, x1, y1); -} - -void MainMenuMediumScaleUpTransition::skip() -{ - update(MAINMENUMEDIUMSCALEUPTRANSITION_END); -} -//----------------------------------------------------------------------------- - -MainMenuSmallScaleDownTransition::MainMenuSmallScaleDownTransition () -{ - m_frameLength = MAINMENUSMALLSCALEDOWNTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; -} - -MainMenuSmallScaleDownTransition::~MainMenuSmallScaleDownTransition() -{ - m_win = nullptr; -} - -void MainMenuSmallScaleDownTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - AsciiString growWinName; - growWinName = m_win->winGetInstanceData()->m_decoratedNameString; - growWinName.concat("Small"); - m_growWin = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey(growWinName)); - if(!m_growWin) - return; - - m_growWin->winGetSize(&m_growSize.x, &m_growSize.y); - m_growWin->winGetScreenPosition(&m_growPos.x, &m_growPos.y ); - - m_isForward = FALSE; - update(MAINMENUSMALLSCALEDOWNTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - m_incrementSize.x = (m_growSize.x - m_size.x) / MAINMENUSMALLSCALEDOWNTRANSITION_END; - m_incrementSize.y = (m_growSize.y - m_size.y) / MAINMENUSMALLSCALEDOWNTRANSITION_END; - const Image *image = m_win->winGetEnabledImage(0); - m_growWin->winSetEnabledImage(0, image); - -} - -void MainMenuSmallScaleDownTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < MAINMENUSMALLSCALEDOWNTRANSITION_START || frame > MAINMENUSMALLSCALEDOWNTRANSITION_END) - { - DEBUG_CRASH(("MainMenuSmallScaleDownTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case MAINMENUSMALLSCALEDOWNTRANSITION_START: - { - - if(m_isForward || !m_win || !m_growWin) - break; - m_win->winHide(FALSE); - m_growWin->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case MAINMENUSMALLSCALEDOWNTRANSITION_1: - case MAINMENUSMALLSCALEDOWNTRANSITION_2: - case MAINMENUSMALLSCALEDOWNTRANSITION_3: - case MAINMENUSMALLSCALEDOWNTRANSITION_4: - case MAINMENUSMALLSCALEDOWNTRANSITION_5: - if(m_win) - m_win->winHide(TRUE); - if(m_growWin) - m_growWin->winHide(TRUE); - m_drawState = frame; - break; - case MAINMENUSMALLSCALEDOWNTRANSITION_END: - { - if(!m_isForward || !m_win || !m_growWin) - break; - m_win->winHide(TRUE); - m_growWin->winHide(FALSE); - m_isFinished = TRUE; - } - } -} - -void MainMenuSmallScaleDownTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void MainMenuSmallScaleDownTransition::draw() -{ - if(!m_win) - return; - if(m_drawState <= MAINMENUSMALLSCALEDOWNTRANSITION_START || m_drawState >= MAINMENUSMALLSCALEDOWNTRANSITION_END) - return; - const Image *image = m_win->winGetEnabledImage(0); - Int x = m_pos.x - ((m_incrementSize.x * m_drawState) /2); - Int y = m_pos.y - ((m_incrementSize.y * m_drawState) / 2); - Int x1 = m_pos.x + m_size.x + ((m_incrementSize.x * m_drawState) / 2); - Int y1 = m_pos.y + m_size.y + ((m_incrementSize.y * m_drawState) / 2); - TheDisplay->drawImage(image, x,y, x1, y1); -} - -void MainMenuSmallScaleDownTransition::skip() -{ - update(MAINMENUSMALLSCALEDOWNTRANSITION_END); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TextTypeTransition::TextTypeTransition () -{ - m_frameLength = TEXTTYPETRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; - m_dStr = nullptr; -} - -TextTypeTransition::~TextTypeTransition() -{ - m_win = nullptr; - if(m_dStr) - TheDisplayStringManager->freeDisplayString(m_dStr); - m_dStr = nullptr; -} - -void TextTypeTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - m_isForward = FALSE; - update(TEXTTYPETRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - m_dStr = TheDisplayStringManager->newDisplayString(); - m_fullText = GadgetStaticTextGetText(m_win); - Int length = m_fullText.getLength(); - m_frameLength = MIN(length, TEXTTYPETRANSITION_END); -} - -void TextTypeTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < TEXTTYPETRANSITION_START || frame > TEXTTYPETRANSITION_END) - { - DEBUG_CRASH(("TextTypeTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case TEXTTYPETRANSITION_START: - { - - if(m_isForward || !m_win ) - break; - m_win->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case TEXTTYPETRANSITION_END: - { - if(!m_isForward || !m_win ) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - } - } - if(frame >= m_frameLength) - { - m_win->winHide(FALSE); - - } - if(frame > TEXTTYPETRANSITION_START && frame < m_frameLength) - { - m_win->winHide(TRUE); - m_drawState = frame; - AudioEventRTS buttonClick("GUITypeText"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - if(m_isForward) - { - m_partialText.concat(m_fullText.getCharAt(frame - 1)); - } - else - { - m_partialText.removeLastChar(); - } - } -} - -void TextTypeTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - - m_partialText = m_fullText; -} - -void TextTypeTransition::draw() -{ - if(m_drawState > TEXTTYPETRANSITION_START && m_drawState < m_frameLength) - { - m_dStr->setText(m_partialText); - drawTypeText(m_win, m_dStr); - } -} - -void TextTypeTransition::skip() -{ - update(TEXTTYPETRANSITION_END); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -CountUpTransition::CountUpTransition () -{ - m_frameLength = COUNTUPTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; - -} - -CountUpTransition::~CountUpTransition() -{ - m_win = nullptr; -} - -void CountUpTransition::init( GameWindow *win ) -{ - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - - if( m_win->winIsHidden() ) - { - m_isForward = TRUE; - m_isFinished = TRUE; - m_frameLength = 0; - return; - } - } - m_fullText = GadgetStaticTextGetText(m_win); - m_isForward = FALSE; - update(COUNTUPTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - AsciiString tempStr; - tempStr.translate(m_fullText); - m_intValue = atoi(tempStr.str()); - DEBUG_LOG(("CountUpTransition::init %hs %s %d", m_fullText.str(), tempStr.str(), m_intValue)); - if(m_intValue < COUNTUPTRANSITION_END) - { - m_countState = COUNT_ONES; - m_frameLength = MIN(m_intValue, COUNTUPTRANSITION_END); - } - else if(m_intValue/100 < COUNTUPTRANSITION_END) - { - m_countState = COUNT_100S; - m_frameLength = MIN(m_intValue/100, COUNTUPTRANSITION_END); - } - else - { - m_countState = COUNT_1000S; - m_frameLength = MIN(m_intValue/1000, COUNTUPTRANSITION_END); - } - - m_currentValue = 0; - UnicodeString currVal; - currVal.format(L"%d",m_currentValue); - GadgetStaticTextSetText(m_win, currVal); -} - -void CountUpTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < COUNTUPTRANSITION_START || frame > COUNTUPTRANSITION_END) - { - DEBUG_CRASH(("CountUpTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case COUNTUPTRANSITION_START: - { - - if(m_isForward || !m_win ) - break; - m_currentValue = 0; - UnicodeString currVal; - currVal.format(L"%d",m_currentValue); - GadgetStaticTextSetText(m_win, currVal); - - m_win->winHide(TRUE); - m_isFinished = TRUE; - } - break; - case COUNTUPTRANSITION_END: - { - if(!m_isForward || !m_win ) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - } - } - if(frame >= m_frameLength) - { - m_win->winHide(FALSE); - - } - if(frame > COUNTUPTRANSITION_START && frame < m_frameLength) - { - m_win->winHide(FALSE); - m_drawState = frame; - AudioEventRTS buttonClick("GUIScoreScreenTick"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - m_currentValue +=m_countState; - if(m_currentValue > m_intValue) - m_currentValue = m_intValue; - - UnicodeString currVal; - currVal.format(L"%d",m_currentValue); - GadgetStaticTextSetText(m_win, currVal); - } - if( frame == m_frameLength ) - { - GadgetStaticTextSetText(m_win, m_fullText); - m_isFinished = TRUE; - } -} - -void CountUpTransition::reverse() -{ - if( m_win->winIsHidden() ) - { - m_isForward = FALSE; - m_isFinished = TRUE; - m_frameLength = 0; - return; - } - m_isFinished = FALSE; - m_isForward = FALSE; - -} - -void CountUpTransition::draw() -{ -} - -void CountUpTransition::skip() -{ - if (!m_isFinished) - update(COUNTUPTRANSITION_END); -} - -//----------------------------------------------------------------------------- - -ScreenFadeTransition::ScreenFadeTransition () -{ - m_frameLength = SCREENFADETRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; - -} - -ScreenFadeTransition::~ScreenFadeTransition() -{ - m_win = nullptr; - -} - -void ScreenFadeTransition::init( GameWindow *win ) -{ - m_isForward = FALSE; - update(SCREENFADETRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - m_percent = 1.0f / (SCREENFADETRANSITION_END - 1); - - m_pos.y = m_pos.x = 0; - m_size.x = TheDisplay->getWidth(); - m_size.y = TheDisplay->getHeight(); - -} - -void ScreenFadeTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < SCREENFADETRANSITION_START || frame > SCREENFADETRANSITION_END) - { - DEBUG_CRASH(("ScreenFadeTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case SCREENFADETRANSITION_START: - { - m_isFinished = TRUE; - } - break; - case SCREENFADETRANSITION_END: - { - m_isFinished = TRUE; - } - } - m_drawState = frame; -} - -void ScreenFadeTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; -} - -void ScreenFadeTransition::draw() -{ - Int alpha = m_percent*255 *m_drawState; - if(alpha > 255) - alpha = 255; - TheDisplay->drawFillRect(m_pos.x, m_pos.y, m_size.x, m_size.y , GameMakeColor(0,0,0,alpha)); - -} - -void ScreenFadeTransition::skip() -{ - update(SCREENFADETRANSITION_END); -} - - -//----------------------------------------------------------------------------- - -ControlBarArrowTransition::ControlBarArrowTransition () -{ - m_frameLength = CONTROLBARARROWTRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; - m_arrowImage = nullptr; - -} - -ControlBarArrowTransition::~ControlBarArrowTransition() -{ - m_win = nullptr; - m_arrowImage = nullptr; -} - -void ControlBarArrowTransition::init( GameWindow *win ) -{ - m_isForward = FALSE; - update(CONTROLBARARROWTRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - m_percent = 1.0f / CONTROLBARARROWTRANSITION_BEGIN_FADE; - m_fadePercent = 1.0f/ (CONTROLBARARROWTRANSITION_END - CONTROLBARARROWTRANSITION_BEGIN_FADE); - - m_arrowImage = TheControlBar->getArrowImage(); - GameWindow *twin = TheWindowManager->winGetWindowFromId(nullptr, TheNameKeyGenerator->nameToKey("ControlBar.wnd:ButtonGeneral")); - if(!twin || !m_arrowImage) - { - m_isFinished = TRUE; - return; - } - ICoord2D screenPos, screenSize; - twin->winGetScreenPosition(&screenPos.x, &screenPos.y); - twin->winGetSize(&screenSize.x, &screenSize.y); - - m_incrementPos.x = 0; - m_incrementPos.y = screenPos.y * m_percent; - - m_pos.y = 0 - m_arrowImage->getImageHeight() + 20; - m_pos.x = (screenPos.x + screenSize.x /2) - m_arrowImage->getImageWidth() /2; - - m_size.x = m_arrowImage->getImageWidth(); - m_size.y = m_arrowImage->getImageHeight(); - -} - -void ControlBarArrowTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < CONTROLBARARROWTRANSITION_START || frame > CONTROLBARARROWTRANSITION_END) - { - DEBUG_CRASH(("ControlBarArrowTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case CONTROLBARARROWTRANSITION_START: - { - m_isFinished = TRUE; - } - break; - case CONTROLBARARROWTRANSITION_END: - { - m_isFinished = TRUE; - } - } - m_drawState = frame; -} - -void ControlBarArrowTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; -} - -void ControlBarArrowTransition::draw() -{ - if(m_drawState < CONTROLBARARROWTRANSITION_START) - return; - if(m_drawState < CONTROLBARARROWTRANSITION_BEGIN_FADE) - { - Int yPos = m_pos.y + m_incrementPos.y* m_drawState; - TheDisplay->drawImage(m_arrowImage, m_pos.x, yPos, m_pos.x + m_size.x, yPos + m_size.y ); - - } - else - { - Int alpha = (1 - (m_fadePercent *(m_drawState - CONTROLBARARROWTRANSITION_BEGIN_FADE )) )*255 ; - if(alpha > 255) - alpha = 255; - Int yPos = m_pos.y + m_incrementPos.y* (CONTROLBARARROWTRANSITION_BEGIN_FADE - 1); - - TheDisplay->drawImage(m_arrowImage, m_pos.x, yPos, m_pos.x + m_size.x, yPos + m_size.y , GameMakeColor(255,255,255,alpha)); - } - -} - -void ControlBarArrowTransition::skip() -{ - update(CONTROLBARARROWTRANSITION_END); -} - - - - - -//----------------------------------------------------------------------------- - -FullFadeTransition::FullFadeTransition () -{ - m_frameLength = FULLFADETRANSITION_END; - m_win = nullptr; - m_drawState = -1; - m_isForward = TRUE; - -} - -FullFadeTransition::~FullFadeTransition() -{ - m_win = nullptr; - -} - -void FullFadeTransition::init( GameWindow *win ) -{ - - if(win) - { - m_win = win; - m_win->winGetSize(&m_size.x, &m_size.y); - m_win->winGetScreenPosition(&m_pos.x, &m_pos.y ); - } - - m_isForward = FALSE; - update(FULLFADETRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - - m_percent = 1.0f / (FULLFADETRANSITION_END/2); - -} - -void FullFadeTransition::update( Int frame ) -{ - m_drawState = -1; - if(frame < FULLFADETRANSITION_START || frame > FULLFADETRANSITION_END) - { - DEBUG_CRASH(("FullFadeTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case FULLFADETRANSITION_START: - { - - if(m_isForward || !m_win ) - break; - - m_win->winHide(TRUE); - m_isFinished = TRUE; - - } - break; - case FULLFADETRANSITION_END: - { - if(!m_isForward || !m_win ) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - - } - } - if(frame == FULLFADETRANSITION_END/2) - { - if(m_isForward) - m_win->winHide(FALSE); - else - m_win->winHide(TRUE); - } - m_drawState = frame; -} - -void FullFadeTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; -} - -void FullFadeTransition::draw() -{ - Int alpha; - if(m_drawState > (FULLFADETRANSITION_END/2)) - alpha = m_percent * 255 * (FULLFADETRANSITION_END - m_drawState); - else - alpha = m_percent * 255 *m_drawState; - if(alpha > 255) - alpha = 255; - TheDisplay->drawFillRect(m_pos.x, m_pos.y, m_size.x, m_size.y , GameMakeColor(0,0,0,alpha)); - TheDisplay->drawOpenRect(m_pos.x, m_pos.y, m_size.x, m_size.y , 1.0f, GameMakeColor(255,190,0,alpha)); -} - -void FullFadeTransition::skip() -{ - update(FULLFADETRANSITION_END); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -TextOnFrameTransition::TextOnFrameTransition () -{ - m_frameLength = TEXTONFRAMETRANSITION_END; - m_win = nullptr; - m_isForward = TRUE; - -} - -TextOnFrameTransition::~TextOnFrameTransition() -{ - m_win = nullptr; - -} - -void TextOnFrameTransition::init( GameWindow *win ) -{ - - if(win) - { - m_win = win; - } - if(m_win->winIsHidden()) - { - m_isFinished = TRUE; - m_isForward = TRUE; - m_frameLength = 0; - } - else - { - m_isForward = FALSE; - update(TEXTONFRAMETRANSITION_START); - m_isFinished = FALSE; - m_isForward = TRUE; - } -} - -void TextOnFrameTransition::update( Int frame ) -{ - if(frame < TEXTONFRAMETRANSITION_START || frame > TEXTONFRAMETRANSITION_END) - { - DEBUG_CRASH(("TextOnFrameTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case TEXTONFRAMETRANSITION_START: - { - - if(m_isForward || !m_win ) - break; - - m_win->winHide(TRUE); - m_isFinished = TRUE; - - } - break; - case TEXTONFRAMETRANSITION_END: - { - if(!m_isForward || !m_win ) - break; - m_win->winHide(FALSE); - m_isFinished = TRUE; - - } - } -} - -void TextOnFrameTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; - if(m_win->winIsHidden()) - { - m_isFinished = TRUE; - m_frameLength = 0; - } -} - -void TextOnFrameTransition::draw() -{ -} - -void TextOnFrameTransition::skip() -{ - if (!m_isFinished) - update(TEXTONFRAMETRANSITION_END); -} - -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- - -ReverseSoundTransition::ReverseSoundTransition () -{ - m_frameLength = REVERSESOUNDTRANSITION_END; - m_win = nullptr; - m_isForward = TRUE; - -} - -ReverseSoundTransition::~ReverseSoundTransition() -{ - m_win = nullptr; - -} - -void ReverseSoundTransition::init( GameWindow *win ) -{ - m_isFinished = TRUE; - m_isForward = TRUE; -} - -void ReverseSoundTransition::update( Int frame ) -{ - if(frame < REVERSESOUNDTRANSITION_START || frame > REVERSESOUNDTRANSITION_END) - { - DEBUG_CRASH(("ReverseSoundTransition::update - Frame is out of the range the this update can handle %d", frame)); - return; - } - switch (frame) { - case REVERSESOUNDTRANSITION_START: - { - - if(m_isForward ) - break; - - m_isFinished = TRUE; - - } - break; - - case REVERSESOUNDTRANSITION_FIRESOUND: - { - AudioEventRTS buttonClick("GUITransitionFade"); - - if( TheAudio ) - { - TheAudio->addAudioEvent( &buttonClick ); - } - } - break; - - case REVERSESOUNDTRANSITION_END: - { - if(!m_isForward ) - break; - m_isFinished = TRUE; - - } - } -} - -void ReverseSoundTransition::reverse() -{ - m_isFinished = FALSE; - m_isForward = FALSE; -} - -void ReverseSoundTransition::draw() -{ -} - -void ReverseSoundTransition::skip() -{ - if (!m_isFinished) - update(REVERSESOUNDTRANSITION_END); -} - - - -//----------------------------------------------------------------------------- -// PRIVATE FUNCTIONS ////////////////////////////////////////////////////////// -//----------------------------------------------------------------------------- - -void PushButtonImageDrawThree(GameWindow *window, Int alpha ) -{ - if (window == nullptr) - return; - if (BitIsSet(window->winGetStatus(), WIN_STATUS_DESTROYED)) - return; - WinInstanceData *instData = window->winGetInstanceData(); - const Image *leftImage, *rightImage, *centerImage; - ICoord2D origin, size, start, end; - Int xOffset, yOffset; - Int i; - Int color = GameMakeColor(255,255,255,alpha); - // get screen position and size - window->winGetScreenPosition( &origin.x, &origin.y ); - window->winGetSize( &size.x, &size.y ); - - // get image offset - xOffset = instData->m_imageOffset.x; - yOffset = instData->m_imageOffset.y; - - leftImage = GadgetButtonGetLeftEnabledImage( window ); - rightImage = GadgetButtonGetRightEnabledImage( window ); - centerImage = GadgetButtonGetMiddleEnabledImage( window ); - - // sanity, we need to have these images to make it look right - if( leftImage == nullptr || rightImage == nullptr || - centerImage == nullptr ) - return; - - // get image sizes for the ends - ICoord2D leftSize, rightSize; - leftSize.x = leftImage->getImageWidth(); - leftSize.y = leftImage->getImageHeight(); - rightSize.x = rightImage->getImageWidth(); - rightSize.y = rightImage->getImageHeight(); - - // get two key points used in the end drawing - ICoord2D leftEnd, rightStart; - leftEnd.x = origin.x + leftSize.x + xOffset; - leftEnd.y = origin.y + size.y + yOffset; - rightStart.x = origin.x + size.x - rightSize.x + xOffset; - rightStart.y = origin.y + yOffset; - - // draw the center repeating bar - Int centerWidth, pieces; - - // get width we have to draw our repeating center in - centerWidth = rightStart.x - leftEnd.x; - - if( centerWidth <= 0) - { - // draw left end - start.x = origin.x + xOffset; - start.y = origin.y + yOffset; - end.y = leftEnd.y; - end.x = origin.x + xOffset + size.x/2; - TheDisplay->drawImage(leftImage, start.x, start.y, end.x, end.y,color); - - // draw right end - start.y = rightStart.y; - start.x = end.x; - end.x = origin.x + size.x; - end.y = start.y + size.y; - TheDisplay->drawImage(rightImage, start.x, start.y, end.x, end.y,color); - } - else - { - - // how many whole repeating pieces will fit in that width - pieces = centerWidth / centerImage->getImageWidth(); - - // draw the pieces - start.x = leftEnd.x; - start.y = origin.y + yOffset; - end.y = start.y + size.y + yOffset; //centerImage->getImageHeight() + yOffset; - for( i = 0; i < pieces; i++ ) - { - - end.x = start.x + centerImage->getImageWidth(); - - TheDisplay->drawImage( centerImage, - start.x, start.y, - end.x, end.y,color ); - start.x += centerImage->getImageWidth(); - - } - - // we will draw the image but clip the parts we don't want to show - IRegion2D reg; - reg.lo.x = start.x; - reg.lo.y = start.y; - reg.hi.x = rightStart.x; - reg.hi.y = end.y; - centerWidth = rightStart.x - start.x; - if( centerWidth > 0) - { - TheDisplay->setClipRegion(®); - end.x = start.x + centerImage->getImageWidth(); - TheDisplay->drawImage( centerImage, - start.x, start.y, - end.x, end.y,color ); - TheDisplay->enableClipping(FALSE); - } - - // draw left end - start.x = origin.x + xOffset; - start.y = origin.y + yOffset; - end = leftEnd; - TheDisplay->drawImage(leftImage, start.x, start.y, end.x, end.y,color); - - // draw right end - start = rightStart; - end.x = start.x + rightSize.x; - end.y = start.y + size.y; - TheDisplay->drawImage(rightImage, start.x, start.y, end.x, end.y,color); - } - -} - -static void drawTypeText( GameWindow *window, DisplayString *str) -{ - TextData *tData = (TextData *)window->winGetUserData(); - Int textColor = window->winGetEnabledTextColor(); - Int textDropColor = window->winGetEnabledTextBorderColor(); - Int textWidth, textHeight, wordWrap; - DisplayString *text = tData->text; - ICoord2D origin, size, textPos; - IRegion2D clipRegion; - // sanity - if( text == nullptr || text->getTextLength() == 0 ) - return; - GameFont *font = text->getFont(); - - str->setFont(font); - - // get window position and size - window->winGetScreenPosition( &origin.x, &origin.y ); - window->winGetSize( &size.x, &size.y ); - - // Set the text Wrap width - wordWrap = size.x - 10; - text->setWordWrap(wordWrap); - str->setWordWrap(wordWrap); - if( BitIsSet(window->winGetStatus(), WIN_STATUS_WRAP_CENTERED) ) - { - str->setWordWrapCentered(TRUE); - text->setWordWrapCentered(TRUE); - } - else - { - text->setWordWrapCentered(FALSE); - str->setWordWrapCentered(FALSE); - - } - - - // how much space will this text take up - text->getSize( &textWidth, &textHeight ); - - //Init the clip region - clipRegion.lo.x = origin.x ; - clipRegion.lo.y = origin.y ; - clipRegion.hi.x = origin.x + size.x ; - clipRegion.hi.y = origin.y + size.y; - - if( tData->centered ) - { - - textPos.x = origin.x + (size.x / 2) - (textWidth / 2); - textPos.y = origin.y + (size.y / 2) - (textHeight / 2); - str->setClipRegion(&clipRegion); - str->draw( textPos.x, textPos.y, textColor, textDropColor ); - } - else - { - - // draw the text - textPos.x = origin.x + 7; - textPos.y = origin.y + (size.y / 2) - (textHeight / 2); - str->setClipRegion(&clipRegion); - str->draw( textPos.x, textPos.y, textColor, textDropColor ); - - } - - -} diff --git a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp index b01f6a2879e..dab5e11711f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/AI/AIStates.cpp @@ -5794,7 +5794,7 @@ Object *AIAttackSquadState::chooseVictim() case DIFFICULTY_EASY: { // pick a random unit - VecObjectPtr objects = victimSquad->getLiveObjects(); + const VecObjectPtr& objects = victimSquad->getLiveObjects(); Int numUnits = objects.size(); if (numUnits == 0) { @@ -5822,7 +5822,7 @@ Object *AIAttackSquadState::chooseVictim() case DIFFICULTY_HARD: { // everyone picks the same unit - VecObjectPtr objects = victimSquad->getLiveObjects(); + const VecObjectPtr& objects = victimSquad->getLiveObjects(); if (!objects.empty()) { return objects[0]; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp index ff9ba9d26bc..1380ce16239 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp @@ -170,6 +170,12 @@ OpenContain::~OpenContain() ("OpenContain %s: m_xferContainIDList is not empty but should be", getObject()->getTemplate()->getName().str() ) ); +#if RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Caball009 18/08/2026 Due to a potential use-after-free bug that cannot be fixed + // with retail compatibility, it's desirable to be able to check if the contain list is empty after its destruction. + // Clear the list explicitly to reset the list size. + m_containList.clear(); +#endif } //------------------------------------------------------------------------------------------------- @@ -419,6 +425,15 @@ void OpenContain::removeFromContain( Object *rider, Bool exposeStealthUnits ) } +#if RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Caball009 18/08/2026 Due to a potential use-after-free bug that cannot be fixed + // with retail compatibility, the 'contained by' pointer of this object may point to an already destroyed object. + // Check the list size before executing the find operation below, otherwise the game crashes if the list + // was already destructed. + if (m_containList.empty()) + return; +#endif + ContainedItemsList::iterator it = std::find(m_containList.begin(), m_containList.end(), rider); if (it != m_containList.end()) { diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp index e72fbeb6334..fb9df30860e 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp @@ -402,6 +402,7 @@ void TunnelContain::onBuildComplete() // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) void TunnelContain::onCapture( Player *oldOwner, Player *newOwner ) { if( m_isCurrentlyRegistered ) @@ -423,6 +424,7 @@ void TunnelContain::onCapture( Player *oldOwner, Player *newOwner ) // extend base class OpenContain::onCapture( oldOwner, newOwner ); } +#endif //------------------------------------------------------------------------------------------------- void TunnelContain::orderAllPassengersToExit( CommandSourceType commandSource ) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp index 07c55418c46..fd7cb272e4f 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -174,7 +174,7 @@ Object::Object( const ThingTemplate *tt, const ObjectStatusMaskType &objectStatu m_physics(nullptr), m_geometryInfo(tt->getTemplateGeometryInfo()), m_containedBy(nullptr), - m_containedByID(INVALID_ID), + m_xferContainedByID(INVALID_ID), m_containedByFrame(0), m_behaviors(nullptr), m_body(nullptr), @@ -623,21 +623,8 @@ void Object::onContainedBy( Object *containedBy ) m_containedBy = containedBy; m_containedByFrame = TheGameLogic->getFrame(); -#if RETAIL_COMPATIBLE_CRC - // TheSuperHackers @info Set INVALID_ID if the container object was destroyed - // to indicate that the pointer will become a dangling pointer in the next frame. - if (containedBy && !containedBy->isDestroyed()) - { - m_containedByID = containedBy->getID(); - } - else - { - m_containedByID = INVALID_ID; - } -#else DEBUG_ASSERTCRASH(containedBy == nullptr || !containedBy->isDestroyed(), - ("Object::onContainedBy - Adding into a destroyed container")); -#endif + ("Object::onContainedBy - Adding to a destroyed container")); } //------------------------------------------------------------------------------------------------- @@ -648,10 +635,6 @@ void Object::onRemovedFrom( Object *removedFrom ) clearStatus( MAKE_OBJECT_STATUS_MASK2( OBJECT_STATUS_MASKED, OBJECT_STATUS_UNSELECTABLE ) ); m_containedBy = nullptr; m_containedByFrame = 0; - -#if RETAIL_COMPATIBLE_CRC - m_containedByID = INVALID_ID; -#endif } //------------------------------------------------------------------------------------------------- @@ -711,33 +694,9 @@ void Object::onDestroy() { // This is the old cleanUpContain safeguard. Say goodbye so they don't try to look us up. - if (m_containedBy) + if( m_containedBy && m_containedBy->getContain() ) { -#if RETAIL_COMPATIBLE_CRC - if (m_containedByID == INVALID_ID) - { - // TheSuperHackers @bugfix Caball009 25/05/2026 Due to a potential use-after-free bug that cannot be fixed - // with retail compatibility, the 'contained by' pointer of this object may point to an already destroyed object. - // Avoid removing this object from the contain list, because it could crash the game, - // as the begin / end iterator for STLPort and MSVC std::list implementations depends on dynamically allocated memory. - DEBUG_CRASH(("container object must be valid; this looks like use-after-free")); - } - else - { - DEBUG_ASSERTCRASH(TheGameLogic->findObjectByID(m_containedByID) == m_containedBy, - ("contained by pointer is out of sync with contained by ID")); - - if (ContainModuleInterface* contain = m_containedBy->getContain()) - { - contain->removeFromContain(this); - } - } -#else - if (ContainModuleInterface* contain = m_containedBy->getContain()) - { - contain->removeFromContain(this); - } -#endif + m_containedBy->getContain()->removeFromContain( this ); } // @@ -3784,19 +3743,16 @@ void Object::xfer( Xfer *xfer ) // No, the contain module is just going to friend_ reach in and set this for us. // Containers more complicated than Open (like Tunnel) can't do that. Our variable, // our responsibility. -#if RETAIL_COMPATIBLE_CRC - // TheSuperHackers @tweak Contained by ID is already set with retail compatibility; don't overwrite it. -#else if( xfer->getXferMode() == XFER_SAVE ) { if( m_containedBy != nullptr ) - m_containedByID = m_containedBy->getID(); + m_xferContainedByID = m_containedBy->getID(); else - m_containedByID = INVALID_ID; + m_xferContainedByID = INVALID_ID; } -#endif - xfer->xferObjectID( &m_containedByID ); + + xfer->xferObjectID( &m_xferContainedByID ); } // contained by frame @@ -4021,8 +3977,8 @@ void Object::xfer( Xfer *xfer ) //------------------------------------------------------------------------------------------------- void Object::loadPostProcess() { - if( m_containedByID != INVALID_ID ) - m_containedBy = TheGameLogic->findObjectByID(m_containedByID); + if( m_xferContainedByID != INVALID_ID ) + m_containedBy = TheGameLogic->findObjectByID(m_xferContainedByID); else m_containedBy = nullptr; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 2e28c811150..2bbeda6ca51 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -3401,7 +3401,13 @@ void AIUpdateInterface::privateAttackPosition( const Coord3D *pos, Int maxShotsT // this fixes an obscure bug with mine-clearing: if you tell someone to clear mines and put the centerpoint // inside a building, the dozer/worker will just go thru the building to that spot. ick. so if you find that // this clause (below) is problematic, you'll probably have to find another way to fix this mine-clearing bug. (srj) +#if RETAIL_COMPATIBLE_CRC if (weapon && weapon->isContactWeapon() && !isPathAvailable(&localPos)) +#else + // TheSuperHackers @bugfix Stubbjax 23/08/2026 Only find a new position if the target is not within the attack range of the weapon. + // This allows contact weapons such as suicide bombs to immediately detonate without first pathing to a nearby position. + if (weapon && weapon->isContactWeapon() && !weapon->isWithinAttackRange(getObject(), &localPos) && !isPathAvailable(&localPos)) +#endif { FindPositionOptions fpOptions; fpOptions.minRadius = 0.0f; diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp index 5d6aec0dfd8..a1acfa88b41 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp @@ -65,8 +65,14 @@ void AssistedTargetingUpdateModuleData::buildFieldParse(MultiIniFieldParse& p) //------------------------------------------------------------------------------------------------- AssistedTargetingUpdate::AssistedTargetingUpdate( Thing *thing, const ModuleData* moduleData ) : UpdateModule( thing, moduleData ) { - m_laserFromAssisted = nullptr; - m_laserToTarget = nullptr; + const AssistedTargetingUpdateModuleData* d = getAssistedTargetingUpdateModuleData(); + + m_laserFromAssisted = TheThingFactory->findTemplate(d->m_laserFromAssistedName); + m_laserToTarget = TheThingFactory->findTemplate(d->m_laserToTargetName); +#if RTS_GENERALS || !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @info Zero Hour needs the update to run once to avoid mismatches with retail. + setWakeFrame(getObject(), UPDATE_SLEEP_FOREVER); +#endif } //------------------------------------------------------------------------------------------------- @@ -138,11 +144,6 @@ void AssistedTargetingUpdate::makeFeedbackLaser( const ThingTemplate *laserTempl //------------------------------------------------------------------------------------------------- UpdateSleepTime AssistedTargetingUpdate::update() { - const AssistedTargetingUpdateModuleData *d = getAssistedTargetingUpdateModuleData(); - - m_laserFromAssisted = TheThingFactory->findTemplate( d->m_laserFromAssistedName ); - m_laserToTarget = TheThingFactory->findTemplate( d->m_laserToTargetName ); - return UPDATE_SLEEP_FOREVER; } @@ -180,11 +181,6 @@ void AssistedTargetingUpdate::xfer( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ void AssistedTargetingUpdate::loadPostProcess() { - const AssistedTargetingUpdateModuleData *d = getAssistedTargetingUpdateModuleData(); - - m_laserFromAssisted = TheThingFactory->findTemplate( d->m_laserFromAssistedName ); - m_laserToTarget = TheThingFactory->findTemplate( d->m_laserToTargetName ); - // extend base class UpdateModule::loadPostProcess(); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp index ea5a60488e3..f182e1d38fd 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp @@ -458,7 +458,7 @@ Bool ProductionUpdate::queueCreateUnit( const ThingTemplate *unitType, Productio //------------------------------------------------------------------------------------------------- /** Cancel the construction of the unit with the matching production ID */ //------------------------------------------------------------------------------------------------- -void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) +Bool ProductionUpdate::cancelUnitCreate( ProductionID productionID ) { // search for the production entry in our queue @@ -470,8 +470,15 @@ void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) if( production->m_productionID == productionID ) { - // give the player the cost of the object back Player *player = getObject()->getControllingPlayer(); + +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix arcticdolphin 07/09/2026 No cancel once the batch has started producing. + if( production->getProductionQuantityRemaining() < production->getProductionQuantity() ) + return FALSE; +#endif + + // give the player the cost of the object back Money *money = player->getMoney(); money->deposit( production->m_objectToProduce->calcCostToBuild( player ), TRUE, FALSE ); @@ -481,12 +488,14 @@ void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) // delete the production entry deleteInstance(production); - return; + return TRUE; } } + return FALSE; + } //------------------------------------------------------------------------------------------------- @@ -659,7 +668,7 @@ UpdateSleepTime ProductionUpdate::update() // if we've become OBJECT_STATUS_SOLD, halt all production ... leave things in the // queue because if the sell process completes we get money back for them, for now we // will be just frozen in time - // Actually, there will be nothing in the queue since everything gets cancel/refunded + // Actually, there will usually be nothing in the queue since everything gets cancel/refunded // at the start of sell, but we still don't want to do anything here. // if( us->getStatusBits().test( OBJECT_STATUS_SOLD ) ) @@ -693,10 +702,8 @@ UpdateSleepTime ProductionUpdate::update() // Don't cancel dozers in the queue. jba. if (!production->getProductionObject()->isKindOf(KINDOF_DOZER)) { - - cancelUnitCreate(production->getProductionID()); - return UPDATE_SLEEP_NONE; - + if( cancelUnitCreate(production->getProductionID()) ) + return UPDATE_SLEEP_NONE; } } @@ -1134,24 +1141,33 @@ void ProductionUpdate::cancelAndRefundAllProduction() { // Empirically, in release the code can loop forever. So we limit to 100 passes. jba. [8/31/2003] const Int productionLimit = 100;// With luck, we never queue up 100 units. [8/31/2003] - Int i; - for (i=0; im_next; + + if( production->getProductionType() == PRODUCTION_UNIT ) { - if( m_productionQueue->getProductionType() == PRODUCTION_UNIT ) - cancelUnitCreate( m_productionQueue->getProductionID() ); - else if( m_productionQueue->getProductionType() == PRODUCTION_UPGRADE ) - cancelUpgrade( m_productionQueue->getProductionUpgrade() ); - else + if( !cancelUnitCreate( production->getProductionID() ) ) { - // unknown production type - DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", - m_productionQueue->getProductionType() )); - return; + removeFromProductionQueue( production ); + deleteInstance( production ); } } + else if( production->getProductionType() == PRODUCTION_UPGRADE ) + cancelUpgrade( production->getProductionUpgrade() ); + else + { + // unknown production type + DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", + production->getProductionType() )); + return; + } + + production = nextProduction; + ++i; } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp index 704ceaa87cb..47f780de669 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp @@ -610,7 +610,7 @@ void ScriptActions::doCreateReinforcements(const AsciiString& team, const AsciiS PartitionSolver partition(vecOfUnits, vecOfTransports, PREFER_FAST_SOLUTION); partition.solve(); - SolutionVec solution = partition.getSolution(); + const SolutionVec& solution = partition.getSolution(); for (size_t i = 0; i < solution.size(); ++i) { Object *unit = TheGameLogic->findObjectByID(solution[i].first); Object *trans = TheGameLogic->findObjectByID(solution[i].second); @@ -1463,7 +1463,7 @@ void ScriptActions::doLoadAllTransports(const AsciiString& teamName) PartitionSolver partition(vecOfUnits, vecOfTransports, PREFER_FAST_SOLUTION); partition.solve(); - SolutionVec solution = partition.getSolution(); + const SolutionVec& solution = partition.getSolution(); for (size_t i = 0; i < solution.size(); ++i) { Object *unit = TheGameLogic->findObjectByID(solution[i].first); Object *trans = TheGameLogic->findObjectByID(solution[i].second); diff --git a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp index ac5a0a71a84..bad2de14acb 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp @@ -199,7 +199,7 @@ void ScriptConditions::objectTypesFromParam(Parameter *pTypeParm, ObjectTypes *o return; } - AsciiString str = pTypeParm->getString(); + const AsciiString &str = pTypeParm->getString(); if (str.isEmpty()) { return; @@ -355,7 +355,7 @@ Bool ScriptConditions::evaluateNamedUnitTotallyDead(Parameter *pUnitParm) //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluateHasUnits(Parameter *pTeamParm) { - AsciiString desiredTeamName = pTeamParm->getString(); + const AsciiString &desiredTeamName = pTeamParm->getString(); // If they are calling a condition, do it. if (desiredTeamName == THIS_TEAM) { Team *theTeam = TheScriptEngine->getTeamNamed( desiredTeamName ); @@ -396,7 +396,6 @@ Bool ScriptConditions::evaluateTeamInsideAreaPartially(Parameter *pTeamParm, Par Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString triggerName = pTriggerAreaParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerAreaParm->getString()); if (pTrig == nullptr) return false; @@ -418,7 +417,6 @@ Bool ScriptConditions::evaluateNamedInsideArea(Parameter *pUnitParm, Parameter * return false; } - AsciiString triggerName = pTriggerAreaParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerAreaParm->getString()); if (pTrig == nullptr) return false; if (theObj) { @@ -435,7 +433,6 @@ Bool ScriptConditions::evaluateNamedInsideArea(Parameter *pUnitParm, Parameter * //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluatePlayerHasUnitTypeInArea(Condition *pCondition, Parameter *pPlayerParm, Parameter *pComparisonParm, Parameter *pCountParm, Parameter *pTypeParm, Parameter *pTriggerParm ) { - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (pTrig == nullptr) return false; @@ -527,7 +524,6 @@ Bool ScriptConditions::evaluatePlayerHasUnitTypeInArea(Condition *pCondition, Pa //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluatePlayerHasUnitKindInArea(Condition *pCondition, Parameter *pPlayerParm, Parameter *pComparisonParm, Parameter *pCountParm, Parameter *pKindParm, Parameter *pTriggerParm ) { - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (pTrig == nullptr) return false; @@ -611,7 +607,7 @@ Bool ScriptConditions::evaluateTeamStateIs(Parameter *pTeamParm, Parameter *pSta Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString stateName = pStateParm->getString(); + const AsciiString &stateName = pStateParm->getString(); if (theTeam) { return (theTeam->getState() == stateName); } @@ -627,7 +623,7 @@ Bool ScriptConditions::evaluateTeamStateIsNot(Parameter *pTeamParm, Parameter *p Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString stateName = pStateParm->getString(); + const AsciiString &stateName = pStateParm->getString(); if (theTeam) { return (!(theTeam->getState() == stateName)); } @@ -651,7 +647,6 @@ Bool ScriptConditions::evaluateTeamInsideAreaEntirely(Parameter *pTeamParm, Para Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (pTrig == nullptr) @@ -1290,7 +1285,7 @@ Bool ScriptConditions::evaluateNamedReachedWaypointsEnd(Parameter *pUnitParm, Pa if (!targetWay) return false; - AsciiString pathName = pWaypointPathParm->getString(); + const AsciiString &pathName = pWaypointPathParm->getString(); if (targetWay->getPathLabel1() == pathName) return true; if (targetWay->getPathLabel2() == pathName) return true; @@ -1309,7 +1304,7 @@ Bool ScriptConditions::evaluateTeamReachedWaypointsEnd(Parameter *pTeamParm, Par return false; } - AsciiString pathName = pWaypointPathParm->getString(); + const AsciiString &pathName = pWaypointPathParm->getString(); Bool anyAtEnd = false; Bool anyNotAtEnd = false; // Note - This returns true if any of the team completed the path. This is as the current @@ -2019,7 +2014,6 @@ Bool ScriptConditions::evaluateSkirmishValueInArea(Condition *pCondition, Parame return false; } - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (!pTrig) { @@ -2574,7 +2568,7 @@ Bool ScriptConditions::evaluateSkirmishPlayerHasDiscoveredPlayer(Parameter *pSki //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluateMusicHasCompleted(Parameter *pMusicParm, Parameter *pIntParm) { - AsciiString str = pMusicParm->getString(); + const AsciiString &str = pMusicParm->getString(); return TheAudio->hasMusicTrackCompleted(str, pIntParm->getInt()); } diff --git a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp index d882f80d8a4..95d1406e0cd 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp @@ -6661,7 +6661,7 @@ Bool ScriptEngine::isSpecialPowerTriggered( Int playerIndex, const AsciiString& for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == completedPower && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -6686,7 +6686,7 @@ Bool ScriptEngine::isSpecialPowerMidway( Int playerIndex, const AsciiString& com for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == completedPower && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -6711,7 +6711,7 @@ Bool ScriptEngine::isSpecialPowerComplete( Int playerIndex, const AsciiString& c for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == completedPower && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -6736,7 +6736,7 @@ Bool ScriptEngine::isUpgradeComplete( Int playerIndex, const AsciiString& upgrad for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == upgrade && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -6853,7 +6853,7 @@ void ScriptEngine::adjustToppleDirection( Object *object, Coord2D *direction) //------------------------------------------------------------------------------------------------- void ScriptEngine::adjustToppleDirection( Object *object, Coord3D *direction) { - AsciiString objName = object->getName(); + const AsciiString &objName = object->getName(); if (objName.isEmpty() || !direction) { return; } diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp index 041d858f61d..23cf1a9cd21 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp @@ -255,7 +255,7 @@ Bool W3DBridge::load(BodyDamageType curDamageState) Int i; for (i=0; iGet_Num_Sub_Objects(); i++) { RenderObjClass *pSub = pObj->Get_Sub_Object(i); - Matrix3D mtx = pSub->Get_Transform(); + const Matrix3D& mtx = pSub->Get_Transform(); if (0==strnicmp(left, pSub->Get_Name(), strlen(left))) { m_leftMtx = mtx; strlcpy(left, pSub->Get_Name(), ARRAY_SIZE(left)); diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp index 356012c265a..ef6fde61bd1 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp @@ -221,8 +221,7 @@ void W3DDebugIcons::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Texture(0, nullptr); DX8Wrapper::Apply_Render_State_Changes(); - Matrix3D tm(Transform); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); Int numRect = m_numDebugIcons; static Real offset = 30; diff --git a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp index c85dd43ab0b..aa53761ff50 100644 --- a/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp +++ b/Generals/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp @@ -246,7 +246,7 @@ void DebugHintObject::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0); DX8Wrapper::Set_Vertex_Buffer(m_vertexBufferTile); - Matrix3D tm(Transform); + Matrix3D tm = Transform; Vector3 vec(m_myLoc.x, m_myLoc.y, m_myLoc.z); tm.Set_Translation(vec); DX8Wrapper::Set_Transform(D3DTS_WORLD, tm); diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp index 8f838f954a9..1293d5306c5 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp @@ -618,7 +618,7 @@ void CameraClass::Update_Frustum() const float znear,zfar; float znear_dist,zfar_dist; - Matrix3D cam_mat = Get_Transform(); + const Matrix3D& cam_mat = Get_Transform(); Get_View_Plane(vpmin, vpmax); // Normalized view plane at a depth of 1.0 Get_Clip_Planes(znear_dist, zfar_dist); diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp index cd1416c0924..3f0dd3302ab 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp @@ -1412,7 +1412,7 @@ void DazzlePersistFactoryClass::Save(ChunkSaveClass & csave,PersistClass * obj) DazzleRenderObjClass * robj = (DazzleRenderObjClass *)obj; unsigned int dazzle_type = robj->Get_Dazzle_Type(); const char * dazzle_type_name = DazzleRenderObjClass::Get_Type_Name(dazzle_type); - Matrix3D tm = robj->Get_Transform(); + const Matrix3D& tm = robj->Get_Transform(); csave.Begin_Chunk(DAZZLEFACTORY_CHUNKID_VARIABLES); WRITE_MICRO_CHUNK(csave,DAZZLEFACTORY_VARIABLE_OBJPOINTER,robj); diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h b/Generals/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h index ce5afef9731..114bacf508a 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h @@ -76,7 +76,7 @@ class DecalMeshClass : public RefCountClass public: DecalMeshClass(MeshClass * parent,DecalSystemClass * system); - virtual ~DecalMeshClass(); + virtual ~DecalMeshClass() override; // world_vertex_locs and world_vertex_norms are dynamically updated worldspace vertex data // which are used by some decal types which cannot use static object geometry (such as decals @@ -121,21 +121,21 @@ class RigidDecalMeshClass : public DecalMeshClass public: RigidDecalMeshClass(MeshClass * parent,DecalSystemClass * system); - virtual ~RigidDecalMeshClass(); + virtual ~RigidDecalMeshClass() override; // Rigid decal meshes have static geometry so they do not use world_vertex_locs/norms - virtual void Render(); + virtual void Render() override; virtual bool Create_Decal( DecalGeneratorClass * generator, const OBBoxClass & localbox, SimpleDynVecClass & apt, - const DynamicVectorClass * world_vertex_locs = 0); + const DynamicVectorClass * world_vertex_locs = 0) override; - virtual bool Delete_Decal(uint32 id); + virtual bool Delete_Decal(uint32 id) override; - int Decal_Count(); - uint32 Get_Decal_ID(int decal_index); + int Decal_Count() override; + uint32 Get_Decal_ID(int decal_index) override; protected: @@ -186,21 +186,21 @@ class SkinDecalMeshClass : public DecalMeshClass public: SkinDecalMeshClass(MeshClass * parent,DecalSystemClass * system); - virtual ~SkinDecalMeshClass(); + virtual ~SkinDecalMeshClass() override; // Skin decals use world_vertex_locs/norms since they cannot use static geometry - virtual void Render(); + virtual void Render() override; virtual bool Create_Decal( DecalGeneratorClass * generator, const OBBoxClass & localbox, SimpleDynVecClass & apt, - const DynamicVectorClass * world_vertex_locs); + const DynamicVectorClass * world_vertex_locs) override; - virtual bool Delete_Decal(uint32 id); + virtual bool Delete_Decal(uint32 id) override; - int Decal_Count(); - uint32 Get_Decal_ID(int decal_index); + int Decal_Count() override; + uint32 Get_Decal_ID(int decal_index) override; protected: diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp index 00182a473f8..7400694bd62 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp @@ -2057,7 +2057,7 @@ bool HLodClass::Get_Proxy (int index, ProxyClass &proxy) const // Lookup the proxy's transform // HTree->Base_Update(Get_Transform()); - Matrix3D transform = HTree->Get_Transform((*ProxyArray)[index].Get_Bone_Index()); + const Matrix3D& transform = HTree->Get_Transform((*ProxyArray)[index].Get_Bone_Index()); Set_Hierarchy_Valid(false); // diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/light.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/light.cpp index 4018f2ad4d2..f9afda2138c 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/light.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/light.cpp @@ -525,7 +525,7 @@ bool LightClass::Save (ChunkSaveClass &csave) Save_W3D(csave); csave.End_Chunk(); - Matrix3D tm = Get_Transform(); + const Matrix3D& tm = Get_Transform(); csave.Begin_Chunk(LIGHT_CHUNK_VARIABLES); WRITE_MICRO_CHUNK(csave,LIGHT_VARIABLE_TRANSFORM,tm); csave.End_Chunk(); diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/meshmdl.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/meshmdl.cpp index 6f4c532a8fe..62c39db89fe 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/meshmdl.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/meshmdl.cpp @@ -336,9 +336,6 @@ void MeshModelClass::compose_deformed_vertex_buffer( for (vi = 0; vi < vertex_count;) { const Matrix3D & tm = htree->Get_Transform(bonelink[vi]); - // Make a copy so we can set the translation to zero - Matrix3D mytm=tm; - int idx=bonelink[vi]; int cnt; for (cnt = vi; cnt < vertex_count; cnt++) { @@ -348,7 +345,7 @@ void MeshModelClass::compose_deformed_vertex_buffer( } for (int pidx=0;pidxx = (A[0][0] * v.X + A[0][1] * v.Y + A[0][2] * v.Z + A[0][3]); diff --git a/Generals/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp b/Generals/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp index bbcde0144d0..b0499392ce2 100644 --- a/Generals/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp +++ b/Generals/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp @@ -997,7 +997,7 @@ void ParticleBufferClass::Prepare_LOD(CameraClass &camera) // treat them as all being the maximum size and being in the center of the bounding sphere). Vector3 cam = camera.Get_Position(); - ViewportClass viewport = camera.Get_Viewport(); + const ViewportClass &viewport = camera.Get_Viewport(); Vector2 vpr_min, vpr_max; camera.Get_View_Plane(vpr_min, vpr_max); float width_factor = viewport.Width() / (vpr_max.X - vpr_min.X); diff --git a/Generals/Code/Tools/WorldBuilder/src/DrawObject.cpp b/Generals/Code/Tools/WorldBuilder/src/DrawObject.cpp index a342e337161..ed8d0210d1b 100644 --- a/Generals/Code/Tools/WorldBuilder/src/DrawObject.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/DrawObject.cpp @@ -1687,12 +1687,9 @@ void DrawObject::Render(RenderInfoClass & rinfo) Bool isTree = false; Vector3 vec(loc.x, loc.y, loc.z); - Matrix3D tm(Transform); Matrix3x3 rot(true); rot.Rotate_Z(pMapObj->getAngle()); - - tm.Set_Translation(vec); - tm.Set_Rotation(rot); + Matrix3D tm(rot, vec); int polyCount = NUM_TRI; if (!pMapObj->isSelected()) { polyCount -= NUM_ARROW_TRI+NUM_SELECT_TRI; @@ -1749,7 +1746,7 @@ void DrawObject::Render(RenderInfoClass & rinfo) count++; Vector3 vec(loc.x, loc.y, loc.z); - Matrix3D tm(Transform); + Matrix3D tm = Transform; tm.Set_Translation(vec); int polyCount = NUM_TRI; @@ -1761,8 +1758,7 @@ void DrawObject::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); DX8Wrapper::Draw_Triangles( 0,polyCount, 0, (m_numTriangles*3)); } - Matrix3D tmReset(Transform); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tmReset); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); DX8Wrapper::Set_Vertex_Buffer(m_vertexBufferTile1); updatePolygonVB(pTrig, polySelected, polySelected && PolygonTool::isSelectedOpen()); DX8Wrapper::Set_Vertex_Buffer(m_vertexFeedback); @@ -1804,12 +1800,9 @@ void DrawObject::Render(RenderInfoClass & rinfo) count++; // ok to here. Vector3 vec(loc.x, loc.y, loc.z); - Matrix3D tmXX(Transform); Matrix3x3 rot(true); rot.Rotate_Z(pBuild->getAngle()); - - tmXX.Set_Translation(vec); - tmXX.Set_Rotation(rot); + Matrix3D tmXX(rot, vec); int polyCountA = NUM_TRI; if (!pBuild->isSelected()) { polyCountA -= NUM_ARROW_TRI+NUM_SELECT_TRI; @@ -1826,8 +1819,7 @@ void DrawObject::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Vertex_Buffer(nullptr); //release reference to vertex buffer DX8Wrapper::Set_Index_Buffer(nullptr,0); //release reference to vertex buffer - Matrix3D tmReset(Transform); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tmReset); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); if (m_drawWaypoints) { updateWaypointVB(); diff --git a/Generals/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp b/Generals/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp index 5e7c6568182..8b27855b125 100644 --- a/Generals/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp @@ -118,7 +118,7 @@ void EditObjectParameter::addObject( const ThingTemplate *thingTemplate ) parent = findOrAdd( parent, "TEST" ); // first sort by Side, either create or find the tree item with matching side name - AsciiString side = thingTemplate->getDefaultOwningSide(); + const AsciiString &side = thingTemplate->getDefaultOwningSide(); DEBUG_ASSERTCRASH(!side.isEmpty(), ("null default side in template") ); parent = findOrAdd( parent, side.str()); diff --git a/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp b/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp index 664cdc9505f..c1b2cce140b 100644 --- a/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/EditParameter.cpp @@ -789,7 +789,7 @@ Bool EditParameter::loadUpgrades(CComboBox *pCombo, AsciiString match) for (int i = 0; i < numUpgrades; ++i) { - AsciiString upgradeName = upgradeNames[i]; + const AsciiString &upgradeName = upgradeNames[i]; if (pCombo) { pCombo->AddString(upgradeName.str()); } diff --git a/Generals/Code/Tools/WorldBuilder/src/ScriptDialog.cpp b/Generals/Code/Tools/WorldBuilder/src/ScriptDialog.cpp index 0264bf1ae37..2d88de1aa93 100644 --- a/Generals/Code/Tools/WorldBuilder/src/ScriptDialog.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/ScriptDialog.cpp @@ -1004,7 +1004,7 @@ void ScriptDialog::markWaypoint(MapObject *pObj) void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, Bool doWaypoints, Bool doTriggers) { if (pParm->getParameterType() == Parameter::WAYPOINT && doWaypoints) { - AsciiString waypointName = pParm->getString(); + const AsciiString &waypointName = pParm->getString(); MapObject *pObj; for (pObj = MapObject::getFirstMapObject(); pObj; pObj = pObj->getNext()) { if (pObj->isWaypoint() && pObj->getWaypointName()==waypointName) { @@ -1013,7 +1013,7 @@ void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, } } if (pParm->getParameterType() == Parameter::WAYPOINT_PATH && doWaypoints) { - AsciiString waypointPathLabel = pParm->getString(); + const AsciiString &waypointPathLabel = pParm->getString(); MapObject *pObj; for (pObj = MapObject::getFirstMapObject(); pObj; pObj = pObj->getNext()) { if (pObj->isWaypoint() ) { @@ -1031,7 +1031,7 @@ void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, } } if (pParm->getParameterType() == Parameter::TEAM) { - AsciiString teamName = pParm->getString(); + const AsciiString &teamName = pParm->getString(); TeamsInfo * pInfo = m_sides.findTeamInfo(teamName); if (pInfo) { pInfo->getDict()->setBool(TheKey_exportWithScript, true); @@ -1048,7 +1048,7 @@ void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, } } if (pParm->getParameterType() == Parameter::UNIT) { - AsciiString unitName = pParm->getString(); + const AsciiString &unitName = pParm->getString(); if (doUnits) { MapObject *pObj; for (pObj = MapObject::getFirstMapObject(); pObj; pObj = pObj->getNext()) { diff --git a/Generals/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp b/Generals/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp index 933c664aa69..3331df9e25f 100644 --- a/Generals/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp @@ -323,7 +323,7 @@ WorldHeightMapEdit::WorldHeightMapEdit(ChunkInputStream *pStrm): Bool WorldHeightMapEdit::remapTextures() { Int i; - Bool anyChanges; + Bool anyChanges = false; for (i=0; iisMusicAlreadyLoaded()) return FALSE; - initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new VideoPlayer())); + initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new NullVideoPlayer())); initSubsystem(TheModuleFactory, (ModuleFactory*)(new W3DModuleFactory())); initSubsystem(TheSidesList, new SidesList()); initSubsystem(TheCaveSystem, new CaveSystem()); diff --git a/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp b/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp index ba3fb4530e4..573dd73ab30 100644 --- a/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp +++ b/Generals/Code/Tools/WorldBuilder/src/wbview3d.cpp @@ -1633,7 +1633,7 @@ Bool WbView3d::viewToDocCoords(CPoint curPt, Coord3D *newPt, Bool constrain) float logY = (Real)curPt.y / (Real)client.Height(); Vector3 intersection(0,0,0); // determine the ray corresponding to the camera and distance to projection plane - Matrix3D camera_matrix = m_camera->Get_Transform(); + const Matrix3D& camera_matrix = m_camera->Get_Transform(); Vector3 camera_location = m_camera->Get_Position(); @@ -1761,7 +1761,7 @@ Bool WbView3d::viewToDocCoordZ(CPoint curPt, Coord3D *newPt, Real theZ) float logY = (Real)curPt.y / (Real)client.Height(); Vector3 intersection(0,0,0); // determine the ray corresponding to the camera and distance to projection plane - Matrix3D camera_matrix = m_camera->Get_Transform(); + const Matrix3D& camera_matrix = m_camera->Get_Transform(); Vector3 camera_location = m_camera->Get_Position(); @@ -1816,7 +1816,7 @@ void WbView3d::updateHysteresis() float logY = (Real)curPt.y / (Real)client.Height(); Vector3 intersection(0,0,0); // determine the ray corresponding to the camera and distance to projection plane - Matrix3D camera_matrix = m_camera->Get_Transform(); + const Matrix3D& camera_matrix = m_camera->Get_Transform(); Vector3 camera_location = m_camera->Get_Position(); diff --git a/GeneralsMD/Code/GameEngine/CMakeLists.txt b/GeneralsMD/Code/GameEngine/CMakeLists.txt index 48727ea6458..56efe42adae 100644 --- a/GeneralsMD/Code/GameEngine/CMakeLists.txt +++ b/GeneralsMD/Code/GameEngine/CMakeLists.txt @@ -135,7 +135,7 @@ set(GAMEENGINE_SRC # Include/Common/XferLoad.h # Include/Common/XferSave.h # Include/GameClient/Anim2D.h - Include/GameClient/AnimateWindowManager.h +# Include/GameClient/AnimateWindowManager.h Include/GameClient/CampaignManager.h # Include/GameClient/ChallengeGenerals.h # Include/GameClient/ClientInstance.h @@ -177,8 +177,8 @@ set(GAMEENGINE_SRC # Include/GameClient/GameText.h # Include/GameClient/GameWindow.h # Include/GameClient/GameWindowGlobal.h - Include/GameClient/GameWindowID.h - Include/GameClient/GameWindowManager.h +# Include/GameClient/GameWindowID.h +# Include/GameClient/GameWindowManager.h # Include/GameClient/GameWindowTransitions.h # Include/GameClient/GlobalLanguage.h # Include/GameClient/GraphDraw.h @@ -694,7 +694,7 @@ set(GAMEENGINE_SRC # Source/GameClient/GameText.cpp # Source/GameClient/GlobalLanguage.cpp # Source/GameClient/GraphDraw.cpp - Source/GameClient/GUI/AnimateWindowManager.cpp +# Source/GameClient/GUI/AnimateWindowManager.cpp # Source/GameClient/GUI/ChallengeGenerals.cpp # Source/GameClient/GUI/ControlBar/ControlBar.cpp # Source/GameClient/GUI/ControlBar/ControlBarBeacon.cpp @@ -724,10 +724,10 @@ set(GAMEENGINE_SRC # Source/GameClient/GUI/GameFont.cpp # Source/GameClient/GUI/GameWindow.cpp # Source/GameClient/GUI/GameWindowGlobal.cpp - Source/GameClient/GUI/GameWindowManager.cpp - Source/GameClient/GUI/GameWindowManagerScript.cpp +# Source/GameClient/GUI/GameWindowManager.cpp +# Source/GameClient/GUI/GameWindowManagerScript.cpp # Source/GameClient/GUI/GameWindowTransitions.cpp - Source/GameClient/GUI/GameWindowTransitionsStyles.cpp +# Source/GameClient/GUI/GameWindowTransitionsStyles.cpp # Source/GameClient/GUI/GUICallbacks/ControlBarCallback.cpp # Source/GameClient/GUI/GUICallbacks/ControlBarPopupDescription.cpp # Source/GameClient/GUI/GUICallbacks/Diplomacy.cpp diff --git a/GeneralsMD/Code/GameEngine/Include/Common/GameState.h b/GeneralsMD/Code/GameEngine/Include/Common/GameState.h index 319cbc6a1d4..ed0d6a6d81c 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/GameState.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/GameState.h @@ -199,6 +199,7 @@ class GameState : public SubsystemInterface, AsciiString getSaveDirectory() const; AsciiString getFilePathInSaveDirectory(const AsciiString& leaf) const; + AsciiString getSaveGamePathForRead(const AsciiString& filenameOrPath) const; Bool isInSaveDirectory(const AsciiString& path) const; AsciiString realMapPathToPortableMapPath(const AsciiString& in) const; diff --git a/GeneralsMD/Code/GameEngine/Include/Common/MapReaderWriterInfo.h b/GeneralsMD/Code/GameEngine/Include/Common/MapReaderWriterInfo.h index c114ad29109..773beecd74d 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/MapReaderWriterInfo.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/MapReaderWriterInfo.h @@ -72,7 +72,7 @@ class InputStream { variety of sources, such as FILE* or CFile. */ class ChunkInputStream : public InputStream{ public: - virtual Int read(void *pData, Int numBytes) = 0; + virtual Int read(void *pData, Int numBytes) override = 0; virtual UnsignedInt tell() = 0; virtual Bool absoluteSeek(UnsignedInt pos) = 0; virtual Bool eof() = 0; diff --git a/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h b/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h index b1e3f5bf492..6e0828a89c6 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/TunnelTracker.h @@ -66,7 +66,11 @@ class TunnelTracker : public MemoryPoolObject, void healObjects(); ///< heal all objects within the tunnel #endif +#if RETAIL_COMPATIBLE_CRC UnsignedInt friend_getTunnelCount() const {return m_tunnelCount;}///< TunnelContains are allowed to ask if they are the last one ahead of deletion time +#else + UnsignedInt friend_getTunnelCount() const { return m_tunnelIDs.size(); }///< TunnelContains are allowed to ask if they are the last one ahead of deletion time +#endif const std::list< ObjectID > *getContainerList() const {return &m_tunnelIDs;} @@ -87,7 +91,9 @@ class TunnelTracker : public MemoryPoolObject, std::list< ObjectID > m_xferContainList;///< for loading of m_containList during post processing Int m_containListSize; ///< size of the contain list UnsignedInt m_heroUnitsContained; ///< cached hero count +#if RETAIL_COMPATIBLE_CRC UnsignedInt m_tunnelCount; ///< How many tunnels have registered so we know when we should kill our contain list +#endif UnsignedInt m_framesForFullHeal; ///< How many frames it takes to fully heal a unit Bool m_needsFullHealTimeUpdate; ///< Set to true when needing to recalc full heal time to batch the operation diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h index 2f89b4c969a..82444f91a4c 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/ProductionUpdate.h @@ -158,7 +158,7 @@ class ProductionUpdateInterface virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const = 0; virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) = 0; - virtual void cancelUnitCreate( ProductionID productionID ) = 0; + virtual Bool cancelUnitCreate( ProductionID productionID ) = 0; virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) = 0; virtual void cancelAndRefundAllProduction() = 0; @@ -214,7 +214,7 @@ class ProductionUpdate : public UpdateModule, public ProductionUpdateInterface, virtual UnsignedInt countUnitTypeInQueue( const ThingTemplate *unitType ) const override; ///< count number of units with matching unit type in the production queue virtual Bool queueCreateUnit( const ThingTemplate *unitType, ProductionID productionID ) override; ///< queue unit to be produced - virtual void cancelUnitCreate( ProductionID productionID ) override; ///< cancel construction of unit with matching production ID + virtual Bool cancelUnitCreate( ProductionID productionID ) override; ///< cancel construction of unit with matching production ID virtual void cancelAllUnitsOfType( const ThingTemplate *unitType) override; ///< cancel all production of type unitType virtual void cancelAndRefundAllProduction() override; ///< cancel and refund anything in the production queue diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h index d539559d42e..41cb104ac18 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Module/TunnelContain.h @@ -97,7 +97,9 @@ class TunnelContain : public OpenContain, public CreateModuleInterface virtual void onContaining( Object *obj, Bool wasSelected ) override; ///< object now contains 'obj' virtual void onRemoving( Object *obj ) override; ///< object no longer contains 'obj' virtual void onSelling() override;///< Container is being sold. Tunnel responds by kicking people out if this is the last tunnel. +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) virtual void onCapture( Player *oldOwner, Player *newOwner ) override; // Need to change who we are registered with. +#endif virtual void orderAllPassengersToExit( CommandSourceType commandSource, Bool instantly ) override; ///< All of the smarts of exiting are in the passenger's AIExit. removeAllFrommContain is a last ditch system call, this is the game Evacuate virtual void orderAllPassengersToIdle( CommandSourceType commandSource ) override; ///< Just like it sounds diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h index 90fc52b3960..13019ab3fa7 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h @@ -452,10 +452,6 @@ class Object : public Thing, public Snapshot const Object* getEnclosingContainedBy() const; ///< Find the first enclosing container in the containment chain. const Object* getOuterObject() const; ///< Get the top-level object -#if RTS_ZEROHOUR && RETAIL_COMPATIBLE_CRC - void friend_setContainedByID(ObjectID id) { m_containedByID = id; } -#endif - // Special Powers ------------------------------------------------------------------------------- SpecialPowerModuleInterface *getSpecialPowerModule( const SpecialPowerTemplate *specialPowerTemplate ) const; void doSpecialPower( const SpecialPowerTemplate *specialPowerTemplate, UnsignedInt commandOptions, Bool forced = false ); ///< execute power @@ -764,7 +760,7 @@ class Object : public Thing, public Snapshot Object* m_containedBy; /**< an object can only be contained by at most one other object, this is that object (if present) */ - ObjectID m_containedByID; ///< ID of the object we're contained by; only to be used when m_containedBy cannot be used + ObjectID m_xferContainedByID; ///< xfer uses IDs to store pointers and looks them up after UnsignedInt m_containedByFrame; ///< frame we were contained by m_containedBy Real m_constructionPercent; ///< for objects being built ... this is the amount completed (0.0 to 100.0) diff --git a/GeneralsMD/Code/GameEngine/Include/GameLogic/VictoryConditions.h b/GeneralsMD/Code/GameEngine/Include/GameLogic/VictoryConditions.h index 418bb958f3c..26c2e0a5027 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameLogic/VictoryConditions.h +++ b/GeneralsMD/Code/GameEngine/Include/GameLogic/VictoryConditions.h @@ -51,9 +51,9 @@ class VictoryConditionsInterface : public SubsystemInterface public: VictoryConditionsInterface() { m_victoryConditions = 0; } - virtual void init() = 0; - virtual void reset() = 0; - virtual void update() = 0; + virtual void init() override = 0; + virtual void reset() override = 0; + virtual void update() override = 0; void setVictoryConditions( Int victoryConditions ) { m_victoryConditions = victoryConditions; } Int getVictoryConditions() { return m_victoryConditions; } diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp index ad9e5c369d5..b009e8fde59 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/Player.cpp @@ -3736,7 +3736,7 @@ void Player::processSelectTeamGameMessage(Int hotkeyNum) { m_currentSelection->clearSquad(); - VecObjectPtr objectList = m_squads[hotkeyNum]->getLiveObjects(); + const VecObjectPtr& objectList = m_squads[hotkeyNum]->getLiveObjects(); Int numObjs = objectList.size(); for (Int i = 0; i < numObjs; ++i) @@ -3768,7 +3768,7 @@ void Player::processAddTeamGameMessage(Int hotkeyNum) { m_currentSelection = newInstance( Squad ); } - VecObjectPtr objectList = m_squads[hotkeyNum]->getLiveObjects(); + const VecObjectPtr& objectList = m_squads[hotkeyNum]->getLiveObjects(); Int numObjs = objectList.size(); for (Int i = 0; i < numObjs; ++i) { diff --git a/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp b/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp index 5e1de31615e..014f62b63b5 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/RTS/TunnelTracker.cpp @@ -50,7 +50,9 @@ // ------------------------------------------------------------------------ TunnelTracker::TunnelTracker() { +#if RETAIL_COMPATIBLE_CRC m_tunnelCount = 0; +#endif m_containListSize = 0; m_heroUnitsContained = 0; m_curNemesisID = INVALID_ID; @@ -224,7 +226,12 @@ Bool TunnelTracker::isInContainer( Object *obj ) // ------------------------------------------------------------------------ void TunnelTracker::onTunnelCreated( const Object *newTunnel ) { + DEBUG_ASSERTCRASH(std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), newTunnel->getID()) == m_tunnelIDs.end(), + ("TunnelTracker::onTunnelCreated - New tunnel was already added; this shouldn't happen")); + +#if RETAIL_COMPATIBLE_CRC m_tunnelCount++; +#endif m_tunnelIDs.push_back( newTunnel->getID() ); m_needsFullHealTimeUpdate = true; } @@ -232,20 +239,61 @@ void TunnelTracker::onTunnelCreated( const Object *newTunnel ) // ------------------------------------------------------------------------ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) { +#if RETAIL_COMPATIBLE_CRC + + DEBUG_ASSERTLOG(static_cast(m_tunnelCount) > 0 && m_tunnelCount == m_tunnelIDs.size(), + ("TunnelTracker::onTunnelDestroyed - Tunnel count is unexpected")); + + const size_t oldSize = m_tunnelIDs.size(); + m_tunnelIDs.remove(deadTunnel->getID()); + + (void)oldSize; + DEBUG_ASSERTLOG(oldSize != m_tunnelIDs.size(), + ("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", deadTunnel->getName().str())); + + m_tunnelCount--; + + if( m_tunnelCount == 0 ) + { + // Kill everyone in our contain list. Cave in! + iterateContained( destroyObject, nullptr, FALSE ); + m_containList.clear(); + m_containListSize = 0; + } + else { - std::list::iterator it = std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), deadTunnel->getID()); - if (it == m_tunnelIDs.end()) + // TheSuperHackers @bugfix Caball009 01/09/2026 Check if container is empty before accessing it. + // The tunnel count may diverge from the container size, because of bugs that cannot be fixed with + // retail compatibility enabled. Expected retail behavior: empty container access results in a nullptr. + Object *tunnel = m_tunnelIDs.empty() ? nullptr : TheGameLogic->findObjectByID( m_tunnelIDs.front() ); + + // Otherwise, make sure nobody inside remembers the dead tunnel as the one they entered + // (scripts need to use so there must be something valid here) + for(ContainedItemsList::iterator it = m_containList.begin(); it != m_containList.end(); ) { - DEBUG_CRASH(("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", deadTunnel->getName().str())); - return; + Object* obj = *it; + ++it; + if( obj->getContainedBy() == deadTunnel ) + obj->onContainedBy( tunnel ); } + } - m_tunnelCount--; +#else + + const std::list::iterator it = std::find(m_tunnelIDs.begin(), m_tunnelIDs.end(), deadTunnel->getID()); + if (it != m_tunnelIDs.end()) + { m_tunnelIDs.erase(it); + m_needsFullHealTimeUpdate = true; } + else + { + DEBUG_CRASH(("TunnelTracker::onTunnelDestroyed - Attempting to remove object '%s' that has never been tracked as a tunnel", + deadTunnel->getName().str())); + } - if( m_tunnelCount == 0 ) + if( m_tunnelIDs.empty() ) { // Kill everyone in our contain list. Cave in! iterateContained( destroyObject, nullptr, FALSE ); @@ -255,6 +303,7 @@ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) else { Object *validTunnel = TheGameLogic->findObjectByID( m_tunnelIDs.front() ); + // Otherwise, make sure nobody inside remembers the dead tunnel as the one they entered // (scripts need to use so there must be something valid here) for(ContainedItemsList::iterator it = m_containList.begin(); it != m_containList.end(); ) @@ -265,6 +314,8 @@ void TunnelTracker::onTunnelDestroyed( const Object *deadTunnel ) obj->onContainedBy( validTunnel ); } } + +#endif // RETAIL_COMPATIBLE_CRC } // ------------------------------------------------------------------------ @@ -379,13 +430,19 @@ void TunnelTracker::crc( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ /** Xfer method * Version Info: - * 1: Initial version */ + * 1: Initial version + * 2: TheSuperHackers @tweak Removed m_tunnelCount (should always be equal to m_tunnelIDs.size()) + */ // ------------------------------------------------------------------------------------------------ void TunnelTracker::xfer( Xfer *xfer ) { // version +#if RETAIL_COMPATIBLE_XFER_SAVE XferVersion currentVersion = 1; +#else + XferVersion currentVersion = 2; +#endif XferVersion version = currentVersion; xfer->xferVersion( &version, currentVersion ); @@ -424,8 +481,25 @@ void TunnelTracker::xfer( Xfer *xfer ) m_needsFullHealTimeUpdate = true; } - // tunnel count - xfer->xferUnsignedInt( &m_tunnelCount ); +#if RETAIL_COMPATIBLE_CRC + if (version <= 1) + { + xfer->xferUnsignedInt(&m_tunnelCount); + } + else + { + if (xfer->getXferMode() == XFER_LOAD) + { + m_tunnelCount = m_tunnelIDs.size(); + } + } +#else + if (version <= 1) + { + UnsignedInt tunnelCount = m_tunnelIDs.size(); + xfer->xferUnsignedInt(&tunnelCount); + } +#endif } diff --git a/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp b/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp index 1317ec4d5a8..d0cc588b4a4 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp @@ -53,6 +53,7 @@ #include "GameClient/GameClient.h" #include "GameClient/GameText.h" #include "GameClient/MapUtil.h" +#include "GameClient/MessageBox.h" #include "GameClient/InGameUI.h" #include "GameClient/ParticleSys.h" #include "GameClient/TerrainVisual.h" @@ -62,6 +63,7 @@ #include "GameLogic/ScriptEngine.h" #include "GameLogic/SidesList.h" #include "GameLogic/TerrainLogic.h" +#include "Lib/PathUtil.h" // PUBLIC DATA //////////////////////////////////////////////////////////////////////////////////// @@ -677,8 +679,7 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo ) // TheGameStateMap->clearScratchPadMaps(); - // construct path to file - AsciiString filepath = getFilePathInSaveDirectory(gameInfo.filename); + AsciiString filepath = getSaveGamePathForRead(gameInfo.filename); // open the save file XferLoad xferLoad; @@ -761,6 +762,15 @@ SaveCode GameState::loadGame( AvailableGameInfo gameInfo ) } +//------------------------------------------------------------------------------------------------- +static void showQueuedSaveGameLoadFailure( void ) +{ + UnicodeString title = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailedTitle", L"CANNOT LOAD SAVE"); + UnicodeString body = TheGameText->FETCH_OR_SUBSTITUTE("GUI:SaveGameLoadFailed", L"The saved game file could not be opened or is invalid."); + + MessageBoxOk(title, body, nullptr); +} + // ------------------------------------------------------------------------------------------------ /** Load the save game requested on startup, after the shell has been initialized */ // ------------------------------------------------------------------------------------------------ @@ -775,26 +785,32 @@ void GameState::loadQueuedSaveGame() TheWritableGlobalData->m_loadSaveGame.clear(); + if( gameInfo.filename.endsWithNoCase( SAVE_GAME_EXTENSION ) == FALSE ) + { + DEBUG_LOG(("Save game '%s' is not a save game file", gameInfo.filename.str())); + showQueuedSaveGameLoadFailure(); + return; + } + // getSaveGameInfoFromFile throws when the file is missing, so check before reading it if( doesSaveGameExist( gameInfo.filename ) == FALSE ) { std::fprintf(stderr, "Save game '%s' was not found\n", gameInfo.filename.str()); std::fflush(stderr); - TheGameEngine->setQuitting( TRUE ); + showQueuedSaveGameLoadFailure(); return; } // getSaveGameInfoFromFile throws on a malformed file instead of returning a SaveCode try { - AsciiString filepath = getFilePathInSaveDirectory( gameInfo.filename ); - getSaveGameInfoFromFile( filepath, &gameInfo.saveGameInfo ); + getSaveGameInfoFromFile( gameInfo.filename, &gameInfo.saveGameInfo ); } catch( ... ) { std::fprintf(stderr, "Save game '%s' could not be read\n", gameInfo.filename.str()); std::fflush(stderr); - TheGameEngine->setQuitting( TRUE ); + showQueuedSaveGameLoadFailure(); return; } @@ -833,6 +849,17 @@ AsciiString GameState::getFilePathInSaveDirectory(const AsciiString& leaf) const return tmp; } +//------------------------------------------------------------------------------------------------- +AsciiString GameState::getSaveGamePathForRead(const AsciiString& filenameOrPath) const +{ + if (isAbsolutePath(filenameOrPath.str())) + { + return filenameOrPath; + } + + return getFilePathInSaveDirectory(filenameOrPath); +} + //------------------------------------------------------------------------------------------------- Bool GameState::isInSaveDirectory(const AsciiString& path) const { @@ -999,8 +1026,7 @@ AsciiString GameState::portableMapPathToRealMapPath(const AsciiString& in) const Bool GameState::doesSaveGameExist( AsciiString filename ) { - // construct full path to file - AsciiString filepath = getFilePathInSaveDirectory(filename); + AsciiString filepath = getSaveGamePathForRead(filename); // open file XferLoad xfer; @@ -1044,6 +1070,8 @@ void GameState::getSaveGameInfoFromFile( AsciiString filename, SaveGameInfo *sav } + filename = getSaveGamePathForRead( filename ); + // open file for partial loading XferLoad xferLoad; xferLoad.open( filename ); diff --git a/GeneralsMD/Code/GameEngine/Source/Common/Thing/Module.cpp b/GeneralsMD/Code/GameEngine/Source/Common/Thing/Module.cpp index e9c31c1c082..de74fa03dc4 100644 --- a/GeneralsMD/Code/GameEngine/Source/Common/Thing/Module.cpp +++ b/GeneralsMD/Code/GameEngine/Source/Common/Thing/Module.cpp @@ -269,7 +269,7 @@ Bool UpgradeMuxData::isTriggeredBy(const std::string &upgrade) const std::vector::const_iterator it; for( it = m_triggerUpgradeNames.begin(); it != m_triggerUpgradeNames.end(); ++it) { - AsciiString trigger = *it; + const AsciiString &trigger = *it; if (stricmp(trigger.str(), upgrade.c_str()) == 0) { return TRUE; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp index ea04ca8b999..b2d1e95d7bd 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLBuddyOverlay.cpp @@ -703,7 +703,7 @@ void PopulateOldBuddyMessages() BuddyMessageList *messages = TheGameSpyInfo->getBuddyMessages(); for (BuddyMessageList::iterator mIt = messages->begin(); mIt != messages->end(); ++mIt) { - BuddyMessage message = *mIt; + const BuddyMessage &message = *mIt; insertChat(message); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp index 3b1e67de325..94c6fa4cae9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/WOLQuickMatchMenu.cpp @@ -587,7 +587,7 @@ static void populateQuickMatchMapSelectListbox( QuickMatchPreferences& pref ) GadgetListBoxReset(listboxMapSelect); for (std::list::const_iterator it = maps.begin(); it != maps.end(); ++it) { - AsciiString theMap = *it; + const AsciiString &theMap = *it; const MapMetaData *md = TheMapCache->findMap(theMap); if (md && md->m_numPlayers >= numPlayers) { @@ -1727,7 +1727,7 @@ WindowMsgHandledType WOLQuickMatchMenuSystem( GameWindow *window, UnsignedInt ms if (cit != ladderInfo->validFactions.end()) { Int numPlayerTemplates = ThePlayerTemplateStore->getPlayerTemplateCount(); - AsciiString sideStr = *cit; + const AsciiString &sideStr = *cit; DEBUG_LOG(("Chose %s as our side... finding", sideStr.str())); for (Int c=0; cgetLiveObjects(); + const VecObjectPtr& objects = victimSquad->getLiveObjects(); Int numUnits = objects.size(); if (numUnits == 0) { @@ -6035,7 +6035,7 @@ Object *AIAttackSquadState::chooseVictim() case DIFFICULTY_HARD: { // everyone picks the same unit - VecObjectPtr objects = victimSquad->getLiveObjects(); + const VecObjectPtr& objects = victimSquad->getLiveObjects(); if (!objects.empty()) { return objects[0]; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/HelixContain.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/HelixContain.cpp index c900e02d348..c6da15c17c5 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/HelixContain.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/HelixContain.cpp @@ -246,35 +246,19 @@ void HelixContain::addToContainList( Object *obj ) { if ( obj->isKindOf( KINDOF_PORTABLE_STRUCTURE ) && m_portableStructureID == INVALID_ID) { - Object *portable = getPortableStructure(); - if ( portable ) + if ( Object *portable = getPortableStructure() ) TheGameLogic->destroyObject( portable ); - portable = obj; - - m_portableStructureID = portable->getID(); - portable->friend_setContainedBy( getObject() );//fool portable into thinking my object is his container + m_portableStructureID = obj->getID(); + obj->friend_setContainedBy( getObject() );//fool portable into thinking my object is his container -#if RETAIL_COMPATIBLE_CRC - Object* containedBy = getObject(); - - // TheSuperHackers @info Set INVALID_ID if the container object was destroyed - // to indicate that the pointer will become a dangling pointer in the next frame. - if (containedBy && !containedBy->isDestroyed()) - { - portable->friend_setContainedByID(containedBy->getID()); - } - else - { - portable->friend_setContainedByID(INVALID_ID); - } -#else DEBUG_ASSERTCRASH(getObject() == nullptr || !getObject()->isDestroyed(), ("HelixContain::addToContainList - Adding to a destroyed container")); -#endif } else - TransportContain::addToContainList( obj ); + { + TransportContain::addToContainList( obj ); + } } //------------------------------------------------------------------------------------------------- @@ -282,35 +266,19 @@ void HelixContain::addToContain( Object *obj ) { if ( obj->isKindOf( KINDOF_PORTABLE_STRUCTURE ) && m_portableStructureID == INVALID_ID) { - Object *portable = getPortableStructure(); - if ( portable ) + if ( Object *portable = getPortableStructure() ) TheGameLogic->destroyObject( portable ); - portable = obj; - - m_portableStructureID = portable->getID(); - portable->friend_setContainedBy( getObject() );//fool portable into thinking my object is his container + m_portableStructureID = obj->getID(); + obj->friend_setContainedBy( getObject() );//fool portable into thinking my object is his container -#if RETAIL_COMPATIBLE_CRC - Object* containedBy = getObject(); - - // TheSuperHackers @info Set INVALID_ID if the container object was destroyed - // to indicate that the pointer will become a dangling pointer in the next frame. - if (containedBy && !containedBy->isDestroyed()) - { - portable->friend_setContainedByID(containedBy->getID()); - } - else - { - portable->friend_setContainedByID(INVALID_ID); - } -#else DEBUG_ASSERTCRASH(getObject() == nullptr || !getObject()->isDestroyed(), ("HelixContain::addToContain - Adding to a destroyed container")); -#endif } else - TransportContain::addToContain( obj ); + { + TransportContain::addToContain( obj ); + } } //------------------------------------------------------------------------------------------------- @@ -321,9 +289,7 @@ void HelixContain::removeFromContain( Object *obj, Bool exposeStealthUnits ) Object *portable = getPortableStructure(); if ( portable ) { -#if RETAIL_COMPATIBLE_CRC - portable->friend_setContainedByID(INVALID_ID); -#else +#if !RETAIL_COMPATIBLE_CRC portable->friend_setContainedBy(nullptr); #endif diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp index b8e721af804..5f9a3707891 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/OpenContain.cpp @@ -177,6 +177,12 @@ OpenContain::~OpenContain() ("OpenContain %s: m_xferContainIDList is not empty but should be", getObject()->getTemplate()->getName().str() ) ); +#if RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Caball009 18/08/2026 Due to a potential use-after-free bug that cannot be fixed + // with retail compatibility, it's desirable to be able to check if the contain list is empty after its destruction. + // Clear the list explicitly to reset the list size. + m_containList.clear(); +#endif } //------------------------------------------------------------------------------------------------- @@ -439,6 +445,15 @@ void OpenContain::removeFromContain( Object *rider, Bool exposeStealthUnits ) } +#if RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix Caball009 18/08/2026 Due to a potential use-after-free bug that cannot be fixed + // with retail compatibility, the 'contained by' pointer of this object may point to an already destroyed object. + // Check the list size before executing the find operation below, otherwise the game crashes if the list + // was already destructed. + if (m_containList.empty()) + return; +#endif + ContainedItemsList::iterator it = std::find(m_containList.begin(), m_containList.end(), rider); if (it != m_containList.end()) { diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp index 437472084d8..16a6f1c8a3c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Contain/TunnelContain.cpp @@ -504,6 +504,7 @@ void TunnelContain::onBuildComplete() // ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------ +#if !(RTS_GENERALS && RETAIL_COMPATIBLE_CRC) void TunnelContain::onCapture( Player *oldOwner, Player *newOwner ) { if( m_isCurrentlyRegistered ) @@ -525,6 +526,7 @@ void TunnelContain::onCapture( Player *oldOwner, Player *newOwner ) // extend base class OpenContain::onCapture( oldOwner, newOwner ); } +#endif //------------------------------------------------------------------------------------------------- void TunnelContain::orderAllPassengersToExit( CommandSourceType commandSource, Bool instantly ) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp index a372f344fdb..42347f63878 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp @@ -183,7 +183,7 @@ Object::Object( const ThingTemplate *tt, const ObjectStatusMaskType &objectStatu m_physics(nullptr), m_geometryInfo(tt->getTemplateGeometryInfo()), m_containedBy(nullptr), - m_containedByID(INVALID_ID), + m_xferContainedByID(INVALID_ID), m_containedByFrame(0), m_behaviors(nullptr), m_body(nullptr), @@ -692,21 +692,8 @@ void Object::onContainedBy( Object *containedBy ) m_containedBy = containedBy; m_containedByFrame = TheGameLogic->getFrame(); -#if RETAIL_COMPATIBLE_CRC - // TheSuperHackers @info Set INVALID_ID if the container object was destroyed - // to indicate that the pointer will become a dangling pointer in the next frame. - if (containedBy && !containedBy->isDestroyed()) - { - m_containedByID = containedBy->getID(); - } - else - { - m_containedByID = INVALID_ID; - } -#else DEBUG_ASSERTCRASH(containedBy == nullptr || !containedBy->isDestroyed(), - ("Object::onContainedBy - Adding into a destroyed container")); -#endif + ("Object::onContainedBy - Adding to a destroyed container")); handlePartitionCellMaintenance(); // which should unlook me now that I am contained @@ -721,10 +708,6 @@ void Object::onRemovedFrom( Object *removedFrom ) m_containedBy = nullptr; m_containedByFrame = 0; -#if RETAIL_COMPATIBLE_CRC - m_containedByID = INVALID_ID; -#endif - handlePartitionCellMaintenance(); // get a clean look, now that I am outdoors, again } @@ -786,33 +769,9 @@ void Object::onDestroy() { // This is the old cleanUpContain safeguard. Say goodbye so they don't try to look us up. - if (m_containedBy) + if( m_containedBy && m_containedBy->getContain() ) { -#if RETAIL_COMPATIBLE_CRC - if (m_containedByID == INVALID_ID) - { - // TheSuperHackers @bugfix Caball009 25/05/2026 Due to a potential use-after-free bug that cannot be fixed - // with retail compatibility, the 'contained by' pointer of this object may point to an already destroyed object. - // Avoid removing this object from the contain list, because it could crash the game, - // as the begin / end iterator for STLPort and MSVC std::list implementations depends on dynamically allocated memory. - DEBUG_CRASH(("container object must be valid; this looks like use-after-free")); - } - else - { - DEBUG_ASSERTCRASH(TheGameLogic->findObjectByID(m_containedByID) == m_containedBy, - ("contained by pointer is out of sync with contained by ID")); - - if (ContainModuleInterface* contain = m_containedBy->getContain()) - { - contain->removeFromContain(this); - } - } -#else - if (ContainModuleInterface* contain = m_containedBy->getContain()) - { - contain->removeFromContain(this); - } -#endif + m_containedBy->getContain()->removeFromContain( this ); } // @@ -4305,19 +4264,16 @@ void Object::xfer( Xfer *xfer ) // No, the contain module is just going to friend_ reach in and set this for us. // Containers more complicated than Open (like Tunnel) can't do that. Our variable, // our responsibility. -#if RETAIL_COMPATIBLE_CRC - // TheSuperHackers @tweak Contained by ID is already set with retail compatibility; don't overwrite it. -#else if( xfer->getXferMode() == XFER_SAVE ) { if( m_containedBy != nullptr ) - m_containedByID = m_containedBy->getID(); + m_xferContainedByID = m_containedBy->getID(); else - m_containedByID = INVALID_ID; + m_xferContainedByID = INVALID_ID; } -#endif - xfer->xferObjectID( &m_containedByID ); + + xfer->xferObjectID( &m_xferContainedByID ); } // contained by frame @@ -4542,8 +4498,8 @@ void Object::xfer( Xfer *xfer ) //------------------------------------------------------------------------------------------------- void Object::loadPostProcess() { - if( m_containedByID != INVALID_ID ) - m_containedBy = TheGameLogic->findObjectByID(m_containedByID); + if( m_xferContainedByID != INVALID_ID ) + m_containedBy = TheGameLogic->findObjectByID(m_xferContainedByID); else m_containedBy = nullptr; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp index 9cc0e121e04..57cfc617175 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp @@ -3556,7 +3556,13 @@ void AIUpdateInterface::privateAttackPosition( const Coord3D *pos, Int maxShotsT // this fixes an obscure bug with mine-clearing: if you tell someone to clear mines and put the centerpoint // inside a building, the dozer/worker will just go thru the building to that spot. ick. so if you find that // this clause (below) is problematic, you'll probably have to find another way to fix this mine-clearing bug. (srj) +#if RETAIL_COMPATIBLE_CRC if (weapon && weapon->isContactWeapon() && !isPathAvailable(&localPos)) +#else + // TheSuperHackers @bugfix Stubbjax 23/08/2026 Only find a new position if the target is not within the attack range of the weapon. + // This allows contact weapons such as suicide bombs to immediately detonate without first pathing to a nearby position. + if (weapon && weapon->isContactWeapon() && !weapon->isWithinAttackRange(getObject(), &localPos) && !isPathAvailable(&localPos)) +#endif { FindPositionOptions fpOptions; fpOptions.minRadius = 0.0f; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp index 4757457d8e6..e8556a5d24c 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AssistedTargetingUpdate.cpp @@ -65,8 +65,14 @@ void AssistedTargetingUpdateModuleData::buildFieldParse(MultiIniFieldParse& p) //------------------------------------------------------------------------------------------------- AssistedTargetingUpdate::AssistedTargetingUpdate( Thing *thing, const ModuleData* moduleData ) : UpdateModule( thing, moduleData ) { - m_laserFromAssisted = nullptr; - m_laserToTarget = nullptr; + const AssistedTargetingUpdateModuleData* d = getAssistedTargetingUpdateModuleData(); + + m_laserFromAssisted = TheThingFactory->findTemplate(d->m_laserFromAssistedName); + m_laserToTarget = TheThingFactory->findTemplate(d->m_laserToTargetName); +#if RTS_GENERALS || !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @info Zero Hour needs the update to run once to avoid mismatches with retail. + setWakeFrame(getObject(), UPDATE_SLEEP_FOREVER); +#endif } //------------------------------------------------------------------------------------------------- @@ -138,11 +144,6 @@ void AssistedTargetingUpdate::makeFeedbackLaser( const ThingTemplate *laserTempl //------------------------------------------------------------------------------------------------- UpdateSleepTime AssistedTargetingUpdate::update() { - const AssistedTargetingUpdateModuleData *d = getAssistedTargetingUpdateModuleData(); - - m_laserFromAssisted = TheThingFactory->findTemplate( d->m_laserFromAssistedName ); - m_laserToTarget = TheThingFactory->findTemplate( d->m_laserToTargetName ); - return UPDATE_SLEEP_FOREVER; } @@ -180,11 +181,6 @@ void AssistedTargetingUpdate::xfer( Xfer *xfer ) // ------------------------------------------------------------------------------------------------ void AssistedTargetingUpdate::loadPostProcess() { - const AssistedTargetingUpdateModuleData *d = getAssistedTargetingUpdateModuleData(); - - m_laserFromAssisted = TheThingFactory->findTemplate( d->m_laserFromAssistedName ); - m_laserToTarget = TheThingFactory->findTemplate( d->m_laserToTargetName ); - // extend base class UpdateModule::loadPostProcess(); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/OCLUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/OCLUpdate.cpp index 9856dc66a80..b5e33b1616e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/OCLUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/OCLUpdate.cpp @@ -209,7 +209,7 @@ UpdateSleepTime OCLUpdate::update() // Loop through the list of faction ocls to find the matching faction that triggers the specific ocls for (OCLUpdateModuleData::FactionOCLList::const_iterator it = data->m_factionOCL.begin(); it != data->m_factionOCL.end(); ++it) { - OCLUpdateModuleData::FactionOCLInfo info = *it; + const OCLUpdateModuleData::FactionOCLInfo &info = *it; if (playerFactionName == info.m_factionName) { ObjectCreationList::create( info.m_ocl, getObject(), &creationCoord, getObject()->getPosition(), getObject()->getOrientation() ); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp index e540ac948d9..204bbdd1a38 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ProductionUpdate.cpp @@ -458,7 +458,7 @@ Bool ProductionUpdate::queueCreateUnit( const ThingTemplate *unitType, Productio //------------------------------------------------------------------------------------------------- /** Cancel the construction of the unit with the matching production ID */ //------------------------------------------------------------------------------------------------- -void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) +Bool ProductionUpdate::cancelUnitCreate( ProductionID productionID ) { // search for the production entry in our queue @@ -470,8 +470,15 @@ void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) if( production->m_productionID == productionID ) { - // give the player the cost of the object back Player *player = getObject()->getControllingPlayer(); + +#if !RETAIL_COMPATIBLE_CRC + // TheSuperHackers @bugfix arcticdolphin 07/09/2026 No cancel once the batch has started producing. + if( production->getProductionQuantityRemaining() < production->getProductionQuantity() ) + return FALSE; +#endif + + // give the player the cost of the object back Money *money = player->getMoney(); money->deposit( production->m_objectToProduce->calcCostToBuild( player ), TRUE, FALSE ); @@ -481,12 +488,14 @@ void ProductionUpdate::cancelUnitCreate( ProductionID productionID ) // delete the production entry deleteInstance(production); - return; + return TRUE; } } + return FALSE; + } //------------------------------------------------------------------------------------------------- @@ -659,7 +668,7 @@ UpdateSleepTime ProductionUpdate::update() // if we've become OBJECT_STATUS_SOLD, halt all production ... leave things in the // queue because if the sell process completes we get money back for them, for now we // will be just frozen in time - // Actually, there will be nothing in the queue since everything gets cancel/refunded + // Actually, there will usually be nothing in the queue since everything gets cancel/refunded // at the start of sell, but we still don't want to do anything here. // if( us->getStatusBits().test( OBJECT_STATUS_SOLD ) ) @@ -693,10 +702,8 @@ UpdateSleepTime ProductionUpdate::update() // Don't cancel dozers in the queue. jba. if (!production->getProductionObject()->isKindOf(KINDOF_DOZER)) { - - cancelUnitCreate(production->getProductionID()); - return UPDATE_SLEEP_NONE; - + if( cancelUnitCreate(production->getProductionID()) ) + return UPDATE_SLEEP_NONE; } } @@ -1138,23 +1145,32 @@ void ProductionUpdate::cancelAndRefundAllProduction() { // Empirically, in release the code can loop forever. So we limit to 100 passes. jba. [8/31/2003] const Int productionLimit = 100;// With luck, we never queue up 100 units. [8/31/2003] - Int i; - for (i=0; im_next; + + if( production->getProductionType() == PRODUCTION_UNIT ) { - if( m_productionQueue->getProductionType() == PRODUCTION_UNIT ) - cancelUnitCreate( m_productionQueue->getProductionID() ); - else if( m_productionQueue->getProductionType() == PRODUCTION_UPGRADE ) - cancelUpgrade( m_productionQueue->getProductionUpgrade() ); - else + if( !cancelUnitCreate( production->getProductionID() ) ) { - // unknown production type - DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", m_productionQueue->getProductionType() )); - return; + removeFromProductionQueue( production ); + deleteInstance( production ); } } + else if( production->getProductionType() == PRODUCTION_UPGRADE ) + cancelUpgrade( production->getProductionUpgrade() ); + else + { + // unknown production type + DEBUG_CRASH(( "ProductionUpdate::cancelAndRefundAllProduction - Unknown production type '%d'", production->getProductionType() )); + return; + } + + production = nextProduction; + ++i; } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp index 99f6b94f5fc..b77f069b462 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp @@ -637,7 +637,7 @@ void ScriptActions::doCreateReinforcements(const AsciiString& team, const AsciiS PartitionSolver partition(vecOfUnits, vecOfTransports, PREFER_FAST_SOLUTION); partition.solve(); - SolutionVec solution = partition.getSolution(); + const SolutionVec& solution = partition.getSolution(); for (size_t i = 0; i < solution.size(); ++i) { Object *unit = TheGameLogic->findObjectByID(solution[i].first); Object *trans = TheGameLogic->findObjectByID(solution[i].second); @@ -1511,7 +1511,7 @@ void ScriptActions::doLoadAllTransports(const AsciiString& teamName) PartitionSolver partition(vecOfUnits, vecOfTransports, PREFER_FAST_SOLUTION); partition.solve(); - SolutionVec solution = partition.getSolution(); + const SolutionVec& solution = partition.getSolution(); for (size_t i = 0; i < solution.size(); ++i) { Object *unit = TheGameLogic->findObjectByID(solution[i].first); Object *trans = TheGameLogic->findObjectByID(solution[i].second); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp index 2de271902bc..3377cd9de4e 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptConditions.cpp @@ -199,7 +199,7 @@ void ScriptConditions::objectTypesFromParam(Parameter *pTypeParm, ObjectTypes *o return; } - AsciiString str = pTypeParm->getString(); + const AsciiString &str = pTypeParm->getString(); if (str.isEmpty()) { return; @@ -355,7 +355,7 @@ Bool ScriptConditions::evaluateNamedUnitTotallyDead(Parameter *pUnitParm) //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluateHasUnits(Parameter *pTeamParm) { - AsciiString desiredTeamName = pTeamParm->getString(); + const AsciiString &desiredTeamName = pTeamParm->getString(); // If they are calling a condition, do it. if (desiredTeamName == THIS_TEAM) { Team *theTeam = TheScriptEngine->getTeamNamed( desiredTeamName ); @@ -396,7 +396,6 @@ Bool ScriptConditions::evaluateTeamInsideAreaPartially(Parameter *pTeamParm, Par Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString triggerName = pTriggerAreaParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerAreaParm->getString()); if (pTrig == nullptr) return false; @@ -418,7 +417,6 @@ Bool ScriptConditions::evaluateNamedInsideArea(Parameter *pUnitParm, Parameter * return false; } - AsciiString triggerName = pTriggerAreaParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerAreaParm->getString()); if (pTrig == nullptr) return false; if (theObj) { @@ -435,7 +433,6 @@ Bool ScriptConditions::evaluateNamedInsideArea(Parameter *pUnitParm, Parameter * //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluatePlayerHasUnitTypeInArea(Condition *pCondition, Parameter *pPlayerParm, Parameter *pComparisonParm, Parameter *pCountParm, Parameter *pTypeParm, Parameter *pTriggerParm ) { - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (pTrig == nullptr) return false; @@ -528,7 +525,6 @@ Bool ScriptConditions::evaluatePlayerHasUnitTypeInArea(Condition *pCondition, Pa //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluatePlayerHasUnitKindInArea(Condition *pCondition, Parameter *pPlayerParm, Parameter *pComparisonParm, Parameter *pCountParm, Parameter *pKindParm, Parameter *pTriggerParm ) { - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (pTrig == nullptr) return false; @@ -612,7 +608,7 @@ Bool ScriptConditions::evaluateTeamStateIs(Parameter *pTeamParm, Parameter *pSta Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString stateName = pStateParm->getString(); + const AsciiString &stateName = pStateParm->getString(); if (theTeam) { return (theTeam->getState() == stateName); } @@ -628,7 +624,7 @@ Bool ScriptConditions::evaluateTeamStateIsNot(Parameter *pTeamParm, Parameter *p Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString stateName = pStateParm->getString(); + const AsciiString &stateName = pStateParm->getString(); if (theTeam) { return (!(theTeam->getState() == stateName)); } @@ -652,7 +648,6 @@ Bool ScriptConditions::evaluateTeamInsideAreaEntirely(Parameter *pTeamParm, Para Team *theTeam = TheScriptEngine->getTeamNamed( pTeamParm->getString() ); // The team is the team based on the name, and the calling team (if any) and the team that // is being considered for the condition. jba. :) - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (pTrig == nullptr) @@ -1333,7 +1328,7 @@ Bool ScriptConditions::evaluateNamedReachedWaypointsEnd(Parameter *pUnitParm, Pa if (!targetWay) return false; - AsciiString pathName = pWaypointPathParm->getString(); + const AsciiString &pathName = pWaypointPathParm->getString(); if (targetWay->getPathLabel1() == pathName) return true; if (targetWay->getPathLabel2() == pathName) return true; @@ -1352,7 +1347,7 @@ Bool ScriptConditions::evaluateTeamReachedWaypointsEnd(Parameter *pTeamParm, Par return false; } - AsciiString pathName = pWaypointPathParm->getString(); + const AsciiString &pathName = pWaypointPathParm->getString(); Bool anyAtEnd = false; Bool anyNotAtEnd = false; // Note - This returns true if any of the team completed the path. This is as the current @@ -2112,7 +2107,6 @@ Bool ScriptConditions::evaluateSkirmishValueInArea(Condition *pCondition, Parame return false; } - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (!pTrig) { @@ -2491,7 +2485,6 @@ Bool ScriptConditions::evaluateSkirmishNamedAreaExists(Parameter *, Parameter *p //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluateSkirmishPlayerHasUnitsInArea(Condition *pCondition, Parameter *pSkirmishPlayerParm, Parameter *pTriggerParm ) { - AsciiString triggerName = pTriggerParm->getString(); PolygonTrigger *pTrig = TheScriptEngine->getQualifiedTriggerAreaByName(pTriggerParm->getString()); if (pTrig == nullptr) return false; @@ -2683,7 +2676,7 @@ Bool ScriptConditions::evaluateSkirmishPlayerHasDiscoveredPlayer(Parameter *pSki //------------------------------------------------------------------------------------------------- Bool ScriptConditions::evaluateMusicHasCompleted(Parameter *pMusicParm, Parameter *pIntParm) { - AsciiString str = pMusicParm->getString(); + const AsciiString &str = pMusicParm->getString(); return TheAudio->hasMusicTrackCompleted(str, pIntParm->getInt()); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp index f01ba6428e9..f1f872fc9c1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp @@ -7362,7 +7362,7 @@ Bool ScriptEngine::isSpecialPowerTriggered( Int playerIndex, const AsciiString& for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == completedPower && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -7387,7 +7387,7 @@ Bool ScriptEngine::isSpecialPowerMidway( Int playerIndex, const AsciiString& com for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == completedPower && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -7412,7 +7412,7 @@ Bool ScriptEngine::isSpecialPowerComplete( Int playerIndex, const AsciiString& c for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == completedPower && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -7437,7 +7437,7 @@ Bool ScriptEngine::isUpgradeComplete( Int playerIndex, const AsciiString& upgrad for (ListAsciiStringObjectIDIt findIt = specialList->begin(); findIt != specialList->end(); ++findIt) { - AsciiStringObjectIDPair pair = *findIt; + const AsciiStringObjectIDPair &pair = *findIt; if (pair.first == upgrade && (sourceObj == INVALID_ID || sourceObj == pair.second)) { if (removeFromList) { @@ -7554,7 +7554,7 @@ void ScriptEngine::adjustToppleDirection( Object *object, Coord2D *direction) //------------------------------------------------------------------------------------------------- void ScriptEngine::adjustToppleDirection( Object *object, Coord3D *direction) { - AsciiString objName = object->getName(); + const AsciiString &objName = object->getName(); if (objName.isEmpty() || !direction) { return; } diff --git a/GeneralsMD/Code/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h b/GeneralsMD/Code/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h deleted file mode 100644 index 274a4843afc..00000000000 --- a/GeneralsMD/Code/GameEngineDevice/Include/VideoDevice/Bink/BinkVideoPlayer.h +++ /dev/null @@ -1,147 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -//---------------------------------------------------------------------------- -// -// Westwood Studios Pacific. -// -// Confidential Information -// Copyright (C) 2001 - All Rights Reserved -// -//---------------------------------------------------------------------------- -// -// Project: Generals -// -// File name: GameClient/VideoPlayer.h -// -// Created: 10/22/01 -// -//---------------------------------------------------------------------------- - -#pragma once - -#ifndef __VIDEODEVICE_BINKDEVICE_H_ -#define __VIDEODEVICE_BINKDEVICE_H_ - - -//---------------------------------------------------------------------------- -// Includes -//---------------------------------------------------------------------------- - -#include "GameClient/VideoPlayer.h" -#ifdef _WIN32 -#include "bink.h" -#else -typedef struct BINK *HBINK; -#endif - -//---------------------------------------------------------------------------- -// Forward References -//---------------------------------------------------------------------------- - -class BinkVideoPlayer; - -//---------------------------------------------------------------------------- -// Type Defines -//---------------------------------------------------------------------------- - -//=============================== -// BinkVideoStream -//=============================== - -class BinkVideoStream : public VideoStream -{ - friend class BinkVideoPlayer; - - protected: - - HBINK m_handle; ///< Bink streaming handle; - Char *m_memFile; ///< Pointer to memory resident file - - BinkVideoStream(); ///< only BinkVideoPlayer can create these - virtual ~BinkVideoStream(); - - public: - - virtual void update( void ); ///< Update bink stream - - virtual Bool isFrameReady( void ); ///< Is the frame ready to be displayed - virtual void frameDecompress( void ); ///< Render current frame in to buffer - virtual void frameRender( VideoBuffer *buffer ); ///< Render current frame in to buffer - virtual void frameNext( void ); ///< Advance to next frame - virtual Int frameIndex( void ); ///< Returns zero based index of current frame - virtual Int frameCount( void ); ///< Returns the total number of frames in the stream - virtual void frameGoto( Int index ); ///< Go to the spcified frame index - virtual Int height( void ); ///< Return the height of the video - virtual Int width( void ); ///< Return the width of the video - - -}; - -//=============================== -// BinkVideoPlayer -//=============================== -/** - * Bink video playback code. - */ -//=============================== - -class BinkVideoPlayer : public VideoPlayer -{ - - protected: - - VideoStreamInterface* createStream( HBINK handle ); - - public: - - // subsytem requirements - virtual void init( void ); ///< Initialize video playback code - virtual void reset( void ); ///< Reset video playback - virtual void update( void ); ///< Services all audio tasks. Should be called frequently - - virtual void deinit( void ); ///< Close down player - - - BinkVideoPlayer(); - ~BinkVideoPlayer(); - - // service - virtual void loseFocus( void ); ///< Should be called when application loses focus - virtual void regainFocus( void ); ///< Should be called when application regains focus - - virtual VideoStreamInterface* open( AsciiString movieTitle ); ///< Open video file for playback - virtual VideoStreamInterface* load( AsciiString movieTitle ); ///< Load video file in to memory for playback - - virtual void notifyVideoPlayerOfNewProvider( Bool nowHasValid ); - virtual void initializeBinkWithMiles( void ); -}; - - -//---------------------------------------------------------------------------- -// Inlining -//---------------------------------------------------------------------------- - - -#endif // __VIDEODEVICE_BINKDEVICE_H_ diff --git a/GeneralsMD/Code/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp b/GeneralsMD/Code/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp deleted file mode 100644 index dde27364500..00000000000 --- a/GeneralsMD/Code/GameEngineDevice/Source/VideoDevice/Bink/BinkVideoPlayer.cpp +++ /dev/null @@ -1,448 +0,0 @@ -/* -** Command & Conquer Generals Zero Hour(tm) -** Copyright 2025 Electronic Arts Inc. -** -** 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 3 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, see . -*/ - -//////////////////////////////////////////////////////////////////////////////// -// // -// (c) 2001-2003 Electronic Arts Inc. // -// // -//////////////////////////////////////////////////////////////////////////////// - -//---------------------------------------------------------------------------- -// -// Westwood Studios Pacific. -// -// Confidential Information -// Copyright (C) 2001 - All Rights Reserved -// -//---------------------------------------------------------------------------- -// -// Project: Generals -// -// Module: VideoDevice -// -// File name: BinkDevice.cpp -// -// Created: 10/22/01 TR -// -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- -// Includes -//---------------------------------------------------------------------------- - -#include "Lib/BaseType.h" -#include "VideoDevice/Bink/BinkVideoPlayer.h" -#include "Common/AudioAffect.h" -#include "Common/GameAudio.h" -#include "Common/GameMemory.h" -#include "Common/GlobalData.h" -#include "Common/Registry.h" - -//---------------------------------------------------------------------------- -// Externals -//---------------------------------------------------------------------------- - - - -//---------------------------------------------------------------------------- -// Defines -//---------------------------------------------------------------------------- -#define VIDEO_LANG_PATH_FORMAT "Data/%s/Movies/%s.%s" -#define VIDEO_PATH "Data\\Movies" -#define VIDEO_EXT "bik" - - - -//---------------------------------------------------------------------------- -// Private Types -//---------------------------------------------------------------------------- - - - -//---------------------------------------------------------------------------- -// Private Data -//---------------------------------------------------------------------------- - - - -//---------------------------------------------------------------------------- -// Public Data -//---------------------------------------------------------------------------- - - - -//---------------------------------------------------------------------------- -// Private Prototypes -//---------------------------------------------------------------------------- - - - -//---------------------------------------------------------------------------- -// Private Functions -//---------------------------------------------------------------------------- - - - -//---------------------------------------------------------------------------- -// Public Functions -//---------------------------------------------------------------------------- - - -//============================================================================ -// BinkVideoPlayer::BinkVideoPlayer -//============================================================================ - -BinkVideoPlayer::BinkVideoPlayer() -{ - -} - -//============================================================================ -// BinkVideoPlayer::~BinkVideoPlayer -//============================================================================ - -BinkVideoPlayer::~BinkVideoPlayer() -{ - deinit(); -} - -//============================================================================ -// BinkVideoPlayer::init -//============================================================================ - -void BinkVideoPlayer::init( void ) -{ - // Need to load the stuff from the ini file. - VideoPlayer::init(); - - initializeBinkWithMiles(); -} - -//============================================================================ -// BinkVideoPlayer::deinit -//============================================================================ - -void BinkVideoPlayer::deinit( void ) -{ - TheAudio->releaseHandleForBink(); - VideoPlayer::deinit(); -} - -//============================================================================ -// BinkVideoPlayer::reset -//============================================================================ - -void BinkVideoPlayer::reset( void ) -{ - VideoPlayer::reset(); -} - -//============================================================================ -// BinkVideoPlayer::update -//============================================================================ - -void BinkVideoPlayer::update( void ) -{ - VideoPlayer::update(); - -} - -//============================================================================ -// BinkVideoPlayer::loseFocus -//============================================================================ - -void BinkVideoPlayer::loseFocus( void ) -{ - VideoPlayer::loseFocus(); -} - -//============================================================================ -// BinkVideoPlayer::regainFocus -//============================================================================ - -void BinkVideoPlayer::regainFocus( void ) -{ - VideoPlayer::regainFocus(); -} - -//============================================================================ -// BinkVideoPlayer::createStream -//============================================================================ - -VideoStreamInterface* BinkVideoPlayer::createStream( HBINK handle ) -{ - - if ( handle == NULL ) - { - return NULL; - } - - BinkVideoStream *stream = NEW BinkVideoStream; - - if ( stream ) - { - - stream->m_handle = handle; - stream->m_next = m_firstStream; - stream->m_player = this; - m_firstStream = stream; - - // never let volume go to 0, as Bink will interpret that as "play at full volume". - Int mod = (Int) ((TheAudio->getVolume(AudioAffect_Speech) * 0.8f) * 100) + 1; - Int volume = (32768*mod)/100; - DEBUG_LOG(("BinkVideoPlayer::createStream() - About to set volume (%g -> %d -> %d\n", - TheAudio->getVolume(AudioAffect_Speech), mod, volume)); - BinkSetVolume( stream->m_handle,0, volume); - DEBUG_LOG(("BinkVideoPlayer::createStream() - set volume\n")); - } - - return stream; -} - -//============================================================================ -// BinkVideoPlayer::open -//============================================================================ - -VideoStreamInterface* BinkVideoPlayer::open( AsciiString movieTitle ) -{ - VideoStreamInterface* stream = NULL; - - const Video* pVideo = getVideo(movieTitle); - if (pVideo) { - DEBUG_LOG(("BinkVideoPlayer::createStream() - About to open bink file\n")); - - if (TheGlobalData->m_modDir.isNotEmpty()) - { - char filePath[ _MAX_PATH ]; - sprintf( filePath, "%s%s\\%s.%s", TheGlobalData->m_modDir.str(), VIDEO_PATH, pVideo->m_filename.str(), VIDEO_EXT ); - HBINK handle = BinkOpen(filePath , BINKPRELOADALL ); - DEBUG_ASSERTLOG(!handle, ("opened bink file %s\n", filePath)); - if (handle) - { - return createStream( handle ); - } - } - - char localizedFilePath[ _MAX_PATH ]; - sprintf( localizedFilePath, VIDEO_LANG_PATH_FORMAT, GetRegistryLanguage().str(), pVideo->m_filename.str(), VIDEO_EXT ); - HBINK handle = BinkOpen(localizedFilePath , BINKPRELOADALL ); - DEBUG_ASSERTLOG(!handle, ("opened localized bink file %s\n", localizedFilePath)); - if (!handle) - { - char filePath[ _MAX_PATH ]; - sprintf( filePath, "%s\\%s.%s", VIDEO_PATH, pVideo->m_filename.str(), VIDEO_EXT ); - handle = BinkOpen(filePath , BINKPRELOADALL ); - DEBUG_ASSERTLOG(!handle, ("opened bink file %s\n", localizedFilePath)); - } - - DEBUG_LOG(("BinkVideoPlayer::createStream() - About to create stream\n")); - stream = createStream( handle ); - } - - return stream; -} - -//============================================================================ -// BinkVideoPlayer::load -//============================================================================ - -VideoStreamInterface* BinkVideoPlayer::load( AsciiString movieTitle ) -{ - return open(movieTitle); // load() used to have the same body as open(), so I'm combining them. Munkee. -} - -//============================================================================ -//============================================================================ -void BinkVideoPlayer::notifyVideoPlayerOfNewProvider( Bool nowHasValid ) -{ - if (!nowHasValid) { - TheAudio->releaseHandleForBink(); - BinkSetSoundTrack(0, 0); - } else { - initializeBinkWithMiles(); - } -} - -//============================================================================ -//============================================================================ -void BinkVideoPlayer::initializeBinkWithMiles() -{ - Int retVal = 0; - void *driver = TheAudio->getHandleForBink(); - - if ( driver ) - { - retVal = BinkSoundUseDirectSound(driver); - } - if( !driver || retVal == 0) - { - BinkSetSoundTrack ( 0,0 ); - } -} - -//============================================================================ -// BinkVideoStream::BinkVideoStream -//============================================================================ - -BinkVideoStream::BinkVideoStream() -: m_handle(NULL) -{ - -} - -//============================================================================ -// BinkVideoStream::~BinkVideoStream -//============================================================================ - -BinkVideoStream::~BinkVideoStream() -{ - if ( m_handle != NULL ) - { - BinkClose( m_handle ); - m_handle = NULL; - } -} - -//============================================================================ -// BinkVideoStream::update -//============================================================================ - -void BinkVideoStream::update( void ) -{ - BinkWait( m_handle ); -} - -//============================================================================ -// BinkVideoStream::isFrameReady -//============================================================================ - -Bool BinkVideoStream::isFrameReady( void ) -{ - return !BinkWait( m_handle ); -} - -//============================================================================ -// BinkVideoStream::frameDecompress -//============================================================================ - -void BinkVideoStream::frameDecompress( void ) -{ - BinkDoFrame( m_handle ); -} - -//============================================================================ -// BinkVideoStream::frameRender -//============================================================================ - -void BinkVideoStream::frameRender( VideoBuffer *buffer ) -{ - if ( buffer ) - { - void *mem = buffer->lock(); - - u32 flags; - - switch ( buffer->format()) - { - case VideoBuffer::TYPE_X8R8G8B8: - flags = BINKSURFACE32; - break; - - case VideoBuffer::TYPE_R8G8B8: - flags = BINKSURFACE24; - break; - - case VideoBuffer::TYPE_R5G6B5: - flags = BINKSURFACE565; - break; - - case VideoBuffer::TYPE_X1R5G5B5: - flags = BINKSURFACE555; - break; - - default: - return; - } - - if ( mem != NULL ) - { - - BinkCopyToBuffer ( m_handle, mem, buffer->pitch(), buffer->height(), - buffer->xPos(), buffer->yPos(), flags ); - buffer->unlock(); - } - } - -} - -//============================================================================ -// BinkVideoStream::frameNext -//============================================================================ - -void BinkVideoStream::frameNext( void ) -{ - BinkNextFrame( m_handle ); -} - -//============================================================================ -// BinkVideoStream::frameIndex -//============================================================================ - -Int BinkVideoStream::frameIndex( void ) -{ - return m_handle->FrameNum - 1; -} - -//============================================================================ -// BinkVideoStream::totalFrames -//============================================================================ - -Int BinkVideoStream::frameCount( void ) -{ - return m_handle->Frames; -} - -//============================================================================ -// BinkVideoStream::frameGoto -//============================================================================ - -void BinkVideoStream::frameGoto( Int index ) -{ - BinkGoto(m_handle, index, NULL ); -} - -//============================================================================ -// VideoStream::height -//============================================================================ - -Int BinkVideoStream::height( void ) -{ - return m_handle->Height; -} - -//============================================================================ -// VideoStream::width -//============================================================================ - -Int BinkVideoStream::width( void ) -{ - return m_handle->Width; -} - - - diff --git a/GeneralsMD/Code/GameEngineDevice/Source/VideoDevice/BinkVideoPlayerStub.cpp b/GeneralsMD/Code/GameEngineDevice/Source/VideoDevice/BinkVideoPlayerStub.cpp index 394470fb657..7a758b7e298 100644 --- a/GeneralsMD/Code/GameEngineDevice/Source/VideoDevice/BinkVideoPlayerStub.cpp +++ b/GeneralsMD/Code/GameEngineDevice/Source/VideoDevice/BinkVideoPlayerStub.cpp @@ -93,4 +93,9 @@ void BinkVideoPlayer::initializeBinkWithMiles(void) fprintf(stderr, "DEBUG: BinkVideoPlayer::initializeBinkWithMiles() - Linux stub\n"); } +void BinkVideoPlayer::setVolume(Real volume) +{ + // Stub: video volume not supported on Linux stub +} + #endif // !_WIN32 diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp index a69b827206a..e5cc4f148ca 100644 --- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp +++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DBridgeBuffer.cpp @@ -255,7 +255,7 @@ Bool W3DBridge::load(BodyDamageType curDamageState) Int i; for (i=0; iGet_Num_Sub_Objects(); i++) { RenderObjClass *pSub = pObj->Get_Sub_Object(i); - Matrix3D mtx = pSub->Get_Transform(); + const Matrix3D& mtx = pSub->Get_Transform(); if (0==strnicmp(left, pSub->Get_Name(), strlen(left))) { m_leftMtx = mtx; strlcpy(left, pSub->Get_Name(), ARRAY_SIZE(left)); diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp index f41be9aa6bf..5842874f376 100644 --- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp +++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDebugIcons.cpp @@ -221,8 +221,7 @@ void W3DDebugIcons::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Texture(0, nullptr); DX8Wrapper::Apply_Render_State_Changes(); - Matrix3D tm(Transform); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); Int numRect = m_numDebugIcons; static Real offset = 30; diff --git a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp index d1fb63d2af4..cf193188048 100644 --- a/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp +++ b/GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DInGameUI.cpp @@ -246,7 +246,7 @@ void DebugHintObject::Render(RenderInfoClass & rinfo) DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0); DX8Wrapper::Set_Vertex_Buffer(m_vertexBufferTile); - Matrix3D tm(Transform); + Matrix3D tm = Transform; Vector3 vec(m_myLoc.x, m_myLoc.y, m_myLoc.z); tm.Set_Translation(vec); DX8Wrapper::Set_Transform(D3DTS_WORLD, tm); diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp index 90332efb9b4..9666f20940b 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/camera.cpp @@ -618,7 +618,7 @@ void CameraClass::Update_Frustum() const float znear,zfar; float znear_dist,zfar_dist; - Matrix3D cam_mat = Get_Transform(); + const Matrix3D& cam_mat = Get_Transform(); Get_View_Plane(vpmin, vpmax); // Normalized view plane at a depth of 1.0 Get_Clip_Planes(znear_dist, zfar_dist); diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp index b242e9be09b..cfe2e251433 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/dazzle.cpp @@ -948,7 +948,7 @@ void DazzleRenderObjClass::Render(RenderInfoClass & rinfo) DX8Wrapper::Get_Transform(D3DTS_PROJECTION,projection_transform); Vector3 camera_loc(rinfo.Camera.Get_Position()); Vector3 camera_dir(-view_transform[2][0],-view_transform[2][1],-view_transform[2][2]); -// Matrix3D cam(rinfo.Camera.Get_Transform()); +// const Matrix3D& cam = rinfo.Camera.Get_Transform(); // Vector3 camera_dir(-cam[2][0],-cam[2][1],-cam[2][2]); // camera_dir.Normalize(); @@ -1515,7 +1515,7 @@ void DazzlePersistFactoryClass::Save(ChunkSaveClass & csave,PersistClass * obj) DazzleRenderObjClass * robj = (DazzleRenderObjClass *)obj; unsigned int dazzle_type = robj->Get_Dazzle_Type(); const char * dazzle_type_name = DazzleRenderObjClass::Get_Type_Name(dazzle_type); - Matrix3D tm = robj->Get_Transform(); + const Matrix3D& tm = robj->Get_Transform(); csave.Begin_Chunk(DAZZLEFACTORY_CHUNKID_VARIABLES); WRITE_MICRO_CHUNK(csave,DAZZLEFACTORY_VARIABLE_OBJPOINTER,robj); diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h index 76721adebe0..93f8de36e52 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/decalmsh.h @@ -76,7 +76,7 @@ class DecalMeshClass : public RefCountClass public: DecalMeshClass(MeshClass * parent,DecalSystemClass * system); - virtual ~DecalMeshClass(); + virtual ~DecalMeshClass() override; // world_vertex_locs and world_vertex_norms are dynamically updated worldspace vertex data // which are used by some decal types which cannot use static object geometry (such as decals @@ -121,21 +121,21 @@ class RigidDecalMeshClass : public DecalMeshClass public: RigidDecalMeshClass(MeshClass * parent,DecalSystemClass * system); - virtual ~RigidDecalMeshClass(); + virtual ~RigidDecalMeshClass() override; // Rigid decal meshes have static geometry so they do not use world_vertex_locs/norms - virtual void Render(); + virtual void Render() override; virtual bool Create_Decal( DecalGeneratorClass * generator, const OBBoxClass & localbox, SimpleDynVecClass & apt, - const DynamicVectorClass * world_vertex_locs = 0); + const DynamicVectorClass * world_vertex_locs = 0) override; - virtual bool Delete_Decal(uint32 id); + virtual bool Delete_Decal(uint32 id) override; - int Decal_Count(); - uint32 Get_Decal_ID(int decal_index); + int Decal_Count() override; + uint32 Get_Decal_ID(int decal_index) override; protected: @@ -186,21 +186,21 @@ class SkinDecalMeshClass : public DecalMeshClass public: SkinDecalMeshClass(MeshClass * parent,DecalSystemClass * system); - virtual ~SkinDecalMeshClass(); + virtual ~SkinDecalMeshClass() override; // Skin decals use world_vertex_locs/norms since they cannot use static geometry - virtual void Render(); + virtual void Render() override; virtual bool Create_Decal( DecalGeneratorClass * generator, const OBBoxClass & localbox, SimpleDynVecClass & apt, - const DynamicVectorClass * world_vertex_locs); + const DynamicVectorClass * world_vertex_locs) override; - virtual bool Delete_Decal(uint32 id); + virtual bool Delete_Decal(uint32 id) override; - int Decal_Count(); - uint32 Get_Decal_ID(int decal_index); + int Decal_Count() override; + uint32 Get_Decal_ID(int decal_index) override; protected: diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp index 0db93d24ad5..19406f4453d 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/hlod.cpp @@ -2057,7 +2057,7 @@ bool HLodClass::Get_Proxy (int index, ProxyClass &proxy) const // Lookup the proxy's transform // HTree->Base_Update(Get_Transform()); - Matrix3D transform = HTree->Get_Transform((*ProxyArray)[index].Get_Bone_Index()); + const Matrix3D& transform = HTree->Get_Transform((*ProxyArray)[index].Get_Bone_Index()); Set_Hierarchy_Valid(false); // diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/light.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/light.cpp index b2c9e5793fa..f0fe0185f04 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/light.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/light.cpp @@ -525,7 +525,7 @@ bool LightClass::Save (ChunkSaveClass &csave) Save_W3D(csave); csave.End_Chunk(); - Matrix3D tm = Get_Transform(); + const Matrix3D& tm = Get_Transform(); csave.Begin_Chunk(LIGHT_CHUNK_VARIABLES); WRITE_MICRO_CHUNK(csave,LIGHT_VARIABLE_TRANSFORM,tm); csave.End_Chunk(); diff --git a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp index 2d9b057ccb2..3a7a9fdaffc 100644 --- a/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp +++ b/GeneralsMD/Code/Libraries/Source/WWVegas/WW3D2/part_buf.cpp @@ -1285,7 +1285,7 @@ void ParticleBufferClass::Prepare_LOD(CameraClass &camera) // treat them as all being the maximum size and being in the center of the bounding sphere). Vector3 cam = camera.Get_Position(); - ViewportClass viewport = camera.Get_Viewport(); + const ViewportClass &viewport = camera.Get_Viewport(); Vector2 vpr_min, vpr_max; camera.Get_View_Plane(vpr_min, vpr_max); float width_factor = viewport.Width() / (vpr_max.X - vpr_min.X); diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/DrawObject.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/DrawObject.cpp index 86ee3342469..f2fe2bc5621 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/DrawObject.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/DrawObject.cpp @@ -2205,12 +2205,9 @@ if (pMapObj->isSelected()) { Bool isTree = false; Vector3 vec(loc.x, loc.y, loc.z); - Matrix3D tm(Transform); Matrix3x3 rot(true); rot.Rotate_Z(pMapObj->getAngle()); - - tm.Set_Translation(vec); - tm.Set_Rotation(rot); + Matrix3D tm(rot, vec); int polyCount = NUM_TRI; if (!pMapObj->isSelected()) { polyCount -= NUM_ARROW_TRI+NUM_SELECT_TRI; @@ -2265,7 +2262,7 @@ if (pMapObj->isSelected()) { count++; Vector3 vec(loc.x, loc.y, loc.z); - Matrix3D tm(Transform); + Matrix3D tm = Transform; tm.Set_Translation(vec); int polyCount = NUM_TRI; @@ -2277,8 +2274,7 @@ if (pMapObj->isSelected()) { DX8Wrapper::Set_Transform(D3DTS_WORLD,tm); DX8Wrapper::Draw_Triangles( 0,polyCount, 0, (m_numTriangles*3)); } - Matrix3D tmReset(Transform); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tmReset); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); DX8Wrapper::Set_Vertex_Buffer(m_vertexBufferTile1); updatePolygonVB(pTrig, polySelected, polySelected && PolygonTool::isSelectedOpen()); DX8Wrapper::Set_Vertex_Buffer(m_vertexFeedback); @@ -2318,12 +2314,9 @@ if (pMapObj->isSelected()) { count++; // ok to here. Vector3 vec(loc.x, loc.y, loc.z); - Matrix3D tmXX(Transform); Matrix3x3 rot(true); rot.Rotate_Z(pBuild->getAngle()); - - tmXX.Set_Translation(vec); - tmXX.Set_Rotation(rot); + Matrix3D tmXX(rot, vec); int polyCountA = NUM_TRI; if (!pBuild->isSelected()) { polyCountA -= NUM_ARROW_TRI+NUM_SELECT_TRI; @@ -2339,8 +2332,7 @@ if (pMapObj->isSelected()) { DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0); DX8Wrapper::Set_Vertex_Buffer(m_vertexBufferWater); - Matrix3D tmReset(Transform); - DX8Wrapper::Set_Transform(D3DTS_WORLD,tmReset); + DX8Wrapper::Set_Transform(D3DTS_WORLD,Transform); if (m_drawWaypoints) { updateWaypointVB(); diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp index 4d319482548..a976d629526 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/EditObjectParameter.cpp @@ -118,7 +118,7 @@ void EditObjectParameter::addObject( const ThingTemplate *thingTemplate ) parent = findOrAdd( parent, "TEST" ); // first sort by Side, either create or find the tree item with matching side name - AsciiString side = thingTemplate->getDefaultOwningSide(); + const AsciiString &side = thingTemplate->getDefaultOwningSide(); DEBUG_ASSERTCRASH(!side.isEmpty(), ("null default side in template") ); parent = findOrAdd( parent, side.str()); diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp index d9189705eae..5b16a2602ac 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/EditParameter.cpp @@ -819,7 +819,7 @@ Bool EditParameter::loadUpgrades(CComboBox *pCombo, AsciiString match) for (int i = 0; i < numUpgrades; ++i) { - AsciiString upgradeName = upgradeNames[i]; + const AsciiString &upgradeName = upgradeNames[i]; if (pCombo) { pCombo->AddString(upgradeName.str()); } diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp index 27af92ec44a..c578e5be9ba 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/ScriptDialog.cpp @@ -1156,7 +1156,7 @@ void ScriptDialog::markWaypoint(MapObject *pObj) void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, Bool doWaypoints, Bool doTriggers) { if (pParm->getParameterType() == Parameter::WAYPOINT && doWaypoints) { - AsciiString waypointName = pParm->getString(); + const AsciiString &waypointName = pParm->getString(); MapObject *pObj; for (pObj = MapObject::getFirstMapObject(); pObj; pObj = pObj->getNext()) { if (pObj->isWaypoint() && pObj->getWaypointName()==waypointName) { @@ -1165,7 +1165,7 @@ void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, } } if (pParm->getParameterType() == Parameter::WAYPOINT_PATH && doWaypoints) { - AsciiString waypointPathLabel = pParm->getString(); + const AsciiString &waypointPathLabel = pParm->getString(); MapObject *pObj; for (pObj = MapObject::getFirstMapObject(); pObj; pObj = pObj->getNext()) { if (pObj->isWaypoint() ) { @@ -1183,7 +1183,7 @@ void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, } } if (pParm->getParameterType() == Parameter::TEAM) { - AsciiString teamName = pParm->getString(); + const AsciiString &teamName = pParm->getString(); TeamsInfo * pInfo = m_sides.findTeamInfo(teamName); if (pInfo) { pInfo->getDict()->setBool(TheKey_exportWithScript, true); @@ -1200,7 +1200,7 @@ void ScriptDialog::scanParmForWaypointsAndTeams(Parameter *pParm, Bool doUnits, } } if (pParm->getParameterType() == Parameter::UNIT) { - AsciiString unitName = pParm->getString(); + const AsciiString &unitName = pParm->getString(); if (doUnits) { MapObject *pObj; for (pObj = MapObject::getFirstMapObject(); pObj; pObj = pObj->getNext()) { diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp index 3aeba787257..66378705e70 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/WHeightMapEdit.cpp @@ -324,7 +324,7 @@ WorldHeightMapEdit::WorldHeightMapEdit(ChunkInputStream *pStrm): Bool WorldHeightMapEdit::remapTextures() { Int i; - Bool anyChanges; + Bool anyChanges = false; for (i=0; iisMusicAlreadyLoaded()) return FALSE; - initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new VideoPlayer())); + initSubsystem(TheVideoPlayer, (VideoPlayerInterface*)(new NullVideoPlayer())); initSubsystem(TheModuleFactory, (ModuleFactory*)(new W3DModuleFactory())); initSubsystem(TheSidesList, new SidesList()); initSubsystem(TheCaveSystem, new CaveSystem()); diff --git a/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp b/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp index a1f39f2fb3f..7d2be013f6c 100644 --- a/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp +++ b/GeneralsMD/Code/Tools/WorldBuilder/src/wbview3d.cpp @@ -1714,7 +1714,7 @@ Bool WbView3d::viewToDocCoords(CPoint curPt, Coord3D *newPt, Bool constrain) float logY = (Real)curPt.y / (Real)client.Height(); Vector3 intersection(0,0,0); // determine the ray corresponding to the camera and distance to projection plane - Matrix3D camera_matrix = m_camera->Get_Transform(); + const Matrix3D& camera_matrix = m_camera->Get_Transform(); Vector3 camera_location = m_camera->Get_Position(); @@ -1842,7 +1842,7 @@ Bool WbView3d::viewToDocCoordZ(CPoint curPt, Coord3D *newPt, Real theZ) float logY = (Real)curPt.y / (Real)client.Height(); Vector3 intersection(0,0,0); // determine the ray corresponding to the camera and distance to projection plane - Matrix3D camera_matrix = m_camera->Get_Transform(); + const Matrix3D& camera_matrix = m_camera->Get_Transform(); Vector3 camera_location = m_camera->Get_Position(); @@ -1897,7 +1897,7 @@ void WbView3d::updateHysteresis() float logY = (Real)curPt.y / (Real)client.Height(); Vector3 intersection(0,0,0); // determine the ray corresponding to the camera and distance to projection plane - Matrix3D camera_matrix = m_camera->Get_Transform(); + const Matrix3D& camera_matrix = m_camera->Get_Transform(); Vector3 camera_location = m_camera->Get_Position(); diff --git a/GeneralsMD/Code/Tools/wdump/mainfrm.h b/GeneralsMD/Code/Tools/wdump/mainfrm.h index e3130518162..bc73b93bc2b 100644 --- a/GeneralsMD/Code/Tools/wdump/mainfrm.h +++ b/GeneralsMD/Code/Tools/wdump/mainfrm.h @@ -46,7 +46,7 @@ class CMainFrame : public CFrameWnd // Implementation public: - virtual ~CMainFrame(); + virtual ~CMainFrame() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/GeneralsMD/Code/Tools/wdump/rawfilem.h b/GeneralsMD/Code/Tools/wdump/rawfilem.h index 540a091f1ca..44ad98dc63f 100644 --- a/GeneralsMD/Code/Tools/wdump/rawfilem.h +++ b/GeneralsMD/Code/Tools/wdump/rawfilem.h @@ -143,28 +143,28 @@ class RawFileMClass : public FileClass RawFileMClass(); RawFileMClass (RawFileMClass const & f); RawFileMClass & operator = (RawFileMClass const & f); - virtual ~RawFileMClass(); - - virtual char const * File_Name() const; - virtual char const * Set_Name(char const *filename); - virtual int Create(); - virtual int Delete(); - virtual bool Is_Available(int forced=false); - virtual bool Is_Open() const; - virtual int Open(char const *filename, int rights=READ); - virtual int Open(int rights=READ); - virtual int Read(void *buffer, int size); - virtual int Seek(int pos, int dir=SEEK_CUR); - virtual int Size(); - virtual int Write(void const *buffer, int size); - virtual void Close(); - virtual unsigned long Get_Date_Time(); - virtual bool Set_Date_Time(unsigned long datetime); + virtual ~RawFileMClass() override; + + virtual char const * File_Name() const override; + virtual char const * Set_Name(char const *filename) override; + virtual int Create() override; + virtual int Delete() override; + virtual bool Is_Available(int forced=false) override; + virtual bool Is_Open() const override; + virtual int Open(char const *filename, int rights=READ) override; + virtual int Open(int rights=READ) override; + virtual int Read(void *buffer, int size) override; + virtual int Seek(int pos, int dir=SEEK_CUR) override; + virtual int Size() override; + virtual int Write(void const *buffer, int size) override; + virtual void Close() override; + virtual unsigned long Get_Date_Time() override; + virtual bool Set_Date_Time(unsigned long datetime) override; virtual void Error(int error, int canretry = false, char const * filename=nullptr); void Bias(int start, int length=-1); - HANDLE_TYPE Get_File_Handle() { return (Handle); }; + HANDLE_TYPE Get_File_Handle() override { return (Handle); }; /* ** These bias values enable a sub-portion of a file to appear as if it diff --git a/GeneralsMD/Code/Tools/wdump/wdeview.h b/GeneralsMD/Code/Tools/wdump/wdeview.h index c1f70adc3f9..79b0a9fd6a5 100644 --- a/GeneralsMD/Code/Tools/wdump/wdeview.h +++ b/GeneralsMD/Code/Tools/wdump/wdeview.h @@ -46,7 +46,7 @@ class CWDumpEditView : public CEditView // Implementation protected: - virtual ~CWDumpEditView(); + virtual ~CWDumpEditView() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/GeneralsMD/Code/Tools/wdump/wdlview.h b/GeneralsMD/Code/Tools/wdump/wdlview.h index e03fd17c1d6..cb89d0a5162 100644 --- a/GeneralsMD/Code/Tools/wdump/wdlview.h +++ b/GeneralsMD/Code/Tools/wdump/wdlview.h @@ -48,7 +48,7 @@ class CWDumpListView : public CListView // Implementation protected: - virtual ~CWDumpListView(); + virtual ~CWDumpListView() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/GeneralsMD/Code/Tools/wdump/wdtview.h b/GeneralsMD/Code/Tools/wdump/wdtview.h index 86631662926..198992bc420 100644 --- a/GeneralsMD/Code/Tools/wdump/wdtview.h +++ b/GeneralsMD/Code/Tools/wdump/wdtview.h @@ -46,7 +46,7 @@ class CWDumpTreeView : public CTreeView // Implementation protected: - virtual ~CWDumpTreeView(); + virtual ~CWDumpTreeView() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/GeneralsMD/Code/Tools/wdump/wdumpdoc.h b/GeneralsMD/Code/Tools/wdump/wdumpdoc.h index 6aef0d8ae06..544a3ca2388 100644 --- a/GeneralsMD/Code/Tools/wdump/wdumpdoc.h +++ b/GeneralsMD/Code/Tools/wdump/wdumpdoc.h @@ -54,7 +54,7 @@ class CWdumpDoc : public CDocument // Implementation public: - virtual ~CWdumpDoc(); + virtual ~CWdumpDoc() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/GeneralsMD/Code/Tools/wdump/wdview.h b/GeneralsMD/Code/Tools/wdump/wdview.h index fc764b4c4dc..1b8ceb6afbb 100644 --- a/GeneralsMD/Code/Tools/wdump/wdview.h +++ b/GeneralsMD/Code/Tools/wdump/wdview.h @@ -46,7 +46,7 @@ class CWdumpView : public CView // Implementation public: - virtual ~CWdumpView(); + virtual ~CWdumpView() override; #ifdef RTS_DEBUG virtual void AssertValid() const override; virtual void Dump(CDumpContext& dc) const override; diff --git a/cmake/config-vcpkg.cmake b/cmake/config-vcpkg.cmake new file mode 100644 index 00000000000..81fa8f0b4ce --- /dev/null +++ b/cmake/config-vcpkg.cmake @@ -0,0 +1,6 @@ +# Contains options for VCPKG features + +option(RTS_BUILD_OPTION_FFMPEG "Enable FFmpeg support" OFF) +if(RTS_BUILD_OPTION_FFMPEG) + list(APPEND VCPKG_MANIFEST_FEATURES "ffmpeg") +endif() diff --git a/docs/WORKDIR/planning/2026-09-08-thesuperhackers-sync-plan.md b/docs/WORKDIR/planning/2026-09-08-thesuperhackers-sync-plan.md new file mode 100644 index 00000000000..5cd3e187973 --- /dev/null +++ b/docs/WORKDIR/planning/2026-09-08-thesuperhackers-sync-plan.md @@ -0,0 +1,147 @@ +# Upstream Sync Plan: TheSuperHackers (2026-09-08) + +## 1. Overview and Objectives +This document establishes the conflict resolution plan for merging `thesuperhackers/main` into `thesuperhackers-sync-09-08-2026`. +The upstream baseline contains commits up to `689a09ac4`, featuring: +- GUI centralization to `Core/GameEngine/` (moving `GameWindowManager`, `GameWindowTransitionsStyles`, `AnimateWindowManager`). +- WW3D2 `IRenderBackend` interface introduction. +- Particle system batching optimizations and lifetime bug fixes. +- Scorch buffer limit extensions and safety checks. +- AI update fixes (contact weapons not blocked by obstacles, assisted targeting initial frame). +- Production cancel/refund bug fixes. +- Audio volume improvements and removal of legacy `has3DSensitiveStreamsPlaying` hack. +- Bink volume calculation improvements and tool stubbing (`NullVideoPlayer`). +- Save game absolute path support and loading failure dialogs. + +The goal is to incorporate these enhancements while preserving GeneralsX's cross-platform architecture (SDL3, DXVK, MiniAudio, OpenAL, FFmpeg), determinism requirements, and CI/CD infrastructure. + +--- + +## 2. Conflicts and Resolution Strategies + +### 2.1 CI/CD Infrastructure +**Files:** +- `.github/workflows/build-toolchain.yml` (deleted in HEAD, modified upstream) +- `.github/workflows/weekly-release.yml` (deleted in HEAD, modified upstream) +- `.github/workflows/ci.yml` (content conflict) + +**Resolution:** +- Per prompt instructions: **Never replace CI/CD infrastructure with upstream versions.** +- Remove `.github/workflows/build-toolchain.yml` and `.github/workflows/weekly-release.yml` (`git rm`). +- Restore `.github/workflows/ci.yml` from HEAD (`git checkout --ours .github/workflows/ci.yml`). + +--- + +### 2.2 Graphics Backend (`Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp`) +**Conflict:** +- In `WW3D::End_Render(bool flip_frame)`: + - HEAD: calls `DX8Wrapper::Set_Transform_Dirty()` to avoid expensive per-frame cache invalidation (~33KB memset + texture unbinds). + - Upstream: calls `Get_Render_Backend()->Invalidate_Cached_Render_States()`. + +**Analysis:** +- Upstream introduced `IRenderBackend` which abstracts backend calls. In the upstream PR, they systematically changed `DX8Wrapper::X` to `Get_Render_Backend()->X`. +- Reverting to `Invalidate_Cached_Render_States()` re-introduces the performance regression that GeneralsX explicitly optimized in commit `801a61035`. +- `ww3d.cpp` still includes `dx8wrapper.h`. +- Resolving with `DX8Wrapper::Set_Transform_Dirty()` preserves GeneralsX's frame performance optimization while remaining fully compatible with the DX8 backend. + +--- + +### 2.3 Windows Library CMake (`Core/Libraries/Source/WWVegas/WWLib/CMakeLists.txt`) +**Conflict:** +- Upstream added `registry.cpp/.h` and `Usp10Loader.cpp/.h` under `if(WIN32)`. + +**Analysis:** +- These files are scoped strictly to `if(WIN32)` and provide necessary support for upstream Windows/VC6 builds without affecting Linux or macOS. +- Accept upstream changes inside `if(WIN32)`. + +--- + +### 2.4 Save Game Diagnostics (`Generals` & `GeneralsMD`: `GameState.cpp`) +**Files:** +- `Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp` +- `GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp` + +**Conflict:** +- HEAD outputs error diagnostics to `stderr` with `fprintf(stderr, ...)` and called `TheGameEngine->setQuitting(TRUE)`. +- Upstream replaced sudden exit with a user-facing dialog `showQueuedSaveGameLoadFailure()` and `DEBUG_LOG`. + +**Analysis:** +- In release builds, `DEBUG_LOG` is compiled out, but console diagnostics are vital for CLI/testing runs as per `AGENTS.md`. +- Showing `showQueuedSaveGameLoadFailure()` is a better UX than terminating the engine abruptly. +- Reconcile both: output `std::fprintf(stderr, ...)` and call `showQueuedSaveGameLoadFailure()`. + +--- + +### 2.5 Unified GUI (`Generals/Code/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp`) +**Conflict:** +- Deleted upstream, modified in HEAD. + +**Analysis:** +- Upstream unified `GameWindowTransitionsStyles.cpp` into `Core/GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp`. +- The unified version in `Core` already received all changes and was auto-merged. +- Delete the redundant file in `Generals/` via `git rm`. + +--- + +### 2.6 WorldBuilder Tool Video Player (`Generals` & `GeneralsMD`: `WorldBuilder.cpp`) +**Files:** +- `Generals/Code/Tools/WorldBuilder/src/WorldBuilder.cpp` +- `GeneralsMD/Code/Tools/WorldBuilder/src/WorldBuilder.cpp` + +**Conflict:** +- HEAD had `if (!TheAudio->isMusicAlreadyLoaded()) return FALSE;` and `VideoPlayer()`. +- Upstream replaced `VideoPlayer()` with `NullVideoPlayer()` since WorldBuilder does not require full video playback engines (preventing unnecessary Bink/FFmpeg dependencies). + +**Analysis:** +- Combine both: keep the music check from HEAD, and use `NullVideoPlayer()` as introduced by upstream. + +--- + +### 2.7 Documentation (`README.md`) +**Conflict:** +- Upstream inserted vcpkg CI caching documentation in place of GeneralsX project description and links. + +**Analysis:** +- Keep GeneralsX documentation (HEAD). + +--- + +### 2.8 CMake Build Configuration (`cmake/config-build.cmake`) +**Conflict:** +- Upstream removed or lacked GeneralsX options (`RTS_BUILD_OPTION_FFMPEG`, `RTS_BUILD_OPTION_DEEP_CRC`, `SAGE_USE_SDL3`, `SAGE_USE_OPENAL`, `SAGE_USE_MINIAUDIO`, `SAGE_UPDATE_CHECK`, `SAGE_USE_MOLTENVK`, `RTS_BUILD_OPTION_SAGE_PATCH`). + +**Analysis:** +- Keep GeneralsX options from HEAD, which are critical for Linux and macOS builds. + +--- + +### 2.9 Package Manifests (`vcpkg.json` and `vcpkg-lock.json`) +**Conflict:** +- Upstream added feature `"ffmpeg"` and updated baseline in `vcpkg.json`; deleted `vcpkg-lock.json`. + +**Analysis:** +- In `vcpkg.json`, keep GeneralsX dependency declarations (`freetype`, `fontconfig`, `openal-soft`, `curl`, `stb`, `glm`, `gli`) and incorporate upstream's `"features": { "ffmpeg": ... }`. +- Retain `vcpkg-lock.json` from HEAD to preserve reproducible dependency versions for macOS ARM64 builds. + +--- + +### 2.10 Audio Parity (Post-Merge Audit) +**Subsystems:** +- `MiniAudioManager` and `OpenALAudioManager`. + +**Action Items:** +- Upstream eliminated `has3DSensitiveStreamsPlaying()` from `AudioManager` and `MilesAudioManager`. +- Remove `has3DSensitiveStreamsPlaying()` from `MiniAudioManager` and `OpenALAudioManager` to maintain strict parity. +- Add `TheVideoPlayer->setVolume(getVolume(AudioAffect_Speech));` inside volume change handlers in `MiniAudioManager` and `OpenALAudioManager` to replicate the Bink/video speech volume dispatch added to `MilesAudioManager`. + +--- + +## 3. Verification & Execution Steps +1. Execute conflict resolutions across the 14 unmerged files. +2. Apply Audio Parity adjustments to MiniAudio and OpenAL devices. +3. Check working tree for any residual conflict markers (`rg "<<<<<<"`). +4. Run CMake configure on `macos-vulkan`: `cmake --preset macos-vulkan`. +5. Build target `z_generals` (or run `./scripts/build/macos/build-macos-zh.sh`). +6. Run smoke validation if feasible. +7. Record worklog entry in `docs/WORKLOG/2026-09-DIARY.md`. +8. Commit the merge and push branch `thesuperhackers-sync-09-08-2026` to origin. diff --git a/docs/WORKLOG/2026-09-DIARY.md b/docs/WORKLOG/2026-09-DIARY.md new file mode 100644 index 00000000000..7634ad32ded --- /dev/null +++ b/docs/WORKLOG/2026-09-DIARY.md @@ -0,0 +1,17 @@ +# September 2026 + +> [!NOTE] +> **AI-Generated Content Disclosure**: This worklog is automatically generated and maintained by AI coding agents to document daily progress, debugging sessions, and technical decisions. + +## 08/09/2026 +### Synchronize TheSuperHackers Upstream +- Merged upstream commits up to `689a09ac4` from `thesuperhackers/main` into sync branch `thesuperhackers-sync-09-08-2026`. +- Resolved 14 conflicted files across build system, rendering, game engine, tools, and documentation. +- Adopted upstream GUI centralization into `Core/GameEngine/` (`GameWindowManager`, `GameWindowTransitionsStyles`, `AnimateWindowManager`) and cleaned up redundant files in `Generals/`. +- Preserved GeneralsX frame performance optimization in `Core/Libraries/Source/WWVegas/WW3D2/ww3d.cpp` (`DX8Wrapper::Set_Transform_Dirty()`) to prevent per-frame render state invalidation overhead (~33KB memset + texture unbinds). +- Reconciled save game loading diagnostics in `GameState.cpp` (both Generals and Zero Hour) combining `std::fprintf(stderr, ...)` release console logging with upstream's `showQueuedSaveGameLoadFailure()` user dialog. +- Maintained strict audio parity across MiniAudio, OpenAL, and Miles by removing deprecated `has3DSensitiveStreamsPlaying()` and dispatching speech volume adjustments to `TheVideoPlayer`. +- Preserved all cross-platform build options in `cmake/config-build.cmake`, pinned dependency versions in `vcpkg-lock.json`, and incorporated upstream's `ffmpeg` manifest feature in `vcpkg.json`. +- Rejected upstream changes to `.github/workflows/` preserving GeneralsX multi-platform CI and replay validation pipelines. +- Successfully configured `macos-vulkan` and built both `z_generals` (Zero Hour) and `g_generals` (Generals) binaries; validated clean startup and subsystem initialization for both games. +- Removed obsolete duplicate `BinkVideoPlayer.h` and `BinkVideoPlayer.cpp` in `GeneralsMD/Code/GameEngineDevice/` that shadowed the canonical `Core` header and caused Windows MSVC builds to fail on abstract `setVolume` instantiation. diff --git a/scripts/cpp/unify_move_files.py b/scripts/cpp/unify_move_files.py index 567a2465030..a242d9bfda7 100644 --- a/scripts/cpp/unify_move_files.py +++ b/scripts/cpp/unify_move_files.py @@ -696,6 +696,14 @@ def main(): #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/ShellMenuScheme.h", Game.CORE, "GameEngine/Include/GameClient/ShellMenuScheme.h") #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/Shell/ShellMenuScheme.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/Shell/ShellMenuScheme.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/AnimateWindowManager.h", Game.CORE, "GameEngine/Include/GameClient/AnimateWindowManager.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GameWindowID.h", Game.CORE, "GameEngine/Include/GameClient/GameWindowID.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Include/GameClient/GameWindowManager.h", Game.CORE, "GameEngine/Include/GameClient/GameWindowManager.h") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GameWindowManager.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GameWindowManager.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GameWindowManagerScript.cpp") + #unify_file(Game.ZEROHOUR, "GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp", Game.CORE, "GameEngine/Source/GameClient/GUI/GameWindowTransitionsStyles.cpp") + return diff --git a/triplets/x86-windows.cmake b/triplets/x86-windows.cmake deleted file mode 100644 index 106900a72d7..00000000000 --- a/triplets/x86-windows.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Include the default x86-windows triplet -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE dynamic) - -# Exclude compiler version from ABI hash so that weekly GitHub runner image -# updates don't invalidate the binary cache. Minor MSVC version bumps do not -# cause ABI incompatibilities for this project. -set(VCPKG_DISABLE_COMPILER_TRACKING ON) diff --git a/vcpkg.json b/vcpkg.json index aba1bd15b32..7273c672890 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,28 +1,34 @@ { - "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", - "builtin-baseline": "533a5fda5c0646d1771345fb572e759283444d5f", - "dependencies": [ - "zlib", - "glm", - "gli", - { - "name": "freetype", - "platform": "!windows" - }, - { - "name": "fontconfig", - "platform": "!windows" - }, - { - "name": "openal-soft", - "platform": "!windows", - "features": [] - }, - { - "name": "curl", - "platform": "!windows", - "features": ["ssl"] - }, - "stb" - ] - } \ No newline at end of file + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", + "builtin-baseline": "533a5fda5c0646d1771345fb572e759283444d5f", + "dependencies": [ + "zlib", + "glm", + "gli", + { + "name": "freetype", + "platform": "!windows" + }, + { + "name": "fontconfig", + "platform": "!windows" + }, + { + "name": "openal-soft", + "platform": "!windows", + "features": [] + }, + { + "name": "curl", + "platform": "!windows", + "features": ["ssl"] + }, + "stb" + ], + "features": { + "ffmpeg": { + "description": "Use FFmpeg instead of Bink for video rendering", + "dependencies": [ "ffmpeg" ] + } + } +}