// MassBuilderSaveTool
// Copyright (C) 2021-2024 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 .
#include
#include
#include
#include "../Configuration/Configuration.h"
#include "../FontAwesome/IconsFontAwesome5.h"
#include "../Maps/Accessories.h"
#define STYLENAMES_DEFINITION
#include "../Maps/StyleNames.h"
#include "Application.h"
namespace mbst {
void
Application::drawMassViewer() {
if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
_currentMass = nullptr;
_currentWeapon = 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(ImVec2{Vector2{float(windowSize().x()), float(windowSize().y()) - ImGui::GetItemRectSize().y} / dpiScaling()},
ImGuiCond_Always);
if(!ImGui::Begin("##MassViewer", nullptr,
ImGuiWindowFlags_NoDecoration|ImGuiWindowFlags_NoMove|
ImGuiWindowFlags_NoBackground|ImGuiWindowFlags_NoBringToFrontOnFocus))
{
ImGui::End();
return;
}
if(ImGui::BeginChild("##MassInfo",
{0.0f, 0.0f},
ImGuiChildFlags_Border, ImGuiWindowFlags_MenuBar))
{
if(ImGui::BeginMenuBar()) {
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().data());
drawTooltip(_currentMass->filename());
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);
_jointsDirty = false;
_stylesDirty = false;
_eyeFlareDirty = false;
}
}
ImGui::TableSetColumnIndex(3);
if(ImGui::SmallButton(ICON_FA_TIMES)) {
_currentWeapon = nullptr;
_currentMass = nullptr;
_uiState = UiState::MainManager;
_jointsDirty = false;
_stylesDirty = false;
_eyeFlareDirty = false;
_selectedArmourSlot = Containers::NullOpt;
_selectedArmourDecals = Containers::StaticArray<38, std::int32_t>{ValueInit};
_selectedArmourAccessories = Containers::StaticArray<38, std::int32_t>{ValueInit};
_selectedBLPlacement = 0;
_selectedWeaponPart = 0;
_selectedWeaponDecal = 0;
_selectedWeaponAccessory = 0;
}
ImGui::EndTable();
}
ImGui::EndMenuBar();
}
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")) {
drawArmour();
ImGui::EndTabItem();
}
if(_currentMass->bulletLauncherAttachmentStyle() != GameObjects::BulletLauncherAttachmentStyle::NotFound &&
ImGui::BeginTabItem("Bullet launcher attachment"))
{
drawBLAttachment();
ImGui::EndTabItem();
}
if(ImGui::BeginTabItem("Custom armour styles")) {
drawCustomArmourStyles();
ImGui::EndTabItem();
}
if(ImGui::BeginTabItem("Weapons")) {
drawWeapons();
ImGui::EndTabItem();
}
if(!_currentMass->globalStyles().isEmpty() && ImGui::BeginTabItem("Global styles")) {
drawGlobalStyles();
ImGui::EndTabItem();
}
#ifdef SAVETOOL_DEBUG_BUILD
if(ImGui::BeginTabItem("Tuning (WIP)")) {
drawTuning();
ImGui::EndTabItem();
}
#endif
ImGui::EndTabBar();
}
}
}
ImGui::EndChild();
ImGui::End();
}
void
Application::drawGlobalStyles() {
if(!_currentMass || _currentMass->state() != GameObjects::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(std::uint32_t i = 0; i < _currentMass->globalStyles().size(); i++) {
ImGui::PushID(int(i));
auto result = drawCustomStyle(_currentMass->globalStyles()[i]);
switch(result) {
case DCS_ResetStyle:
_currentMass->getGlobalStyles();
break;
case DCS_Save:
_modifiedBySaveTool = true;
if(!_currentMass->writeGlobalStyle(i)) {
_modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError());
}
break;
default:
break;
}
ImGui::PopID();
}
ImGui::EndChild();
}
void
Application::drawTuning() {
if(!_currentMass || _currentMass->state() != GameObjects::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(std::uint32_t 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(std::uint32_t 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(std::uint32_t i = 0; i < _currentMass->techs().size(); i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%i", _currentMass->techs()[i]);
}
ImGui::EndTable();
}
ImGui::EndTable();
}
Application::DCSResult
Application::drawCustomStyle(GameObjects::CustomStyle& style) {
if(!_currentMass || _currentMass->state() != GameObjects::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", {}, ImGuiChildFlags_Border|ImGuiChildFlags_AutoResizeY,
ImGuiWindowFlags_MenuBar))
{
ImGui::EndChild();
return DCS_Fail;
}
if(ImGui::BeginMenuBar()) {
ImGui::TextUnformatted(style.name.cbegin(), style.name.cend());
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.data(), 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();
drawAlignedText("Colour:");
drawAlignedText("Metallic:");
drawAlignedText("Gloss:");
drawAlignedText("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();
drawAlignedText("Pattern:");
drawAlignedText("Opacity:");
drawAlignedText("X offset:");
drawAlignedText("Y offset:");
drawAlignedText("Rotation:");
drawAlignedText("Scale:");
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup();
drawAlignedText("%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
Application::drawDecalEditor(GameObjects::Decal& decal) {
ImGui::Text("ID: %i", decal.id);
if(ImGui::BeginTable("##DecalTable", conf().advancedMode() ? 2 : 1, ImGuiTableFlags_BordersInnerV)) {
ImGui::TableSetupColumn("##Normal", ImGuiTableColumnFlags_WidthStretch);
if(conf().advancedMode()) {
ImGui::TableSetupColumn("##Advanced", ImGuiTableColumnFlags_WidthStretch);
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::BeginGroup();
drawAlignedText("Colour:");
drawAlignedText("Offset:");
drawAlignedText("Rotation:");
drawAlignedText("Scale:");
drawAlignedText("Flip X:");
drawAlignedText("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();
if(conf().advancedMode()) {
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();
drawAlignedText("Position:");
drawAlignedText("U axis:");
drawAlignedText("V axis:");
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::PushItemWidth(-1.0f);
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::PopItemWidth();
ImGui::EndGroup();
}
ImGui::EndTable();
}
}
void
Application::drawAccessoryEditor(GameObjects::Accessory& accessory, Containers::ArrayView style_view) {
if(accessory.id < 1) {
ImGui::TextUnformatted("Accessory: ");
}
else if(GameData::accessories.find(accessory.id) != GameData::accessories.cend()) {
ImGui::Text("Accessory #%.4i - %s", accessory.id, GameData::accessories.at(accessory.id).name.data());
}
else {
ImGui::Text("Accessory #%i", accessory.id);
drawTooltip("WARNING: accessory mapping is a WIP.");
}
ImGui::SameLine();
static std::int32_t tab = 0;
static Containers::Optional size = Containers::NullOpt;
if(ImGui::SmallButton("Change")) {
ImGui::OpenPopup("##AccessoryPopup");
if(accessory.id >= 3000) {
tab = 3;
}
else if(accessory.id >= 2000) {
tab = 2;
}
else if(accessory.id >= 1000) {
tab = 1;
}
else {
tab = 0;
}
}
if(ImGui::BeginPopup("##AccessoryPopup")) {
static const char* size_labels[] = {
"S",
"M",
"L",
"XL"
};
static const float selectable_width = 90.0f;
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, {0.5f, 0.0f});
if(ImGui::Selectable("Primitives", tab == 0, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
tab = 0;
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
if(ImGui::Selectable("Armours", tab == 1, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
tab = 1;
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
if(ImGui::Selectable("Components", tab == 2, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
tab = 2;
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
if(ImGui::Selectable("Connectors", tab == 3, ImGuiSelectableFlags_DontClosePopups, {selectable_width, 0.0f})) {
tab = 3;
}
ImGui::PopStyleVar();
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, {0.5f, 0.0f});
if(ImGui::Selectable("All", !size, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
size = Containers::NullOpt;
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
if(ImGui::Selectable("S", size && *size == GameData::Accessory::Size::S, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) {
size.emplace();
}
*size = GameData::Accessory::Size::S;
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
if(ImGui::Selectable("M", size && *size == GameData::Accessory::Size::M, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) {
size.emplace();
}
*size = GameData::Accessory::Size::M;
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
if(ImGui::Selectable("L", size && *size == GameData::Accessory::Size::L, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) {
size.emplace();
}
*size = GameData::Accessory::Size::L;
}
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine();
if(ImGui::Selectable("XL", size && *size == GameData::Accessory::Size::XL, ImGuiSelectableFlags_DontClosePopups, {70.0f, 0.0f})) {
if(!size) {
size.emplace();
}
*size = GameData::Accessory::Size::XL;
}
ImGui::PopStyleVar();
ImGui::Separator();
if(ImGui::BeginListBox("##AccessoryListbox", {-1.0f, 0.0f})) {
for(const auto& acc : GameData::accessories) {
if(acc.first >= tab * 1000 && acc.first < ((tab + 1) * 1000) && (!size || *size == acc.second.size)) {
if(ImGui::Selectable(Utility::format("#{:.4d} - {} ({})", acc.first, acc.second.name, size_labels[acc.second.size]).data(),
acc.first == accessory.id))
{
accessory.id = acc.first;
accessory.attachIndex = 0;
}
if(acc.first == accessory.id) {
ImGui::SetItemDefaultFocus();
}
}
}
ImGui::EndListBox();
}
ImGui::EndPopup();
}
if(accessory.id > 0) {
ImGui::SameLine();
if(ImGui::SmallButton("Unequip")) {
accessory.id = 0;
accessory.attachIndex = -1;
}
}
ImGui::BeginGroup();
drawAlignedText("Styles:");
if(conf().advancedMode()) {
drawAlignedText("Base position:");
}
drawAlignedText("Position offset:");
if(conf().advancedMode()) {
drawAlignedText("Base rotation:");
}
drawAlignedText("Rotation offset:");
drawAlignedText("Scale:");
ImGui::EndGroup();
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::PushMultiItemsWidths(2, ImGui::CalcItemWidth());
if(ImGui::BeginCombo("##Style1", getStyleName(accessory.styles[0], style_view).data())) {
for(const auto& style : GameData::builtin_style_names) {
if(ImGui::Selectable(getStyleName(style.first, style_view).data(), 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).data())) {
for(const auto& style : GameData::builtin_style_names) {
if(ImGui::Selectable(getStyleName(style.first, style_view).data(), accessory.styles[1] == style.first)) {
accessory.styles[1] = style.first;
}
}
ImGui::EndCombo();
}
ImGui::PopItemWidth();
if(conf().advancedMode()) {
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");
if(conf().advancedMode()) {
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();
}
Containers::StringView
Application::getStyleName(std::int32_t id, Containers::ArrayView view) {
if(id >= 0 && id <= 15) {
return view[id].name;
}
else if(id >= 50 && id <= 65) {
return _currentMass->globalStyles()[id - 50].name;
}
else {
return GameData::builtin_style_names.at(id);
}
}
}