WoW Model Viewer
Your premiere tool for viewing, equipping and animating World of Warcraft models.
Loading...
Searching...
No Matches
PresetManager.cpp
Go to the documentation of this file.
1#include "PresetManager.h"
2#include "AppState.h"
3#include "ModelLoader.h"
4
5#ifdef _WIN32
6#include <windows.h>
7#endif
8
9#include <cstring>
10#include <filesystem>
11#include <string>
12
13#include "Logger.h"
14#include "IniFile.h"
15#include "WoWModel.h"
16#include "WoWItem.h"
17#include "CharDetails.h"
18
20{
21
22void save(const char* path, AppState& app)
23{
25 if (!model || !app.scene.isChar)
26 {
27 app.exporting.presetStatus = "No character model loaded.";
28 return;
29 }
30
31 std::string pathStr{path};
32 core::IniFile ini{pathStr};
33
34 const auto& cd = model->cd;
35 ini.setValue("Display/ShowUnderwear", cd.showUnderwear);
36 ini.setValue("Display/ShowHair", cd.showHair);
37 ini.setValue("Display/ShowFacialHair", cd.showFacialHair);
38 ini.setValue("Display/ShowEars", cd.showEars);
39 ini.setValue("Display/ShowFeet", cd.showFeet);
40 ini.setValue("Display/AutoHideGeosets", cd.autoHideGeosetsForHeadItems);
41 ini.setValue("Display/Sheathe", model->bSheathe);
42 ini.setValue("Display/EyeGlow", static_cast<int>(cd.eyeGlowType));
43
44 int optIdx = 0;
45 for (const auto& opt : app.character.customizationOptions)
46 {
47 std::string key = "Customization/" + std::to_string(optIdx);
48 ini.setValue(key + "_OptionID", static_cast<int>(opt.optionID));
49 if (opt.selectedIndex >= 0 && opt.selectedIndex < static_cast<int>(opt.choiceIDs.size()))
50 ini.setValue(key + "_ChoiceID", static_cast<int>(opt.choiceIDs[opt.selectedIndex]));
51 ++optIdx;
52 }
53 ini.setValue("Customization/Count", optIdx);
54
55 for (int s = 0; s < NUM_CHAR_SLOTS; ++s)
56 {
57 WoWItem* witem = model->getItem(static_cast<CharSlots>(s));
58 std::string key = "Equipment/" + std::to_string(s);
59 ini.setValue(key + "_ID", witem ? static_cast<int>(witem->id()) : 0);
60 ini.setValue(key + "_Level", app.character.equipSlotLevels[s]);
61 }
62
63 ini.sync();
64 app.exporting.presetStatus = std::string("Preset saved: ") + path;
65 LOG_INFO << "Character preset saved to " << path;
66}
67
68void load(const char* path, AppState& app)
69{
71 if (!model || !app.scene.isChar)
72 {
73 app.exporting.presetStatus = "No character model loaded.";
74 return;
75 }
76
77 if (!std::filesystem::exists(path))
78 {
79 app.exporting.presetStatus = std::string("File not found: ") + path;
80 return;
81 }
82
83 std::string pathStr{path};
84 core::IniFile ini{pathStr};
85
86 auto& cd = model->cd;
87 cd.showUnderwear = ini.getBool("Display/ShowUnderwear", true);
88 cd.showHair = ini.getBool("Display/ShowHair", true);
89 cd.showFacialHair = ini.getBool("Display/ShowFacialHair", true);
90 cd.showEars = ini.getBool("Display/ShowEars", true);
91 cd.showFeet = ini.getBool("Display/ShowFeet", false);
92 cd.autoHideGeosetsForHeadItems = ini.getBool("Display/AutoHideGeosets", true);
93 model->bSheathe = ini.getBool("Display/Sheathe", false);
94 cd.eyeGlowType = static_cast<EyeGlowTypes>(ini.getInt("Display/EyeGlow", EGT_DEFAULT));
95
96 int optCount = ini.getInt("Customization/Count", 0);
97 for (int i = 0; i < optCount; ++i)
98 {
99 std::string key = "Customization/" + std::to_string(i);
100 unsigned int optionID = static_cast<unsigned int>(ini.getInt(key + "_OptionID", 0));
101 unsigned int choiceID = static_cast<unsigned int>(ini.getInt(key + "_ChoiceID", 0));
102 if (optionID == 0) continue;
103
104 cd.set(optionID, choiceID);
105
106 for (auto& opt : app.character.customizationOptions)
107 {
108 if (opt.optionID == optionID)
109 {
110 for (int c = 0; c < static_cast<int>(opt.choiceIDs.size()); ++c)
111 {
112 if (opt.choiceIDs[c] == choiceID)
113 {
114 opt.selectedIndex = c;
115 break;
116 }
117 }
118 break;
119 }
120 }
121 }
122
123 for (int s = 0; s < NUM_CHAR_SLOTS; ++s)
124 {
125 std::string key = "Equipment/" + std::to_string(s);
126 int itemId = ini.getInt(key + "_ID", 0);
127 int level = ini.getInt(key + "_Level", 0);
128
129 WoWItem* witem = model->getItem(static_cast<CharSlots>(s));
130 if (witem)
131 {
132 witem->setId(itemId);
133 if (level > 0) witem->setLevel(level);
134 }
135 app.character.equipSlotLevels[s] = level;
136 }
137
138 model->refresh();
139 app.exporting.presetStatus = std::string("Preset loaded: ") + path;
140 LOG_INFO << "Character preset loaded from " << path;
141}
142
143} // namespace PresetManager
#define LOG_INFO
Definition Logger.h:10
bool showUnderwear
Definition CharDetails.h:93
Represents an equipped item on a character model.
Definition WoWItem.h:39
int id() const
Definition WoWItem.h:44
void setId(int id)
Definition WoWItem.cpp:34
void setLevel(int level)
Definition WoWItem.cpp:123
Core WoW .m2 model: geometry, animation, textures, and character data.
Definition WoWModel.h:50
WoWItem * getItem(CharSlots slot)
void refresh()
CharDetails cd
Definition WoWModel.h:214
bool bSheathe
Definition WoWModel.h:220
Simple INI file reader/writer with section/key support.
Definition IniFile.h:15
WoWModel * getLoadedModel(AppState &app)
Return the currently loaded WoWModel (first child of root), or nullptr.
void load(const char *path, AppState &app)
Load a previously saved character preset from an INI file.
void save(const char *path, AppState &app)
Top-level aggregate of all mutable application state.
Definition AppState.h:261
SceneState scene
Definition AppState.h:262
ExportState exporting
Definition AppState.h:268
CharacterState character
Definition AppState.h:266
std::vector< CustomizationOption > customizationOptions
Definition AppState.h:174
int equipSlotLevels[NUM_CHAR_SLOTS]
Definition AppState.h:179
std::string presetStatus
Definition AppState.h:246
bool isChar
Definition AppState.h:82
CharSlots
Character equipment slot indices.
Definition wow_enums.h:5
@ NUM_CHAR_SLOTS
Definition wow_enums.h:21
EyeGlowTypes
Definition wow_enums.h:333
@ EGT_DEFAULT
Definition wow_enums.h:335