diff --git a/src/SaveTool/SaveTool.h b/src/SaveTool/SaveTool.h index a4b49b2..ead76cf 100644 --- a/src/SaveTool/SaveTool.h +++ b/src/SaveTool/SaveTool.h @@ -282,6 +282,7 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener bool _eyeFlareDirty{false}; Containers::StaticArray<38, Int> _selectedArmourDecals{ValueInit}; Containers::StaticArray<38, Int> _selectedArmourAccessories{ValueInit}; + Int _selectedBLPlacement{0}; Int _selectedWeaponPart{0}; Int _selectedWeaponDecal{0}; Int _selectedWeaponAccessory{0}; diff --git a/src/SaveTool/SaveTool_MassViewer.cpp b/src/SaveTool/SaveTool_MassViewer.cpp index a47ccfd..7cdd563 100644 --- a/src/SaveTool/SaveTool_MassViewer.cpp +++ b/src/SaveTool/SaveTool_MassViewer.cpp @@ -87,6 +87,7 @@ void SaveTool::drawMassViewer() { _eyeFlareDirty = false; _selectedArmourDecals = Containers::StaticArray<38, Int>{ValueInit}; _selectedArmourAccessories = Containers::StaticArray<38, Int>{ValueInit}; + _selectedBLPlacement = 0; _selectedWeaponPart = 0; _selectedWeaponDecal = 0; _selectedWeaponAccessory = 0; diff --git a/src/SaveTool/SaveTool_MassViewer_Armour.cpp b/src/SaveTool/SaveTool_MassViewer_Armour.cpp index 74616b5..9fb8c4a 100644 --- a/src/SaveTool/SaveTool_MassViewer_Armour.cpp +++ b/src/SaveTool/SaveTool_MassViewer_Armour.cpp @@ -28,6 +28,7 @@ void SaveTool::drawArmour() { if(ImGui::Button(ICON_FA_UNDO_ALT " Reset all")) { _currentMass->getArmourParts(); + _currentMass->getBulletLauncherAttachments(); } if(!ImGui::BeginChild("##ArmourParts", {0.0f, 0.0f}, true)) { @@ -160,6 +161,126 @@ void SaveTool::drawArmour() { ImGui::PopID(); } + if(_currentMass->bulletLauncherAttachmentStyle() != BulletLauncherAttachmentStyle::NotFound && + ImGui::CollapsingHeader("Bullet launcher placement")) + { + drawAlignedText("Attachment style:"_s); + ImGui::SameLine(); + ImGui::RadioButton("Active one", + _currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::ActiveOne); + ImGui::SameLine(); + ImGui::RadioButton("Active one per slot", + _currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::ActiveOnePerSlot); + ImGui::SameLine(); + ImGui::RadioButton("All equipped", + _currentMass->bulletLauncherAttachmentStyle() == BulletLauncherAttachmentStyle::AllEquipped); + + ImGui::Separator(); + + drawAlignedText("Launcher slot:"); + ImGui::SameLine(); + ImGui::RadioButton("1", &_selectedBLPlacement, 0); + ImGui::SameLine(); + ImGui::RadioButton("2", &_selectedBLPlacement, 1); + ImGui::SameLine(); + ImGui::RadioButton("3", &_selectedBLPlacement, 2); + ImGui::SameLine(); + ImGui::RadioButton("4", &_selectedBLPlacement, 3); + + auto& placement = _currentMass->bulletLauncherAttachments()[_selectedBLPlacement]; + + static const Containers::StringView socket_labels[] = { + #define c(enumerator, enumstr, name) name, + #include "../Maps/BulletLauncherSockets.hpp" + #undef c + }; + + drawAlignedText("Socket:"); + ImGui::SameLine(); + if(ImGui::BeginCombo("##Socket", socket_labels[UnsignedInt(placement.socket)].data())) { + for(UnsignedInt i = 0; i < (sizeof(socket_labels) / sizeof(socket_labels[0])); i++) { + if(ImGui::Selectable(socket_labels[i].data(), i == UnsignedInt(placement.socket), ImGuiSelectableFlags_SpanAvailWidth)) { + placement.socket = static_cast(i); + } + } + ImGui::EndCombo(); + } + + if(placement.socket != BulletLauncherSocket::Auto) { + ImGui::BeginGroup(); + drawAlignedText("Relative position:"); + drawAlignedText("Offset position:"); + drawAlignedText("Relative rotation:"); + drawAlignedText("Offset rotation:"); + drawAlignedText("Scale:"); + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::DragFloat("##RelPosX", &placement.relativeLocation.x(), 1.0f, -FLT_MAX, +FLT_MAX, "X: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::DragFloat("##RelPosY", &placement.relativeLocation.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Y: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::DragFloat("##RelPosZ", &placement.relativeLocation.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Z: %.3f"); + ImGui::PopItemWidth(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::SliderFloat("##OffPosX", &placement.offsetLocation.x(), -500.0f, +500.0f, "X: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SliderFloat("##OffPosY", &placement.offsetLocation.y(), -500.0f, +500.0f, "Y: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SliderFloat("##OffPosZ", &placement.offsetLocation.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", &placement.relativeRotation.x(), 1.0f, -FLT_MAX, +FLT_MAX, "Roll: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::DragFloat("##RotY", &placement.relativeRotation.y(), 1.0f, -FLT_MAX, +FLT_MAX, "Yaw: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::DragFloat("##RotZ", &placement.relativeRotation.z(), 1.0f, -FLT_MAX, +FLT_MAX, "Pitch: %.3f"); + ImGui::PopItemWidth(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::SliderFloat("##RotOffsetZ", &placement.offsetRotation.z(), -180.0f, +180.0f, "Roll: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SliderFloat("##RotOffsetX", &placement.offsetRotation.x(), -30.0f, +30.0f, "Pitch: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SliderFloat("##RotOffsetY", &placement.offsetRotation.y(), -30.0f, +30.0f, "Yaw: %.3f"); + ImGui::PopItemWidth(); + + ImGui::PushMultiItemsWidths(3, ImGui::CalcItemWidth()); + ImGui::SliderFloat("##ScaleX", &placement.relativeScale.x(), 0.5f, 1.5f, "X: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SliderFloat("##ScaleY", &placement.relativeScale.y(), 0.5f, 1.5f, "Y: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); + ImGui::SliderFloat("##ScaleZ", &placement.relativeScale.z(), 0.5f, 1.5f, "Z: %.3f"); + ImGui::PopItemWidth(); + ImGui::SameLine(); + drawHelpMarker("0.5 = 50 in-game\n1.5 = 150 in-game"); + ImGui::EndGroup(); + } + + if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); }) && + !_currentMass->writeBulletLauncherAttachments()) + { + _queue.addToast(Toast::Type::Error, _currentMass->lastError()); + } + } + ImGui::EndChild(); }