MassBuilderSaveTool/src/SaveTool/SaveTool_MassViewer.cpp

424 lines
15 KiB
C++

// MassBuilderSaveTool
// Copyright (C) 2021 Guillaume Jacquemin
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <Magnum/ImGuiIntegration/Integration.h>
#include "../Maps/StyleNames.h"
#include "../FontAwesome/IconsFontAwesome5.h"
#include "SaveTool.h"
void SaveTool::drawMassViewer() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
_currentMass = nullptr;
_uiState = UiState::MainManager;
_queue.addToast(Toast::Type::Error, "The selected M.A.S.S. isn't valid anymore.");
return;
}
ImGui::SetNextWindowPos({0.0f, ImGui::GetItemRectSize().y}, ImGuiCond_Always);
ImGui::SetNextWindowSize({Float(windowSize().x()), Float(windowSize().y()) - ImGui::GetItemRectSize().y},
ImGuiCond_Always);
if(!ImGui::Begin("##MainWindow", nullptr,
ImGuiWindowFlags_NoDecoration|ImGuiWindowFlags_NoMove|
ImGuiWindowFlags_NoBackground|ImGuiWindowFlags_NoBringToFrontOnFocus))
{
ImGui::End();
return;
}
ImGui::Text("Current M.A.S.S.: %s (%s)",
(*_currentMass->name()).c_str(),
_currentMass->filename().c_str());
ImGui::SameLine();
if(ImGui::SmallButton(ICON_FA_ARROW_LEFT " Back to main manager")) {
_currentMass = nullptr;
_uiState = UiState::MainManager;
}
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
ImGui::SameLine();
ImGui::TextWrapped("WARNING: Colours in this app may look different from in-game colours, due to unavoidable differences in the rendering pipeline.");
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
ImGui::SameLine();
ImGui::TextWrapped("Real-time updates are disabled while on this screen. %s", _currentMass->dirty() ? "The save file has been changed." : "");
if(_currentMass->dirty()) {
ImGui::SameLine();
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
_currentMass->refreshValues();
_currentMass->setDirty(false);
}
}
if(ImGui::BeginChild("##MassInfo",
{ImGui::GetContentRegionAvailWidth() * 0.60f, 0.0f},
true, ImGuiWindowFlags_MenuBar))
{
if(ImGui::BeginMenuBar()) {
ImGui::TextUnformatted("M.A.S.S. Information");
ImGui::EndMenuBar();
}
if(ImGui::BeginTabBar("##MassTabBar")) {
if(ImGui::BeginTabItem("Frame")) {
drawFrameInfo();
ImGui::EndTabItem();
}
ImGui::EndTabBar();
}
}
ImGui::EndChild();
ImGui::SameLine();
if(ImGui::BeginChild("##GlobalStyles", {0.0f, 0.0f},
true, ImGuiWindowFlags_MenuBar))
{
if(ImGui::BeginMenuBar()) {
ImGui::TextUnformatted("Global styles");
ImGui::EndMenuBar();
}
ImGui::TextUnformatted("Placeholder");
}
ImGui::EndChild();
ImGui::End();
}
void SaveTool::drawFrameInfo() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
return;
}
ImGui::TextUnformatted("Frame type: Skeleton"); // Placeholder for now, replace with actual code once other frames are implemented.
drawJointSliders();
drawFramePaint();
}
void SaveTool::drawJointSliders() {
if(!ImGui::CollapsingHeader("Joint sliders")) {
return;
}
static Joints sliders = _currentMass->jointSliders();
static bool joints_edit = false;
static bool joints_dirty = false;
ImGui::TextWrapped("In-game values are multiplied by 100.\nFor example, 0.500 here is equal to 50 in-game.");
if(ImGui::BeginTable("##JointSliderTable", 2, ImGuiTableFlags_Borders)) {
ImGui::TableSetupColumn("##SliderLabel", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("##Sliders", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Neck");
ImGui::TableSetColumnIndex(1);
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##NeckSlider", &sliders.neck, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().neck));
}
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Body");
ImGui::TableSetColumnIndex(1);
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##BodySlider", &sliders.body, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().body));
}
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Shoulders");
ImGui::TableSetColumnIndex(1);
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##ShouldersSlider", &sliders.shoulders, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().shoulders));
}
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Hips");
ImGui::TableSetColumnIndex(1);
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##HipsSlider", &sliders.hips, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().hips));
}
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(1);
if(ImGui::BeginTable("##UpperLowerLayoutTable", 2, ImGuiTableFlags_BordersInnerV)) {
ImGui::TableSetupColumn("##Upper", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##Lower", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Upper");
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Lower");
ImGui::EndTable();
}
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Arms");
ImGui::TableSetColumnIndex(1);
if(ImGui::BeginTable("##UpperLowerArmsLayoutTable", 2, ImGuiTableFlags_BordersInnerV)) {
ImGui::TableSetupColumn("##UpperArms", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##LowerArms", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextColumn();
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##UpperArmsSlider", &sliders.upperArms, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().upperArms));
}
ImGui::TableNextColumn();
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##LowerArmsSlider", &sliders.lowerArms, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().lowerArms));
}
ImGui::EndTable();
}
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Legs");
ImGui::TableSetColumnIndex(1);
if(ImGui::BeginTable("##UpperLowerLegsLayoutTable", 2, ImGuiTableFlags_BordersInnerV)) {
ImGui::TableSetupColumn("##UpperLegs", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("##LowerLegs", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextColumn();
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##UpperLegsSlider", &sliders.upperLegs, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().upperLegs));
}
ImGui::TableNextColumn();
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##LowerLegsSlider", &sliders.lowerLegs, 0.0f, 1.0f)) {
joints_dirty = true;
}
}
else {
ImGui::AlignTextToFramePadding();
ImGui::Text("%.3f", Double(_currentMass->jointSliders().lowerLegs));
}
ImGui::EndTable();
}
ImGui::EndTable();
}
if(joints_edit) {
if(!joints_dirty) {
ImGui::BeginDisabled();
ImGui::Button(ICON_FA_SAVE " Save changes");
ImGui::SameLine();
ImGui::Button(ICON_FA_UNDO " Reset sliders");
ImGui::EndDisabled();
}
else {
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save changes"); })) {
if(!_currentMass->setSliders(sliders)) {
_queue.addToast(Toast::Type::Error, "Error writing the joint sliders.");
}
joints_dirty = false;
joints_edit = false;
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_UNDO " Reset sliders")) {
sliders = _currentMass->jointSliders();
joints_dirty = false;
}
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_TIMES " Cancel editing")) {
sliders = _currentMass->jointSliders();
joints_dirty = false;
joints_edit = false;
}
ImGui::TextUnformatted("To input out-of-range values, hold Ctrl and click on a slider.");
}
else {
if(ImGui::Button(ICON_FA_EDIT " Edit sliders")) {
sliders = _currentMass->jointSliders();
joints_edit = true;
}
}
}
void SaveTool::drawFramePaint() {
if(!ImGui::CollapsingHeader("Paint")) {
return;
}
ImGui::TextUnformatted("Frame styles:");
for(Int i = 0; i < 4; i++) {
ImGui::AlignTextToFramePadding();
ImGui::Text("Slot %d:", i + 1);
ImGui::SameLine();
ImGui::PushID(i);
GameState game_state = _gameState;
if(!_unsafeMode && game_state != GameState::NotRunning) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f);
}
if(ImGui::BeginCombo("##Style", style_names.at(_currentMass->frameStyles()[i]))) {
for(const auto& style : style_names) {
if(ImGui::Selectable(style.second, _currentMass->frameStyles()[i] == style.first)) {
if(!_currentMass->setFrameStyle(i, style.first)) {
_queue.addToast(Toast::Type::Error, Mass::lastError());
}
else {
_currentMass->refreshValues();
}
}
}
ImGui::EndCombo();
}
if(!_unsafeMode && game_state != GameState::NotRunning) {
ImGui::PopItemFlag();
ImGui::PopStyleVar();
}
ImGui::PopID();
}
ImGui::Separator();
static bool eye_flare_edit = false;
static bool eye_flare_dirty = false;
static Color4 eye_flare = _currentMass->eyeFlareColour();
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Eye flare colour:");
ImGui::SameLine();
ImGui::BeginGroup();
if(eye_flare_edit) {
if(ImGui::ColorEdit3("##EyeFlarePicker", &eye_flare.x())) {
eye_flare_dirty = true;
}
ImGui::SameLine();
drawHelpMarker("Right-click for more option, click the coloured square for the full picker.", 250.0f);
if(!eye_flare_dirty) {
ImGui::BeginDisabled();
ImGui::Button(ICON_FA_SAVE " Save");
ImGui::SameLine();
ImGui::Button(ICON_FA_UNDO " Reset");
ImGui::EndDisabled();
}
else {
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
if(!_currentMass->setEyeFlareColour(eye_flare)) {
_queue.addToast(Toast::Type::Error, "Error writing the eye flare colour.");
}
eye_flare_dirty = false;
eye_flare_edit = false;
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
eye_flare = _currentMass->eyeFlareColour();
eye_flare_dirty = false;
}
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_TIMES " Cancel")) {
eye_flare = _currentMass->eyeFlareColour();
eye_flare_dirty = false;
eye_flare_edit = false;
}
}
else {
ImGui::BeginDisabled();
ImColor colour{_currentMass->eyeFlareColour()};
ImGui::ColorEdit3("##EyeFlarePicker", &colour.Value.x);
ImGui::EndDisabled();
if(ImGui::Button(ICON_FA_EDIT " Edit")) {
eye_flare = _currentMass->eyeFlareColour();
eye_flare_edit = true;
}
}
ImGui::EndGroup();
}