mirror of
https://github.com/redstrate/Novus.git
synced 2025-04-25 05:17:44 +00:00
Add editable character parameters to FMV
This commit is contained in:
parent
a9d121d885
commit
97dda3d091
2 changed files with 128 additions and 27 deletions
|
@ -14,19 +14,27 @@ public:
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void gearChanged();
|
void gearChanged();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void clear();
|
void clear();
|
||||||
void addGear(GearInfo& info);
|
void addGear(GearInfo &info);
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void reloadGear();
|
void reloadGear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void updateHeightScaling(float scale);
|
||||||
|
void updateBustScaling(float scale);
|
||||||
|
void updateCharacterParameters();
|
||||||
|
|
||||||
std::optional<GearInfo> topSlot;
|
std::optional<GearInfo> topSlot;
|
||||||
std::optional<GearInfo> bottomSlot;\
|
std::optional<GearInfo> bottomSlot;
|
||||||
|
|
||||||
GearView* gearView = nullptr;
|
GearView *gearView = nullptr;
|
||||||
QComboBox* raceCombo, *genderCombo;
|
QComboBox *raceCombo, *genderCombo;
|
||||||
|
|
||||||
GameData* data = nullptr;
|
GameData *data = nullptr;
|
||||||
|
physis_CMP cmp;
|
||||||
|
|
||||||
|
float heightScale = 0.5f;
|
||||||
|
float bustScale = 0.5f;
|
||||||
};
|
};
|
|
@ -1,7 +1,9 @@
|
||||||
#include "fullmodelviewer.h"
|
#include "fullmodelviewer.h"
|
||||||
|
|
||||||
#include "magic_enum.hpp"
|
|
||||||
#include "boneeditor.h"
|
#include "boneeditor.h"
|
||||||
|
#include "magic_enum.hpp"
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
FullModelViewer::FullModelViewer(GameData *data) : data(data) {
|
FullModelViewer::FullModelViewer(GameData *data) : data(data) {
|
||||||
|
@ -12,20 +14,52 @@ FullModelViewer::FullModelViewer(GameData *data) : data(data) {
|
||||||
auto layout = new QVBoxLayout();
|
auto layout = new QVBoxLayout();
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
|
cmp = physis_cmp_parse(
|
||||||
|
physis_gamedata_extract_file(data, "chara/xls/charamake/human.cmp"));
|
||||||
|
|
||||||
gearView = new GearView(data);
|
gearView = new GearView(data);
|
||||||
|
updateCharacterParameters();
|
||||||
|
|
||||||
|
connect(gearView, &GearView::modelReloaded, this,
|
||||||
|
&FullModelViewer::updateCharacterParameters);
|
||||||
|
|
||||||
auto viewportLayout = new QHBoxLayout();
|
auto viewportLayout = new QHBoxLayout();
|
||||||
viewportLayout->addWidget(gearView, 1);
|
viewportLayout->addWidget(gearView, 1);
|
||||||
viewportLayout->addWidget(new BoneEditor(gearView));
|
|
||||||
layout->addLayout(viewportLayout);
|
layout->addLayout(viewportLayout);
|
||||||
|
|
||||||
|
auto characterEditorWidget = new QWidget();
|
||||||
|
auto characterEditorLayout = new QFormLayout();
|
||||||
|
characterEditorWidget->setLayout(characterEditorLayout);
|
||||||
|
|
||||||
|
auto characterHeight = new QSlider();
|
||||||
|
characterHeight->setOrientation(Qt::Horizontal);
|
||||||
|
characterHeight->setSliderPosition(50);
|
||||||
|
connect(characterHeight, &QSlider::sliderMoved, this, [this](int position) {
|
||||||
|
const float scale = (float)position / 100.0f;
|
||||||
|
updateHeightScaling(scale);
|
||||||
|
});
|
||||||
|
characterEditorLayout->addRow("Height", characterHeight);
|
||||||
|
|
||||||
|
auto bustSize = new QSlider();
|
||||||
|
bustSize->setOrientation(Qt::Horizontal);
|
||||||
|
bustSize->setSliderPosition(50);
|
||||||
|
connect(bustSize, &QSlider::sliderMoved, this, [this](int position) {
|
||||||
|
const float scale = (float)position / 100.0f;
|
||||||
|
updateBustScaling(scale);
|
||||||
|
});
|
||||||
|
characterEditorLayout->addRow("Bust Size", bustSize);
|
||||||
|
|
||||||
|
auto tabWidget = new QTabWidget();
|
||||||
|
tabWidget->addTab(new BoneEditor(gearView), "Bone Editor");
|
||||||
|
tabWidget->addTab(characterEditorWidget, "Character Editor");
|
||||||
|
viewportLayout->addWidget(tabWidget);
|
||||||
|
|
||||||
auto controlLayout = new QHBoxLayout();
|
auto controlLayout = new QHBoxLayout();
|
||||||
layout->addLayout(controlLayout);
|
layout->addLayout(controlLayout);
|
||||||
|
|
||||||
raceCombo = new QComboBox();
|
raceCombo = new QComboBox();
|
||||||
connect(raceCombo, qOverload<int>(&QComboBox::currentIndexChanged), [this](int index) {
|
connect(raceCombo, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||||
gearView->setRace((Race)index);
|
[this](int index) { gearView->setRace((Race)index); });
|
||||||
});
|
|
||||||
controlLayout->addWidget(raceCombo);
|
controlLayout->addWidget(raceCombo);
|
||||||
|
|
||||||
for (auto [race, race_name] : magic_enum::enum_entries<Race>()) {
|
for (auto [race, race_name] : magic_enum::enum_entries<Race>()) {
|
||||||
|
@ -95,4 +129,63 @@ void FullModelViewer::reloadGear() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FullModelViewer::updateHeightScaling(float scale) {
|
||||||
|
auto &boneData = *gearView->part().skeleton;
|
||||||
|
for (int i = 0; i < boneData.num_bones; i++) {
|
||||||
|
const std::string_view name{boneData.bones[i].name};
|
||||||
|
if (name == "n_root") {
|
||||||
|
auto racialScaling = physis_cmp_get_racial_scaling_parameters(
|
||||||
|
cmp, gearView->currentRace, gearView->currentSubrace);
|
||||||
|
|
||||||
|
const float minSize = gearView->currentGender == Gender::Male
|
||||||
|
? racialScaling.male_min_size
|
||||||
|
: racialScaling.female_min_size;
|
||||||
|
const float maxSize = gearView->currentGender == Gender::Male
|
||||||
|
? racialScaling.male_max_size
|
||||||
|
: racialScaling.female_max_size;
|
||||||
|
|
||||||
|
const float size = glm::mix(minSize, maxSize, scale);
|
||||||
|
|
||||||
|
boneData.bones[i].scale[0] = size;
|
||||||
|
boneData.bones[i].scale[1] = size;
|
||||||
|
boneData.bones[i].scale[2] = size;
|
||||||
|
|
||||||
|
gearView->part().reloadRenderer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heightScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullModelViewer::updateBustScaling(float scale) {
|
||||||
|
auto &boneData = *gearView->part().skeleton;
|
||||||
|
for (int i = 0; i < boneData.num_bones; i++) {
|
||||||
|
const std::string_view name{boneData.bones[i].name};
|
||||||
|
if (name == "j_mune_l" || name == "j_mune_r") {
|
||||||
|
auto racialScaling = physis_cmp_get_racial_scaling_parameters(
|
||||||
|
cmp, gearView->currentRace, gearView->currentSubrace);
|
||||||
|
|
||||||
|
const float rangeX = glm::mix(racialScaling.bust_min_x,
|
||||||
|
racialScaling.bust_max_x, scale);
|
||||||
|
const float rangeY = glm::mix(racialScaling.bust_min_y,
|
||||||
|
racialScaling.bust_max_y, scale);
|
||||||
|
const float rangeZ = glm::mix(racialScaling.bust_min_z,
|
||||||
|
racialScaling.bust_max_z, scale);
|
||||||
|
|
||||||
|
boneData.bones[i].scale[0] = rangeX;
|
||||||
|
boneData.bones[i].scale[1] = rangeY;
|
||||||
|
boneData.bones[i].scale[2] = rangeZ;
|
||||||
|
|
||||||
|
gearView->part().reloadRenderer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bustScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FullModelViewer::updateCharacterParameters() {
|
||||||
|
updateHeightScaling(heightScale);
|
||||||
|
updateBustScaling(bustScale);
|
||||||
|
}
|
||||||
|
|
||||||
#include "moc_fullmodelviewer.cpp"
|
#include "moc_fullmodelviewer.cpp"
|
Loading…
Add table
Reference in a new issue