/* * Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved. */ #include #include #include #include "tilesheeteditorview.hpp" namespace nostalgia::core { TileSheetEditorView::TileSheetEditorView(Context *ctx, const ox::String &path): m_model(ctx, path), m_pixelsDrawer(&m_model) { // build shaders oxThrowError(m_pixelsDrawer.buildShader()); oxThrowError(m_pixelGridDrawer.buildShader()); m_model.activeSubsheetChanged.connect(this, &TileSheetEditorView::setActiveSubsheet); } void TileSheetEditorView::draw() noexcept { constexpr Color32 bgColor = 0x717d7e; glClearColor(redf(bgColor), greenf(bgColor), bluef(bgColor), 1.f); glClear(GL_COLOR_BUFFER_BIT); m_pixelsDrawer.draw(updated(), m_scrollOffset); m_pixelGridDrawer.draw(updated(), m_scrollOffset); } void TileSheetEditorView::scrollV(const geo::Vec2 &paneSz, float wheel, bool zoomMod) noexcept { const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz); const ImVec2 sheetSize(pixelSize.x * static_cast(m_model.activeSubSheet()->columns) * TileWidth, pixelSize.y * static_cast(m_model.activeSubSheet()->rows) * TileHeight); if (zoomMod) { m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f); m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod); m_pixelGridDrawer.setPixelSizeMod(m_pixelSizeMod); m_updated = true; } else { m_scrollOffset.y -= wheel * 0.1f; } // adjust scroll offset in both cases because the image can be zoomed // or scrolled off screen m_scrollOffset.y = ox::clamp(m_scrollOffset.y, 0.f, sheetSize.y / 2); } void TileSheetEditorView::scrollH(const geo::Vec2 &paneSz, float wheelh) noexcept { const auto pixelSize = m_pixelsDrawer.pixelSize(paneSz); const ImVec2 sheetSize(pixelSize.x * static_cast(m_model.activeSubSheet()->columns) * TileWidth, pixelSize.y * static_cast(m_model.activeSubSheet()->rows) * TileHeight); m_scrollOffset.x += wheelh * 0.1f; m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f); } void TileSheetEditorView::clickDraw(const geo::Vec2 &paneSize, const geo::Vec2 &clickPos) noexcept { const auto pt = clickPoint(paneSize, clickPos); m_model.drawCommand(pt, m_palIdx); } void TileSheetEditorView::clickSelect(const geo::Vec2 &paneSize, const geo::Vec2 &clickPos) noexcept { const auto pt = clickPoint(paneSize, clickPos); m_model.select(pt); } void TileSheetEditorView::clickFill(const geo::Vec2 &paneSize, const geo::Vec2 &clickPos) noexcept { const auto pt = clickPoint(paneSize, clickPos); m_model.fill(pt, m_palIdx); } void TileSheetEditorView::releaseMouseButton() noexcept { m_model.endDrawCommand(); m_model.completeSelection(); } void TileSheetEditorView::resizeView(const geo::Vec2 &sz) noexcept { m_viewSize = sz; initView(); } bool TileSheetEditorView::updated() const noexcept { return m_updated || m_model.updated(); } void TileSheetEditorView::ackUpdate() noexcept { m_updated = false; m_model.ackUpdate(); } void TileSheetEditorView::initView() noexcept { m_pixelsDrawer.initBufferSet(m_viewSize); m_pixelGridDrawer.initBufferSet(m_viewSize, *m_model.activeSubSheet()); } geo::Point TileSheetEditorView::clickPoint(const geo::Vec2 &paneSize, const geo::Vec2 &clickPos) const noexcept { auto [x, y] = clickPos; const auto pixDrawSz = m_pixelsDrawer.pixelSize(paneSize); x /= paneSize.x; y /= paneSize.y; x += -m_scrollOffset.x / 2; y += m_scrollOffset.y / 2; x /= pixDrawSz.x; y /= pixDrawSz.y; return {static_cast(x * 2), static_cast(y * 2)}; } ox::Error TileSheetEditorView::setActiveSubsheet(const TileSheet::SubSheetIdx&) noexcept { initView(); return OxError(0); } }