diff --git a/TheForceEngine/TFE_Editor/LevelEditor/editNotes.cpp b/TheForceEngine/TFE_Editor/LevelEditor/editNotes.cpp index 12ae26d8..9d1230e0 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/editNotes.cpp +++ b/TheForceEngine/TFE_Editor/LevelEditor/editNotes.cpp @@ -2,6 +2,7 @@ #include "hotkeys.h" #include "levelEditor.h" #include "levelEditorData.h" +#include "levelEditorHistory.h" #include "sharedState.h" #include #include @@ -110,7 +111,11 @@ namespace LevelEditor // Test newNote.note = "Test Note\n * Item 1\n * Item 2\n"; // - addLevelNoteToLevel(&newNote); + s32 resultId = addLevelNoteToLevel(&newNote); + if (resultId >= 0) + { + cmd_levelNoteSnapshot(LName_LevelNote_Create, false); + } } else if (s_singleClick && s_hoveredLevelNote >= 0) { @@ -211,6 +216,17 @@ namespace LevelEditor s_editMove = false; } } + else if (!s_leftMouseDown && s_editMove) + { + // Only record in history if moved, not clicked + if (s_moveBasePos3d.x != s_level.notes[s_curLevelNote].pos.x || + s_moveBasePos3d.y != s_level.notes[s_curLevelNote].pos.y || + s_moveBasePos3d.z != s_level.notes[s_curLevelNote].pos.z) + { + cmd_levelNoteSnapshot(LName_LevelNote_Move, false); + } + s_editMove = false; + } else { s_editMove = false; @@ -231,6 +247,7 @@ namespace LevelEditor } if (deleted) { + cmd_levelNoteSnapshot(LName_LevelNote_Delete, false); clearLevelNoteSelection(); } } diff --git a/TheForceEngine/TFE_Editor/LevelEditor/infoPanel.cpp b/TheForceEngine/TFE_Editor/LevelEditor/infoPanel.cpp index fa68ca8d..711f3df1 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/infoPanel.cpp +++ b/TheForceEngine/TFE_Editor/LevelEditor/infoPanel.cpp @@ -2882,22 +2882,23 @@ namespace LevelEditor { s32 id = s_curLevelNote >= 0 ? s_curLevelNote : s_hoveredLevelNote; if (id < 0) { return; } - + LevelNote* note = &s_level.notes[id]; + bool changed = false; - ImGui::CheckboxFlags("2D Only", ¬e->flags, LNF_2D_ONLY); ImGui::SameLine(); - ImGui::CheckboxFlags("No Fade in 3D", ¬e->flags, LNF_3D_NO_FADE); ImGui::SameLine(); - ImGui::CheckboxFlags("Always Show Text", ¬e->flags, LNF_TEXT_ALWAYS_SHOW); + changed |= ImGui::CheckboxFlags("2D Only", ¬e->flags, LNF_2D_ONLY); ImGui::SameLine(); + changed |= ImGui::CheckboxFlags("No Fade in 3D", ¬e->flags, LNF_3D_NO_FADE); ImGui::SameLine(); + changed |= ImGui::CheckboxFlags("Always Show Text", ¬e->flags, LNF_TEXT_ALWAYS_SHOW); ImGui::Spacing(); ImGui::SetNextItemWidth(128.0f); ImGui::LabelText("##Label", "Start Fade (3D)"); ImGui::SameLine(); ImGui::SetNextItemWidth(128.0f); - ImGui::InputFloat("##StartFade", ¬e->fade.x, 1.0f, 10.0f, "%.1f"); + changed |= ImGui::InputFloat("##StartFade", ¬e->fade.x, 1.0f, 10.0f, "%.1f"); s_textInputFocused |= ImGui::IsItemActive(); ImGui::SetNextItemWidth(128.0f); ImGui::LabelText("##Label", "End Fade (3D)"); ImGui::SameLine(); ImGui::SetNextItemWidth(128.0f); - ImGui::InputFloat("##EndFade", ¬e->fade.z, 1.0f, 10.0f, "%.1f"); + changed |= ImGui::InputFloat("##EndFade", ¬e->fade.z, 1.0f, 10.0f, "%.1f"); s_textInputFocused |= ImGui::IsItemActive(); ImGui::Separator(); ImGui::SetNextItemWidth(128.0f); @@ -2905,6 +2906,7 @@ namespace LevelEditor Vec4f iconColor = packedColorToVec4(note->iconColor); if (ImGui::ColorEdit4(editor_getUniqueLabel(""), iconColor.m, ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoInputs)) { + changed = true; note->iconColor = colorVec4ToPacked(iconColor); } ImGui::SetNextItemWidth(128.0f); @@ -2912,6 +2914,7 @@ namespace LevelEditor Vec4f textColor = packedColorToVec4(note->textColor); if (ImGui::ColorEdit4(editor_getUniqueLabel(""), textColor.m, ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_NoInputs)) { + changed = true; note->textColor = colorVec4ToPacked(textColor); } ImGui::Separator(); @@ -2923,9 +2926,23 @@ namespace LevelEditor if (ImGui::InputTextMultiline(textInputId, tmpBuffer, 4096, { s_infoWith - 16.0f, 354.0f })) { + changed = true; note->note = tmpBuffer; } s_textInputFocused |= ImGui::IsItemActive(); + + if (changed) + { + if (s_prevLevelNote == s_curLevelNote) + { + cmd_levelNoteSnapshot(LName_LevelNote_Change, false); + } + else + { + cmd_levelNoteSnapshot(LName_LevelNote_Change, true); + } + s_prevLevelNote = s_curLevelNote; + } } bool drawInfoPanel(EditorView view) diff --git a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.cpp b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.cpp index 00f45013..f6e7d79d 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.cpp +++ b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.cpp @@ -5291,6 +5291,33 @@ namespace LevelEditor readGuidelineFromSnapshot(guideline); } + void level_createLevelNoteSnapshot(SnapshotBuffer* buffer) + { + setSnapshotWriteBuffer(buffer); + const u32 noteCount = (u32)s_level.notes.size(); + const LevelNote* note = s_level.notes.data(); + + writeU32(noteCount); + for (u32 i = 0; i < noteCount; i++, note++) + { + writeLevelNoteToSnapshot(note); + } + } + + void level_unpackLevelNoteSnapshot(u32 size, void* data) + { + setSnapshotReadBuffer((u8*)data, size); + + const u32 noteCount = readU32(); + s_level.notes.resize(noteCount); + + LevelNote* note = s_level.notes.data(); + for (u32 i = 0; i < noteCount; i++, note++) + { + readLevelNoteFromSnapshot(note); + } + } + // Find a sector based on DF rules. EditorSector* findSectorDf(const Vec3f pos) { diff --git a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.h b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.h index dc39fe83..485a6683 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.h +++ b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorData.h @@ -335,6 +335,7 @@ namespace LevelEditor void level_createFeatureTextureSnapshot(TFE_Editor::SnapshotBuffer* buffer, s32 count, const FeatureId* feature); void level_createEntiyListSnapshot(TFE_Editor::SnapshotBuffer* buffer, s32 sectorId); void level_createGuidelineSnapshot(TFE_Editor::SnapshotBuffer* buffer); + void level_createLevelNoteSnapshot(TFE_Editor::SnapshotBuffer* buffer); void level_createSingleGuidelineSnapshot(TFE_Editor::SnapshotBuffer* buffer, s32 index); void level_createLevelSectorSnapshotSameAssets(std::vector& sectors); @@ -348,6 +349,7 @@ namespace LevelEditor void level_unpackEntiyListSnapshot(u32 size, void* data); void level_unpackGuidelineSnapshot(u32 size, void* data); void level_unpackSingleGuidelineSnapshot(u32 size, void* data); + void level_unpackLevelNoteSnapshot(u32 size, void* data); // Spatial Queries s32 findSectorByName(const char* name, s32 excludeId = -1); diff --git a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.cpp b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.cpp index f390b227..e4c32d68 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.cpp +++ b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.cpp @@ -29,6 +29,7 @@ namespace LevelEditor LCmd_Set_Textures, LCmd_Guideline_Snapshot, LCmd_Guideline_Snapshot_Single, + LCmd_LevelNote_Snapshot, LCmd_Count }; @@ -46,6 +47,7 @@ namespace LevelEditor void cmd_applySetTextures(); void cmd_applyGuidelineSnapshot(); void cmd_applyGuidelineSingleSnapshot(); + void cmd_applyLevelNoteSnapshot(); /////////////////////////////////// // API @@ -61,6 +63,7 @@ namespace LevelEditor history_registerCommand(LCmd_Set_Textures, cmd_applySetTextures); history_registerCommand(LCmd_Guideline_Snapshot, cmd_applyGuidelineSnapshot); history_registerCommand(LCmd_Guideline_Snapshot_Single, cmd_applyGuidelineSingleSnapshot); + history_registerCommand(LCmd_LevelNote_Snapshot, cmd_applyLevelNoteSnapshot); history_registerName(LName_MoveVertex, "Move Vertice(s)"); history_registerName(LName_SetVertex, "Set Vertex Position"); @@ -100,6 +103,10 @@ namespace LevelEditor history_registerName(LName_Guideline_Create, "Create Guidelines"); history_registerName(LName_Guideline_Delete, "Delete Guidelines"); history_registerName(LName_Guideline_Edit, "Edit Guidelines"); + history_registerName(LName_LevelNote_Create, "Create Note"); + history_registerName(LName_LevelNote_Delete, "Delete Note"); + history_registerName(LName_LevelNote_Move, "Move Note"); + history_registerName(LName_LevelNote_Change, "Change Note"); } void levHistory_destroy() @@ -305,6 +312,34 @@ namespace LevelEditor } CMD_END(); } + + void cmd_levelNoteSnapshot(u32 name, bool idChanged) + { + // Bundle consecutive attribute changes + u16 prevCmd, prevName; + history_getPrevCmdAndName(prevCmd, prevName); + if (prevName == LName_LevelNote_Change && name == prevName && !idChanged) + { + history_removeLast(); + } + + s_workBuffer[0].clear(); + s_workBuffer[1].clear(); + level_createLevelNoteSnapshot(&s_workBuffer[0]); + if (s_workBuffer[0].empty()) { return; } + + const u32 uncompressedSize = (u32)s_workBuffer[0].size(); + const u32 compressedSize = compressBuffer(); + if (!compressedSize) { return; } + + CMD_BEGIN(LCmd_LevelNote_Snapshot, name); + { + hBuffer_addU32(uncompressedSize); + hBuffer_addU32(compressedSize); + hBuffer_addArrayU8(compressedSize, s_workBuffer[1].data()); + } + CMD_END(); + } //////////////////////////////// // History Commands @@ -400,6 +435,19 @@ namespace LevelEditor } } + void cmd_applyLevelNoteSnapshot() + { + const u32 uncompressedSize = hBuffer_getU32(); + const u32 compressedSize = hBuffer_getU32(); + const u8* compressedData = hBuffer_getArrayU8(compressedSize); + + s_workBuffer[0].resize(uncompressedSize); + if (zstd_decompress(s_workBuffer[0].data(), uncompressedSize, compressedData, compressedSize)) + { + level_unpackLevelNoteSnapshot(uncompressedSize, s_workBuffer[0].data()); + } + } + ////////////////////////////////////////////////// // Internal ////////////////////////////////////////////////// diff --git a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.h b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.h index 4d9f8a87..863b67cf 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.h +++ b/TheForceEngine/TFE_Editor/LevelEditor/levelEditorHistory.h @@ -46,6 +46,10 @@ namespace LevelEditor LName_Guideline_Create, LName_Guideline_Delete, LName_Guideline_Edit, + LName_LevelNote_Create, + LName_LevelNote_Delete, + LName_LevelNote_Move, + LName_LevelNote_Change, LName_Count }; @@ -65,5 +69,6 @@ namespace LevelEditor void cmd_objectListSnapshot(u32 name, s32 sectorId); void cmd_setTextures(u32 name, s32 count, FeatureId* features); void cmd_guidelineSnapshot(u32 name); + void cmd_levelNoteSnapshot(u32 name, bool idChanged); void cmd_guidelineSingleSnapshot(u32 name, s32 index, bool idChanged); } diff --git a/TheForceEngine/TFE_Editor/LevelEditor/note.cpp b/TheForceEngine/TFE_Editor/LevelEditor/note.cpp index 0b7827e4..2f472adc 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/note.cpp +++ b/TheForceEngine/TFE_Editor/LevelEditor/note.cpp @@ -36,6 +36,7 @@ namespace LevelEditor s32 s_hoveredLevelNote = -1; s32 s_curLevelNote = -1; + s32 s_prevLevelNote = -1; // For bundling consecutive attrib changes as one undo void clearLevelNoteSelection() { diff --git a/TheForceEngine/TFE_Editor/LevelEditor/note.h b/TheForceEngine/TFE_Editor/LevelEditor/note.h index ddf5d87a..610ce4a8 100644 --- a/TheForceEngine/TFE_Editor/LevelEditor/note.h +++ b/TheForceEngine/TFE_Editor/LevelEditor/note.h @@ -48,6 +48,7 @@ namespace LevelEditor extern const u32 c_noteColors[3]; extern s32 s_hoveredLevelNote; extern s32 s_curLevelNote; + extern s32 s_prevLevelNote; void clearLevelNoteSelection(); }