2021-08-19 20:35:00 +02:00
|
|
|
// 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/>.
|
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
#include <Corrade/Containers/ScopeGuard.h>
|
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
#include <Magnum/ImGuiIntegration/Integration.h>
|
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
#include "../Maps/Accessories.h"
|
|
|
|
#include "../Maps/ArmourSets.h"
|
|
|
|
#include "../Maps/ArmourSlots.h"
|
2021-09-10 16:16:21 +02:00
|
|
|
#include "../Maps/StyleNames.h"
|
2021-12-02 19:23:28 +01:00
|
|
|
#include "../Maps/WeaponTypes.h"
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-08-19 20:35:00 +02:00
|
|
|
#include "../FontAwesome/IconsFontAwesome5.h"
|
|
|
|
|
|
|
|
#include "SaveTool.h"
|
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
static Weapon* current_weapon = nullptr;
|
|
|
|
|
2021-08-19 20:35:00 +02:00
|
|
|
void SaveTool::drawMassViewer() {
|
2021-08-28 20:22:04 +02:00
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
_currentMass = nullptr;
|
2021-12-02 19:23:28 +01:00
|
|
|
current_weapon = nullptr;
|
2021-08-28 20:22:04 +02:00
|
|
|
_uiState = UiState::MainManager;
|
2021-09-27 17:54:30 +02:00
|
|
|
_queue.addToast(Toast::Type::Error, "The selected M.A.S.S. isn't valid anymore.");
|
2021-08-28 20:22:04 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-08-19 20:35:00 +02:00
|
|
|
ImGui::SetNextWindowPos({0.0f, ImGui::GetItemRectSize().y}, ImGuiCond_Always);
|
|
|
|
ImGui::SetNextWindowSize({Float(windowSize().x()), Float(windowSize().y()) - ImGui::GetItemRectSize().y},
|
|
|
|
ImGuiCond_Always);
|
2022-01-07 09:35:32 +01:00
|
|
|
if(!ImGui::Begin("##MassViewer", nullptr,
|
2021-08-19 20:35:00 +02:00
|
|
|
ImGuiWindowFlags_NoDecoration|ImGuiWindowFlags_NoMove|
|
|
|
|
ImGuiWindowFlags_NoBackground|ImGuiWindowFlags_NoBringToFrontOnFocus))
|
|
|
|
{
|
|
|
|
ImGui::End();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-08-28 21:03:06 +02:00
|
|
|
if(ImGui::BeginChild("##MassInfo",
|
2021-12-02 19:23:28 +01:00
|
|
|
{0.0f, 0.0f},
|
2021-08-28 21:03:06 +02:00
|
|
|
true, ImGuiWindowFlags_MenuBar))
|
|
|
|
{
|
|
|
|
if(ImGui::BeginMenuBar()) {
|
2021-12-02 19:23:28 +01:00
|
|
|
if(ImGui::BeginTable("##MassViewerMenuTable", 4)) {
|
|
|
|
ImGui::TableSetupColumn("##MassName");
|
|
|
|
ImGui::TableSetupColumn("##Spacer", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
ImGui::TableSetupColumn("##Updates");
|
|
|
|
ImGui::TableSetupColumn("##Close", ImGuiTableColumnFlags_WidthFixed);
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
ImGui::Text("M.A.S.S.: %s", (*_currentMass->name()).c_str());
|
|
|
|
drawTooltip(_currentMass->filename().c_str());
|
|
|
|
|
|
|
|
ImGui::TableSetColumnIndex(2);
|
|
|
|
if(_currentMass->dirty()) {
|
|
|
|
ImGui::TextUnformatted("External changes detected");
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
|
|
|
|
_currentMass->refreshValues();
|
|
|
|
_currentMass->setDirty(false);
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = false;
|
|
|
|
_stylesDirty = false;
|
|
|
|
_eyeFlareDirty = false;
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableSetColumnIndex(3);
|
|
|
|
if(ImGui::SmallButton(ICON_FA_TIMES)) {
|
|
|
|
current_weapon = nullptr;
|
|
|
|
_currentMass = nullptr;
|
|
|
|
_uiState = UiState::MainManager;
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = false;
|
|
|
|
_stylesDirty = false;
|
|
|
|
_eyeFlareDirty = false;
|
|
|
|
_selectedArmourDecals = Containers::StaticArray<38, Int>{ValueInit};
|
|
|
|
_selectedArmourAccessories = Containers::StaticArray<38, Int>{ValueInit};
|
|
|
|
_selectedWeaponPart = 0;
|
|
|
|
_selectedWeaponDecal = 0;
|
|
|
|
_selectedWeaponAccessory = 0;
|
|
|
|
};
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
2021-08-28 21:03:06 +02:00
|
|
|
ImGui::EndMenuBar();
|
|
|
|
}
|
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
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(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::TextWrapped("Real-time updates are disabled on this screen.");
|
|
|
|
|
|
|
|
if(_currentMass) {
|
|
|
|
if(ImGui::BeginTabBar("##MassTabBar")) {
|
|
|
|
if(ImGui::BeginTabItem("Frame")) {
|
|
|
|
drawFrameInfo();
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::BeginTabItem("Custom frame styles")) {
|
|
|
|
drawCustomFrameStyles();
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::BeginTabItem("Armour parts")) {
|
|
|
|
drawArmour();
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
2021-08-28 21:03:06 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
if(ImGui::BeginTabItem("Custom armour styles")) {
|
|
|
|
drawCustomArmourStyles();
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::BeginTabItem("Weapons (WIP)")) {
|
|
|
|
drawWeapons();
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!_currentMass->demo() && ImGui::BeginTabItem("Global styles")) {
|
|
|
|
drawGlobalStyles();
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::BeginTabItem("Tuning (WIP)")) {
|
|
|
|
drawTuning();
|
|
|
|
ImGui::EndTabItem();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTabBar();
|
|
|
|
}
|
2021-08-28 21:03:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::End();
|
|
|
|
}
|
2021-08-28 21:03:06 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
void SaveTool::drawFrameInfo() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!ImGui::BeginChild("##FrameInfo")) {
|
|
|
|
ImGui::EndChild();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
|
|
|
if(ImGui::BeginChild("##JointSliders", {(ImGui::GetContentRegionAvailWidth() / 2.0f) - (ImGui::GetStyle().WindowPadding.x / 2.0f), 300.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
2021-08-28 21:03:06 +02:00
|
|
|
if(ImGui::BeginMenuBar()) {
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::TextUnformatted("Joint sliders");
|
|
|
|
|
2021-08-28 21:03:06 +02:00
|
|
|
ImGui::EndMenuBar();
|
|
|
|
}
|
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
drawJointSliders();
|
2021-08-28 21:03:06 +02:00
|
|
|
}
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
if(ImGui::BeginChild("##FrameStyles", {(ImGui::GetContentRegionAvailWidth() / 2.0f) - (ImGui::GetStyle().WindowPadding.x / 2.0f), 0.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
|
|
|
if(ImGui::BeginMenuBar()) {
|
|
|
|
ImGui::TextUnformatted("Frame styles");
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::EndMenuBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
drawFrameStyles();
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::EndChild();
|
|
|
|
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
if(ImGui::BeginChild("##EyeFlare", {0.0f, 0.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
|
|
|
if(ImGui::BeginMenuBar()) {
|
|
|
|
ImGui::TextUnformatted("Eye flare colour");
|
|
|
|
drawHelpMarker("Right-click the picker for more options.", 250.0f);
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::EndMenuBar();
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
drawEyeColourPicker();
|
|
|
|
}
|
|
|
|
ImGui::EndChild();
|
2021-09-27 17:54:30 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::EndChild();
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawJointSliders() {
|
2021-12-02 19:23:28 +01:00
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
2021-09-27 17:54:30 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##NeckSlider", &_currentMass->jointSliders().neck, 0.0f, 1.0f)) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Body");
|
|
|
|
ImGui::TableSetColumnIndex(1);
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##BodySlider", &_currentMass->jointSliders().body, 0.0f, 1.0f)) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Shoulders");
|
|
|
|
ImGui::TableSetColumnIndex(1);
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##ShouldersSlider", &_currentMass->jointSliders().shoulders, 0.0f, 1.0f)) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Hips");
|
|
|
|
ImGui::TableSetColumnIndex(1);
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##HipsSlider", &_currentMass->jointSliders().hips, 0.0f, 1.0f)) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Arms");
|
|
|
|
ImGui::TableSetColumnIndex(1);
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{2.0f, 1.0f});
|
|
|
|
if(ImGui::BeginTable("##UpperLowerArmsLayoutTable", 2)) {
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::TableSetupColumn("##UpperArms", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
ImGui::TableSetupColumn("##LowerArms", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##UpperArmsSlider", &_currentMass->jointSliders().upperArms, 0.0f, 1.0f, "Upper: %.3f")) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::TableNextColumn();
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##LowerArmsSlider", &_currentMass->jointSliders().lowerArms, 0.0f, 1.0f, "Lower: %.3f")) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::PopStyleVar();
|
2021-09-27 17:54:30 +02:00
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Legs");
|
|
|
|
ImGui::TableSetColumnIndex(1);
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{2.0f, 1.0f});
|
|
|
|
if(ImGui::BeginTable("##UpperLowerLegsLayoutTable", 2)) {
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::TableSetupColumn("##UpperLegs", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
ImGui::TableSetupColumn("##LowerLegs", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##UpperLegsSlider", &_currentMass->jointSliders().upperLegs, 0.0f, 1.0f, "Upper: %.3f")) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::TableNextColumn();
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SetNextItemWidth(-1.0f);
|
|
|
|
if(ImGui::SliderFloat("##LowerLegsSlider", &_currentMass->jointSliders().lowerLegs, 0.0f, 1.0f, "Lower: %.3f")) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = true;
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::PopStyleVar();
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
if(!_jointsDirty) {
|
2021-12-02 19:23:28 +01:00
|
|
|
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->writeJointSliders()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Error: " + Mass::lastError());
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = false;
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
2021-12-02 19:23:28 +01:00
|
|
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
|
|
|
_currentMass->getJointSliders();
|
2022-01-14 13:22:51 +01:00
|
|
|
_jointsDirty = false;
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
void SaveTool::drawFrameStyles() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
2021-09-27 17:54:30 +02:00
|
|
|
return;
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
for(Int i = 0; i < 4; i++) {
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::Text("Slot %d:", i + 1);
|
2021-12-02 19:23:28 +01:00
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::SameLine();
|
2021-12-02 19:23:28 +01:00
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::PushID(i);
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
if(ImGui::BeginCombo("##Style", getStyleName(_currentMass->frameStyles()[i], _currentMass->frameCustomStyles()))) {
|
2021-09-27 17:54:30 +02:00
|
|
|
for(const auto& style : style_names) {
|
2021-12-02 19:23:28 +01:00
|
|
|
if(ImGui::Selectable(getStyleName(style.first, _currentMass->frameCustomStyles()), _currentMass->frameStyles()[i] == style.first)) {
|
|
|
|
_currentMass->frameStyles()[i] = style.first;
|
2022-01-14 13:22:51 +01:00
|
|
|
_stylesDirty = true;
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
2021-12-02 19:23:28 +01:00
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::PopID();
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
if(!_stylesDirty) {
|
2021-12-02 19:23:28 +01:00
|
|
|
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->writeFrameStyles()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Error: " + Mass::lastError());
|
|
|
|
}
|
2022-01-14 13:22:51 +01:00
|
|
|
_stylesDirty = false;
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
|
|
|
_currentMass->getFrameStyles();
|
2022-01-14 13:22:51 +01:00
|
|
|
_stylesDirty = false;
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawEyeColourPicker() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return;
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
if(ImGui::ColorPicker3("##EyeFlarePicker", &_currentMass->eyeFlareColour().x())) {
|
2022-01-14 13:22:51 +01:00
|
|
|
_eyeFlareDirty = true;
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
2021-09-27 17:54:30 +02:00
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
if(!_eyeFlareDirty) {
|
2021-12-02 19:23:28 +01:00
|
|
|
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->writeEyeFlareColour()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Error writing the eye flare colour.");
|
|
|
|
}
|
2022-01-14 13:22:51 +01:00
|
|
|
_eyeFlareDirty = false;
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
|
|
|
_currentMass->getEyeFlareColour();
|
2022-01-14 13:22:51 +01:00
|
|
|
_eyeFlareDirty = false;
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-27 17:54:30 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
void SaveTool::drawCustomFrameStyles() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return;
|
|
|
|
}
|
2021-09-27 17:54:30 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
if(!ImGui::BeginChild("##FrameStyles")) {
|
|
|
|
ImGui::EndChild();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TextWrapped("In-game values are multiplied by 100. For example, 0.500 here is equal to 50 in-game.");
|
|
|
|
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->frameCustomStyles().size(); i++) {
|
|
|
|
ImGui::PushID(i);
|
|
|
|
DCSResult result;
|
|
|
|
result = drawCustomStyle(_currentMass->frameCustomStyles()[i]);
|
|
|
|
switch(result) {
|
|
|
|
case DCS_ResetStyle:
|
|
|
|
_currentMass->getFrameCustomStyles();
|
|
|
|
break;
|
|
|
|
case DCS_Save:
|
|
|
|
_currentMass->writeFrameCustomStyle(i);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::PopID();
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::EndChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawArmour() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset all")) {
|
|
|
|
_currentMass->getArmourParts();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!ImGui::BeginChild("##ArmourParts")) {
|
|
|
|
ImGui::EndChild();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->armourParts().size(); i++) {
|
|
|
|
ImGui::PushID(i);
|
|
|
|
|
|
|
|
auto& part = _currentMass->armourParts()[i];
|
|
|
|
|
|
|
|
static char header[129] = {'\0'};
|
|
|
|
|
|
|
|
std::memset(header, '\0', 129);
|
|
|
|
|
|
|
|
if(armour_sets.find(part.id) != armour_sets.cend()) {
|
|
|
|
std::snprintf(header, 128, "%s: %s###%s", armour_slots.at(part.slot), armour_sets.at(part.id).name, part.slot.c_str());
|
2021-09-27 17:54:30 +02:00
|
|
|
}
|
|
|
|
else {
|
2021-12-02 19:23:28 +01:00
|
|
|
std::snprintf(header, 128, "%s: %i###%s", armour_slots.at(part.slot), part.id, part.slot.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::CollapsingHeader(header)) {
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
|
|
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth() * 0.491f);
|
|
|
|
if(ImGui::BeginListBox("##ChangePart")) {
|
|
|
|
if(std::strncmp("Neck", armour_slots.at(part.slot), 4) != 0) {
|
|
|
|
for(auto& set : armour_sets) {
|
|
|
|
if(ImGui::Selectable(set.second.name, set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
|
|
|
part.id = set.first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for(auto& set : armour_sets) {
|
|
|
|
if(!set.second.neck_compatible) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::Selectable(set.second.name, set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) {
|
|
|
|
part.id = set.first;
|
|
|
|
}
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::EndListBox();
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
2021-09-27 17:54:30 +02:00
|
|
|
ImGui::SameLine();
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
|
2021-09-10 16:16:21 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::SameLine();
|
2021-09-27 17:54:30 +02:00
|
|
|
|
2021-12-02 19:23:28 +01:00
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
|
|
|
ImGui::TextUnformatted("Styles:");
|
|
|
|
|
|
|
|
for(Int j = 0; j < 4; j++) {
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::Text("Slot %d:", j + 1);
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::PushID(j);
|
|
|
|
|
|
|
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvailWidth() - 2.0f);
|
|
|
|
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[j], _currentMass->armourCustomStyles()))) {
|
|
|
|
for(const auto& style : style_names) {
|
|
|
|
if(ImGui::Selectable(getStyleName(style.first, _currentMass->armourCustomStyles()), part.styles[j] == style.first)) {
|
|
|
|
part.styles[j] = style.first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
ImGui::PushID("Decal");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Showing/editing decal");
|
|
|
|
for(UnsignedLong j = 0; j < part.demoDecals; j++) {
|
|
|
|
ImGui::SameLine();
|
2022-01-14 13:22:51 +01:00
|
|
|
ImGui::RadioButton(std::to_string(j + 1).c_str(), &_selectedArmourDecals[i], j);
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
drawDecalEditor(part.decals[_selectedArmourDecals[i]]);
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
|
|
|
|
if(!_currentMass->demo()) {
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
ImGui::PushID("Accessory");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Showing/editing accessory");
|
|
|
|
for(UnsignedInt j = 0; j < part.accessories.size(); j++) {
|
|
|
|
ImGui::SameLine();
|
2022-01-14 13:22:51 +01:00
|
|
|
ImGui::RadioButton(std::string{char(65 + j)}.c_str(), &_selectedArmourAccessories[i], j);
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
drawAccessoryEditor(part.accessories[_selectedArmourAccessories[i]], _currentMass->armourCustomStyles());
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
|
|
|
_currentMass->writeArmourPart(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawCustomArmourStyles() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!ImGui::BeginChild("##ArmourStyles")) {
|
|
|
|
ImGui::EndChild();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TextWrapped("In-game values are multiplied by 100. For example, 0.500 here is equal to 50 in-game.");
|
|
|
|
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->armourCustomStyles().size(); i++) {
|
|
|
|
ImGui::PushID(i);
|
|
|
|
DCSResult result;
|
|
|
|
result = drawCustomStyle(_currentMass->armourCustomStyles()[i]);
|
|
|
|
switch(result) {
|
|
|
|
case DCS_ResetStyle:
|
|
|
|
_currentMass->getArmourCustomStyles();
|
|
|
|
break;
|
|
|
|
case DCS_Save:
|
|
|
|
_currentMass->writeArmourCustomStyle(i);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawWeapons() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
current_weapon = nullptr;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!ImGui::BeginTable("##WeaponsList", 1, ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersOuter|ImGuiTableFlags_BordersInnerH, {ImGui::GetContentRegionAvailWidth() * 0.2f, 0.0f})) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableSetupColumn("Weapon");
|
|
|
|
|
|
|
|
int id = 0;
|
|
|
|
|
|
|
|
#define weapcat(header, array, payload_type, payload_tooltip) \
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers); \
|
|
|
|
ImGui::TableNextColumn(); \
|
|
|
|
ImGui::TextUnformatted(header); \
|
|
|
|
\
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->array().size(); i++) { \
|
|
|
|
auto& weapon = _currentMass->array()[i]; \
|
|
|
|
\
|
|
|
|
ImGui::TableNextRow(); \
|
|
|
|
ImGui::TableNextColumn(); \
|
|
|
|
ImGui::PushID(id); \
|
|
|
|
if(ImGui::Selectable(weapon.name.c_str(), current_weapon == &weapon)) { \
|
|
|
|
current_weapon = &weapon; \
|
|
|
|
} \
|
|
|
|
if(ImGui::BeginDragDropSource()) { \
|
|
|
|
ImGui::SetDragDropPayload(payload_type, &i, sizeof(UnsignedInt)); \
|
|
|
|
ImGui::Text(payload_tooltip " %i - %s", i + 1, weapon.name.c_str()); \
|
|
|
|
ImGui::EndDragDropSource(); \
|
|
|
|
} \
|
|
|
|
if(ImGui::BeginDragDropTarget()) { \
|
|
|
|
if(const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(payload_type)) { \
|
|
|
|
int index = *static_cast<int*>(payload->Data); \
|
|
|
|
\
|
|
|
|
if(current_weapon == &_currentMass->array()[index]) { \
|
|
|
|
current_weapon = &_currentMass->array()[i]; \
|
|
|
|
} \
|
|
|
|
else if (current_weapon == &_currentMass->array()[i]) { \
|
|
|
|
current_weapon = &_currentMass->array()[index]; \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
std::swap(_currentMass->array()[index], _currentMass->array()[i]); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
ImGui::EndDragDropTarget(); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
ImGui::PopID(); \
|
|
|
|
id++; \
|
|
|
|
\
|
|
|
|
if(weapon.attached == true) { \
|
|
|
|
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, 0x1F008CFFu); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
weapcat("Melee weapons", meleeWeapons, "MeleeWeapon", "Melee weapon")
|
|
|
|
weapcat("Shield", shields, "Shield", "Shield")
|
|
|
|
weapcat("Bullet shooters", bulletShooters, "BShooter", "Bullet shooter")
|
|
|
|
weapcat("Energy shooters", energyShooters, "EShooter", "Energy shooter")
|
|
|
|
weapcat("Bullet launchers", bulletLaunchers, "BLauncher", "Bullet launcher")
|
|
|
|
weapcat("Energy launchers", energyLaunchers, "ELauncher", "Energy launcher")
|
|
|
|
|
|
|
|
#undef weapcat
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
if(!current_weapon) {
|
|
|
|
ImGui::TextUnformatted("No weapon selected.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
|
|
|
|
const Float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
|
|
|
|
if(!ImGui::BeginChild("##WeaponChild", {0.0f, -footer_height_to_reserve})) {
|
|
|
|
ImGui::EndChild();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
drawWeaponEditor(*current_weapon);
|
|
|
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
if(drawUnsafeWidget([](){ return ImGui::Button(ICON_FA_SAVE " Save changes to weapon category"); })) {
|
|
|
|
if(current_weapon->type == "enuWeaponTypes::NewEnumerator0") {
|
|
|
|
if(!_currentMass->writeMeleeWeapons()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Couldn't save melee weapons");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator5") {
|
|
|
|
if(!_currentMass->writeShields()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Couldn't save shields");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator1") {
|
|
|
|
if(!_currentMass->writeBulletShooters()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Couldn't save bullet shooters");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator2") {
|
|
|
|
if(!_currentMass->writeEnergyShooters()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Couldn't save energy shooters");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator3") {
|
|
|
|
if(!_currentMass->writeBulletLaunchers()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Couldn't save bullet launchers");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator4") {
|
|
|
|
if(!_currentMass->writeEnergyLaunchers()) {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Couldn't save energy launchers");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset weapon category")) {
|
|
|
|
if(current_weapon->type == "enuWeaponTypes::NewEnumerator0") {
|
|
|
|
_currentMass->getMeleeWeapons();
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator5") {
|
|
|
|
_currentMass->getShields();
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator1") {
|
|
|
|
_currentMass->getBulletShooters();
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator2") {
|
|
|
|
_currentMass->getEnergyShooters();
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator3") {
|
|
|
|
_currentMass->getBulletLaunchers();
|
|
|
|
}
|
|
|
|
else if(current_weapon->type == "enuWeaponTypes::NewEnumerator4") {
|
|
|
|
_currentMass->getEnergyLaunchers();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_queue.addToast(Toast::Type::Error, "Unknown weapon type");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndGroup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawWeaponEditor(Weapon& weapon) {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid || !current_weapon) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::Text("%s: %s", weapon_types.at(weapon.type), weapon.name.c_str());
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
static Containers::StaticArray<33, char> name_buf{ValueInit};
|
|
|
|
if(ImGui::Button(ICON_FA_EDIT " Rename")) {
|
|
|
|
for(auto& c : name_buf) {
|
|
|
|
c = '\0';
|
|
|
|
}
|
|
|
|
std::strncpy(name_buf.data(), weapon.name.c_str(), 32);
|
|
|
|
ImGui::OpenPopup("name_edit");
|
|
|
|
}
|
|
|
|
if(drawRenamePopup(name_buf)) {
|
|
|
|
weapon.name = name_buf.data();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Equipped:");
|
|
|
|
|
|
|
|
if(weapon.type != "enuWeaponTypes::NewEnumerator5") {
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Damage type:");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(weapon.type == "enuWeaponTypes::NewEnumerator0") {
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Dual-wield:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Custom effect mode:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Custom effect colour:");
|
|
|
|
}
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::Checkbox("##EquippedCheckbox", &weapon.attached);
|
|
|
|
|
|
|
|
if(weapon.type != "enuWeaponTypes::NewEnumerator5") {
|
|
|
|
if(weapon.type == "enuWeaponTypes::NewEnumerator0" &&
|
|
|
|
ImGui::RadioButton("Physical##NoElement", weapon.damageType == "enuDamageProperty::NewEnumerator0"))
|
|
|
|
{
|
|
|
|
weapon.damageType = "enuDamageProperty::NewEnumerator0";
|
|
|
|
}
|
|
|
|
else if((weapon.type == "enuWeaponTypes::NewEnumerator1" || weapon.type == "enuWeaponTypes::NewEnumerator3") &&
|
|
|
|
ImGui::RadioButton("Piercing##NoElement", weapon.damageType == "enuDamageProperty::NewEnumerator1"))
|
|
|
|
{
|
|
|
|
weapon.damageType = "enuDamageProperty::NewEnumerator1";
|
|
|
|
}
|
|
|
|
else if((weapon.type == "enuWeaponTypes::NewEnumerator2" || weapon.type == "enuWeaponTypes::NewEnumerator4") &&
|
|
|
|
ImGui::RadioButton("Plasma##NoElement", weapon.damageType == "enuDamageProperty::NewEnumerator5"))
|
|
|
|
{
|
|
|
|
weapon.damageType = "enuDamageProperty::NewEnumerator5";
|
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::RadioButton("Heat##Heat", weapon.damageType == "enuDamageProperty::NewEnumerator2")) {
|
|
|
|
weapon.damageType = "enuDamageProperty::NewEnumerator2";
|
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::RadioButton("Freeze##Freeze", weapon.damageType == "enuDamageProperty::NewEnumerator3")) {
|
|
|
|
weapon.damageType = "enuDamageProperty::NewEnumerator3";
|
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::RadioButton("Shock##Shock", weapon.damageType == "enuDamageProperty::NewEnumerator4")) {
|
|
|
|
weapon.damageType = "enuDamageProperty::NewEnumerator4";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(weapon.type == "enuWeaponTypes::NewEnumerator0") {
|
|
|
|
ImGui::Checkbox("##DualWield", &weapon.dualWield);
|
|
|
|
|
|
|
|
if(ImGui::RadioButton("Default##Default", weapon.effectColourMode == "enuWeaponEffectColorMode::NewEnumerator0")) {
|
|
|
|
weapon.effectColourMode = "enuWeaponEffectColorMode::NewEnumerator0";
|
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::RadioButton("Custom##Custom", weapon.effectColourMode == "enuWeaponEffectColorMode::NewEnumerator1")) {
|
|
|
|
weapon.effectColourMode = "enuWeaponEffectColorMode::NewEnumerator1";
|
|
|
|
}
|
|
|
|
|
|
|
|
bool custom_effect = (weapon.effectColourMode == "enuWeaponEffectColorMode::NewEnumerator1");
|
|
|
|
if(!custom_effect) {
|
|
|
|
ImGui::BeginDisabled();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::ColorEdit3("##CustomEffectColourPicker", &weapon.effectColour.x(), ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_Float);
|
|
|
|
|
|
|
|
if(!custom_effect) {
|
|
|
|
ImGui::EndDisabled();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
if(ImGui::CollapsingHeader("Weapon parts")) {
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Viewing/editing part:");
|
|
|
|
for(Int i = 0; UnsignedLong(i) < weapon.parts.size(); i++) {
|
2022-01-14 13:22:51 +01:00
|
|
|
if(UnsignedLong(_selectedWeaponPart) >= weapon.parts.size()) {
|
|
|
|
_selectedWeaponPart = 0;
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
2022-01-14 13:22:51 +01:00
|
|
|
ImGui::RadioButton(std::to_string(i + 1).c_str(), &_selectedWeaponPart, i);
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
auto& part = weapon.parts[_selectedWeaponPart];
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
ImGui::Text("ID: %i", part.id);
|
|
|
|
|
|
|
|
if(ImGui::BeginChild("##PartDetails", {0.0f, 0.0f}, true)) {
|
|
|
|
ImGui::TextUnformatted("Styles:");
|
|
|
|
|
|
|
|
for(Int i = 0; i < 4; i++) {
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::Text("Slot %d:", i + 1);
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::PushID(i);
|
|
|
|
|
|
|
|
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[i], weapon.customStyles))) {
|
|
|
|
for(const auto& style: style_names) {
|
|
|
|
if(ImGui::Selectable(getStyleName(style.first, weapon.customStyles),
|
|
|
|
part.styles[i] == style.first)) {
|
|
|
|
part.styles[i] = style.first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
ImGui::PushID("Decal");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Showing/editing decal");
|
|
|
|
for(UnsignedLong i = 0; i < part.demoDecals; i++) {
|
|
|
|
ImGui::SameLine();
|
2022-01-14 13:22:51 +01:00
|
|
|
ImGui::RadioButton(std::to_string(i + 1).c_str(), &_selectedWeaponDecal, i);
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
drawDecalEditor(part.decals[_selectedWeaponDecal]);
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
|
|
|
|
if(_currentMass->demo() == false) {
|
|
|
|
ImGui::Separator();
|
|
|
|
|
|
|
|
ImGui::PushID("Accessory");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Showing/editing accessory");
|
|
|
|
for(UnsignedLong i = 0; i < part.accessories.size(); i++) {
|
|
|
|
ImGui::SameLine();
|
2022-01-14 13:22:51 +01:00
|
|
|
ImGui::RadioButton(std::string{char(65 + i)}.c_str(), &_selectedWeaponAccessory, i);
|
2021-12-02 19:23:28 +01:00
|
|
|
}
|
|
|
|
|
2022-01-14 13:22:51 +01:00
|
|
|
drawAccessoryEditor(part.accessories[_selectedWeaponAccessory], weapon.customStyles);
|
2021-12-02 19:23:28 +01:00
|
|
|
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawGlobalStyles() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!ImGui::BeginChild("##GlobalStyles")) {
|
|
|
|
ImGui::EndChild();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TextWrapped("In-game values are multiplied by 100. For example, 0.500 here is equal to 50 in-game.");
|
|
|
|
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->globalStyles().size(); i++) {
|
|
|
|
ImGui::PushID(i);
|
|
|
|
DCSResult result;
|
|
|
|
result = drawCustomStyle(_currentMass->globalStyles()[i]);
|
|
|
|
switch(result) {
|
|
|
|
case DCS_ResetStyle:
|
|
|
|
_currentMass->getGlobalStyles();
|
|
|
|
break;
|
|
|
|
case DCS_Save:
|
|
|
|
_currentMass->writeGlobalStyle(i);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
ImGui::PopID();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawTuning() {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!ImGui::BeginTable("##TuningTable", 3)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableSetupColumn("##EngineColumn");
|
|
|
|
ImGui::TableSetupColumn("##OSColumn");
|
|
|
|
ImGui::TableSetupColumn("##ArchitectureColumn");
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
|
|
|
ImGui::TableSetColumnIndex(0);
|
|
|
|
|
|
|
|
if(ImGui::BeginTable("##EngineTable", 1, ImGuiTableFlags_Borders)) {
|
|
|
|
ImGui::TableSetupColumn("##Engine");
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted("Engine");
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%i", _currentMass->engine());
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted("Gears");
|
|
|
|
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->gears().size(); i++) {
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%i", _currentMass->gears()[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableSetColumnIndex(1);
|
|
|
|
|
|
|
|
if(ImGui::BeginTable("##OSTable", 1, ImGuiTableFlags_Borders)) {
|
|
|
|
ImGui::TableSetupColumn("##OS");
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted("OS");
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%i", _currentMass->os());
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted("Modules");
|
|
|
|
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->modules().size(); i++) {
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%i", _currentMass->modules()[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::TableSetColumnIndex(2);
|
|
|
|
|
|
|
|
if(ImGui::BeginTable("##ArchTable", 1, ImGuiTableFlags_Borders)) {
|
|
|
|
ImGui::TableSetupColumn("##Arch");
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted("Architecture");
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%i", _currentMass->architecture());
|
|
|
|
|
|
|
|
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::TextUnformatted("Techs");
|
|
|
|
|
|
|
|
for(UnsignedInt i = 0; i < _currentMass->techs().size(); i++) {
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
ImGui::Text("%i", _currentMass->techs()[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto SaveTool::drawCustomStyle(CustomStyle& style) -> DCSResult {
|
|
|
|
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
|
|
|
|
return DCS_Fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {8.0f, 0.0f});
|
|
|
|
|
|
|
|
Containers::ScopeGuard guard{[]{ ImGui::PopStyleVar(); }};
|
|
|
|
|
|
|
|
DCSResult return_value = DCS_Fail;
|
|
|
|
|
|
|
|
if(!ImGui::BeginChild("##CustomStyle", {0.0f, 244.0f}, true, ImGuiWindowFlags_MenuBar)) {
|
|
|
|
ImGui::EndChild();
|
|
|
|
return DCS_Fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::BeginMenuBar()) {
|
|
|
|
ImGui::TextUnformatted(style.name.c_str());
|
|
|
|
|
|
|
|
static Containers::StaticArray<33, char> name_buf{ValueInit};
|
|
|
|
if(ImGui::SmallButton(ICON_FA_EDIT " Rename")) {
|
|
|
|
for(auto& c : name_buf) {
|
|
|
|
c = '\0';
|
|
|
|
}
|
|
|
|
std::strncpy(name_buf.data(), style.name.c_str(), 32);
|
|
|
|
ImGui::OpenPopup("name_edit");
|
|
|
|
}
|
|
|
|
if(drawRenamePopup(name_buf)) {
|
|
|
|
style.name = name_buf.data();
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndMenuBar();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ImGui::BeginTable("##StyleTable", 2, ImGuiTableFlags_BordersInnerV)) {
|
|
|
|
ImGui::TableSetupColumn("##Colour", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
ImGui::TableSetupColumn("##Pattern", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Colour:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Metallic:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Gloss:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Glow:");
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::ColorEdit3("##Picker", &style.colour.r());
|
|
|
|
ImGui::SameLine();
|
|
|
|
drawHelpMarker("Right-click for more option, click the coloured square for the full picker.");
|
|
|
|
|
|
|
|
ImGui::SetNextItemWidth(-FLT_MIN);
|
|
|
|
ImGui::SliderFloat("##SliderMetallic", &style.metallic, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
ImGui::SetNextItemWidth(-FLT_MIN);
|
|
|
|
ImGui::SliderFloat("##SliderGloss", &style.gloss,0.0f, 1.0f);
|
|
|
|
|
|
|
|
ImGui::Checkbox("##Glow", &style.glow);
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Pattern:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Opacity:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("X offset:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Y offset:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Rotation:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Scale:");
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::Text("%i", style.patternId);
|
|
|
|
ImGui::PushItemWidth(-FLT_MIN);
|
|
|
|
ImGui::SliderFloat("##SliderOpacity", &style.opacity, 0.0f, 1.0f);
|
|
|
|
ImGui::SliderFloat("##SliderOffsetX", &style.offset.x(), 0.0f, 1.0f);
|
|
|
|
ImGui::SliderFloat("##SliderOffsetY", &style.offset.y(), 0.0f, 1.0f);
|
|
|
|
ImGui::SliderFloat("##SliderRotation", &style.rotation, 0.0f, 1.0f);
|
|
|
|
ImGui::SliderFloat("##SliderScale", &style.scale, 0.0f, 1.0f);
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
|
|
|
|
return_value = DCS_Save;
|
|
|
|
}
|
|
|
|
ImGui::SameLine();
|
|
|
|
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
|
|
|
|
return_value = DCS_ResetStyle;
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
|
|
|
return return_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawDecalEditor(Decal& decal) {
|
|
|
|
ImGui::Text("ID: %i", decal.id);
|
|
|
|
|
|
|
|
if(ImGui::BeginTable("##DecalTable", 2, ImGuiTableFlags_BordersInnerV)) {
|
|
|
|
ImGui::TableSetupColumn("##Normal", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
ImGui::TableSetupColumn("##Advanced", ImGuiTableColumnFlags_WidthStretch);
|
|
|
|
|
|
|
|
ImGui::TableNextRow();
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Colour:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Offset:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Rotation:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Scale:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Flip X:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Surface wrap:");
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::ColorEdit3("##Picker", &decal.colour.r());
|
|
|
|
ImGui::SameLine();
|
|
|
|
drawHelpMarker("Right-click for more option, click the coloured square for the full picker.");
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());
|
|
|
|
ImGui::SliderFloat("##OffsetX", &decal.offset.x(), 0.0f, 1.0f, "X: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::SliderFloat("##OffsetY", &decal.offset.y(), 0.0f, 1.0f, "Y: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine();
|
|
|
|
drawHelpMarker("0.0 = -100 in-game\n1.0 = 100 in-game");
|
|
|
|
|
|
|
|
ImGui::SliderFloat("##Rotation", &decal.rotation, 0.0f, 1.0f);
|
|
|
|
ImGui::SameLine();
|
|
|
|
drawHelpMarker("0.0 = 0 in-game\n1.0 = 360 in-game");
|
|
|
|
|
|
|
|
ImGui::SliderFloat("##Scale", &decal.scale, 0.0f, 1.0f);
|
|
|
|
ImGui::SameLine();
|
|
|
|
drawHelpMarker("0.0 = 1 in-game\n1.0 = 100 in-game");
|
|
|
|
|
|
|
|
ImGui::Checkbox("##Flip", &decal.flip);
|
|
|
|
|
|
|
|
ImGui::Checkbox("##Wrap", &decal.wrap);
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
|
|
|
|
|
|
|
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::TextUnformatted("Advanced settings. Touch these at your own risk.");
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Position:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("U axis:");
|
|
|
|
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("V axis:");
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::DragFloat("##PosX", &decal.position.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##PosY", &decal.position.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##PosZ", &decal.position.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::DragFloat("##UX", &decal.uAxis.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##UY", &decal.uAxis.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##UZ", &decal.uAxis.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::DragFloat("##VX", &decal.vAxis.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##VY", &decal.vAxis.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##VZ", &decal.vAxis.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTool::drawAccessoryEditor(Accessory& accessory, Containers::ArrayView<CustomStyle> style_view) {
|
|
|
|
if(accessory.id < 1) {
|
|
|
|
ImGui::TextUnformatted("Accessory: <none>");
|
|
|
|
}
|
|
|
|
else if(accessories.find(accessory.id) != accessories.cend()) {
|
|
|
|
ImGui::Text("Accessory #%i - %s", accessory.id, accessories.at(accessory.id));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ImGui::Text("Accessory #%i", accessory.id);
|
|
|
|
drawTooltip("WARNING: accessory mapping is a WIP.");
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SAVETOOL_DEBUG_BUILD
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().FramePadding.x * 5.0f);
|
|
|
|
ImGui::Text("Attach index: %i", accessory.attachIndex);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Styles:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Base position:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Position offset:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Base rotation:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Rotation offset:");
|
|
|
|
ImGui::AlignTextToFramePadding();
|
|
|
|
ImGui::TextUnformatted("Scale:");
|
|
|
|
ImGui::EndGroup();
|
|
|
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
|
|
|
ImGui::BeginGroup();
|
|
|
|
ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());
|
|
|
|
if(ImGui::BeginCombo("##Style1", getStyleName(accessory.styles[0], style_view))) {
|
|
|
|
for(const auto& style : style_names) {
|
|
|
|
if(ImGui::Selectable(getStyleName(style.first, style_view), accessory.styles[0] == style.first)) {
|
|
|
|
accessory.styles[0] = style.first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
if(ImGui::BeginCombo("##Style2", getStyleName(accessory.styles[1], style_view))) {
|
|
|
|
for(const auto& style : style_names) {
|
|
|
|
if(ImGui::Selectable(getStyleName(style.first, style_view), accessory.styles[1] == style.first)) {
|
|
|
|
accessory.styles[1] = style.first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
}
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::DragFloat("##PosX", &accessory.relativePosition.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##PosY", &accessory.relativePosition.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##PosZ", &accessory.relativePosition.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::SliderFloat("##PosOffsetX", &accessory.relativePositionOffset.x(), -500.0f, +500.0f, "X: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::SliderFloat("##PosOffsetY", &accessory.relativePositionOffset.y(), -500.0f, +500.0f, "Y: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::SliderFloat("##PosOffsetZ", &accessory.relativePositionOffset.z(), -500.0f, +500.0f, "Z: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine();
|
|
|
|
drawHelpMarker("+/-500.0 = +/-250 in-game");
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::DragFloat("##RotX", &accessory.relativeRotation.x(), 1.0f, -FLT_MAX, +FLT_MAX, "Roll: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##RotY", &accessory.relativeRotation.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Yaw: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::DragFloat("##RotZ", &accessory.relativeRotation.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Pitch: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::SliderFloat("##RotOffsetX", &accessory.relativeRotationOffset.x(), -180.0f, +180.0f, "Roll: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::SliderFloat("##RotOffsetY", &accessory.relativeRotationOffset.y(), -180.0f, +180.0f, "Yaw: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::SliderFloat("##RotOffsetZ", &accessory.relativeRotationOffset.z(), -180.0f, +180.0f, "Pitch: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
|
|
ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth());
|
|
|
|
ImGui::SliderFloat("##ScaleX", &accessory.localScale.x(), -3.0f, +3.0f, "X: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::SliderFloat("##ScaleY", &accessory.localScale.y(), -3.0f, +3.0f, "Y: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
|
|
|
|
ImGui::SliderFloat("##ScaleZ", &accessory.localScale.z(), -3.0f, +3.0f, "Z: %.3f");
|
|
|
|
ImGui::PopItemWidth();
|
|
|
|
ImGui::SameLine();
|
|
|
|
drawHelpMarker("+/-3.0 = +/-150 in-game");
|
|
|
|
ImGui::EndGroup();
|
|
|
|
}
|
|
|
|
|
|
|
|
auto SaveTool::getStyleName(Int id, Containers::ArrayView<CustomStyle> view) -> const char* {
|
|
|
|
if(id >= 0 && id <= 15) {
|
|
|
|
return view[id].name.c_str();
|
|
|
|
}
|
|
|
|
else if(id >= 50 && id <= 65) {
|
|
|
|
return _currentMass->globalStyles()[id - 50].name.c_str();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return style_names.at(id);
|
|
|
|
}
|
2021-09-10 16:16:21 +02:00
|
|
|
}
|