Expand all graphics retrieval with bitmap and vram
This commit is contained in:
@@ -49,7 +49,7 @@ add_executable(
|
|||||||
app/core/constants.cc
|
app/core/constants.cc
|
||||||
app/core/controller.cc
|
app/core/controller.cc
|
||||||
app/gfx/bitmap.cc
|
app/gfx/bitmap.cc
|
||||||
app/gfx/psuedo_vram.cc
|
app/gfx/pseudo_vram.cc
|
||||||
app/gfx/snes_tile.cc
|
app/gfx/snes_tile.cc
|
||||||
app/gfx/snes_palette.cc
|
app/gfx/snes_palette.cc
|
||||||
app/zelda3/overworld.cc
|
app/zelda3/overworld.cc
|
||||||
|
|||||||
@@ -192,90 +192,7 @@ void OverworldEditor::DrawOverworldMapSettings() {
|
|||||||
void OverworldEditor::DrawOverworldCanvas() {
|
void OverworldEditor::DrawOverworldCanvas() {
|
||||||
DrawOverworldMapSettings();
|
DrawOverworldMapSettings();
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
static ImVector<ImVec2> points;
|
overworld_map_canvas_.Update();
|
||||||
static ImVec2 scrolling(0.0f, 0.0f);
|
|
||||||
static bool opt_enable_context_menu = true;
|
|
||||||
static bool adding_line = false;
|
|
||||||
ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
|
|
||||||
ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
|
|
||||||
auto canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
|
|
||||||
|
|
||||||
// Draw border and background color
|
|
||||||
const ImGuiIO &io = ImGui::GetIO();
|
|
||||||
ImDrawList *draw_list = ImGui::GetWindowDrawList();
|
|
||||||
draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(32, 32, 32, 255));
|
|
||||||
draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
|
|
||||||
|
|
||||||
// This will catch our interactions
|
|
||||||
ImGui::InvisibleButton(
|
|
||||||
"canvas", canvas_sz,
|
|
||||||
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
|
|
||||||
const bool is_hovered = ImGui::IsItemHovered(); // Hovered
|
|
||||||
const bool is_active = ImGui::IsItemActive(); // Held
|
|
||||||
const ImVec2 origin(canvas_p0.x + scrolling.x,
|
|
||||||
canvas_p0.y + scrolling.y); // Lock scrolled origin
|
|
||||||
const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x,
|
|
||||||
io.MousePos.y - origin.y);
|
|
||||||
|
|
||||||
// Add first and second point
|
|
||||||
if (is_hovered && !adding_line &&
|
|
||||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
|
||||||
points.push_back(mouse_pos_in_canvas);
|
|
||||||
points.push_back(mouse_pos_in_canvas);
|
|
||||||
adding_line = true;
|
|
||||||
}
|
|
||||||
if (adding_line) {
|
|
||||||
points.back() = mouse_pos_in_canvas;
|
|
||||||
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) adding_line = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pan (we use a zero mouse threshold when there's no context menu)
|
|
||||||
const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
|
|
||||||
if (is_active &&
|
|
||||||
ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
|
|
||||||
scrolling.x += io.MouseDelta.x;
|
|
||||||
scrolling.y += io.MouseDelta.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Context menu (under default mouse threshold)
|
|
||||||
ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
|
|
||||||
if (opt_enable_context_menu && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
|
|
||||||
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
|
|
||||||
if (ImGui::BeginPopup("context")) {
|
|
||||||
if (adding_line) points.resize(points.size() - 2);
|
|
||||||
adding_line = false;
|
|
||||||
if (ImGui::MenuItem("Remove one", nullptr, false, points.Size > 0)) {
|
|
||||||
points.resize(points.size() - 2);
|
|
||||||
}
|
|
||||||
if (ImGui::MenuItem("Remove all", nullptr, false, points.Size > 0)) {
|
|
||||||
points.clear();
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw grid + all lines in the canvas
|
|
||||||
draw_list->PushClipRect(canvas_p0, canvas_p1, true);
|
|
||||||
if (opt_enable_grid) {
|
|
||||||
const float GRID_STEP = 64.0f;
|
|
||||||
for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x;
|
|
||||||
x += GRID_STEP)
|
|
||||||
draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y),
|
|
||||||
ImVec2(canvas_p0.x + x, canvas_p1.y),
|
|
||||||
IM_COL32(200, 200, 200, 40));
|
|
||||||
for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y;
|
|
||||||
y += GRID_STEP)
|
|
||||||
draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y),
|
|
||||||
ImVec2(canvas_p1.x, canvas_p0.y + y),
|
|
||||||
IM_COL32(200, 200, 200, 40));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int n = 0; n < points.Size; n += 2)
|
|
||||||
draw_list->AddLine(
|
|
||||||
ImVec2(origin.x + points[n].x, origin.y + points[n].y),
|
|
||||||
ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y),
|
|
||||||
IM_COL32(255, 255, 0, 255), 2.0f);
|
|
||||||
|
|
||||||
draw_list->PopClipRect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::DrawTileSelector() {
|
void OverworldEditor::DrawTileSelector() {
|
||||||
@@ -300,7 +217,10 @@ void OverworldEditor::DrawTileSelector() {
|
|||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
|
if (ImGui::BeginTabItem("VRAM")) {
|
||||||
|
DrawPseudoVRAM();
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
ImGui::EndTabBar();
|
ImGui::EndTabBar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -392,13 +312,14 @@ void OverworldEditor::DrawTile8Selector() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (all_gfx_loaded_) {
|
if (all_gfx_loaded_) {
|
||||||
for (const auto &[key, value] : all_texture_sheet_) {
|
for (const auto &[key, value] : graphics_bin_) {
|
||||||
int offset = 64 * (key + 1);
|
int offset = 64 * (key + 1);
|
||||||
int top_left_y = canvas_p0.y + 2;
|
int top_left_y = canvas_p0.y + 2;
|
||||||
if (key >= 1) {
|
if (key >= 1) {
|
||||||
top_left_y = canvas_p0.y + 64 * key;
|
top_left_y = canvas_p0.y + 64 * key;
|
||||||
}
|
}
|
||||||
draw_list->AddImage((void *)value, ImVec2(canvas_p0.x + 2, top_left_y),
|
draw_list->AddImage((void *)value.GetTexture(),
|
||||||
|
ImVec2(canvas_p0.x + 2, top_left_y),
|
||||||
ImVec2(canvas_p0.x + 256, canvas_p0.y + offset));
|
ImVec2(canvas_p0.x + 256, canvas_p0.y + offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,12 +343,20 @@ void OverworldEditor::DrawTile8Selector() const {
|
|||||||
draw_list->PopClipRect();
|
draw_list->PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverworldEditor::LoadGraphics() {
|
void OverworldEditor::DrawPseudoVRAM() {
|
||||||
for (int i = 0; i < kNumSheetsToLoad; i++) {
|
if (!vram_loaded_ && rom_.isLoaded()) {
|
||||||
all_texture_sheet_[i] = rom_.DrawGraphicsSheet(i);
|
for (int tileset_index = 0; tileset_index < 16; tileset_index++) {
|
||||||
|
rom_.GetVRAM().GetTileset(tileset_index);
|
||||||
|
}
|
||||||
|
pseudo_vram_canvas_.Update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OverworldEditor::LoadGraphics() {
|
||||||
|
rom_.DrawAllGraphicsData();
|
||||||
|
graphics_bin_ = rom_.GetGraphicsBin();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace editor
|
} // namespace editor
|
||||||
} // namespace app
|
} // namespace app
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "app/gfx/snes_palette.h"
|
#include "app/gfx/snes_palette.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
#include "app/zelda3/overworld.h"
|
#include "app/zelda3/overworld.h"
|
||||||
|
#include "gui/canvas.h"
|
||||||
#include "gui/icons.h"
|
#include "gui/icons.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
@@ -30,6 +31,7 @@ class OverworldEditor {
|
|||||||
void DrawTileSelector();
|
void DrawTileSelector();
|
||||||
void DrawTile16Selector() const;
|
void DrawTile16Selector() const;
|
||||||
void DrawTile8Selector() const;
|
void DrawTile8Selector() const;
|
||||||
|
void DrawPseudoVRAM();
|
||||||
|
|
||||||
void LoadBlockset();
|
void LoadBlockset();
|
||||||
void LoadGraphics();
|
void LoadGraphics();
|
||||||
@@ -38,6 +40,8 @@ class OverworldEditor {
|
|||||||
|
|
||||||
zelda3::Overworld overworld_;
|
zelda3::Overworld overworld_;
|
||||||
gfx::SNESPalette palette_;
|
gfx::SNESPalette palette_;
|
||||||
|
gui::Canvas overworld_map_canvas_;
|
||||||
|
gui::Canvas pseudo_vram_canvas_;
|
||||||
|
|
||||||
// pointer size 1048576
|
// pointer size 1048576
|
||||||
gfx::Bitmap tile16_blockset_bmp_;
|
gfx::Bitmap tile16_blockset_bmp_;
|
||||||
@@ -51,6 +55,7 @@ class OverworldEditor {
|
|||||||
gfx::Bitmap mapblockset16Bitmap;
|
gfx::Bitmap mapblockset16Bitmap;
|
||||||
|
|
||||||
std::unordered_map<unsigned int, SDL_Texture *> all_texture_sheet_;
|
std::unordered_map<unsigned int, SDL_Texture *> all_texture_sheet_;
|
||||||
|
std::unordered_map<unsigned int, gfx::Bitmap> graphics_bin_;
|
||||||
|
|
||||||
int current_world_ = 0;
|
int current_world_ = 0;
|
||||||
char map_gfx_[3] = "";
|
char map_gfx_[3] = "";
|
||||||
@@ -64,10 +69,11 @@ class OverworldEditor {
|
|||||||
bool opt_enable_grid = true;
|
bool opt_enable_grid = true;
|
||||||
bool all_gfx_loaded_ = false;
|
bool all_gfx_loaded_ = false;
|
||||||
bool map_blockset_loaded_ = false;
|
bool map_blockset_loaded_ = false;
|
||||||
|
bool vram_loaded_ = false;
|
||||||
|
|
||||||
constexpr static int kByteSize = 3;
|
constexpr static int kByteSize = 3;
|
||||||
constexpr static int kMessageIdSize = 5;
|
constexpr static int kMessageIdSize = 5;
|
||||||
constexpr static int kNumSheetsToLoad = 100;
|
constexpr static int kNumSheetsToLoad = 223;
|
||||||
constexpr static int kTile8DisplayHeight = 64;
|
constexpr static int kTile8DisplayHeight = 64;
|
||||||
constexpr static float kInputFieldSize = 30.f;
|
constexpr static float kInputFieldSize = 30.f;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "psuedo_vram.h"
|
#include "pseudo_vram.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace app {
|
namespace app {
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#ifndef YAZE_APP_GFX_PSUEDO_VRAM_H
|
#ifndef YAZE_APP_GFX_PSEUDO_VRAM_H
|
||||||
#define YAZE_APP_GFX_PSUEDO_VRAM_H
|
#define YAZE_APP_GFX_PSEUDO_VRAM_H
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
@@ -21,22 +21,24 @@ namespace gfx {
|
|||||||
// Palette: 256 entries; 15-Bit color (BGR555) for a total of 32,768 colors.
|
// Palette: 256 entries; 15-Bit color (BGR555) for a total of 32,768 colors.
|
||||||
// Resolution: between 256x224 and 512x448.
|
// Resolution: between 256x224 and 512x448.
|
||||||
|
|
||||||
class psuedo_vram {
|
class pseudo_vram {
|
||||||
public:
|
public:
|
||||||
void ChangeGraphicsSet(const std::vector<Bitmap>& graphics_set);
|
void ChangeGraphicsTileset(const std::vector<Bitmap>& graphics_set);
|
||||||
void ChangeGraphicsPalette(const SNESPalette& graphics_pal);
|
void ChangeGraphicsPalette(const SNESPalette& graphics_pal);
|
||||||
void ChangeSpriteSet(const std::vector<Bitmap>& sprite_set);
|
void ChangeSpriteTileset(const std::vector<Bitmap>& sprite_set);
|
||||||
void ChangeSpritePalette(const SNESPalette& sprite_pal);
|
void ChangeSpritePalette(const SNESPalette& sprite_pal);
|
||||||
|
|
||||||
|
auto GetTileset(int index) const { return m_vram.at(index); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<uint32_t, Bitmap> m_vram;
|
std::unordered_map<int, Bitmap> m_vram;
|
||||||
static const uint32_t REAL_VRAM_SIZE = 0x8000;
|
static const uint32_t REAL_VRAM_SIZE = 0x8000;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<Bitmap> CreateGraphicsSet(
|
std::vector<Bitmap> CreateGraphicsSet(
|
||||||
int id, const std::unordered_map<uint32_t, Bitmap>& all_graphics);
|
int id, const std::unordered_map<int, Bitmap>& all_graphics);
|
||||||
std::vector<Bitmap> CreateSpriteSet(
|
std::vector<Bitmap> CreateSpriteSet(
|
||||||
int id, const std::unordered_map<uint32_t, Bitmap>& all_graphics);
|
int id, const std::unordered_map<int, Bitmap>& all_graphics);
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
} // namespace app
|
} // namespace app
|
||||||
@@ -239,6 +239,10 @@ void ROM::DrawAllGraphicsData() {
|
|||||||
data = Decompress(gfx_addr, core::constants::UncompressedSheetSize);
|
data = Decompress(gfx_addr, core::constants::UncompressedSheetSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfx::Bitmap tilesheet_bmp(128, 32, 8, SNES3bppTo8bppSheet(data));
|
||||||
|
tilesheet_bmp.CreateTexture(sdl_renderer_);
|
||||||
|
graphics_bin_[i] = tilesheet_bmp;
|
||||||
|
|
||||||
for (int j = 0; j < sizeof(data); j++) {
|
for (int j = 0; j < sizeof(data); j++) {
|
||||||
buffer[j + buffer_pos] = data[j];
|
buffer[j + buffer_pos] = data[j];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include "app/core/common.h"
|
#include "app/core/common.h"
|
||||||
#include "app/core/constants.h"
|
#include "app/core/constants.h"
|
||||||
|
#include "app/gfx/pseudo_vram.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
@@ -28,7 +29,7 @@ class ROM {
|
|||||||
void Close();
|
void Close();
|
||||||
void SetupRenderer(std::shared_ptr<SDL_Renderer> renderer);
|
void SetupRenderer(std::shared_ptr<SDL_Renderer> renderer);
|
||||||
void LoadFromFile(const std::string& path);
|
void LoadFromFile(const std::string& path);
|
||||||
void LoadFromPointer(uchar *data);
|
void LoadFromPointer(uchar* data);
|
||||||
|
|
||||||
uchar* DecompressGraphics(int pos, int size);
|
uchar* DecompressGraphics(int pos, int size);
|
||||||
uchar* DecompressOverworld(int pos, int size);
|
uchar* DecompressOverworld(int pos, int size);
|
||||||
@@ -43,25 +44,27 @@ class ROM {
|
|||||||
gfx::SNESPalette ExtractPalette(uint addr, int bpp);
|
gfx::SNESPalette ExtractPalette(uint addr, int bpp);
|
||||||
|
|
||||||
uchar* data() { return current_rom_; }
|
uchar* data() { return current_rom_; }
|
||||||
auto Renderer() { return sdl_renderer_; }
|
|
||||||
const uchar* getTitle() const { return title; }
|
const uchar* getTitle() const { return title; }
|
||||||
long getSize() const { return size_; }
|
long getSize() const { return size_; }
|
||||||
bool isLoaded() const { return is_loaded_; }
|
bool isLoaded() const { return is_loaded_; }
|
||||||
|
auto Renderer() { return sdl_renderer_; }
|
||||||
|
auto GetGraphicsBin() const { return graphics_bin_; }
|
||||||
|
auto GetVRAM() const { return pseudo_vram_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_loaded_ = false;
|
|
||||||
int num_sheets_ = 0;
|
int num_sheets_ = 0;
|
||||||
long size_ = 0;
|
long size_ = 0;
|
||||||
uchar* current_rom_;
|
uchar* current_rom_;
|
||||||
uchar title[21] = "ROM Not Loaded";
|
uchar title[21] = "ROM Not Loaded";
|
||||||
enum rom_type type_ = LoROM;
|
bool is_loaded_ = false;
|
||||||
bool isbpp3[core::constants::NumberOfSheets];
|
bool isbpp3[core::constants::NumberOfSheets];
|
||||||
|
enum rom_type type_ = LoROM;
|
||||||
|
|
||||||
std::shared_ptr<uchar> rom_ptr_;
|
gfx::pseudo_vram pseudo_vram_;
|
||||||
std::vector<uchar*> decompressed_graphic_sheets_;
|
std::vector<uchar*> decompressed_graphic_sheets_;
|
||||||
std::vector<uchar*> converted_graphic_sheets_;
|
std::vector<uchar*> converted_graphic_sheets_;
|
||||||
std::vector<SDL_Surface> surfaces_;
|
|
||||||
std::shared_ptr<SDL_Renderer> sdl_renderer_;
|
std::shared_ptr<SDL_Renderer> sdl_renderer_;
|
||||||
|
std::unordered_map<unsigned int, gfx::Bitmap> graphics_bin_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
#include "app/core/constants.h"
|
#include "app/core/constants.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/psuedo_vram.h"
|
#include "app/gfx/pseudo_vram.h"
|
||||||
#include "app/gfx/snes_tile.h"
|
#include "app/gfx/snes_tile.h"
|
||||||
#include "app/rom.h"
|
#include "app/rom.h"
|
||||||
#include "app/zelda3/overworld_map.h"
|
#include "app/zelda3/overworld_map.h"
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ void OverworldMap::CopyTile8bpp16(int x, int y, int tile, uchar* destbmpPtr,
|
|||||||
void OverworldMap::CopyTile8bpp16From8(int xP, int yP, int tileID,
|
void OverworldMap::CopyTile8bpp16From8(int xP, int yP, int tileID,
|
||||||
uchar* destbmpPtr, uchar* sourcebmpPtr) {
|
uchar* destbmpPtr, uchar* sourcebmpPtr) {
|
||||||
auto gfx16Data = destbmpPtr;
|
auto gfx16Data = destbmpPtr;
|
||||||
// TODO: PSUEDO VRAM
|
// TODO: PSEUDO VRAM
|
||||||
auto gfx8Data = currentOWgfx16Ptr_;
|
auto gfx8Data = currentOWgfx16Ptr_;
|
||||||
|
|
||||||
int offsets[] = {0, 8, 4096, 4104};
|
int offsets[] = {0, 8, 4096, 4104};
|
||||||
@@ -342,7 +342,7 @@ void OverworldMap::BuildTileset(int gameState) {
|
|||||||
staticgfx[7] = 91;
|
staticgfx[7] = 91;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: PSUEDO VRAM DATA HERE
|
// TODO: PSEUDO VRAM DATA HERE
|
||||||
uchar* currentmapgfx8Data = currentOWgfx16Ptr_;
|
uchar* currentmapgfx8Data = currentOWgfx16Ptr_;
|
||||||
// TODO: PUT GRAPHICS DATA HERE
|
// TODO: PUT GRAPHICS DATA HERE
|
||||||
uchar const* allgfxData = allGfx16Ptr_;
|
uchar const* allgfxData = allGfx16Ptr_;
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ namespace gui {
|
|||||||
|
|
||||||
void Canvas::Update() {
|
void Canvas::Update() {
|
||||||
ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
|
ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
|
||||||
ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
|
if (!custom_canvas_size_) canvas_sz_ = ImGui::GetContentRegionAvail();
|
||||||
auto canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
|
|
||||||
|
auto canvas_p1 =
|
||||||
|
ImVec2(canvas_p0.x + canvas_sz_.x, canvas_p0.y + canvas_sz_.y);
|
||||||
|
|
||||||
// Draw border and background color
|
// Draw border and background color
|
||||||
const ImGuiIO &io = ImGui::GetIO();
|
const ImGuiIO &io = ImGui::GetIO();
|
||||||
@@ -21,7 +23,7 @@ void Canvas::Update() {
|
|||||||
|
|
||||||
// This will catch our interactions
|
// This will catch our interactions
|
||||||
ImGui::InvisibleButton(
|
ImGui::InvisibleButton(
|
||||||
"canvas", canvas_sz,
|
"canvas", canvas_sz_,
|
||||||
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
|
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
|
||||||
const bool is_hovered = ImGui::IsItemHovered(); // Hovered
|
const bool is_hovered = ImGui::IsItemHovered(); // Hovered
|
||||||
const bool is_active = ImGui::IsItemActive(); // Held
|
const bool is_active = ImGui::IsItemActive(); // Held
|
||||||
@@ -67,12 +69,12 @@ void Canvas::Update() {
|
|||||||
draw_list->PushClipRect(canvas_p0, canvas_p1, true);
|
draw_list->PushClipRect(canvas_p0, canvas_p1, true);
|
||||||
if (enable_grid_) {
|
if (enable_grid_) {
|
||||||
const float GRID_STEP = 64.0f;
|
const float GRID_STEP = 64.0f;
|
||||||
for (float x = fmodf(scrolling_.x, GRID_STEP); x < canvas_sz.x;
|
for (float x = fmodf(scrolling_.x, GRID_STEP); x < canvas_sz_.x;
|
||||||
x += GRID_STEP)
|
x += GRID_STEP)
|
||||||
draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y),
|
draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y),
|
||||||
ImVec2(canvas_p0.x + x, canvas_p1.y),
|
ImVec2(canvas_p0.x + x, canvas_p1.y),
|
||||||
IM_COL32(200, 200, 200, 40));
|
IM_COL32(200, 200, 200, 40));
|
||||||
for (float y = fmodf(scrolling_.y, GRID_STEP); y < canvas_sz.y;
|
for (float y = fmodf(scrolling_.y, GRID_STEP); y < canvas_sz_.y;
|
||||||
y += GRID_STEP)
|
y += GRID_STEP)
|
||||||
draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y),
|
draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y),
|
||||||
ImVec2(canvas_p1.x, canvas_p0.y + y),
|
ImVec2(canvas_p1.x, canvas_p0.y + y),
|
||||||
@@ -89,5 +91,95 @@ void Canvas::Update() {
|
|||||||
draw_list->PopClipRect();
|
draw_list->PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawBackground() {
|
||||||
|
canvas_p0_ = ImGui::GetCursorScreenPos();
|
||||||
|
if (!custom_canvas_size_) canvas_sz_ = ImGui::GetContentRegionAvail();
|
||||||
|
|
||||||
|
canvas_p1_ = ImVec2(canvas_p0_.x + canvas_sz_.x, canvas_p0_.y + canvas_sz_.y);
|
||||||
|
|
||||||
|
// Draw border and background color
|
||||||
|
draw_list_ = ImGui::GetWindowDrawList();
|
||||||
|
draw_list_->AddRectFilled(canvas_p0_, canvas_p1_, IM_COL32(32, 32, 32, 255));
|
||||||
|
draw_list_->AddRect(canvas_p0_, canvas_p1_, IM_COL32(255, 255, 255, 255));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::UpdateContext() {
|
||||||
|
// This will catch our interactions
|
||||||
|
const ImGuiIO &io = ImGui::GetIO();
|
||||||
|
ImGui::InvisibleButton(
|
||||||
|
"canvas", canvas_sz_,
|
||||||
|
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
|
||||||
|
const bool is_hovered = ImGui::IsItemHovered(); // Hovered
|
||||||
|
const bool is_active = ImGui::IsItemActive(); // Held
|
||||||
|
const ImVec2 origin(canvas_p0_.x + scrolling_.x,
|
||||||
|
canvas_p0_.y + scrolling_.y); // Lock scrolled origin
|
||||||
|
const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x,
|
||||||
|
io.MousePos.y - origin.y);
|
||||||
|
|
||||||
|
// Add first and second point
|
||||||
|
if (is_hovered && !dragging_select_ &&
|
||||||
|
ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||||
|
points_.push_back(mouse_pos_in_canvas);
|
||||||
|
points_.push_back(mouse_pos_in_canvas);
|
||||||
|
dragging_select_ = true;
|
||||||
|
}
|
||||||
|
if (dragging_select_) {
|
||||||
|
points_.back() = mouse_pos_in_canvas;
|
||||||
|
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) dragging_select_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pan (we use a zero mouse threshold when there's no context menu)
|
||||||
|
const float mouse_threshold_for_pan = enable_context_menu_ ? -1.0f : 0.0f;
|
||||||
|
if (is_active &&
|
||||||
|
ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan)) {
|
||||||
|
scrolling_.x += io.MouseDelta.x;
|
||||||
|
scrolling_.y += io.MouseDelta.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Context menu (under default mouse threshold)
|
||||||
|
ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
|
||||||
|
if (enable_context_menu_ && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
|
||||||
|
ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
|
||||||
|
if (ImGui::BeginPopup("context")) {
|
||||||
|
if (dragging_select_) points_.resize(points_.size() - 2);
|
||||||
|
dragging_select_ = false;
|
||||||
|
if (ImGui::MenuItem("Remove all", nullptr, false, points_.Size > 0)) {
|
||||||
|
points_.clear();
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawGrid() {
|
||||||
|
// Draw grid + all lines in the canvas
|
||||||
|
draw_list_->PushClipRect(canvas_p0_, canvas_p1_, true);
|
||||||
|
if (enable_grid_) {
|
||||||
|
const float GRID_STEP = 64.0f;
|
||||||
|
for (float x = fmodf(scrolling_.x, GRID_STEP); x < canvas_sz_.x;
|
||||||
|
x += GRID_STEP)
|
||||||
|
draw_list_->AddLine(ImVec2(canvas_p0_.x + x, canvas_p0_.y),
|
||||||
|
ImVec2(canvas_p0_.x + x, canvas_p1_.y),
|
||||||
|
IM_COL32(200, 200, 200, 40));
|
||||||
|
for (float y = fmodf(scrolling_.y, GRID_STEP); y < canvas_sz_.y;
|
||||||
|
y += GRID_STEP)
|
||||||
|
draw_list_->AddLine(ImVec2(canvas_p0_.x, canvas_p0_.y + y),
|
||||||
|
ImVec2(canvas_p1_.x, canvas_p0_.y + y),
|
||||||
|
IM_COL32(200, 200, 200, 40));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawOverlay() {
|
||||||
|
const ImVec2 origin(canvas_p0_.x + scrolling_.x,
|
||||||
|
canvas_p0_.y + scrolling_.y); // Lock scrolled origin
|
||||||
|
for (int n = 0; n < points_.Size; n += 2) {
|
||||||
|
draw_list_->AddRect(
|
||||||
|
ImVec2(origin.x + points_[n].x, origin.y + points_[n].y),
|
||||||
|
ImVec2(origin.x + points_[n + 1].x, origin.y + points_[n + 1].y),
|
||||||
|
IM_COL32(255, 255, 255, 255), 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_list_->PopClipRect();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <imgui/imgui.h>
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
@@ -11,18 +12,30 @@ namespace gui {
|
|||||||
class Canvas {
|
class Canvas {
|
||||||
public:
|
public:
|
||||||
Canvas() = default;
|
Canvas() = default;
|
||||||
|
Canvas(ImVec2 canvas_size)
|
||||||
|
: canvas_sz_(canvas_size), custom_canvas_size_(true) {}
|
||||||
|
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
|
void DrawBackground();
|
||||||
|
void UpdateContext();
|
||||||
|
void DrawGrid();
|
||||||
|
void DrawOverlay(); // last
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool enable_grid_ = true;
|
bool enable_grid_ = true;
|
||||||
bool enable_context_menu_ = true;
|
bool enable_context_menu_ = true;
|
||||||
bool dragging_select_ = false;
|
bool dragging_select_ = false;
|
||||||
|
bool custom_canvas_size_ = false;
|
||||||
|
|
||||||
std::string title_;
|
std::string title_;
|
||||||
|
|
||||||
|
ImDrawList* draw_list_;
|
||||||
ImVector<ImVec2> points_;
|
ImVector<ImVec2> points_;
|
||||||
ImVec2 scrolling_;
|
ImVec2 scrolling_;
|
||||||
|
ImVec2 canvas_sz_;
|
||||||
|
ImVec2 canvas_p0_;
|
||||||
|
ImVec2 canvas_p1_;
|
||||||
};
|
};
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ add_executable(
|
|||||||
yaze_test.cc
|
yaze_test.cc
|
||||||
rom_test.cc
|
rom_test.cc
|
||||||
../src/app/rom.cc
|
../src/app/rom.cc
|
||||||
|
../src/app/gfx/bitmap.cc
|
||||||
../src/app/gfx/snes_tile.cc
|
../src/app/gfx/snes_tile.cc
|
||||||
../src/app/gfx/snes_palette.cc
|
../src/app/gfx/snes_palette.cc
|
||||||
../src/app/core/common.cc
|
../src/app/core/common.cc
|
||||||
|
|||||||
Reference in New Issue
Block a user