Build viewer/editor #13

Manually merged
williamjcm merged 128 commits from mass-viewer into master 2022-03-02 14:50:10 +01:00
4 changed files with 325 additions and 229 deletions
Showing only changes of commit e839d1c19b - Show all commits

View file

@ -212,8 +212,13 @@ void SaveTool::handleFileAction(efsw::WatchID watch_id,
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
_massManager->refreshHangar(index);
}
else {
_currentMass->setDirty();
}
}
}
break;
case efsw::Actions::Delete:
@ -221,8 +226,13 @@ void SaveTool::handleFileAction(efsw::WatchID watch_id,
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
_massManager->refreshHangar(index);
}
else {
_currentMass->setDirty();
}
}
}
break;
case efsw::Actions::Modified:
@ -233,16 +243,29 @@ void SaveTool::handleFileAction(efsw::WatchID watch_id,
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
if(!_currentMass || _currentMass != &(_massManager->hangar(index))) {
_massManager->refreshHangar(index);
}
else {
_currentMass->setDirty();
}
}
}
break;
case efsw::Actions::Moved:
if(Utility::String::endsWith(filename, _currentProfile->steamId() + ".sav")) {
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : ""))) {
if(Utility::String::endsWith(old_filename, ".tmp")) {
return;
}
if(Utility::String::beginsWith(filename, Utility::formatString("{}Unit", _currentProfile->type() == ProfileType::Demo ? "Demo" : "")) &&
Utility::String::endsWith(old_filename, ".sav"))
{
int index = ((filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
(filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
_massManager->refreshHangar(index);
int old_index = ((old_filename[_currentProfile->type() == ProfileType::Demo ? 8 : 4] - 0x30) * 10) +
(old_filename[_currentProfile->type() == ProfileType::Demo ? 9 : 5] - 0x30);
_massManager->refreshHangar(old_index);
@ -526,8 +549,6 @@ auto SaveTool::findGameDataDirectory() -> bool {
}
void SaveTool::initialiseMassManager() {
_currentProfile->refreshValues();
_massManager.emplace(_saveDir,
_currentProfile->steamId(),
_currentProfile->type() == ProfileType::Demo,

View file

@ -105,6 +105,9 @@ class SaveTool: public Platform::Sdl2Application, public efsw::FileWatchListener
void drawMassViewer();
void drawFrameInfo();
void drawJointSliders();
void drawFramePaint();
void drawCustomStyles(Containers::ArrayView<CustomStyle> styles);
void drawAbout();
void drawGameState();

View file

@ -435,7 +435,7 @@ void SaveTool::drawMassManager() {
drag_drop_index = i;
ImGui::SetDragDropPayload("Mass", &drag_drop_index, sizeof(int));
ImGui::Text("%s - Hangar %.2d", _massManager->hangar(i).name().c_str(), i + 1);
ImGui::Text("%s - Hangar %.2d", (*_massManager->hangar(i).name()).c_str(), i + 1);
ImGui::EndDragDropSource();
}
@ -484,7 +484,7 @@ void SaveTool::drawMassManager() {
ImGui::TextDisabled("<invalid>");
break;
case Mass::State::Valid:
ImGui::TextUnformatted(_massManager->hangar(i).name().c_str());
ImGui::TextUnformatted((*_massManager->hangar(i).name()).c_str());
break;
}
@ -614,7 +614,7 @@ auto SaveTool::drawDeleteMassPopup(int mass_index) -> ImGuiID {
}
else {
ImGui::Text("Are you sure you want to delete the M.A.S.S. named %s in hangar %.2i ? This operation is irreversible.",
_massManager->hangar(mass_index).name().c_str(), mass_index + 1);
(*_massManager->hangar(mass_index).name()).c_str(), mass_index + 1);
}
ImGui::PopTextWrapPos();

View file

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <Magnum/ImGuiIntegration/Integration.h>
#include "../Maps/StyleNames.h"
#include "../FontAwesome/IconsFontAwesome5.h"
@ -24,6 +26,7 @@ void SaveTool::drawMassViewer() {
if(!_currentMass || _currentMass->state() != Mass::State::Valid) {
_currentMass = nullptr;
_uiState = UiState::MainManager;
_queue.addToast(Toast::Type::Error, "The selected M.A.S.S. isn't valid anymore.");
return;
}
@ -38,12 +41,11 @@ void SaveTool::drawMassViewer() {
return;
}
ImGui::AlignTextToFramePadding();
ImGui::Text("Current M.A.S.S.: %s (%s)",
_currentMass->name().c_str(),
(*_currentMass->name()).c_str(),
_currentMass->filename().c_str());
ImGui::SameLine();
if(ImGui::Button(ICON_FA_ARROW_LEFT " Back to main manager")) {
if(ImGui::SmallButton(ICON_FA_ARROW_LEFT " Back to main manager")) {
_currentMass = nullptr;
_uiState = UiState::MainManager;
}
@ -52,6 +54,17 @@ void SaveTool::drawMassViewer() {
ImGui::SameLine();
ImGui::TextWrapped("WARNING: Colours in this app may look different from in-game colours, due to unavoidable differences in the rendering pipeline.");
ImGui::TextColored(ImColor(255, 255, 0), ICON_FA_EXCLAMATION_TRIANGLE);
ImGui::SameLine();
ImGui::TextWrapped("Real-time updates are disabled while on this screen. %s", _currentMass->dirty() ? "The save file has been changed." : "");
if(_currentMass->dirty()) {
ImGui::SameLine();
if(ImGui::SmallButton(ICON_FA_SYNC_ALT " Refresh")) {
_currentMass->refreshValues();
_currentMass->setDirty(false);
}
}
if(ImGui::BeginChild("##MassInfo",
{ImGui::GetContentRegionAvailWidth() * 0.60f, 0.0f},
true, ImGuiWindowFlags_MenuBar))
@ -96,10 +109,19 @@ void SaveTool::drawFrameInfo() {
ImGui::TextUnformatted("Frame type: Skeleton"); // Placeholder for now, replace with actual code once other frames are implemented.
if(ImGui::CollapsingHeader("Joint sliders")) {
drawJointSliders();
drawFramePaint();
}
void SaveTool::drawJointSliders() {
if(!ImGui::CollapsingHeader("Joint sliders")) {
return;
}
static Joints sliders = _currentMass->jointSliders();
static bool edit = false;
static bool dirty = false;
static bool joints_edit = false;
static bool joints_dirty = false;
ImGui::TextWrapped("In-game values are multiplied by 100.\nFor example, 0.500 here is equal to 50 in-game.");
@ -112,10 +134,10 @@ void SaveTool::drawFrameInfo() {
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Neck");
ImGui::TableSetColumnIndex(1);
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##NeckSlider", &sliders.neck, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -128,10 +150,10 @@ void SaveTool::drawFrameInfo() {
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Body");
ImGui::TableSetColumnIndex(1);
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##BodySlider", &sliders.body, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -144,10 +166,10 @@ void SaveTool::drawFrameInfo() {
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Shoulders");
ImGui::TableSetColumnIndex(1);
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##ShouldersSlider", &sliders.shoulders, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -160,10 +182,10 @@ void SaveTool::drawFrameInfo() {
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Hips");
ImGui::TableSetColumnIndex(1);
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##HipsSlider", &sliders.hips, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -197,10 +219,10 @@ void SaveTool::drawFrameInfo() {
ImGui::TableSetupColumn("##LowerArms", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextColumn();
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##UpperArmsSlider", &sliders.upperArms, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -208,10 +230,10 @@ void SaveTool::drawFrameInfo() {
ImGui::Text("%.3f", Double(_currentMass->jointSliders().upperArms));
}
ImGui::TableNextColumn();
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##LowerArmsSlider", &sliders.lowerArms, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -232,10 +254,10 @@ void SaveTool::drawFrameInfo() {
ImGui::TableSetupColumn("##LowerLegs", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableNextColumn();
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##UpperLegsSlider", &sliders.upperLegs, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -243,10 +265,10 @@ void SaveTool::drawFrameInfo() {
ImGui::Text("%.3f", Double(_currentMass->jointSliders().upperLegs));
}
ImGui::TableNextColumn();
if(edit) {
if(joints_edit) {
ImGui::SetNextItemWidth(-1.0f);
if(ImGui::SliderFloat("##LowerLegsSlider", &sliders.lowerLegs, 0.0f, 1.0f)) {
dirty = true;
joints_dirty = true;
}
}
else {
@ -260,43 +282,50 @@ void SaveTool::drawFrameInfo() {
ImGui::EndTable();
}
if(edit) {
if(!dirty) {
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f);
if(joints_edit) {
if(!joints_dirty) {
ImGui::BeginDisabled();
ImGui::Button(ICON_FA_SAVE " Save changes");
ImGui::SameLine();
ImGui::Button(ICON_FA_UNDO " Reset sliders");
ImGui::PopStyleVar();
ImGui::PopItemFlag();
ImGui::EndDisabled();
}
else {
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save changes"); })) {
dirty = false;
if(!_currentMass->setSliders(sliders)) {
_queue.addToast(Toast::Type::Error, "Error writing the joint sliders.");
}
joints_dirty = false;
joints_edit = false;
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_UNDO " Reset sliders")) {
sliders = _currentMass->jointSliders();
dirty = false;
joints_dirty = false;
}
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_TIMES " Cancel editing")) {
sliders = _currentMass->jointSliders();
dirty = false;
edit = false;
joints_dirty = false;
joints_edit = false;
}
ImGui::TextUnformatted("To input out-of-range values, hold Ctrl and click on a slider.");
}
else {
if(ImGui::Button(ICON_FA_EDIT " Edit sliders")) {
edit = true;
sliders = _currentMass->jointSliders();
joints_edit = true;
}
}
}
if(ImGui::CollapsingHeader("Paint")) {
void SaveTool::drawFramePaint() {
if(!ImGui::CollapsingHeader("Paint")) {
return;
}
ImGui::TextUnformatted("Frame styles:");
for(Int i = 0; i < 4; i++) {
ImGui::AlignTextToFramePadding();
@ -331,21 +360,64 @@ void SaveTool::drawFrameInfo() {
ImGui::Separator();
static const Int hex_literals[] = {0x3DF68F08, 0x3E791C4C, 0x00000000};
static Float colour_components[3];
static bool run_once = true;
if(run_once) {
std::memcpy(colour_components, hex_literals, sizeof(Float) * 3);
run_once = false;
}
static bool eye_flare_edit = false;
static bool eye_flare_dirty = false;
static Color4 eye_flare = _currentMass->eyeFlareColour();
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted("Eye flare colour:");
ImGui::SameLine();
ImGui::SetNextItemWidth(-1.0f);
ImGui::ColorEdit3("##EyeFlarePicker", &colour_components[0]);
ImGui::Separator();
ImGui::BeginGroup();
if(eye_flare_edit) {
if(ImGui::ColorEdit3("##EyeFlarePicker", &eye_flare.x())) {
eye_flare_dirty = true;
}
ImGui::SameLine();
drawHelpMarker("Right-click for more option, click the coloured square for the full picker.", 250.0f);
ImGui::TextUnformatted("The frame's custom styles will go here.");
if(!eye_flare_dirty) {
ImGui::BeginDisabled();
ImGui::Button(ICON_FA_SAVE " Save");
ImGui::SameLine();
ImGui::Button(ICON_FA_UNDO " Reset");
ImGui::EndDisabled();
}
else {
if(drawUnsafeWidget([]{ return ImGui::Button(ICON_FA_SAVE " Save"); })) {
if(!_currentMass->setEyeFlareColour(eye_flare)) {
_queue.addToast(Toast::Type::Error, "Error writing the eye flare colour.");
}
eye_flare_dirty = false;
eye_flare_edit = false;
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_UNDO " Reset")) {
eye_flare = _currentMass->eyeFlareColour();
eye_flare_dirty = false;
}
}
ImGui::SameLine();
if(ImGui::Button(ICON_FA_TIMES " Cancel")) {
eye_flare = _currentMass->eyeFlareColour();
eye_flare_dirty = false;
eye_flare_edit = false;
}
}
else {
ImGui::BeginDisabled();
ImColor colour{_currentMass->eyeFlareColour()};
ImGui::ColorEdit3("##EyeFlarePicker", &colour.Value.x);
ImGui::EndDisabled();
if(ImGui::Button(ICON_FA_EDIT " Edit")) {
eye_flare = _currentMass->eyeFlareColour();
eye_flare_edit = true;
}
}
ImGui::EndGroup();
}