Compare commits

...

2 commits

4 changed files with 281 additions and 234 deletions

View file

@ -137,6 +137,7 @@ class Application: public Platform::Sdl2Application, public efsw::FileWatchListe
void drawEyeColourPicker(); void drawEyeColourPicker();
void drawCustomFrameStyles(); void drawCustomFrameStyles();
void drawArmour(); void drawArmour();
void drawBLAttachment();
void drawCustomArmourStyles(); void drawCustomArmourStyles();
void drawWeapons(); void drawWeapons();
void drawWeaponCategory(Containers::StringView name, Containers::ArrayView<GameObjects::Weapon> weapons_view, void drawWeaponCategory(Containers::StringView name, Containers::ArrayView<GameObjects::Weapon> weapons_view,
@ -276,9 +277,10 @@ class Application: public Platform::Sdl2Application, public efsw::FileWatchListe
bool _bLaunchersDirty = false; bool _bLaunchersDirty = false;
bool _eLaunchersDirty = false; bool _eLaunchersDirty = false;
Containers::Optional<std::size_t> _selectedArmourSlot{Containers::NullOpt};
Containers::StaticArray<38, std::int32_t> _selectedArmourDecals{ValueInit}; Containers::StaticArray<38, std::int32_t> _selectedArmourDecals{ValueInit};
Containers::StaticArray<38, std::int32_t> _selectedArmourAccessories{ValueInit}; Containers::StaticArray<38, std::int32_t> _selectedArmourAccessories{ValueInit};
std::int32_t _selectedBLPlacement = 0; std::uint32_t _selectedBLPlacement = 0;
std::int32_t _selectedWeaponPart = 0; std::int32_t _selectedWeaponPart = 0;
std::int32_t _selectedWeaponDecal = 0; std::int32_t _selectedWeaponDecal = 0;
std::int32_t _selectedWeaponAccessory = 0; std::int32_t _selectedWeaponAccessory = 0;

View file

@ -88,6 +88,7 @@ Application::drawMassViewer() {
_jointsDirty = false; _jointsDirty = false;
_stylesDirty = false; _stylesDirty = false;
_eyeFlareDirty = false; _eyeFlareDirty = false;
_selectedArmourSlot = Containers::NullOpt;
_selectedArmourDecals = Containers::StaticArray<38, std::int32_t>{ValueInit}; _selectedArmourDecals = Containers::StaticArray<38, std::int32_t>{ValueInit};
_selectedArmourAccessories = Containers::StaticArray<38, std::int32_t>{ValueInit}; _selectedArmourAccessories = Containers::StaticArray<38, std::int32_t>{ValueInit};
_selectedBLPlacement = 0; _selectedBLPlacement = 0;
@ -126,6 +127,13 @@ Application::drawMassViewer() {
ImGui::EndTabItem(); ImGui::EndTabItem();
} }
if(_currentMass->bulletLauncherAttachmentStyle() != GameObjects::BulletLauncherAttachmentStyle::NotFound &&
ImGui::BeginTabItem("Bullet launcher attachment"))
{
drawBLAttachment();
ImGui::EndTabItem();
}
if(ImGui::BeginTabItem("Custom armour styles")) { if(ImGui::BeginTabItem("Custom armour styles")) {
drawCustomArmourStyles(); drawCustomArmourStyles();
ImGui::EndTabItem(); ImGui::EndTabItem();

View file

@ -29,63 +29,77 @@ Application::drawArmour() {
return; return;
} }
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset all")) { constexpr static Containers::StringView slot_labels[] = {
_currentMass->getArmourParts();
_currentMass->getBulletLauncherAttachments();
}
if(!ImGui::BeginChild("##ArmourParts", {}, ImGuiChildFlags_Border)) {
ImGui::EndChild();
return;
}
static Containers::StringView slot_labels[] = {
#define c(enumerator, strenum, name) name, #define c(enumerator, strenum, name) name,
#include "../Maps/ArmourSlots.hpp" #include "../Maps/ArmourSlots.hpp"
#undef c #undef c
}; };
for(std::uint32_t i = 0; i < _currentMass->armourParts().size(); i++) { auto labels_view = arrayView(slot_labels);
ImGui::PushID(int(i));
auto& part = _currentMass->armourParts()[i]; const static float footer_height_to_reserve = ImGui::GetFrameHeightWithSpacing();
static char header[129] = {'\0'};
std::memset(header, '\0', 129);
if(GameData::armour_sets.find(part.id) != GameData::armour_sets.cend()) {
std::snprintf(header, 128, "%s: %s###%u",
slot_labels[std::uint32_t(part.slot)].data(),
GameData::armour_sets.at(part.id).name.data(),
std::uint32_t(part.slot));
}
else {
std::snprintf(header, 128, "%s: %i###%u",
slot_labels[std::uint32_t(part.slot)].data(),
part.id,
std::uint32_t(part.slot));
}
if(ImGui::CollapsingHeader(header)) {
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.491f); if(ImGui::BeginTable("##SlotsTable", 1,
if(ImGui::BeginListBox("##ChangePart")) { ImGuiTableFlags_ScrollY|ImGuiTableFlags_BordersOuter|ImGuiTableFlags_BordersInnerH,
if(std::strncmp("Neck", slot_labels[std::uint32_t(part.slot)].data(), 4) != 0) { {ImGui::GetContentRegionAvail().x * 0.15f, -footer_height_to_reserve}))
for(auto& set : GameData::armour_sets) { {
if(ImGui::Selectable(set.second.name.data(), set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) { ImGui::TableSetupColumn("##Slots", ImGuiTableColumnFlags_WidthStretch);
part.id = set.first;
for(std::size_t i = 0; i < labels_view.size(); i++) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
if(ImGui::Selectable(labels_view[i].data(), _selectedArmourSlot && (*_selectedArmourSlot) == i,
ImGuiSelectableFlags_SpanAvailWidth))
{
_selectedArmourSlot = i;
} }
} }
}
else {
for(auto& set : GameData::armour_sets) {
if(!set.second.neck_compatible) {
continue;
}
if(ImGui::Selectable(set.second.name.data(), set.first == part.id, ImGuiSelectableFlags_SpanAvailWidth)) { ImGui::EndTable();
}
if(ImGui::Button(ICON_FA_UNDO_ALT " Reset all")) {
_currentMass->getArmourParts();
}
ImGui::EndGroup();
ImGui::SameLine();
if(!_selectedArmourSlot) {
ImGui::TextUnformatted("No selected armour slot.");
return;
}
auto& part = _currentMass->armourParts()[*_selectedArmourSlot];
ImGui::BeginGroup();
if(ImGui::BeginChild("##ArmourEditor", {0.0f, -footer_height_to_reserve})) {
ImGui::SeparatorText("Part");
if(GameData::armour_sets.find(part.id) != GameData::armour_sets.cend()) {
ImGui::Text("Set name: %s", GameData::armour_sets.at(part.id).name.data());
}
else {
ImGui::Text("Set ID: %u", part.id);
}
ImGui::SameLine();
if(ImGui::SmallButton("Change")) {
ImGui::OpenPopup("##ArmourPartPopup");
}
if(ImGui::BeginPopup("##ArmourPartPopup")) {
if(ImGui::BeginListBox("##ChangePart")) {
for(auto& set : GameData::armour_sets) {
if(part.slot != GameObjects::ArmourPart::Slot::Neck || set.second.neck_compatible) {
if(ImGui::Selectable(set.second.name.data(), set.first == part.id,
ImGuiSelectableFlags_SpanAvailWidth))
{
part.id = set.first; part.id = set.first;
} }
} }
@ -93,72 +107,79 @@ Application::drawArmour() {
ImGui::EndListBox(); ImGui::EndListBox();
} }
ImGui::EndGroup(); ImGui::EndPopup();
}
ImGui::SeparatorText("Styles");
for(std::int32_t i = 0; i < 4; i++) {
drawAlignedText("Slot %d:", i + 1);
ImGui::SameLine(); ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical); ImGui::PushID(i);
if(ImGui::BeginCombo("##Style",
ImGui::SameLine(); getStyleName(part.styles[i], _currentMass->armourCustomStyles()).data()))
{
ImGui::BeginGroup();
ImGui::TextUnformatted("Styles:");
for(std::int32_t j = 0; j < 4; j++) {
drawAlignedText("Slot %d:", j + 1);
ImGui::SameLine();
ImGui::PushID(j);
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 2.0f);
if(ImGui::BeginCombo("##Style", getStyleName(part.styles[j], _currentMass->armourCustomStyles()).data())) {
for(const auto& style : GameData::style_names) { for(const auto& style : GameData::style_names) {
if(ImGui::Selectable(getStyleName(style.first, _currentMass->armourCustomStyles()).data(), part.styles[j] == style.first)) { if(ImGui::Selectable(getStyleName(style.first, _currentMass->armourCustomStyles()).data(),
part.styles[j] = style.first; part.styles[i] == style.first))
{
part.styles[i] = style.first;
} }
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
ImGui::PopID(); ImGui::PopID();
} }
ImGui::EndGroup(); ImGui::SeparatorText("Decals");
ImGui::Separator(); constexpr static float selectable_width = 25.0f;
ImGui::PushID("Decal"); drawAlignedText("Showing/editing decal:");
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, {0.5f, 0.0f});
drawAlignedText("Showing/editing decal"); for(std::uint32_t i = 0; i < part.decals.size(); i++) {
for(std::uint32_t j = 0; j < part.decals.size(); j++) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton(std::to_string(j + 1).c_str(), &_selectedArmourDecals[i], int(j)); if(ImGui::Selectable(std::to_string(i + 1).c_str(), _selectedArmourDecals[*_selectedArmourSlot] == int(i),
ImGuiSelectableFlags_None, {selectable_width, 0.0f}))
{
_selectedArmourDecals[*_selectedArmourSlot] = int(i);
} }
if(i != part.decals.size() - 1) {
drawDecalEditor(part.decals[_selectedArmourDecals[i]]); ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::PopID(); }
}
ImGui::PopStyleVar();
drawDecalEditor(part.decals[_selectedArmourDecals[*_selectedArmourSlot]]);
if(!part.accessories.isEmpty()) { if(!part.accessories.isEmpty()) {
ImGui::Separator(); ImGui::SeparatorText("Accessories");
ImGui::PushID("Accessory"); drawAlignedText("Showing/editing accessory:");
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, {0.5f, 0.0f});
drawAlignedText("Showing/editing accessory"); for(std::uint32_t i = 0; i < part.accessories.size(); i++) {
for(std::uint32_t j = 0; j < part.accessories.size(); j++) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton(std::string{char(65 + j)}.c_str(), &_selectedArmourAccessories[i], int(j)); if(ImGui::Selectable((std::string{} + char(i + 65)).c_str(),
_selectedArmourAccessories[*_selectedArmourSlot] == int(i),
ImGuiSelectableFlags_None, {selectable_width, 0.0f}))
{
_selectedArmourAccessories[*_selectedArmourSlot] = int(i);
}
if(i != part.accessories.size() - 1) {
ImGui::SameLine();
ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
}
}
ImGui::PopStyleVar();
drawAccessoryEditor(part.accessories[_selectedArmourAccessories[*_selectedArmourSlot]],
_currentMass->armourCustomStyles());
}
} }
drawAccessoryEditor(part.accessories[_selectedArmourAccessories[i]], _currentMass->armourCustomStyles()); ImGui::EndChild();
ImGui::PopID();
}
ImGui::Separator();
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) { if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
_modifiedBySaveTool = true; _modifiedBySaveTool = true;
@ -167,36 +188,54 @@ Application::drawArmour() {
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
} }
} }
ImGui::EndGroup();
}
void
Application::drawBLAttachment() {
if(!_currentMass || _currentMass->state() != GameObjects::Mass::State::Valid) {
return;
} }
ImGui::PopID();
}
if(_currentMass->bulletLauncherAttachmentStyle() != GameObjects::BulletLauncherAttachmentStyle::NotFound &&
ImGui::CollapsingHeader("Bullet launcher placement"))
{
drawAlignedText("Attachment style:"_s); drawAlignedText("Attachment style:"_s);
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("Active one", if(ImGui::RadioButton("Active one",
_currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::ActiveOne); _currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::ActiveOne))
{
_currentMass->bulletLauncherAttachmentStyle() = GameObjects::BulletLauncherAttachmentStyle::ActiveOne;
}
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("Active one per slot", if(ImGui::RadioButton("Active one per slot",
_currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::ActiveOnePerSlot); _currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::ActiveOnePerSlot))
{
_currentMass->bulletLauncherAttachmentStyle() = GameObjects::BulletLauncherAttachmentStyle::ActiveOnePerSlot;
}
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("All equipped", if(ImGui::RadioButton("All equipped",
_currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::AllEquipped); _currentMass->bulletLauncherAttachmentStyle() == GameObjects::BulletLauncherAttachmentStyle::AllEquipped))
{
_currentMass->bulletLauncherAttachmentStyle() = GameObjects::BulletLauncherAttachmentStyle::ActiveOnePerSlot;
}
ImGui::Separator(); ImGui::Separator();
constexpr static float selectable_width = 25.0f;
drawAlignedText("Launcher slot:"); drawAlignedText("Launcher slot:");
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, {0.5f, 0.0f});
for(auto i = 0u; i < _currentMass->bulletLauncherAttachments().size(); i++) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("1", &_selectedBLPlacement, 0); if(ImGui::Selectable(std::to_string(i).c_str(), _selectedBLPlacement == i, ImGuiSelectableFlags_None,
{selectable_width, 0.0f}))
{
_selectedBLPlacement = i;
}
if(i != _currentMass->bulletLauncherAttachments().size() - 1) {
ImGui::SameLine(); ImGui::SameLine();
ImGui::RadioButton("2", &_selectedBLPlacement, 1); ImGui::SeparatorEx(ImGuiSeparatorFlags_Vertical);
ImGui::SameLine(); }
ImGui::RadioButton("3", &_selectedBLPlacement, 2); }
ImGui::SameLine(); ImGui::PopStyleVar();
ImGui::RadioButton("4", &_selectedBLPlacement, 3);
auto& placement = _currentMass->bulletLauncherAttachments()[_selectedBLPlacement]; auto& placement = _currentMass->bulletLauncherAttachments()[_selectedBLPlacement];
@ -286,15 +325,13 @@ Application::drawArmour() {
} }
_modifiedBySaveTool = true; _modifiedBySaveTool = true;
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); }) && if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
!_currentMass->writeBulletLauncherAttachments()) _modifiedBySaveTool = true;
{ if(!_currentMass->writeBulletLauncherAttachments()) {
_modifiedBySaveTool = false; _modifiedBySaveTool = false;
_queue.addToast(Toast::Type::Error, _currentMass->lastError()); _queue.addToast(Toast::Type::Error, _currentMass->lastError());
} }
} }
ImGui::EndChild();
} }
void void

View file

@ -72,7 +72,7 @@ Application::drawAbout() {
if(ImGui::Button("Open in browser")) { if(ImGui::Button("Open in browser")) {
openUri(website); openUri(website);
} }
auto repo = "https://williamjcm.ovh/git/williamjcm/MassBuilderSaveTool"; auto repo = "https://git.williamjcm.ovh/williamjcm/MassBuilderSaveTool";
drawAlignedText(ICON_FA_GIT_ALT " %s", repo); drawAlignedText(ICON_FA_GIT_ALT " %s", repo);
ImGui::SameLine(); ImGui::SameLine();
if(ImGui::Button("Copy to clipboard")) { if(ImGui::Button("Copy to clipboard")) {