WoW Model Viewer
Your premiere tool for viewing, equipping and animating World of Warcraft models.
Loading...
Searching...
No Matches
URLImportHandler.cpp
Go to the documentation of this file.
1#include "URLImportHandler.h"
2#include "AppState.h"
3#include "ModelLoader.h"
4
5#include <string>
6
7#include "Logger.h"
8#include "ImporterPlugin.h"
9#include "CharInfos.h"
10#include "NPCInfos.h"
11#include "RaceInfos.h"
12#include "WoWModel.h"
13#include "WoWItem.h"
14#include "CharDetails.h"
15#include "Game.h"
16#include "WoWDatabase.h"
17#include "DB2Table.h"
18#include "database.h"
19#include "video.h"
20#include "wow_enums.h"
21
22namespace
23{
24
25void applyImportedChar(CharInfos* info, AppState& app)
26{
27 if (!info || !info->valid)
28 {
29 app.exporting.importStatus = "Import returned no valid character data.";
30 return;
31 }
32
33 // Find the character model by race + gender
34 int raceID = static_cast<int>(info->raceId);
35 int sexID = (info->gender == "FEMALE" || info->gender == "Female") ? 1 : 0;
36
37 int fileDataID = RaceInfos::getFileIDForRaceSex(raceID, sexID);
38 if (fileDataID <= 0)
39 {
40 app.exporting.importStatus = "Could not determine model for race " + std::to_string(raceID);
41 return;
42 }
43
44 GameFile* file = GAMEDIRECTORY.getFile(fileDataID);
45 if (!file)
46 {
47 app.exporting.importStatus = "Model file not found for race " + std::to_string(raceID);
48 return;
49 }
50
52
54 if (!model || !app.scene.isChar)
55 {
56 app.exporting.importStatus = "Failed to load character model.";
57 return;
58 }
59
60 // Apply customizations
61 auto& cd = model->cd;
62 for (const auto& [optionId, choiceId] : info->customizations)
63 cd.set(optionId, choiceId);
64
65 // Apply eye glow
66 cd.eyeGlowType = static_cast<EyeGlowTypes>(info->eyeGlowType);
67
68 // Apply equipment
69 for (int s = 0; s < NUM_CHAR_SLOTS && s < static_cast<int>(info->equipment.size()); ++s)
70 {
71 int itemId = info->equipment[s];
72 if (itemId <= 0) continue;
73 WoWItem* witem = model->getItem(static_cast<CharSlots>(s));
74 if (witem)
75 witem->setId(itemId);
76 }
77
78 model->refresh();
79
80 // Update customization UI state
82
83 app.exporting.importStatus = "Character imported successfully.";
84 LOG_INFO << "Character imported from URL.";
85}
86
87void applyImportedNPC(NPCInfos* info, AppState& app)
88{
89 if (!info || info->displayId <= 0)
90 {
91 app.exporting.importStatus = "Import returned no valid NPC data.";
92 return;
93 }
94
95 // Use DB2Table to resolve CreatureDisplayInfo -> CreatureModelData -> FileDataID
96 const auto* cdiTable = WOWDB.getTable("CreatureDisplayInfo");
97 const auto* cmdTable = WOWDB.getTable("CreatureModelData");
98 if (!cdiTable || !cmdTable)
99 {
100 app.exporting.importStatus = "NPC display ID " + std::to_string(info->displayId) + " not found in database.";
101 return;
102 }
103 auto cdiRow = cdiTable->getRow(static_cast<uint32_t>(info->displayId));
104 if (!cdiRow)
105 {
106 app.exporting.importStatus = "NPC display ID " + std::to_string(info->displayId) + " not found in database.";
107 return;
108 }
109 auto cmdRow = cmdTable->getRow(cdiRow.getUInt("ModelID"));
110 uint32_t npcFDID = cmdRow ? cmdRow.getUInt("FileDataID") : 0;
111 if (npcFDID == 0)
112 {
113 app.exporting.importStatus = "NPC display ID " + std::to_string(info->displayId) + " not found in database.";
114 return;
115 }
116
117 GameFile* file = GAMEDIRECTORY.getFile(npcFDID);
118 if (!file)
119 {
120 app.exporting.importStatus = "NPC model file not found.";
121 return;
122 }
123
124 ModelLoader::loadModel(file, app, video.fov);
125 app.exporting.importStatus = std::string("NPC imported: ") + ModelLoader::wstringToString(info->name);
126 LOG_INFO << "NPC imported from URL: " << ModelLoader::wstringToString(info->name);
127}
128
129void applyImportedItem(ItemRecord* rec, AppState& app)
130{
131 if (!rec || rec->id <= 0)
132 {
133 app.exporting.importStatus = "Import returned no valid item data.";
134 return;
135 }
136
137 ModelLoader::loadItemModel(static_cast<unsigned int>(rec->id), app, video.fov);
138 app.exporting.importStatus = std::string("Item imported: ") + rec->name;
139 LOG_INFO << "Item imported from URL: " << rec->name;
140}
141
142} // anonymous namespace
143
145{
146
148{
149 const std::string& url = app.exporting.importUrlBuf;
150 if (url.empty())
151 {
152 app.exporting.importStatus = "Please enter a URL.";
153 return;
154 }
155
156 app.exporting.importStatus = "Importing...";
157
158 // Find matching importer
159 ImporterPlugin* importer = nullptr;
160 for (const auto& imp : app.exporting.importers)
161 {
162 if (imp->acceptURL(url))
163 {
164 importer = imp.get();
165 break;
166 }
167 }
168
169 if (!importer)
170 {
171 app.exporting.importStatus = "No importer recognises this URL. Supported: battle.net, worldofwarcraft.com, wowhead.com";
172 return;
173 }
174
175 // Try character import first (Armory)
176 CharInfos* charInfo = importer->importChar(url);
177 if (charInfo && charInfo->valid)
178 {
179 applyImportedChar(charInfo, app);
180 delete charInfo;
181 return;
182 }
183 delete charInfo;
184
185 // Try NPC import (Wowhead)
186 NPCInfos* npcInfo = importer->importNPC(url);
187 if (npcInfo && npcInfo->displayId > 0)
188 {
189 applyImportedNPC(npcInfo, app);
190 delete npcInfo;
191 return;
192 }
193 delete npcInfo;
194
195 // Try item import
196 ItemRecord* itemRec = importer->importItem(url);
197 if (itemRec && itemRec->id > 0)
198 {
199 applyImportedItem(itemRec, app);
200 delete itemRec;
201 return;
202 }
203 delete itemRec;
204
205 app.exporting.importStatus = "Could not import anything from this URL.";
206}
207
208} // namespace URLImportHandler
#define GAMEDIRECTORY
Definition Game.h:9
#define LOG_INFO
Definition Logger.h:10
#define WOWDB
Definition WoWDatabase.h:65
EyeGlowTypes eyeGlowType
Definition CharDetails.h:91
Stores imported character information (race, gender, equipment, customisations, tabard).
Definition CharInfos.h:8
std::string gender
Gender string ("male" or "female").
Definition CharInfos.h:16
std::vector< int > equipment
Equipment item IDs per slot.
Definition CharInfos.h:29
unsigned int raceId
Character race ID.
Definition CharInfos.h:15
bool valid
Whether the data was successfully parsed.
Definition CharInfos.h:12
unsigned int eyeGlowType
Eye glow type (none, default, death knight).
Definition CharInfos.h:19
Abstract base class representing a file within the game data archive.
Definition GameFile.h:12
Abstract base class for URL-based import plugins (Armory, Wowhead, etc.).
virtual CharInfos * importChar(const std::string &url) const =0
virtual NPCInfos * importNPC(const std::string &url) const =0
virtual ItemRecord * importItem(const std::string &url) const =0
Stores basic NPC metadata (id, display id, type, name) imported from external sources.
Definition NPCInfos.h:7
int displayId
Creature display info ID.
Definition NPCInfos.h:15
std::wstring name
Display name (wide string).
Definition NPCInfos.h:17
static int getFileIDForRaceSex(const int &race, const int &sex)
Get the model file ID for a specific race and sex.
float fov
Definition video.h:69
Represents an equipped item on a character model.
Definition WoWItem.h:39
void setId(int id)
Definition WoWItem.cpp:34
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
std::string wstringToString(const std::wstring &ws)
Convert a wide string to narrow ASCII (lossy, for display only).
void loadModel(GameFile *file, AppState &app, float fov)
Load a .m2 GameFile, create a WoWModel, attach to root, init controls.
void initCharacterControl(WoWModel *model, AppState &app)
Populate app.customizationOptions from the model's ChrCustomization DB.
void loadItemModel(unsigned int itemId, AppState &app, float fov)
WoWModel * getLoadedModel(AppState &app)
Return the currently loaded WoWModel (first child of root), or nullptr.
void doImport(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
std::vector< std::unique_ptr< ImporterPlugin > > importers
Definition AppState.h:249
std::string importUrlBuf
Definition AppState.h:250
std::string importStatus
Definition AppState.h:251
A single equipment item record from the item database.
Definition database.h:26
std::string name
Display name of the item.
Definition database.h:27
bool isChar
Definition AppState.h:82
VideoSettings video
Definition video.cpp:38
CharSlots
Character equipment slot indices.
Definition wow_enums.h:5
EyeGlowTypes
Definition wow_enums.h:333