mirror of
https://github.com/redstrate/Novus.git
synced 2025-06-07 21:57:46 +00:00
Move gar loading to a different thread and prevent unnecessary updates
This commit is contained in:
parent
e67011ad71
commit
d8d890bfbb
9 changed files with 254 additions and 129 deletions
|
@ -18,6 +18,7 @@ public:
|
|||
|
||||
Q_SIGNALS:
|
||||
void gearChanged();
|
||||
void loadingChanged(bool loading);
|
||||
|
||||
public Q_SLOTS:
|
||||
void clear();
|
||||
|
|
|
@ -24,6 +24,11 @@ struct GearInfo {
|
|||
}
|
||||
};
|
||||
|
||||
inline bool operator==(const GearInfo &a, const GearInfo &b)
|
||||
{
|
||||
return a.name == b.name && a.slot == b.slot;
|
||||
}
|
||||
|
||||
struct GameData;
|
||||
|
||||
class GearView : public QWidget {
|
||||
|
@ -51,6 +56,7 @@ public:
|
|||
Q_SIGNALS:
|
||||
void gearChanged();
|
||||
void modelReloaded();
|
||||
void loadingChanged(bool loading);
|
||||
|
||||
void raceChanged();
|
||||
void subraceChanged();
|
||||
|
@ -63,8 +69,8 @@ Q_SIGNALS:
|
|||
void tailChanged();
|
||||
|
||||
public Q_SLOTS:
|
||||
void clear();
|
||||
void addGear(GearInfo& gear);
|
||||
void removeGear(GearInfo &gear);
|
||||
|
||||
void setRace(Race race);
|
||||
void setSubrace(Subrace subrace);
|
||||
|
@ -76,7 +82,6 @@ public Q_SLOTS:
|
|||
void setEar(int bodyVer);
|
||||
void setTail(int bodyVer);
|
||||
|
||||
void reloadModel();
|
||||
void reloadRaceDeforms();
|
||||
|
||||
private:
|
||||
|
@ -84,11 +89,29 @@ private:
|
|||
|
||||
uint32_t maxLod = 0;
|
||||
|
||||
std::vector<GearInfo> gears;
|
||||
struct LoadedGear {
|
||||
GearInfo info;
|
||||
physis_MDL mdl;
|
||||
};
|
||||
|
||||
std::vector<LoadedGear> loadedGears;
|
||||
std::vector<LoadedGear> queuedGearAdditions;
|
||||
std::vector<LoadedGear> queuedGearRemovals;
|
||||
bool gearDirty = false;
|
||||
|
||||
std::optional<int> face = 1, hair = 1, ear = 1, tail;
|
||||
bool faceDirty = false, hairDirty = false, earDirty = false, tailDirty = false;
|
||||
bool raceDirty = false;
|
||||
|
||||
MDLPart* mdlPart = nullptr;
|
||||
|
||||
GameData* data;
|
||||
FileCache& cache;
|
||||
|
||||
bool updating = false;
|
||||
void updatePart();
|
||||
bool needsUpdate() const;
|
||||
|
||||
void gearUpdate(LoadedGear &gear);
|
||||
void queueGearUpdate(LoadedGear &gear);
|
||||
};
|
|
@ -34,6 +34,8 @@ public Q_SLOTS:
|
|||
void setGender(Gender gender);
|
||||
void setLevelOfDetail(int lod);
|
||||
|
||||
void setFMVAvailable(bool available);
|
||||
|
||||
private Q_SLOTS:
|
||||
void reloadGear();
|
||||
|
||||
|
@ -50,6 +52,7 @@ private:
|
|||
QPushButton *addToFMVButton, *exportButton;
|
||||
|
||||
bool loadingComboData = false;
|
||||
bool fmvAvailable = false;
|
||||
|
||||
GameData* data = nullptr;
|
||||
};
|
|
@ -124,6 +124,13 @@ FullModelViewer::FullModelViewer(GameData* data, FileCache& cache) : data(data)
|
|||
}
|
||||
|
||||
connect(this, &FullModelViewer::gearChanged, this, &FullModelViewer::reloadGear);
|
||||
connect(gearView, &GearView::loadingChanged, this, &FullModelViewer::loadingChanged);
|
||||
connect(this, &FullModelViewer::loadingChanged, this, [this, tabWidget](const bool loading) {
|
||||
raceCombo->setEnabled(!loading);
|
||||
subraceCombo->setEnabled(!loading);
|
||||
genderCombo->setEnabled(!loading);
|
||||
tabWidget->setEnabled(!loading);
|
||||
});
|
||||
|
||||
reloadGear();
|
||||
}
|
||||
|
@ -138,10 +145,14 @@ void FullModelViewer::clear() {
|
|||
void FullModelViewer::addGear(GearInfo& info) {
|
||||
switch (info.slot) {
|
||||
case Slot::Body:
|
||||
if (topSlot ? *topSlot != info : true) {
|
||||
topSlot = info;
|
||||
}
|
||||
break;
|
||||
case Slot::Legs:
|
||||
if (bottomSlot ? *bottomSlot != info : true) {
|
||||
bottomSlot = info;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -150,9 +161,8 @@ void FullModelViewer::addGear(GearInfo& info) {
|
|||
Q_EMIT gearChanged();
|
||||
}
|
||||
|
||||
void FullModelViewer::reloadGear() {
|
||||
gearView->clear();
|
||||
|
||||
void FullModelViewer::reloadGear()
|
||||
{
|
||||
if (topSlot.has_value()) {
|
||||
gearView->addGear(*topSlot);
|
||||
} else {
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#include "gearview.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QThreadPool>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtConcurrent>
|
||||
|
||||
#include "filecache.h"
|
||||
#include "magic_enum.hpp"
|
||||
|
@ -18,36 +20,30 @@ GearView::GearView(GameData* data, FileCache& cache) : data(data), cache(cache)
|
|||
layout->addWidget(mdlPart);
|
||||
setLayout(layout);
|
||||
|
||||
connect(this, &GearView::gearChanged, this, [=] {
|
||||
reloadModel();
|
||||
});
|
||||
connect(this, &GearView::raceChanged, this, [=] {
|
||||
reloadRaceDeforms();
|
||||
reloadModel();
|
||||
});
|
||||
connect(this, &GearView::subraceChanged, this, [=] {
|
||||
reloadRaceDeforms();
|
||||
reloadModel();
|
||||
});
|
||||
connect(this, &GearView::genderChanged, this, [=] {
|
||||
reloadRaceDeforms();
|
||||
reloadModel();
|
||||
});
|
||||
connect(this, &GearView::levelOfDetailChanged, this, &GearView::reloadModel);
|
||||
mdlPart->requestUpdate = [this] {
|
||||
if (updating) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(this, &GearView::faceChanged, this, &GearView::reloadModel);
|
||||
connect(this, &GearView::hairChanged, this, &GearView::reloadModel);
|
||||
connect(this, &GearView::earChanged, this, &GearView::reloadModel);
|
||||
connect(this, &GearView::tailChanged, this, &GearView::reloadModel);
|
||||
if (needsUpdate()) {
|
||||
updating = true;
|
||||
|
||||
Q_EMIT loadingChanged(true);
|
||||
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), [this] {
|
||||
updatePart();
|
||||
Q_EMIT loadingChanged(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::vector<std::pair<Race, Subrace>> GearView::supportedRaces() const {
|
||||
std::vector<std::pair<Race, Subrace>> races;
|
||||
for (const auto& gear : gears) {
|
||||
for (const auto &gear : loadedGears) {
|
||||
for (auto [race, race_name] : magic_enum::enum_entries<Race>()) {
|
||||
for (auto subrace : physis_get_supported_subraces(race).subraces) {
|
||||
auto equip_path =
|
||||
physis_build_equipment_path(gear.modelInfo.primaryID, race, subrace, currentGender, gear.slot);
|
||||
auto equip_path = physis_build_equipment_path(gear.info.modelInfo.primaryID, race, subrace, currentGender, gear.info.slot);
|
||||
|
||||
if (cache.fileExists(QLatin1String(equip_path)))
|
||||
races.emplace_back(race, subrace);
|
||||
|
@ -60,10 +56,9 @@ std::vector<std::pair<Race, Subrace>> GearView::supportedRaces() const {
|
|||
|
||||
std::vector<Gender> GearView::supportedGenders() const {
|
||||
std::vector<Gender> genders;
|
||||
for (const auto& gear : gears) {
|
||||
for (const auto &gear : loadedGears) {
|
||||
for (auto [gender, gender_name] : magic_enum::enum_entries<Gender>()) {
|
||||
auto equip_path = physis_build_equipment_path(
|
||||
gear.modelInfo.primaryID, currentRace, Subrace::Midlander, currentGender, gear.slot);
|
||||
auto equip_path = physis_build_equipment_path(gear.info.modelInfo.primaryID, currentRace, Subrace::Midlander, currentGender, gear.info.slot);
|
||||
|
||||
if (cache.fileExists(QLatin1String(equip_path)))
|
||||
genders.push_back(gender);
|
||||
|
@ -81,16 +76,22 @@ void GearView::exportModel(const QString& fileName) {
|
|||
mdlPart->exportModel(fileName);
|
||||
}
|
||||
|
||||
void GearView::clear() {
|
||||
gears.clear();
|
||||
void GearView::addGear(GearInfo &gear)
|
||||
{
|
||||
qDebug() << "Adding gear" << gear.name.c_str();
|
||||
|
||||
queuedGearAdditions.emplace_back(gear);
|
||||
gearDirty = true;
|
||||
|
||||
Q_EMIT gearChanged();
|
||||
}
|
||||
|
||||
void GearView::addGear(GearInfo& gear) {
|
||||
qDebug() << "Adding gear" << gear.name.c_str();
|
||||
void GearView::removeGear(GearInfo &gear)
|
||||
{
|
||||
qDebug() << "Removing gear" << gear.name.c_str();
|
||||
|
||||
gears.push_back(gear);
|
||||
queuedGearRemovals.emplace_back(gear);
|
||||
gearDirty = true;
|
||||
|
||||
Q_EMIT gearChanged();
|
||||
}
|
||||
|
@ -102,9 +103,8 @@ void GearView::setRace(Race race) {
|
|||
|
||||
currentRace = race;
|
||||
|
||||
auto supportedSubraces = physis_get_supported_subraces(race);
|
||||
if (supportedSubraces.subraces[0] == currentSubrace || supportedSubraces.subraces[1] == currentSubrace) {
|
||||
} else {
|
||||
const auto supportedSubraces = physis_get_supported_subraces(race);
|
||||
if (supportedSubraces.subraces[0] != currentSubrace && supportedSubraces.subraces[1] != currentSubrace) {
|
||||
setSubrace(supportedSubraces.subraces[0]);
|
||||
}
|
||||
|
||||
|
@ -114,6 +114,8 @@ void GearView::setRace(Race race) {
|
|||
setTail(-1);
|
||||
}
|
||||
|
||||
raceDirty = true;
|
||||
|
||||
Q_EMIT raceChanged();
|
||||
}
|
||||
|
||||
|
@ -123,6 +125,12 @@ void GearView::setSubrace(Subrace subrace) {
|
|||
}
|
||||
|
||||
currentSubrace = subrace;
|
||||
|
||||
// Hyur is the only race that has two different subraces
|
||||
if (currentRace == Race::Hyur) {
|
||||
raceDirty = true;
|
||||
}
|
||||
|
||||
Q_EMIT subraceChanged();
|
||||
}
|
||||
|
||||
|
@ -132,6 +140,9 @@ void GearView::setGender(Gender gender) {
|
|||
}
|
||||
|
||||
currentGender = gender;
|
||||
|
||||
raceDirty = true;
|
||||
|
||||
Q_EMIT genderChanged();
|
||||
}
|
||||
|
||||
|
@ -141,81 +152,126 @@ void GearView::setLevelOfDetail(int lod) {
|
|||
}
|
||||
|
||||
currentLod = lod;
|
||||
|
||||
Q_EMIT levelOfDetailChanged();
|
||||
}
|
||||
|
||||
void GearView::setFace(int bodyVer) {
|
||||
if (face == bodyVer) {
|
||||
void GearView::setFace(const int faceCode)
|
||||
{
|
||||
if (face == faceCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bodyVer == -1) {
|
||||
if (faceCode == -1) {
|
||||
face = std::nullopt;
|
||||
} else {
|
||||
face = bodyVer;
|
||||
face = faceCode;
|
||||
}
|
||||
|
||||
faceDirty = true;
|
||||
Q_EMIT faceChanged();
|
||||
}
|
||||
|
||||
void GearView::setHair(int bodyVer) {
|
||||
if (hair == bodyVer) {
|
||||
void GearView::setHair(int hairCode)
|
||||
{
|
||||
if (hair == hairCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bodyVer == -1) {
|
||||
if (hairCode == -1) {
|
||||
hair = std::nullopt;
|
||||
} else {
|
||||
hair = bodyVer;
|
||||
hair = hairCode;
|
||||
}
|
||||
|
||||
hairDirty = true;
|
||||
Q_EMIT hairChanged();
|
||||
}
|
||||
|
||||
void GearView::setEar(int bodyVer) {
|
||||
if (ear == bodyVer) {
|
||||
void GearView::setEar(const int earCode)
|
||||
{
|
||||
if (ear == earCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bodyVer == -1) {
|
||||
if (earCode == -1) {
|
||||
ear = std::nullopt;
|
||||
} else {
|
||||
ear = bodyVer;
|
||||
ear = earCode;
|
||||
}
|
||||
|
||||
earDirty = true;
|
||||
Q_EMIT earChanged();
|
||||
}
|
||||
|
||||
void GearView::setTail(int bodyVer) {
|
||||
if (tail == bodyVer) {
|
||||
void GearView::setTail(const int tailCode)
|
||||
{
|
||||
if (tail == tailCode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bodyVer == -1) {
|
||||
if (tailCode == -1) {
|
||||
tail = std::nullopt;
|
||||
} else {
|
||||
tail = bodyVer;
|
||||
tail = tailCode;
|
||||
}
|
||||
|
||||
tailDirty = true;
|
||||
Q_EMIT tailChanged();
|
||||
}
|
||||
|
||||
void GearView::reloadModel() {
|
||||
mdlPart->clear();
|
||||
void GearView::reloadRaceDeforms()
|
||||
{
|
||||
qDebug() << "Loading race deform matrices for " << magic_enum::enum_name(currentRace).data() << magic_enum::enum_name(currentSubrace).data()
|
||||
<< magic_enum::enum_name(currentGender).data();
|
||||
const int raceCode = physis_get_race_code(currentRace, currentSubrace, currentGender);
|
||||
qDebug() << "Race code: " << raceCode;
|
||||
|
||||
maxLod = 0;
|
||||
QString skelName = QString{"c%1b0001.skel"}.arg(raceCode, 4, 10, QLatin1Char{'0'});
|
||||
mdlPart->setSkeleton(physis_skeleton_from_skel(physis_read_file(skelName.toStdString().c_str())));
|
||||
|
||||
for (const auto& gear : gears) {
|
||||
auto mdl_data = cache.lookupFile(physis_build_equipment_path(
|
||||
gear.modelInfo.primaryID, currentRace, currentSubrace, currentGender, gear.slot));
|
||||
// racial deforms don't work on Hyur Midlander, not needed? TODO not sure
|
||||
if (currentSubrace != Subrace::Midlander) {
|
||||
QString deformName = QString{"c%1_deform.json"}.arg(raceCode, 4, 10, QLatin1Char{'0'});
|
||||
mdlPart->loadRaceDeformMatrices(physis_read_file(deformName.toStdString().c_str()));
|
||||
} else {
|
||||
for (auto &data : mdlPart->boneData) {
|
||||
data.deformRaceMatrix = glm::mat4(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MDLPart &GearView::part() const
|
||||
{
|
||||
return *mdlPart;
|
||||
}
|
||||
|
||||
void GearView::updatePart()
|
||||
{
|
||||
qInfo() << raceDirty << gearDirty << updating;
|
||||
if (raceDirty) {
|
||||
// if race changes, all of the models need to be reloaded.
|
||||
// TODO: in the future, we can be a bit smarter about this, lots of races use the same model (hyur)
|
||||
for (auto &part : loadedGears) {
|
||||
mdlPart->removeModel(part.mdl);
|
||||
}
|
||||
queuedGearAdditions = loadedGears;
|
||||
loadedGears.clear();
|
||||
gearDirty = true;
|
||||
}
|
||||
|
||||
if (gearDirty) {
|
||||
for (auto &gearAddition : queuedGearAdditions) {
|
||||
auto mdl_data = cache.lookupFile(
|
||||
physis_build_equipment_path(gearAddition.info.modelInfo.primaryID, currentRace, currentSubrace, currentGender, gearAddition.info.slot));
|
||||
|
||||
// attempt to load the next best race
|
||||
// currently hardcoded to hyur midlander
|
||||
Race fallbackRace = currentRace;
|
||||
Subrace fallbackSubrace = currentSubrace;
|
||||
if (mdl_data.size == 0) {
|
||||
mdl_data = cache.lookupFile(physis_build_equipment_path(
|
||||
gear.modelInfo.primaryID, Race::Hyur, Subrace::Midlander, currentGender, gear.slot));
|
||||
mdl_data = cache.lookupFile(
|
||||
physis_build_equipment_path(gearAddition.info.modelInfo.primaryID, Race::Hyur, Subrace::Midlander, currentGender, gearAddition.info.slot));
|
||||
fallbackRace = Race::Hyur;
|
||||
fallbackSubrace = Subrace::Midlander;
|
||||
}
|
||||
|
@ -225,10 +281,11 @@ void GearView::reloadModel() {
|
|||
|
||||
std::vector<physis_Material> materials;
|
||||
for (int i = 0; i < mdl.num_material_names; i++) {
|
||||
const char* material_name = mdl.material_names[i];
|
||||
const char *material_name = mdl.material_names[i];
|
||||
|
||||
const std::string mtrl_path = gear.getMtrlPath(material_name);
|
||||
const std::string skinmtrl_path = physis_build_skin_material_path(physis_get_race_code(fallbackRace, fallbackSubrace, currentGender), 1, material_name);
|
||||
const std::string mtrl_path = gearAddition.info.getMtrlPath(material_name);
|
||||
const std::string skinmtrl_path =
|
||||
physis_build_skin_material_path(physis_get_race_code(fallbackRace, fallbackSubrace, currentGender), 1, material_name);
|
||||
|
||||
if (cache.fileExists(QLatin1String(mtrl_path.c_str()))) {
|
||||
auto mat = physis_material_parse(cache.lookupFile(mtrl_path.c_str()));
|
||||
|
@ -244,12 +301,24 @@ void GearView::reloadModel() {
|
|||
maxLod = std::max(mdl.num_lod, maxLod);
|
||||
|
||||
mdlPart->addModel(mdl, materials, currentLod);
|
||||
gearAddition.mdl = mdl;
|
||||
loadedGears.push_back(gearAddition);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &queuedRemoval : queuedGearRemovals) {
|
||||
mdlPart->removeModel(queuedRemoval.mdl);
|
||||
loadedGears.erase(std::remove_if(loadedGears.begin(),
|
||||
loadedGears.end(),
|
||||
[queuedRemoval](const LoadedGear other) {
|
||||
return queuedRemoval.info == other.info;
|
||||
}),
|
||||
loadedGears.end());
|
||||
}
|
||||
}
|
||||
|
||||
if (face) {
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(
|
||||
CharacterCategory::Face, *face, currentRace, currentSubrace, currentGender));
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(CharacterCategory::Face, *face, currentRace, currentSubrace, currentGender));
|
||||
|
||||
if (mdl_data.size > 0) {
|
||||
auto mdl = physis_mdl_parse(mdl_data.size, mdl_data.data);
|
||||
|
@ -270,8 +339,7 @@ void GearView::reloadModel() {
|
|||
}
|
||||
|
||||
if (hair) {
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(
|
||||
CharacterCategory::Hair, *hair, currentRace, currentSubrace, currentGender));
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(CharacterCategory::Hair, *hair, currentRace, currentSubrace, currentGender));
|
||||
|
||||
if (mdl_data.size > 0) {
|
||||
auto mdl = physis_mdl_parse(mdl_data.size, mdl_data.data);
|
||||
|
@ -292,8 +360,7 @@ void GearView::reloadModel() {
|
|||
}
|
||||
|
||||
if (ear) {
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(
|
||||
CharacterCategory::Hair, *ear, currentRace, currentSubrace, currentGender));
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(CharacterCategory::Hair, *ear, currentRace, currentSubrace, currentGender));
|
||||
|
||||
if (mdl_data.size > 0) {
|
||||
auto mdl = physis_mdl_parse(mdl_data.size, mdl_data.data);
|
||||
|
@ -314,8 +381,7 @@ void GearView::reloadModel() {
|
|||
}
|
||||
|
||||
if (tail) {
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(
|
||||
CharacterCategory::Tail, *tail, currentRace, currentSubrace, currentGender));
|
||||
auto mdl_data = cache.lookupFile(physis_build_character_path(CharacterCategory::Tail, *tail, currentRace, currentSubrace, currentGender));
|
||||
|
||||
if (mdl_data.size > 0) {
|
||||
auto mdl = physis_mdl_parse(mdl_data.size, mdl_data.data);
|
||||
|
@ -330,31 +396,18 @@ void GearView::reloadModel() {
|
|||
}
|
||||
}
|
||||
|
||||
Q_EMIT modelReloaded();
|
||||
raceDirty = false;
|
||||
gearDirty = false;
|
||||
updating = false;
|
||||
faceDirty = false;
|
||||
hairDirty = false;
|
||||
earDirty = false;
|
||||
tailDirty = false;
|
||||
}
|
||||
|
||||
void GearView::reloadRaceDeforms() {
|
||||
qDebug() << "Loading race deform matrices for " << magic_enum::enum_name(currentRace).data()
|
||||
<< magic_enum::enum_name(currentSubrace).data() << magic_enum::enum_name(currentGender).data();
|
||||
const int raceCode = physis_get_race_code(currentRace, currentSubrace, currentGender);
|
||||
qDebug() << "Race code: " << raceCode;
|
||||
|
||||
QString skelName = QString{"c%1b0001.skel"}.arg(raceCode, 4, 10, QLatin1Char{'0'});
|
||||
mdlPart->setSkeleton(physis_skeleton_from_skel(physis_read_file(skelName.toStdString().c_str())));
|
||||
|
||||
// racial deforms don't work on Hyur Midlander, not needed? TODO not sure
|
||||
if (currentSubrace != Subrace::Midlander) {
|
||||
QString deformName = QString{"c%1_deform.json"}.arg(raceCode, 4, 10, QLatin1Char{'0'});
|
||||
mdlPart->loadRaceDeformMatrices(physis_read_file(deformName.toStdString().c_str()));
|
||||
} else {
|
||||
for (auto& data : mdlPart->boneData) {
|
||||
data.deformRaceMatrix = glm::mat4(1.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MDLPart& GearView::part() const {
|
||||
return *mdlPart;
|
||||
bool GearView::needsUpdate() const
|
||||
{
|
||||
return gearDirty || raceDirty || faceDirty || hairDirty || earDirty || tailDirty;
|
||||
}
|
||||
|
||||
#include "moc_gearview.cpp"
|
||||
|
|
|
@ -83,6 +83,9 @@ MainWindow::MainWindow(GameData* in_data) : data(*in_data), cache(FileCache{*in_
|
|||
connect(gearView, &SingleGearView::addToFullModelViewer, this, [=](GearInfo& info) {
|
||||
fullModelViewer->addGear(info);
|
||||
});
|
||||
connect(fullModelViewer, &FullModelViewer::loadingChanged, this, [=](const bool loading) {
|
||||
gearView->setFMVAvailable(!loading);
|
||||
});
|
||||
layout->addWidget(gearView);
|
||||
|
||||
fullModelViewer = new FullModelViewer(&data, cache);
|
||||
|
|
|
@ -100,15 +100,25 @@ SingleGearView::SingleGearView(GameData* data, FileCache& cache) : data(data) {
|
|||
}
|
||||
|
||||
void SingleGearView::clear() {
|
||||
if (currentGear) {
|
||||
gearView->removeGear(*currentGear);
|
||||
}
|
||||
currentGear.reset();
|
||||
|
||||
Q_EMIT gearChanged();
|
||||
}
|
||||
|
||||
void SingleGearView::setGear(const GearInfo& info) {
|
||||
if (info != currentGear) {
|
||||
if (currentGear) {
|
||||
gearView->removeGear(*currentGear);
|
||||
}
|
||||
|
||||
currentGear = info;
|
||||
gearView->addGear(*currentGear);
|
||||
|
||||
Q_EMIT gearChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void SingleGearView::setRace(Race race) {
|
||||
|
@ -147,19 +157,16 @@ void SingleGearView::setLevelOfDetail(int lod) {
|
|||
Q_EMIT levelOfDetailChanged();
|
||||
}
|
||||
|
||||
void SingleGearView::reloadGear() {
|
||||
gearView->clear();
|
||||
|
||||
void SingleGearView::reloadGear()
|
||||
{
|
||||
raceCombo->setEnabled(currentGear.has_value());
|
||||
subraceCombo->setEnabled(currentGear.has_value());
|
||||
genderCombo->setEnabled(currentGear.has_value());
|
||||
lodCombo->setEnabled(currentGear.has_value());
|
||||
addToFMVButton->setEnabled(currentGear.has_value());
|
||||
addToFMVButton->setEnabled(currentGear.has_value() && fmvAvailable);
|
||||
exportButton->setEnabled(currentGear.has_value());
|
||||
|
||||
if (currentGear.has_value()) {
|
||||
gearView->addGear(*currentGear);
|
||||
|
||||
loadingComboData = true;
|
||||
|
||||
const auto oldRace = static_cast<Race>(raceCombo->itemData(raceCombo->currentIndex()).toInt());
|
||||
|
@ -212,4 +219,12 @@ void SingleGearView::reloadGear() {
|
|||
}
|
||||
}
|
||||
|
||||
void SingleGearView::setFMVAvailable(const bool available)
|
||||
{
|
||||
if (fmvAvailable != available) {
|
||||
fmvAvailable = available;
|
||||
addToFMVButton->setEnabled(currentGear.has_value() && available);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_singlegearview.cpp"
|
|
@ -116,6 +116,9 @@ public:
|
|||
}
|
||||
|
||||
void render() {
|
||||
if (part->requestUpdate)
|
||||
part->requestUpdate();
|
||||
|
||||
glm::vec3 position(
|
||||
part->cameraDistance * sin(part->yaw),
|
||||
part->cameraDistance * part->pitch,
|
||||
|
@ -554,4 +557,14 @@ void MDLPart::calculateBone(physis_Skeleton& skeleton, physis_Bone& bone, const
|
|||
}
|
||||
}
|
||||
|
||||
void MDLPart::removeModel(const physis_MDL &mdl)
|
||||
{
|
||||
models.erase(std::remove_if(models.begin(),
|
||||
models.end(),
|
||||
[mdl](const RenderModel other) {
|
||||
return mdl.lods == other.model.lods;
|
||||
}),
|
||||
models.end());
|
||||
}
|
||||
|
||||
#include "moc_mdlpart.cpp"
|
|
@ -47,6 +47,8 @@ public:
|
|||
|
||||
std::vector<BoneData> boneData;
|
||||
|
||||
std::function<void()> requestUpdate;
|
||||
|
||||
Q_SIGNALS:
|
||||
void modelChanged();
|
||||
void skeletonChanged();
|
||||
|
@ -58,6 +60,8 @@ public Q_SLOTS:
|
|||
/// Adds a new MDL with a list of materials used.
|
||||
void addModel(physis_MDL mdl, std::vector<physis_Material> materials, int lod);
|
||||
|
||||
void removeModel(const physis_MDL &mdl);
|
||||
|
||||
/// Sets the skeleton any skinned MDLs should bind to.
|
||||
void setSkeleton(physis_Skeleton skeleton);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue