diff --git a/src/canvas.cpp b/src/canvas.cpp index 19560a0..e885625 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -89,11 +89,13 @@ namespace anm2ed glBindVertexArray(0); - // Framebuffer - glGenTextures(1, &texture); + // Framebuffer(s) glGenFramebuffers(1, &fbo); glGenRenderbuffers(1, &rbo); + // Framebuffer(s) Texture + glGenTextures(1, &texture); + framebuffer_set(); } @@ -267,39 +269,15 @@ namespace anm2ed void Canvas::viewport_set() const { glViewport(0, 0, size.x, size.y); } - void Canvas::clear(const vec4& color) const + void Canvas::clear(vec4 color) const { - glDisable(GL_BLEND); glClearColor(color.r, color.g, color.b, color.a); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_BLEND); } - void Canvas::bind() const - { - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + void Canvas::bind() const { glBindFramebuffer(GL_FRAMEBUFFER, fbo); } - GLboolean blendEnabled = glIsEnabled(GL_BLEND); - if (!blendEnabled) glEnable(GL_BLEND); - - glGetIntegerv(GL_BLEND_SRC_RGB, &previousSrcRGB); - glGetIntegerv(GL_BLEND_DST_RGB, &previousDstRGB); - glGetIntegerv(GL_BLEND_SRC_ALPHA, &previousSrcAlpha); - glGetIntegerv(GL_BLEND_DST_ALPHA, &previousDstAlpha); - previousBlendStored = true; - - glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - - void Canvas::unbind() const - { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - if (previousBlendStored) - { - glBlendFuncSeparate(previousSrcRGB, previousDstRGB, previousSrcAlpha, previousDstAlpha); - previousBlendStored = false; - } - } + void Canvas::unbind() const { glBindFramebuffer(GL_FRAMEBUFFER, 0); } std::vector Canvas::pixels_get() const { @@ -332,10 +310,8 @@ namespace anm2ed { uint8_t rgba[4]{}; - glBindTexture(GL_READ_FRAMEBUFFER, fbo); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(position.x, framebufferSize.y - 1 - position.y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgba); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); return vec4(math::uint8_to_float(rgba[0]), math::uint8_to_float(rgba[1]), math::uint8_to_float(rgba[2]), math::uint8_to_float(rgba[3])); diff --git a/src/canvas.h b/src/canvas.h index e29c063..b019077 100644 --- a/src/canvas.h +++ b/src/canvas.h @@ -25,6 +25,8 @@ namespace anm2ed::canvas constexpr auto GRID_SIZE_MAX = 10000; constexpr auto GRID_OFFSET_MIN = 0; constexpr auto GRID_OFFSET_MAX = 10000; + + constexpr auto CHECKER_SIZE = 32.0f; } namespace anm2ed @@ -46,11 +48,6 @@ namespace anm2ed GLuint texture{}; glm::vec2 previousSize{}; glm::vec2 size{}; - mutable GLint previousSrcRGB{}; - mutable GLint previousDstRGB{}; - mutable GLint previousSrcAlpha{}; - mutable GLint previousDstAlpha{}; - mutable bool previousBlendStored{}; Canvas(); Canvas(glm::vec2); @@ -70,7 +67,7 @@ namespace anm2ed float dashLength = canvas::DASH_LENGTH, float dashGap = canvas::DASH_GAP, float dashOffset = canvas::DASH_OFFSET) const; void viewport_set() const; - void clear(const glm::vec4&) const; + void clear(glm::vec4 = glm::vec4()) const; void bind() const; void unbind() const; void zoom_set(float&, glm::vec2&, glm::vec2, float) const; diff --git a/src/imgui/taskbar.cpp b/src/imgui/taskbar.cpp index d2199a3..3a1e75f 100644 --- a/src/imgui/taskbar.cpp +++ b/src/imgui/taskbar.cpp @@ -164,10 +164,7 @@ namespace anm2ed::imgui } if (ImGui::MenuItem("Save", settings.shortcutSave.c_str(), false, document)) - { if (settings.fileIsWarnOverwrite) overwritePopup.open(); - manager.save(); - } if (ImGui::MenuItem("Save As", settings.shortcutSaveAs.c_str(), false, document)) dialog.file_save(dialog::ANM2_SAVE); diff --git a/src/imgui/window/animation_preview.cpp b/src/imgui/window/animation_preview.cpp index 23b2a93..295eeb7 100644 --- a/src/imgui/window/animation_preview.cpp +++ b/src/imgui/window/animation_preview.cpp @@ -6,6 +6,7 @@ #include +#include "imgui_internal.h" #include "log.h" #include "math_.h" #include "toast.h" @@ -78,9 +79,7 @@ namespace anm2ed::imgui auto& columns = settings.renderColumns; if (renderFrames.empty()) - { toasts.warning("No frames captured for spritesheet export."); - } else { const auto& firstFrame = renderFrames.front(); @@ -154,8 +153,7 @@ namespace anm2ed::imgui if (auto animation = document.animation_get(); animation && animation->triggers.isVisible && (!isOnlyShowLayers || manager.isRecording)) { - if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); - trigger.is_visible(anm2::TRIGGER)) + if (auto trigger = animation->triggers.frame_generate(playback.time, anm2::TRIGGER); trigger.isVisible) if (anm2.content.sounds.contains(trigger.soundID)) anm2.content.sounds[trigger.soundID].audio.play(false, mixer); } @@ -295,6 +293,8 @@ namespace anm2ed::imgui ImGui::EndChild(); auto cursorScreenPos = ImGui::GetCursorScreenPos(); + auto min = cursorScreenPos; + auto max = to_imvec2(to_vec2(min) + size); if (manager.isRecordingStart) { @@ -307,6 +307,7 @@ namespace anm2ed::imgui settings.previewBackgroundColor = vec4(); settings.previewIsGrid = false; settings.previewIsAxes = false; + settings.previewIsBorder = false; settings.timelineIsOnlyShowLayers = true; settings.onionskinIsEnabled = false; @@ -331,7 +332,7 @@ namespace anm2ed::imgui if (isSizeTrySet) size_set(to_vec2(ImGui::GetContentRegionAvail())); viewport_set(); bind(); - clear(backgroundColor); + clear(); if (isAxes) axes_render(shaderAxes, zoom, pan, axesColor); if (isGrid) grid_render(shaderGrid, zoom, pan, gridSize, gridOffset, gridColor); @@ -362,7 +363,7 @@ namespace anm2ed::imgui auto& layer = anm2.content.layers.at(id); - if (auto frame = layerAnimation.frame_generate(time, anm2::LAYER); frame.is_visible()) + if (auto frame = layerAnimation.frame_generate(time, anm2::LAYER); frame.isVisible) { auto spritesheet = anm2.spritesheet_get(layer.spritesheetID); if (!spritesheet || !spritesheet->is_valid()) continue; @@ -467,6 +468,9 @@ namespace anm2ed::imgui unbind(); + ImGui::RenderColorRectWithAlphaCheckerboard(ImGui::GetWindowDrawList(), min, max, 0, CHECKER_SIZE, + to_imvec2(-size + pan)); + ImGui::GetCurrentWindow()->DrawList->AddRectFilled(min, max, ImGui::GetColorU32(to_imvec4(backgroundColor))); ImGui::Image(texture, to_imvec2(size)); isPreviewHovered = ImGui::IsItemHovered(); diff --git a/src/imgui/window/spritesheet_editor.cpp b/src/imgui/window/spritesheet_editor.cpp index e7f2b8c..7094796 100644 --- a/src/imgui/window/spritesheet_editor.cpp +++ b/src/imgui/window/spritesheet_editor.cpp @@ -3,6 +3,7 @@ #include #include +#include "imgui_internal.h" #include "math_.h" #include "tool.h" #include "types.h" @@ -15,13 +16,16 @@ using namespace glm; namespace anm2ed::imgui { + constexpr auto BORDER_DASH_LENGTH = 1.0f; + constexpr auto BORDER_DASH_GAP = 0.5f; + constexpr auto BORDER_DASH_OFFSET = 0.0f; + constexpr auto PIVOT_COLOR = color::PINK; SpritesheetEditor::SpritesheetEditor() : Canvas(vec2()) {} void SpritesheetEditor::update(Manager& manager, Settings& settings, Resources& resources) { - auto& document = *manager.get(); auto& anm2 = document.anm2; auto& reference = document.reference; @@ -106,11 +110,13 @@ namespace anm2ed::imgui ImGui::EndChild(); auto cursorScreenPos = ImGui::GetCursorScreenPos(); + auto min = ImGui::GetCursorScreenPos(); + auto max = to_imvec2(to_vec2(min) + size); size_set(to_vec2(ImGui::GetContentRegionAvail())); bind(); viewport_set(); - clear(backgroundColor); + clear(); auto frame = document.frame_get(); @@ -122,7 +128,9 @@ namespace anm2ed::imgui auto spritesheetModel = math::quad_model_get(texture.size); auto spritesheetTransform = transform * spritesheetModel; texture_render(shaderTexture, texture.id, spritesheetTransform); - if (isBorder) rect_render(dashedShader, spritesheetTransform, spritesheetModel); + if (isBorder) + rect_render(dashedShader, spritesheetTransform, spritesheetModel, color::WHITE, BORDER_DASH_LENGTH, + BORDER_DASH_GAP, BORDER_DASH_OFFSET); if (frame && reference.itemID > -1 && anm2.content.layers.at(reference.itemID).spritesheetID == referenceSpritesheet) @@ -141,6 +149,9 @@ namespace anm2ed::imgui unbind(); + ImGui::RenderColorRectWithAlphaCheckerboard(ImGui::GetWindowDrawList(), min, max, 0, CHECKER_SIZE, + to_imvec2(-size * 0.5f + pan)); + ImGui::GetCurrentWindow()->DrawList->AddRectFilled(min, max, ImGui::GetColorU32(to_imvec4(backgroundColor))); ImGui::Image(texture, to_imvec2(size)); if (ImGui::IsItemHovered()) @@ -233,11 +244,12 @@ namespace anm2ed::imgui case tool::MOVE: if (!frame) break; if (isBegin) document.snapshot("Frame Pivot"); - if (isMouseDown) frame->pivot = ivec2(mousePos - frame->crop); + if (isMouseDown) frame->pivot = vec2(ivec2(mousePos - frame->crop)); if (isLeftPressed) frame->pivot.x -= step; if (isRightPressed) frame->pivot.x += step; if (isUpPressed) frame->pivot.y -= step; if (isDownPressed) frame->pivot.y += step; + frame->pivot = vec2(ivec2(frame->pivot)); if (isDuring) { if (ImGui::BeginTooltip()) @@ -258,27 +270,29 @@ namespace anm2ed::imgui if (isMouseClicked) { cropAnchor = mousePos; - frame->crop = cropAnchor; + frame->crop = vec2(ivec2(cropAnchor)); frame->size = vec2(); } if (isMouseDown) { auto [minPoint, maxPoint] = snap_rect(glm::min(cropAnchor, mousePos), glm::max(cropAnchor, mousePos)); - frame->crop = minPoint; - frame->size = maxPoint - minPoint; + frame->crop = vec2(ivec2(minPoint)); + frame->size = vec2(ivec2(maxPoint - minPoint)); } if (isLeftPressed) frame->crop.x -= stepX; if (isRightPressed) frame->crop.x += stepX; if (isUpPressed) frame->crop.y -= stepY; if (isDownPressed) frame->crop.y += stepY; + frame->crop = vec2(ivec2(frame->crop)); + frame->size = vec2(ivec2(frame->size)); if (isDuring) { if (!isMouseDown) { auto minPoint = glm::min(frame->crop, frame->crop + frame->size); auto maxPoint = glm::max(frame->crop, frame->crop + frame->size); - frame->crop = minPoint; - frame->size = maxPoint - minPoint; + frame->crop = vec2(ivec2(minPoint)); + frame->size = vec2(ivec2(maxPoint - minPoint)); if (isGridSnap) { auto [snapMin, snapMax] = snap_rect(frame->crop, frame->crop + frame->size);