mirror of
https://github.com/redstrate/Novus.git
synced 2025-04-23 12:37:45 +00:00
Add support for loading faces, hairs, ears and tails
This commit is contained in:
parent
77ad2b7298
commit
01b3fc6ef2
2 changed files with 199 additions and 0 deletions
|
@ -59,6 +59,11 @@ Q_SIGNALS:
|
||||||
void genderChanged();
|
void genderChanged();
|
||||||
void levelOfDetailChanged();
|
void levelOfDetailChanged();
|
||||||
|
|
||||||
|
void faceChanged();
|
||||||
|
void hairChanged();
|
||||||
|
void earChanged();
|
||||||
|
void tailChanged();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void clear();
|
void clear();
|
||||||
void addGear(GearInfo& gear);
|
void addGear(GearInfo& gear);
|
||||||
|
@ -68,6 +73,11 @@ public Q_SLOTS:
|
||||||
void setGender(Gender gender);
|
void setGender(Gender gender);
|
||||||
void setLevelOfDetail(int lod);
|
void setLevelOfDetail(int lod);
|
||||||
|
|
||||||
|
void setFace(int bodyVer);
|
||||||
|
void setHair(int bodyVer);
|
||||||
|
void setEar(int bodyVer);
|
||||||
|
void setTail(int bodyVer);
|
||||||
|
|
||||||
void reloadModel();
|
void reloadModel();
|
||||||
void reloadRaceDeforms();
|
void reloadRaceDeforms();
|
||||||
|
|
||||||
|
@ -77,6 +87,7 @@ private:
|
||||||
uint32_t maxLod = 0;
|
uint32_t maxLod = 0;
|
||||||
|
|
||||||
std::vector<GearInfo> gears;
|
std::vector<GearInfo> gears;
|
||||||
|
std::optional<int> face = 1, hair = 1, ear = 1, tail;
|
||||||
|
|
||||||
MDLPart* mdlPart = nullptr;
|
MDLPart* mdlPart = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,11 @@ GearView::GearView(GameData* data) : data(data) {
|
||||||
reloadModel();
|
reloadModel();
|
||||||
});
|
});
|
||||||
connect(this, &GearView::levelOfDetailChanged, this, &GearView::reloadModel);
|
connect(this, &GearView::levelOfDetailChanged, this, &GearView::reloadModel);
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<Race, Subrace>> GearView::supportedRaces() const {
|
std::vector<std::pair<Race, Subrace>> GearView::supportedRaces() const {
|
||||||
|
@ -98,6 +103,12 @@ void GearView::setRace(Race race) {
|
||||||
setSubrace(supportedSubraces.subraces[0]);
|
setSubrace(supportedSubraces.subraces[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (race == Race::AuRa || race == Race::Miqote) {
|
||||||
|
setTail(1);
|
||||||
|
} else {
|
||||||
|
setTail(-1);
|
||||||
|
}
|
||||||
|
|
||||||
Q_EMIT raceChanged();
|
Q_EMIT raceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +139,62 @@ void GearView::setLevelOfDetail(int lod) {
|
||||||
Q_EMIT levelOfDetailChanged();
|
Q_EMIT levelOfDetailChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GearView::setFace(int bodyVer) {
|
||||||
|
if (face == bodyVer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bodyVer == -1) {
|
||||||
|
face = std::nullopt;
|
||||||
|
} else {
|
||||||
|
face = bodyVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_EMIT faceChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GearView::setHair(int bodyVer) {
|
||||||
|
if (hair == bodyVer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bodyVer == -1) {
|
||||||
|
hair = std::nullopt;
|
||||||
|
} else {
|
||||||
|
hair = bodyVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_EMIT hairChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GearView::setEar(int bodyVer) {
|
||||||
|
if (ear == bodyVer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bodyVer == -1) {
|
||||||
|
ear = std::nullopt;
|
||||||
|
} else {
|
||||||
|
ear = bodyVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_EMIT earChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GearView::setTail(int bodyVer) {
|
||||||
|
if (tail == bodyVer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bodyVer == -1) {
|
||||||
|
tail = std::nullopt;
|
||||||
|
} else {
|
||||||
|
tail = bodyVer;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_EMIT tailChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void GearView::reloadModel() {
|
void GearView::reloadModel() {
|
||||||
mdlPart->clear();
|
mdlPart->clear();
|
||||||
|
|
||||||
|
@ -195,6 +262,127 @@ void GearView::reloadModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (face) {
|
||||||
|
auto mdl_data = physis_gamedata_extract_file(
|
||||||
|
data,
|
||||||
|
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);
|
||||||
|
|
||||||
|
std::vector<physis_Material> materials;
|
||||||
|
for (int i = 0; i < mdl.num_material_names; i++) {
|
||||||
|
const char* material_name = mdl.material_names[i];
|
||||||
|
|
||||||
|
std::string skinmtrl_path = fmt::format(
|
||||||
|
"chara/human/c{raceCode:04d}/obj/face/f{bodyCode:04d}/"
|
||||||
|
"material{}",
|
||||||
|
material_name,
|
||||||
|
fmt::arg("raceCode", physis_get_race_code(currentRace, currentSubrace, currentGender)),
|
||||||
|
fmt::arg("bodyCode", *face));
|
||||||
|
|
||||||
|
fmt::print("oops: {}", skinmtrl_path);
|
||||||
|
|
||||||
|
if (physis_gamedata_exists(data, skinmtrl_path.c_str())) {
|
||||||
|
auto mat = physis_material_parse(physis_gamedata_extract_file(data, skinmtrl_path.c_str()));
|
||||||
|
materials.push_back(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mdlPart->addModel(mdl, materials, currentLod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hair) {
|
||||||
|
auto mdl_data = physis_gamedata_extract_file(
|
||||||
|
data,
|
||||||
|
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);
|
||||||
|
|
||||||
|
std::vector<physis_Material> materials;
|
||||||
|
for (int i = 0; i < mdl.num_material_names; i++) {
|
||||||
|
const char* material_name = mdl.material_names[i];
|
||||||
|
|
||||||
|
std::string skinmtrl_path = fmt::format(
|
||||||
|
"chara/human/c{raceCode:04d}/obj/hair/h{bodyCode:04d}/"
|
||||||
|
"material/v0001{}",
|
||||||
|
material_name,
|
||||||
|
fmt::arg("raceCode", physis_get_race_code(currentRace, currentSubrace, currentGender)),
|
||||||
|
fmt::arg("bodyCode", *hair));
|
||||||
|
|
||||||
|
fmt::print("oops: {}", skinmtrl_path);
|
||||||
|
|
||||||
|
if (physis_gamedata_exists(data, skinmtrl_path.c_str())) {
|
||||||
|
auto mat = physis_material_parse(physis_gamedata_extract_file(data, skinmtrl_path.c_str()));
|
||||||
|
materials.push_back(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mdlPart->addModel(mdl, materials, currentLod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ear) {
|
||||||
|
auto mdl_data = physis_gamedata_extract_file(
|
||||||
|
data,
|
||||||
|
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);
|
||||||
|
|
||||||
|
std::vector<physis_Material> materials;
|
||||||
|
for (int i = 0; i < mdl.num_material_names; i++) {
|
||||||
|
const char* material_name = mdl.material_names[i];
|
||||||
|
|
||||||
|
std::string skinmtrl_path = fmt::format(
|
||||||
|
"chara/human/c{raceCode:04d}/obj/ear/e{bodyCode:04d}/"
|
||||||
|
"material/v0001{}",
|
||||||
|
material_name,
|
||||||
|
fmt::arg("raceCode", physis_get_race_code(currentRace, currentSubrace, currentGender)),
|
||||||
|
fmt::arg("bodyCode", *ear));
|
||||||
|
|
||||||
|
fmt::print("oops: {}", skinmtrl_path);
|
||||||
|
|
||||||
|
if (physis_gamedata_exists(data, skinmtrl_path.c_str())) {
|
||||||
|
auto mat = physis_material_parse(physis_gamedata_extract_file(data, skinmtrl_path.c_str()));
|
||||||
|
materials.push_back(mat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mdlPart->addModel(mdl, materials, currentLod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tail) {
|
||||||
|
auto mdl_data = physis_gamedata_extract_file(
|
||||||
|
data,
|
||||||
|
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);
|
||||||
|
|
||||||
|
const char* material_name = mdl.material_names[0];
|
||||||
|
|
||||||
|
std::string skinmtrl_path = fmt::format(
|
||||||
|
"chara/human/c{raceCode:04d}/obj/tail/t{bodyCode:04d}/"
|
||||||
|
"material/v0001{}",
|
||||||
|
material_name,
|
||||||
|
fmt::arg("raceCode", physis_get_race_code(currentRace, currentSubrace, currentGender)),
|
||||||
|
fmt::arg("bodyCode", *tail));
|
||||||
|
|
||||||
|
if (physis_gamedata_exists(data, skinmtrl_path.c_str())) {
|
||||||
|
auto mat = physis_material_parse(physis_gamedata_extract_file(data, skinmtrl_path.c_str()));
|
||||||
|
mdlPart->addModel(mdl, {mat}, currentLod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Q_EMIT modelReloaded();
|
Q_EMIT modelReloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue