Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6ad65bb
Fix GZH profile location
MahBoiDeveloper Jun 10, 2026
65017ff
Initial profile implementation
MahBoiDeveloper Jun 10, 2026
78023e7
Rearanging files and create temporary generals profile
MahBoiDeveloper Jun 11, 2026
de1ddec
Patch editor be able load main styles sheet file
MahBoiDeveloper Jun 11, 2026
8671a74
Testing new window rendering
MahBoiDeveloper Jun 12, 2026
dc28f92
Make `Resources` directories synchronized
MahBoiDeveloper Jun 12, 2026
e56c8fe
Refactoring `SelectProfileWindow` and `SetUpWindowsWrapper`
MahBoiDeveloper Jun 12, 2026
cb57c72
Linking buttons and actions
MahBoiDeveloper Jun 13, 2026
b17d7ad
Make editor load global and default styles
MahBoiDeveloper Jun 13, 2026
a586ec9
Add temporary profiles
MahBoiDeveloper Jun 13, 2026
4ae8fed
Fix editor be able reapply style on every profile deselection/selection
MahBoiDeveloper Jun 13, 2026
3450a81
Update test styles
MahBoiDeveloper Jun 13, 2026
5532ca3
Experimenting with styles
MahBoiDeveloper Jun 13, 2026
b74085f
Make editor search icons in specific profile folder
MahBoiDeveloper Jun 14, 2026
2e2bac8
Adjust ZH style
MahBoiDeveloper Jun 14, 2026
8ef6069
Bump minimal version due to new synchronization target cmake features
MahBoiDeveloper Jun 14, 2026
e31db3e
Add new backgrounds for Generals profile
MahBoiDeveloper Jul 17, 2026
191033d
Patch vanilla theme to change USA colors
MahBoiDeveloper Jul 17, 2026
ccfe59b
Adjust styles
MahBoiDeveloper Jul 17, 2026
3ae5ada
Fix Generals tech tree
MahBoiDeveloper Jul 17, 2026
dc45ca7
Rework faction button layouting
MahBoiDeveloper Jul 18, 2026
919f636
Adjust conditions and text
MahBoiDeveloper Jul 18, 2026
b0b0efd
Add boss generals
MahBoiDeveloper Jul 18, 2026
13e01ce
Shorting code by using defines
MahBoiDeveloper Jul 18, 2026
2a7fe19
Remove extra \n
MahBoiDeveloper Jul 18, 2026
d285208
Add missing icon
MahBoiDeveloper Jul 18, 2026
0b18628
Patch loading from the game
MahBoiDeveloper Jul 18, 2026
dc79ab0
Fix naming
MahBoiDeveloper Jul 18, 2026
5125688
Rename files
MahBoiDeveloper Jul 18, 2026
a226489
Replace names in files
MahBoiDeveloper Jul 18, 2026
211c0af
Fix styles and add settings button
MahBoiDeveloper Jul 18, 2026
1056300
Remove test custom profiles
MahBoiDeveloper Jul 18, 2026
eee5f3a
Adjustments
MahBoiDeveloper Jul 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
cmake_minimum_required(VERSION 3.26 FATAL_ERROR)

if (NOT WIN32)
message(FATAL_ERROR "This program has been specified to compile on Microsoft Windows OS only.")
Expand Down
26 changes: 7 additions & 19 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -147,27 +147,15 @@
)

# Copying Resource folder with subfolders, configs and files
file(
COPY "${PROJECT_RESOURCE_FOLDER}"
DESTINATION ${PROJECT_DESTINATION_RESOURCES_FOLDER}/..
)

# Managing additional source files
# Declare json files
set(
ADDITIONAL_RESOURCES
"${PROJECT_RESOURCE_FOLDER}/TechTree.json"
"${PROJECT_RESOURCE_FOLDER}/Settings.json"
# https://discourse.cmake.org/t/copying-files-with-destination-folder-depending-on-build-config/10686
add_custom_target(SyncResourceDir
COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different
"${PROJECT_RESOURCE_FOLDER}"
"${PROJECT_DESTINATION_RESOURCES_FOLDER}"
COMMENT "Synchronize resources directories"
)

# Copy json files if file updates
foreach(CURRENT_FILE ${ADDITIONAL_RESOURCES})
configure_file(
${CURRENT_FILE}
${PROJECT_DESTINATION_RESOURCES_FOLDER}
COPYONLY
)
endforeach()
add_dependencies(${MAIN_TARGET_NAME} SyncResourceDir)

# Qt libs linking aka copying dependecies to the standalone release version of the project
# Find the qt libs deploy program
Expand Down
3 changes: 2 additions & 1 deletion src/Core/Faction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ class Faction
QString displayNameDescription;
QMap<GameObject, GameObjectTypes> techTree;
public:
inline static const int BASIC_FACTION_COUNT = 12;
inline static constexpr int MINIMAL_FACTION_COUNT = 3; // 3 factions are a bare minimum set upped by vanilla
inline static constexpr int MAXIMUM_FACTION_COUNT = 15; // 15 factions are a known game maximum set upped by ZH

private: // Methods
QMap<GameObject, GameObjectTypes> ParseJsonObject(const QJsonObject& obj);
Expand Down
5 changes: 5 additions & 0 deletions src/Core/ProgramConstants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@ void ProgramConstants::InitializeTranslations()
Languages.insert(i, {file.completeBaseName().toLower(), Windows::Locale::LanguageName(file.completeBaseName().toLower())});
}
}

void ProgramConstants::InitializeProfiles()
{

}
36 changes: 24 additions & 12 deletions src/Core/ProgramConstants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,28 @@ class ProgramConstants
// Colors
const QString LINK_COLOR = "#baff0c";

// Folders
// General strings
const QString STYLES_FILENAME = "Styles.css";
const QString TECH_TREE_FILENAME = "TechTree.json";
const QString G_FOLDER_NAME = "Generals";
const QString GZH_FOLDER_NAME = "GeneralsZH";
const QString ICONS_FOLDER_NAME = "Icons";

// General editor folders
const QString QT_ICONS_FOLDER = ":/icons";
const QString RESOURCE_FOLDER = "Resources";
const QString BINARIES_FOLDER = RESOURCE_FOLDER + "\\Binaries";
const QString TRANSLATIONS_FOLDER = RESOURCE_FOLDER + "/Translations";
const QString ICONS_FOLDER = RESOURCE_FOLDER + "/Icons";
const QString THEME_FOLDER = RESOURCE_FOLDER + "/Theme";
const QString QT_ICONS_FOLDER = ":/icons";

// Resource files
const QString TECH_TREE_FILE = RESOURCE_FOLDER + "/TechTree.json";

// Profile folders
const QString PROFILES_FOLDER = RESOURCE_FOLDER + "/Profiles";
const QString G_PROFILE_FOLDER = PROFILES_FOLDER + "/" + G_FOLDER_NAME;
const QString GZH_PROFILE_FOLDER = PROFILES_FOLDER + "/" + GZH_FOLDER_NAME;
const QString MAIN_STYLES_FILE = PROFILES_FOLDER + "/" + STYLES_FILENAME;

// Profile unrelated resource files
const QString SETTINGS_FILE = RESOURCE_FOLDER + "/Settings.json";
const QString STYLES_SHEET_FILE = THEME_FOLDER + "/Styles.css";
const QString GLOBAL_STYLES_FILE = RESOURCE_FOLDER + STYLES_FILENAME;

// Build-in files
const QString MISSING_ICON_FILE = QT_ICONS_FOLDER + "/NoImageSmall.webp";
Expand Down Expand Up @@ -101,15 +111,15 @@ class ProgramConstants
const QString NON_ASCII_HOTKEY_ERROR_DESCRIPTION = QObject::tr("You have assign as hotkey a non-ASCII character \"%1\".\nMake sure that you are using ASCII only symbols.");
const QString FORBIDDEN_HOTKEY_ERROR_DESCRIPTION = QObject::tr("You have assign as hotkey a forbidden character \"%1\".\nMake sure that you are using only allowed symbols.");

// Other string constants
// CSF string constants
const QString HOTKEY_CSF_CATEGORY = "CONTROLBAR";
const QString OBJECT_CSF_CATEGORY = "OBJECT";
const QString BIG_ARCHIVE_CSF_PATH = "Data\\English\\generals.csf";

// Constant containers
const QVector<QString> GLA_SHORT_NAMES = {"GLA", "TOX", "STL", "DML"};
const QVector<QString> USA_SHORT_NAMES = {"USA", "SWG", "AIR", "LSR"};
const QVector<QString> PRC_SHORT_NAMES = {"PRC", "TNK", "INF", "NUK"};
const QVector<QString> GLA_SHORT_NAMES = {"GLA", "TOX", "STL", "DML", "DTS"};
const QVector<QString> USA_SHORT_NAMES = {"USA", "SWG", "AIR", "LSR", "IRS"};
const QVector<QString> PRC_SHORT_NAMES = {"PRC", "TNK", "INF", "NUK", "LNG"};

const QSet<Qt::Key> DEFAULT_ALLOWED_KEYS =
{
Expand Down Expand Up @@ -159,4 +169,6 @@ class ProgramConstants
void InitializeFileSettings();
/// @brief Parse `*.qm` files in the `Resources\Translations` folder.
void InitializeTranslations();
/// @brief Parse folders in `Resources\Profiles` folder.
void InitializeProfiles();
};
3 changes: 0 additions & 3 deletions src/GUI/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,3 @@

# Link the libwebp target to the GUI target
target_link_libraries(${TARGET_NAME} PRIVATE ${LIB_WEBP_TARGET_NAME})

# Copy Styles.css with updates
configure_file("${PROJECT_RESOURCE_FOLDER}/Theme/Styles.css" "${PROJECT_DESTINATION_RESOURCES_FOLDER}/Theme/Styles.css")
131 changes: 82 additions & 49 deletions src/GUI/EditorWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
#include <QComboBox>
#include <QFileDialog>

#include "../Extensions/ExceptionExt.hpp"
#include "../Extensions/BoolExt.hpp"
#include "../Extensions/L10NExt.hpp"
#include "../Windows/Registry.hpp"
#include "../Windows/Locale.hpp"
#include "../Parsers/CSFParser.hpp"
#include "../Core/Logger.hpp"
#include "../Core/Convert.hpp"
#include "../Parsers/CSFParser.hpp"
#include "../Managers/FactionsManager.hpp"
#include "../Windows/Registry.hpp"
#include "../Windows/Locale.hpp"
#include "../Info.hpp"

#include "ImageManager.hpp"
Expand Down Expand Up @@ -58,58 +59,86 @@ EditorWindow::EditorWindow(QWidget* parent)
int factonsCount = FACTIONS_MANAGER->Count();
size_t language = PROGRAM_CONSTANTS->pSettingsFile->GetLanguage();

if (factonsCount == Faction::BASIC_FACTION_COUNT)
ltFactions = new QHBoxLayout();
ltFactions->setObjectName(nameof(ltFactions));

if (factonsCount > Faction::MAXIMUM_FACTION_COUNT)
{
ltFactions = new QHBoxLayout();
ltFactions->setObjectName(nameof(ltFactions));
throw ExceptionExt("Unable to parse more than " + ToQString(Faction::MAXIMUM_FACTION_COUNT) + " factions. Found factions: " + factonsCount);
}

// Only 3 blocks with factions and subfactions. 4 in each block and 12 in total
for (int sectionIndex = 0; sectionIndex < Faction::BASIC_FACTION_COUNT; sectionIndex += 4)
{
QVBoxLayout* ltCurrentFaction = new QVBoxLayout();
QHBoxLayout* ltCurrentSubfaction = new QHBoxLayout();
ltCurrentFaction->setObjectName(nameof(ltCurrentFaction));
ltCurrentSubfaction->setObjectName(nameof(ltCurrentSubfaction));
if (factonsCount < Faction::MINIMAL_FACTION_COUNT)
{
throw ExceptionExt("Unable to parse less than " + ToQString(Faction::MINIMAL_FACTION_COUNT) + " factions. Found factions: " + factonsCount);
}

for (int i = 0; i < 4; ++i)
{
const Faction currFaction = FACTIONS_MANAGER->FindByIndex(sectionIndex + i);
QVBoxLayout* ltFactionsUSA = new QVBoxLayout();
QHBoxLayout* ltSubfactionsUSA = new QHBoxLayout();
ltFactionsUSA->setObjectName(nameof(ltFactionsUSA));
ltSubfactionsUSA->setObjectName(nameof(ltSubfactionsUSA));

QVBoxLayout* ltFactionsPRC = new QVBoxLayout();
QHBoxLayout* ltSubfactionsPRC = new QHBoxLayout();
ltFactionsPRC->setObjectName(nameof(ltFactionsPRC));
ltSubfactionsPRC->setObjectName(nameof(ltSubfactionsPRC));

QVBoxLayout* ltFactionsGLA = new QVBoxLayout();
QHBoxLayout* ltSubfactionsGLA = new QHBoxLayout();
ltFactionsGLA->setObjectName(nameof(ltFactionsGLA));
ltSubfactionsGLA->setObjectName(nameof(ltSubfactionsGLA));

#define ADD_TO_LAYOUT(x) \
{ \
if (PROGRAM_CONSTANTS->x##_SHORT_NAMES.contains(shortName)) \
{ \
factionButton->setProperty("faction", QString(#x)); \
if (shortName == QString(#x)) \
ltFactions##x->addWidget(factionButton); \
else \
ltSubfactions##x->addWidget(factionButton); \
} \
}

QPushButton* factionButton = new QPushButton{currFaction.GetDisplayName()};
factionButton->setToolTip(currFaction.GetDisplayNameDescription());
for (int i = 0; i < FACTIONS_MANAGER->Count(); ++i)
{
const Faction& currFaction = FACTIONS_MANAGER->FindByIndex(i);

auto shortName = currFaction.GetShortName();
QPushButton* factionButton = new QPushButton(currFaction.GetDisplayName());
factionButton->setToolTip(currFaction.GetDisplayNameDescription());

if (PROGRAM_CONSTANTS->USA_SHORT_NAMES.contains(shortName))
factionButton->setProperty("faction", "USA");
QString shortName = currFaction.GetShortName();

if (PROGRAM_CONSTANTS->PRC_SHORT_NAMES.contains(shortName))
factionButton->setProperty("faction", "PRC");
ADD_TO_LAYOUT(USA);
ADD_TO_LAYOUT(PRC);
ADD_TO_LAYOUT(GLA);

if (PROGRAM_CONSTANTS->GLA_SHORT_NAMES.contains(shortName))
factionButton->setProperty("faction", "GLA");
connect(factionButton, &QPushButton::pressed, this, [=, this]()
{
SetGameObjectList(shortName);
});

connect(factionButton, &QPushButton::pressed, this, [=, this]()
{
SetGameObjectList(shortName);
});
pFactionsButtonsGroup->addButton(factionButton);
}

#undef ADD_TO_LAYOUT

#define RM_IF_EMPTY(x) \
{ \
if (!ltSubfactions##x->count()) \
ltSubfactions##x->deleteLater(); \
else \
ltFactions##x->addLayout(ltSubfactions##x); \
}

pFactionsButtonsGroup->addButton(factionButton);
RM_IF_EMPTY(USA);
RM_IF_EMPTY(PRC);
RM_IF_EMPTY(GLA);

if (i == 0) // main faction
ltCurrentFaction->addWidget(factionButton);
else // subfactions
ltCurrentSubfaction->addWidget(factionButton);
}
#undef RM_IF_EMPTY

ltCurrentFaction->addLayout(ltCurrentSubfaction);
ltFactions->addLayout(ltCurrentFaction);
}
}
else
{
LOGMSG("Unable to parse more than 12 factions. Found factions : " + factonsCount);
}
ltFactions->addLayout(ltFactionsUSA);
ltFactions->addLayout(ltFactionsPRC);
ltFactions->addLayout(ltFactionsGLA);

connect(pFactionsButtonsGroup, &QButtonGroup::idClicked, this, [=, this](int id)
{
Expand All @@ -136,7 +165,7 @@ EditorWindow::EditorWindow(QWidget* parent)
QHBoxLayout* pKeyboardThirdLine;
QVBoxLayout* pKeyboardLines = new QVBoxLayout();

QPushButton* btnEmptyButton= new QPushButton();
QPushButton* btnEmptyButton = new QPushButton();
btnEmptyButton->setProperty("key", "null");
btnEmptyButton->setFixedWidth(PROGRAM_CONSTANTS->EMPTY_KEY_WIDTH);

Expand Down Expand Up @@ -561,10 +590,15 @@ void EditorWindow::ActSave_Triggered()

if (CSF_PARSER->Path.ends_with(L".big") || CSF_PARSER->Path.ends_with(L".BIG"))
{
CSF_PARSER->Path = (QString::fromStdWString(
Windows::Registry::GetPathToGame(
Windows::Registry::Games::GeneralsZeroHour))
+ "Data\\English\\generals.csf"q).toStdWString();
CSF_PARSER->Path =
(
(
WINDOW_MANAGER->ProfileFolder.split('/')[2] == PROGRAM_CONSTANTS->G_FOLDER_NAME
? QString::fromStdWString(Windows::Registry::GetPathToGame(Windows::Registry::Games::Generals))
: QString::fromStdWString(Windows::Registry::GetPathToGame(Windows::Registry::Games::GeneralsZeroHour))
)
+ "Data\\English\\generals.csf"q
).toStdWString();
}

CSF_PARSER->Save();
Expand Down Expand Up @@ -629,4 +663,3 @@ void EditorWindow::SettingsWindow_LanguageChanged()
}

#pragma endregion

64 changes: 0 additions & 64 deletions src/GUI/GreetingWindow.cpp

This file was deleted.

15 changes: 0 additions & 15 deletions src/GUI/GreetingWindow.hpp

This file was deleted.

Loading
Loading