Copy image to clipboard for GraphicsEditor
This commit is contained in:
@@ -86,6 +86,7 @@ if(APPLE)
|
|||||||
app/core/platform/file_dialog.mm
|
app/core/platform/file_dialog.mm
|
||||||
app/core/platform/app_delegate.mm
|
app/core/platform/app_delegate.mm
|
||||||
app/core/platform/font_loader.mm
|
app/core/platform/font_loader.mm
|
||||||
|
app/core/platform/clipboard.mm
|
||||||
)
|
)
|
||||||
|
|
||||||
find_library(COCOA_LIBRARY Cocoa)
|
find_library(COCOA_LIBRARY Cocoa)
|
||||||
|
|||||||
10
src/app/core/platform/clipboard.h
Normal file
10
src/app/core/platform/clipboard.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
void CopyImageToClipboard(const std::vector<uint8_t>& data);
|
||||||
|
void GetImageFromClipboard(std::vector<uint8_t>& data, int& width, int& height);
|
||||||
|
|
||||||
|
#endif
|
||||||
42
src/app/core/platform/clipboard.mm
Normal file
42
src/app/core/platform/clipboard.mm
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
#include "clipboard.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
void CopyImageToClipboard(const std::vector<uint8_t>& pngData) {
|
||||||
|
NSData* data = [NSData dataWithBytes:pngData.data() length:pngData.size()];
|
||||||
|
NSImage* image = [[NSImage alloc] initWithData:data];
|
||||||
|
|
||||||
|
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||||
|
[pasteboard clearContents];
|
||||||
|
[pasteboard writeObjects:@[ image ]];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetImageFromClipboard(std::vector<uint8_t>& pixel_data, int& width, int& height) {
|
||||||
|
NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
|
||||||
|
NSArray* classArray = [NSArray arrayWithObject:[NSImage class]];
|
||||||
|
NSDictionary* options = [NSDictionary dictionary];
|
||||||
|
|
||||||
|
NSImage* image = [pasteboard readObjectsForClasses:classArray options:options].firstObject;
|
||||||
|
if (!image) {
|
||||||
|
width = height = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assuming the image is in an RGBA format
|
||||||
|
CGImageRef cgImage = [image CGImageForProposedRect:nil context:nil hints:nil];
|
||||||
|
width = (int)CGImageGetWidth(cgImage);
|
||||||
|
height = (int)CGImageGetHeight(cgImage);
|
||||||
|
|
||||||
|
size_t bytesPerRow = 4 * width;
|
||||||
|
size_t totalBytes = bytesPerRow * height;
|
||||||
|
pixel_data.resize(totalBytes);
|
||||||
|
|
||||||
|
CGContextRef context = CGBitmapContextCreate(
|
||||||
|
pixel_data.data(), width, height, 8, bytesPerRow, CGColorSpaceCreateDeviceRGB(),
|
||||||
|
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
|
||||||
|
CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage);
|
||||||
|
CGContextRelease(context);
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "absl/status/status.h"
|
#include "absl/status/status.h"
|
||||||
#include "absl/status/statusor.h"
|
#include "absl/status/statusor.h"
|
||||||
|
#include "app/core/platform/clipboard.h"
|
||||||
#include "app/editor/modules/palette_editor.h"
|
#include "app/editor/modules/palette_editor.h"
|
||||||
#include "app/gfx/bitmap.h"
|
#include "app/gfx/bitmap.h"
|
||||||
#include "app/gfx/compression.h"
|
#include "app/gfx/compression.h"
|
||||||
@@ -28,6 +29,16 @@ using ImGui::InputInt;
|
|||||||
using ImGui::InputText;
|
using ImGui::InputText;
|
||||||
using ImGui::SameLine;
|
using ImGui::SameLine;
|
||||||
|
|
||||||
|
constexpr ImGuiTableFlags kGfxEditTableFlags =
|
||||||
|
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable |
|
||||||
|
ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable |
|
||||||
|
ImGuiTableFlags_SizingFixedFit;
|
||||||
|
|
||||||
|
constexpr ImGuiTabBarFlags kGfxEditTabBarFlags =
|
||||||
|
ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable |
|
||||||
|
ImGuiTabBarFlags_FittingPolicyResizeDown |
|
||||||
|
ImGuiTabBarFlags_TabListPopupButton;
|
||||||
|
|
||||||
absl::Status GraphicsEditor::Update() {
|
absl::Status GraphicsEditor::Update() {
|
||||||
TAB_BAR("##TabBar")
|
TAB_BAR("##TabBar")
|
||||||
status_ = UpdateGfxEdit();
|
status_ = UpdateGfxEdit();
|
||||||
@@ -41,11 +52,7 @@ absl::Status GraphicsEditor::Update() {
|
|||||||
absl::Status GraphicsEditor::UpdateGfxEdit() {
|
absl::Status GraphicsEditor::UpdateGfxEdit() {
|
||||||
TAB_ITEM("Graphics Editor")
|
TAB_ITEM("Graphics Editor")
|
||||||
|
|
||||||
if (ImGui::BeginTable("##GfxEditTable", 3,
|
if (ImGui::BeginTable("##GfxEditTable", 3, kGfxEditTableFlags,
|
||||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable |
|
|
||||||
ImGuiTableFlags_Reorderable |
|
|
||||||
ImGuiTableFlags_Hideable |
|
|
||||||
ImGuiTableFlags_SizingFixedFit,
|
|
||||||
ImVec2(0, 0))) {
|
ImVec2(0, 0))) {
|
||||||
for (const auto& name : kGfxEditColumnNames)
|
for (const auto& name : kGfxEditColumnNames)
|
||||||
ImGui::TableSetupColumn(name.data());
|
ImGui::TableSetupColumn(name.data());
|
||||||
@@ -73,33 +80,62 @@ absl::Status GraphicsEditor::UpdateGfxEdit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsEditor::DrawGfxEditToolset() {
|
void GraphicsEditor::DrawGfxEditToolset() {
|
||||||
if (ImGui::BeginTable("##GfxEditToolset", 7, ImGuiTableFlags_SizingFixedFit,
|
if (ImGui::BeginTable("##GfxEditToolset", 9, ImGuiTableFlags_SizingFixedFit,
|
||||||
ImVec2(0, 0))) {
|
ImVec2(0, 0))) {
|
||||||
for (const auto& name : {"Select", "Pencil", "Fill", "Zoom Out", "Zoom In",
|
for (const auto& name :
|
||||||
"Current Color", "Tile Size"})
|
{"Select", "Pencil", "Fill", "Copy Sheet", "Paste Sheet", "Zoom Out",
|
||||||
|
"Zoom In", "Current Color", "Tile Size"})
|
||||||
ImGui::TableSetupColumn(name);
|
ImGui::TableSetupColumn(name);
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_SELECT_ALL)) {
|
if (Button(ICON_MD_SELECT_ALL)) {
|
||||||
|
gfx_edit_mode_ = GfxEditMode::kSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_DRAW)) {
|
if (Button(ICON_MD_DRAW)) {
|
||||||
|
gfx_edit_mode_ = GfxEditMode::kPencil;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_FORMAT_COLOR_FILL)) {
|
if (Button(ICON_MD_FORMAT_COLOR_FILL)) {
|
||||||
|
gfx_edit_mode_ = GfxEditMode::kFill;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_ZOOM_OUT)) {
|
if (Button(ICON_MD_CONTENT_COPY)) {
|
||||||
|
std::vector<uint8_t> png_data =
|
||||||
|
rom()->bitmap_manager().GetBitmap(current_sheet_)->GetPngData();
|
||||||
|
CopyImageToClipboard(png_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (Button(ICON_MD_CONTENT_PASTE)) {
|
||||||
|
std::vector<uint8_t> png_data;
|
||||||
|
int width, height;
|
||||||
|
GetImageFromClipboard(png_data, width, height);
|
||||||
|
if (png_data.size() > 0) {
|
||||||
|
rom()
|
||||||
|
->bitmap_manager()
|
||||||
|
.GetBitmap(current_sheet_)
|
||||||
|
->LoadFromPngData(png_data, width, height);
|
||||||
|
rom()->UpdateBitmap(rom()
|
||||||
|
->mutable_bitmap_manager()
|
||||||
|
->mutable_bitmap(current_sheet_)
|
||||||
|
.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HOVER_HINT("Paste from Clipboard");
|
||||||
|
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
if (Button(ICON_MD_ZOOM_OUT)) {
|
||||||
if (current_scale_ >= 0.0f) {
|
if (current_scale_ >= 0.0f) {
|
||||||
current_scale_ -= 1.0f;
|
current_scale_ -= 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button(ICON_MD_ZOOM_IN)) {
|
if (Button(ICON_MD_ZOOM_IN)) {
|
||||||
if (current_scale_ <= 16.0f) {
|
if (current_scale_ <= 16.0f) {
|
||||||
current_scale_ += 1.0f;
|
current_scale_ += 1.0f;
|
||||||
}
|
}
|
||||||
@@ -129,38 +165,42 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() {
|
|||||||
ImGuiWindowFlags_NoDecoration);
|
ImGuiWindowFlags_NoDecoration);
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
gui::Canvas graphics_bin_canvas_;
|
gui::Canvas graphics_bin_canvas_;
|
||||||
graphics_bin_canvas_.UpdateEvent(
|
auto select_tile_event = [&]() {
|
||||||
[&]() {
|
if (value.get()->IsActive()) {
|
||||||
if (value.get()->IsActive()) {
|
auto texture = value.get()->texture();
|
||||||
auto texture = value.get()->texture();
|
graphics_bin_canvas_.GetDrawList()->AddImage(
|
||||||
graphics_bin_canvas_.GetDrawList()->AddImage(
|
(void*)texture,
|
||||||
(void*)texture,
|
ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 2,
|
||||||
ImVec2(graphics_bin_canvas_.GetZeroPoint().x + 2,
|
graphics_bin_canvas_.GetZeroPoint().y + 2),
|
||||||
graphics_bin_canvas_.GetZeroPoint().y + 2),
|
ImVec2(graphics_bin_canvas_.GetZeroPoint().x +
|
||||||
ImVec2(graphics_bin_canvas_.GetZeroPoint().x +
|
value.get()->width() * sheet_scale_,
|
||||||
value.get()->width() * sheet_scale_,
|
graphics_bin_canvas_.GetZeroPoint().y +
|
||||||
graphics_bin_canvas_.GetZeroPoint().y +
|
value.get()->height() * sheet_scale_));
|
||||||
value.get()->height() * sheet_scale_));
|
|
||||||
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
|
||||||
current_sheet_ = key;
|
|
||||||
open_sheets_.insert(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a slightly transparent rectangle behind the text
|
if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
|
||||||
ImVec2 textPos(graphics_bin_canvas_.GetZeroPoint().x + 2,
|
current_sheet_ = key;
|
||||||
graphics_bin_canvas_.GetZeroPoint().y + 2);
|
open_sheets_.insert(key);
|
||||||
ImVec2 textSize =
|
}
|
||||||
ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str());
|
|
||||||
ImVec2 rectMin(textPos.x, textPos.y);
|
// Add a slightly transparent rectangle behind the text
|
||||||
ImVec2 rectMax(textPos.x + textSize.x, textPos.y + textSize.y);
|
ImVec2 text_pos(graphics_bin_canvas_.GetZeroPoint().x + 2,
|
||||||
graphics_bin_canvas_.GetDrawList()->AddRectFilled(
|
graphics_bin_canvas_.GetZeroPoint().y + 2);
|
||||||
rectMin, rectMax, IM_COL32(0, 125, 0, 128));
|
ImVec2 text_size =
|
||||||
graphics_bin_canvas_.GetDrawList()->AddText(
|
ImGui::CalcTextSize(absl::StrFormat("%02X", key).c_str());
|
||||||
textPos, IM_COL32(125, 255, 125, 255),
|
ImVec2 rent_min(text_pos.x, text_pos.y);
|
||||||
absl::StrFormat("%02X", key).c_str());
|
ImVec2 rent_max(text_pos.x + text_size.x, text_pos.y + text_size.y);
|
||||||
}
|
|
||||||
},
|
graphics_bin_canvas_.GetDrawList()->AddRectFilled(
|
||||||
ImVec2(0x100 + 1, 0x40 + 1), 0x20, sheet_scale_,
|
rent_min, rent_max, IM_COL32(0, 125, 0, 128));
|
||||||
|
|
||||||
|
graphics_bin_canvas_.GetDrawList()->AddText(
|
||||||
|
text_pos, IM_COL32(125, 255, 125, 255),
|
||||||
|
absl::StrFormat("%02X", key).c_str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
graphics_bin_canvas_.UpdateEvent(
|
||||||
|
select_tile_event, ImVec2(0x100 + 1, 0x40 + 1), 0x20, sheet_scale_,
|
||||||
/*grid_size=*/16.0f);
|
/*grid_size=*/16.0f);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@@ -173,11 +213,7 @@ absl::Status GraphicsEditor::UpdateGfxSheetList() {
|
|||||||
absl::Status GraphicsEditor::UpdateGfxTabView() {
|
absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||||
static int next_tab_id = 0;
|
static int next_tab_id = 0;
|
||||||
|
|
||||||
if (ImGui::BeginTabBar("##GfxEditTabBar",
|
if (ImGui::BeginTabBar("##GfxEditTabBar", kGfxEditTabBarFlags)) {
|
||||||
ImGuiTabBarFlags_AutoSelectNewTabs |
|
|
||||||
ImGuiTabBarFlags_Reorderable |
|
|
||||||
ImGuiTabBarFlags_FittingPolicyResizeDown |
|
|
||||||
ImGuiTabBarFlags_TabListPopupButton)) {
|
|
||||||
if (ImGui::TabItemButton(
|
if (ImGui::TabItemButton(
|
||||||
"+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) {
|
"+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) {
|
||||||
open_sheets_.insert(next_tab_id++);
|
open_sheets_.insert(next_tab_id++);
|
||||||
@@ -185,6 +221,8 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
|||||||
|
|
||||||
// Submit our regular tabs
|
// Submit our regular tabs
|
||||||
for (auto& each : open_sheets_) {
|
for (auto& each : open_sheets_) {
|
||||||
|
current_sheet_ = each;
|
||||||
|
|
||||||
bool open = true;
|
bool open = true;
|
||||||
if (ImGui::BeginTabItem(absl::StrFormat("%d", each).c_str(), &open,
|
if (ImGui::BeginTabItem(absl::StrFormat("%d", each).c_str(), &open,
|
||||||
ImGuiTabItemFlags_None)) {
|
ImGuiTabItemFlags_None)) {
|
||||||
@@ -197,59 +235,61 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
|||||||
child_window_sheets_.insert(each);
|
child_window_sheets_.insert(each);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::BeginChild(
|
|
||||||
absl::StrFormat("##GfxEditPaletteChild%d", each).c_str(),
|
const auto child_id =
|
||||||
ImVec2(0, 0), true,
|
absl::StrFormat("##GfxEditPaletteChildWindow%d", each);
|
||||||
ImGuiWindowFlags_NoDecoration |
|
ImGui::BeginChild(child_id.c_str(), ImVec2(0, 0), true,
|
||||||
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
ImGuiWindowFlags_NoDecoration |
|
||||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
||||||
current_sheet_ = each;
|
ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||||
|
|
||||||
|
auto draw_tile_event = [&]() {
|
||||||
|
// Convert the ImVec4 into a 16-bit value
|
||||||
|
Uint8 r = static_cast<Uint8>(current_color_.x * 31);
|
||||||
|
Uint8 g = static_cast<Uint8>(current_color_.y * 31);
|
||||||
|
Uint8 b = static_cast<Uint8>(current_color_.z * 31);
|
||||||
|
Uint16 snes_color =
|
||||||
|
((r & 0x1F) << 10) | ((g & 0x1F) << 5) | (b & 0x1F);
|
||||||
|
|
||||||
|
auto click_position =
|
||||||
|
current_sheet_canvas_.GetCurrentDrawnTilePosition();
|
||||||
|
|
||||||
|
// Calculate the tile index for x and y based on the
|
||||||
|
// click_position
|
||||||
|
int tile_index_x =
|
||||||
|
(static_cast<int>(click_position.x) % 8) / tile_size_;
|
||||||
|
int tile_index_y =
|
||||||
|
(static_cast<int>(click_position.y) % 8) / tile_size_;
|
||||||
|
|
||||||
|
// Calculate the pixel start position based on tile index and tile
|
||||||
|
// size
|
||||||
|
ImVec2 start_position;
|
||||||
|
start_position.x = tile_index_x * tile_size_;
|
||||||
|
start_position.y = tile_index_y * tile_size_;
|
||||||
|
|
||||||
|
// Get the current map's bitmap from the BitmapTable
|
||||||
|
gfx::Bitmap& current_bitmap = *rom()->bitmap_manager()[each];
|
||||||
|
|
||||||
|
// Update the bitmap's pixel data based on the start_position and
|
||||||
|
// tile_data
|
||||||
|
for (int y = 0; y < tile_size_; ++y) {
|
||||||
|
for (int x = 0; x < tile_size_; ++x) {
|
||||||
|
int pixel_index =
|
||||||
|
(start_position.y + y) * current_bitmap.width() +
|
||||||
|
(start_position.x + x);
|
||||||
|
current_bitmap.WriteToPixel(pixel_index, snes_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rom()->bitmap_manager()[each]->WriteToPixel(position,
|
||||||
|
// snesColor);
|
||||||
|
|
||||||
|
rom()->UpdateBitmap(
|
||||||
|
rom()->mutable_bitmap_manager()->mutable_bitmap(each).get());
|
||||||
|
};
|
||||||
|
|
||||||
current_sheet_canvas_.UpdateColorPainter(
|
current_sheet_canvas_.UpdateColorPainter(
|
||||||
*rom()->bitmap_manager()[each], current_color_,
|
*rom()->bitmap_manager()[each], current_color_, draw_tile_event,
|
||||||
[&]() {
|
|
||||||
// Convert the ImVec4 into a 16-bit value
|
|
||||||
Uint8 r = static_cast<Uint8>(current_color_.x * 31);
|
|
||||||
Uint8 g = static_cast<Uint8>(current_color_.y * 31);
|
|
||||||
Uint8 b = static_cast<Uint8>(current_color_.z * 31);
|
|
||||||
Uint16 snesColor =
|
|
||||||
((r & 0x1F) << 10) | ((g & 0x1F) << 5) | (b & 0x1F);
|
|
||||||
|
|
||||||
auto click_position =
|
|
||||||
current_sheet_canvas_.GetCurrentDrawnTilePosition();
|
|
||||||
|
|
||||||
// Calculate the tile index for x and y based on the
|
|
||||||
// click_position
|
|
||||||
int tile_index_x =
|
|
||||||
(static_cast<int>(click_position.x) % 8) / tile_size_;
|
|
||||||
int tile_index_y =
|
|
||||||
(static_cast<int>(click_position.y) % 8) / tile_size_;
|
|
||||||
|
|
||||||
// Calculate the pixel start position based on tile index and tile
|
|
||||||
// size
|
|
||||||
ImVec2 start_position;
|
|
||||||
start_position.x = tile_index_x * tile_size_;
|
|
||||||
start_position.y = tile_index_y * tile_size_;
|
|
||||||
|
|
||||||
// Get the current map's bitmap from the BitmapTable
|
|
||||||
gfx::Bitmap& current_bitmap = *rom()->bitmap_manager()[each];
|
|
||||||
|
|
||||||
// Update the bitmap's pixel data based on the start_position and
|
|
||||||
// tile_data
|
|
||||||
for (int y = 0; y < tile_size_; ++y) {
|
|
||||||
for (int x = 0; x < tile_size_; ++x) {
|
|
||||||
int pixel_index =
|
|
||||||
(start_position.y + y) * current_bitmap.width() +
|
|
||||||
(start_position.x + x);
|
|
||||||
current_bitmap.WriteToPixel(pixel_index, snesColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rom()->bitmap_manager()[each]->WriteToPixel(position,
|
|
||||||
// snesColor);
|
|
||||||
|
|
||||||
rom()->UpdateBitmap(
|
|
||||||
rom()->mutable_bitmap_manager()->mutable_bitmap(each).get());
|
|
||||||
},
|
|
||||||
ImVec2(0x100, 0x40), tile_size_, current_scale_, 8.0f);
|
ImVec2(0x100, 0x40), tile_size_, current_scale_, 8.0f);
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
@@ -297,7 +337,7 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
absl::Status GraphicsEditor::UpdatePaletteColumn() {
|
absl::Status GraphicsEditor::UpdatePaletteColumn() {
|
||||||
auto palette_group = rom()->GetPaletteGroup(
|
auto palette_group = rom()->palette_group(
|
||||||
kPaletteGroupAddressesKeys[edit_palette_group_name_index_]);
|
kPaletteGroupAddressesKeys[edit_palette_group_name_index_]);
|
||||||
|
|
||||||
auto palette = palette_group[edit_palette_index_];
|
auto palette = palette_group[edit_palette_index_];
|
||||||
@@ -678,7 +718,7 @@ absl::Status GraphicsEditor::DecompressImportData(int size) {
|
|||||||
converted_sheet);
|
converted_sheet);
|
||||||
|
|
||||||
if (rom()->isLoaded()) {
|
if (rom()->isLoaded()) {
|
||||||
auto palette_group = rom()->GetPaletteGroup("ow_main");
|
auto palette_group = rom()->palette_group("ow_main");
|
||||||
z3_rom_palette_ = palette_group[current_palette_];
|
z3_rom_palette_ = palette_group[current_palette_];
|
||||||
if (col_file_) {
|
if (col_file_) {
|
||||||
bin_bitmap_.ApplyPalette(col_file_palette_);
|
bin_bitmap_.ApplyPalette(col_file_palette_);
|
||||||
@@ -711,7 +751,7 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
|
|||||||
} else {
|
} else {
|
||||||
// ROM palette
|
// ROM palette
|
||||||
auto palette_group =
|
auto palette_group =
|
||||||
rom()->GetPaletteGroup(kPaletteGroupAddressesKeys[current_palette_]);
|
rom()->palette_group(kPaletteGroupAddressesKeys[current_palette_]);
|
||||||
z3_rom_palette_ = palette_group[current_palette_index_];
|
z3_rom_palette_ = palette_group[current_palette_index_];
|
||||||
graphics_bin_[i].ApplyPalette(z3_rom_palette_);
|
graphics_bin_[i].ApplyPalette(z3_rom_palette_);
|
||||||
}
|
}
|
||||||
@@ -736,7 +776,7 @@ absl::Status GraphicsEditor::DecompressSuperDonkey() {
|
|||||||
} else {
|
} else {
|
||||||
// ROM palette
|
// ROM palette
|
||||||
auto palette_group =
|
auto palette_group =
|
||||||
rom()->GetPaletteGroup(kPaletteGroupAddressesKeys[current_palette_]);
|
rom()->palette_group(kPaletteGroupAddressesKeys[current_palette_]);
|
||||||
z3_rom_palette_ = palette_group[current_palette_index_];
|
z3_rom_palette_ = palette_group[current_palette_index_];
|
||||||
graphics_bin_[i].ApplyPalette(z3_rom_palette_);
|
graphics_bin_[i].ApplyPalette(z3_rom_palette_);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,12 +67,18 @@ class GraphicsEditor : public SharedROM {
|
|||||||
absl::Status Update();
|
absl::Status Update();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class GfxEditMode {
|
||||||
|
kSelect,
|
||||||
|
kPencil,
|
||||||
|
kFill,
|
||||||
|
};
|
||||||
|
|
||||||
// Graphics Editor Tab
|
// Graphics Editor Tab
|
||||||
absl::Status UpdateGfxEdit();
|
absl::Status UpdateGfxEdit();
|
||||||
void DrawGfxEditToolset();
|
|
||||||
absl::Status UpdateGfxSheetList();
|
absl::Status UpdateGfxSheetList();
|
||||||
absl::Status UpdateGfxTabView();
|
absl::Status UpdateGfxTabView();
|
||||||
absl::Status UpdatePaletteColumn();
|
absl::Status UpdatePaletteColumn();
|
||||||
|
void DrawGfxEditToolset();
|
||||||
|
|
||||||
// Link Graphics Edit Tab
|
// Link Graphics Edit Tab
|
||||||
absl::Status UpdateLinkGfxView();
|
absl::Status UpdateLinkGfxView();
|
||||||
@@ -80,23 +86,24 @@ class GraphicsEditor : public SharedROM {
|
|||||||
// Prototype Graphics Viewer
|
// Prototype Graphics Viewer
|
||||||
absl::Status UpdateScadView();
|
absl::Status UpdateScadView();
|
||||||
|
|
||||||
absl::Status DrawToolset();
|
// Import Functions
|
||||||
|
|
||||||
absl::Status DrawCgxImport();
|
absl::Status DrawCgxImport();
|
||||||
absl::Status DrawScrImport();
|
absl::Status DrawScrImport();
|
||||||
absl::Status DrawFileImport();
|
absl::Status DrawFileImport();
|
||||||
absl::Status DrawObjImport();
|
absl::Status DrawObjImport();
|
||||||
absl::Status DrawTilemapImport();
|
absl::Status DrawTilemapImport();
|
||||||
|
|
||||||
|
// Other Functions
|
||||||
|
absl::Status DrawToolset();
|
||||||
absl::Status DrawPaletteControls();
|
absl::Status DrawPaletteControls();
|
||||||
absl::Status DrawClipboardImport();
|
absl::Status DrawClipboardImport();
|
||||||
absl::Status DrawExperimentalFeatures();
|
absl::Status DrawExperimentalFeatures();
|
||||||
absl::Status DrawMemoryEditor();
|
absl::Status DrawMemoryEditor();
|
||||||
|
|
||||||
absl::Status DecompressImportData(int size);
|
absl::Status DecompressImportData(int size);
|
||||||
|
|
||||||
absl::Status DecompressSuperDonkey();
|
absl::Status DecompressSuperDonkey();
|
||||||
|
|
||||||
|
// Member Variables
|
||||||
ImVec4 current_color_;
|
ImVec4 current_color_;
|
||||||
uint16_t current_sheet_ = 0;
|
uint16_t current_sheet_ = 0;
|
||||||
uint8_t tile_size_ = 0x08;
|
uint8_t tile_size_ = 0x08;
|
||||||
@@ -115,92 +122,67 @@ class GraphicsEditor : public SharedROM {
|
|||||||
uint64_t current_offset_ = 0;
|
uint64_t current_offset_ = 0;
|
||||||
uint64_t current_size_ = 0;
|
uint64_t current_size_ = 0;
|
||||||
uint64_t current_palette_index_ = 0;
|
uint64_t current_palette_index_ = 0;
|
||||||
|
|
||||||
int current_bpp_ = 0;
|
int current_bpp_ = 0;
|
||||||
|
|
||||||
int scr_mod_value_ = 0;
|
int scr_mod_value_ = 0;
|
||||||
|
|
||||||
uint64_t num_sheets_to_load_ = 1;
|
uint64_t num_sheets_to_load_ = 1;
|
||||||
|
|
||||||
uint64_t bin_size_ = 0;
|
uint64_t bin_size_ = 0;
|
||||||
|
|
||||||
uint64_t clipboard_offset_ = 0;
|
uint64_t clipboard_offset_ = 0;
|
||||||
uint64_t clipboard_size_ = 0;
|
uint64_t clipboard_size_ = 0;
|
||||||
|
|
||||||
bool refresh_graphics_ = false;
|
bool refresh_graphics_ = false;
|
||||||
bool open_memory_editor_ = false;
|
bool open_memory_editor_ = false;
|
||||||
|
|
||||||
bool gfx_loaded_ = false;
|
bool gfx_loaded_ = false;
|
||||||
bool is_open_ = false;
|
bool is_open_ = false;
|
||||||
bool super_donkey_ = false;
|
bool super_donkey_ = false;
|
||||||
|
|
||||||
bool col_file_ = false;
|
bool col_file_ = false;
|
||||||
bool cgx_loaded_ = false;
|
bool cgx_loaded_ = false;
|
||||||
bool scr_loaded_ = false;
|
bool scr_loaded_ = false;
|
||||||
bool obj_loaded_ = false;
|
bool obj_loaded_ = false;
|
||||||
|
|
||||||
bool tilemap_loaded_ = false;
|
bool tilemap_loaded_ = false;
|
||||||
|
|
||||||
char file_path_[256] = "";
|
char file_path_[256] = "";
|
||||||
char col_file_path_[256] = "";
|
char col_file_path_[256] = "";
|
||||||
char col_file_name_[256] = "";
|
char col_file_name_[256] = "";
|
||||||
|
|
||||||
char cgx_file_path_[256] = "";
|
char cgx_file_path_[256] = "";
|
||||||
char cgx_file_name_[256] = "";
|
char cgx_file_name_[256] = "";
|
||||||
|
|
||||||
char scr_file_path_[256] = "";
|
char scr_file_path_[256] = "";
|
||||||
char scr_file_name_[256] = "";
|
char scr_file_name_[256] = "";
|
||||||
|
|
||||||
char obj_file_path_[256] = "";
|
char obj_file_path_[256] = "";
|
||||||
|
|
||||||
char tilemap_file_path_[256] = "";
|
char tilemap_file_path_[256] = "";
|
||||||
char tilemap_file_name_[256] = "";
|
char tilemap_file_name_[256] = "";
|
||||||
|
|
||||||
|
GfxEditMode gfx_edit_mode_ = GfxEditMode::kSelect;
|
||||||
|
|
||||||
ROM temp_rom_;
|
ROM temp_rom_;
|
||||||
ROM tilemap_rom_;
|
ROM tilemap_rom_;
|
||||||
|
|
||||||
zelda3::Overworld overworld_;
|
zelda3::Overworld overworld_;
|
||||||
|
|
||||||
MemoryEditor cgx_memory_editor_;
|
MemoryEditor cgx_memory_editor_;
|
||||||
MemoryEditor col_memory_editor_;
|
MemoryEditor col_memory_editor_;
|
||||||
|
|
||||||
PaletteEditor palette_editor_;
|
PaletteEditor palette_editor_;
|
||||||
|
|
||||||
Bytes import_data_;
|
Bytes import_data_;
|
||||||
Bytes graphics_buffer_;
|
Bytes graphics_buffer_;
|
||||||
|
|
||||||
std::vector<uint8_t> decoded_cgx_;
|
std::vector<uint8_t> decoded_cgx_;
|
||||||
std::vector<uint8_t> cgx_data_;
|
std::vector<uint8_t> cgx_data_;
|
||||||
std::vector<uint8_t> extra_cgx_data_;
|
std::vector<uint8_t> extra_cgx_data_;
|
||||||
std::vector<SDL_Color> decoded_col_;
|
std::vector<SDL_Color> decoded_col_;
|
||||||
|
|
||||||
std::vector<uint8_t> scr_data_;
|
std::vector<uint8_t> scr_data_;
|
||||||
std::vector<uint8_t> decoded_scr_data_;
|
std::vector<uint8_t> decoded_scr_data_;
|
||||||
|
|
||||||
gfx::Bitmap cgx_bitmap_;
|
gfx::Bitmap cgx_bitmap_;
|
||||||
gfx::Bitmap scr_bitmap_;
|
gfx::Bitmap scr_bitmap_;
|
||||||
gfx::Bitmap bin_bitmap_;
|
gfx::Bitmap bin_bitmap_;
|
||||||
|
|
||||||
gfx::Bitmap link_full_sheet_;
|
gfx::Bitmap link_full_sheet_;
|
||||||
|
|
||||||
gfx::BitmapTable graphics_bin_;
|
gfx::BitmapTable graphics_bin_;
|
||||||
gfx::BitmapTable clipboard_graphics_bin_;
|
gfx::BitmapTable clipboard_graphics_bin_;
|
||||||
|
|
||||||
gfx::BitmapTable link_graphics_;
|
gfx::BitmapTable link_graphics_;
|
||||||
|
|
||||||
gfx::PaletteGroup col_file_palette_group_;
|
gfx::PaletteGroup col_file_palette_group_;
|
||||||
|
|
||||||
gfx::SNESPalette z3_rom_palette_;
|
gfx::SNESPalette z3_rom_palette_;
|
||||||
gfx::SNESPalette col_file_palette_;
|
gfx::SNESPalette col_file_palette_;
|
||||||
|
|
||||||
gfx::SNESPalette link_palette_;
|
gfx::SNESPalette link_palette_;
|
||||||
|
|
||||||
gui::Canvas import_canvas_;
|
gui::Canvas import_canvas_;
|
||||||
gui::Canvas scr_canvas_;
|
gui::Canvas scr_canvas_;
|
||||||
gui::Canvas super_donkey_canvas_;
|
gui::Canvas super_donkey_canvas_;
|
||||||
gui::Canvas current_sheet_canvas_;
|
gui::Canvas current_sheet_canvas_;
|
||||||
// gui::Canvas graphics_bin_canvas_;
|
|
||||||
|
|
||||||
absl::Status status_;
|
absl::Status status_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "bitmap.h"
|
#include "bitmap.h"
|
||||||
|
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#include <png.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -23,6 +24,174 @@ void GrayscalePalette(SDL_Palette *palette) {
|
|||||||
palette->colors[i].b = i * 31;
|
palette->colors[i].b = i * 31;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PngWriteCallback(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||||
|
std::vector<uint8_t> *p = (std::vector<uint8_t> *)png_get_io_ptr(png_ptr);
|
||||||
|
p->insert(p->end(), data, data + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConvertSurfaceToPNG(SDL_Surface *surface, std::vector<uint8_t> &buffer) {
|
||||||
|
png_structp png_ptr = png_create_write_struct("1.6.40", NULL, NULL, NULL);
|
||||||
|
if (!png_ptr) {
|
||||||
|
SDL_Log("Failed to create PNG write struct");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr) {
|
||||||
|
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||||
|
SDL_Log("Failed to create PNG info struct");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
SDL_Log("Error during PNG write");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_set_write_fn(png_ptr, &buffer, PngWriteCallback, NULL);
|
||||||
|
|
||||||
|
png_colorp pal_ptr;
|
||||||
|
|
||||||
|
/* Prepare chunks */
|
||||||
|
int colortype = PNG_COLOR_MASK_COLOR;
|
||||||
|
int i = 0;
|
||||||
|
SDL_Palette *pal;
|
||||||
|
if (surface->format->BytesPerPixel > 0 &&
|
||||||
|
surface->format->BytesPerPixel <= 8 && (pal = surface->format->palette)) {
|
||||||
|
SDL_Log("Writing PNG image with palette");
|
||||||
|
colortype |= PNG_COLOR_MASK_PALETTE;
|
||||||
|
pal_ptr = (png_colorp)malloc(pal->ncolors * sizeof(png_color));
|
||||||
|
for (i = 0; i < pal->ncolors; i++) {
|
||||||
|
pal_ptr[i].red = pal->colors[i].r;
|
||||||
|
pal_ptr[i].green = pal->colors[i].g;
|
||||||
|
pal_ptr[i].blue = pal->colors[i].b;
|
||||||
|
}
|
||||||
|
png_set_PLTE(png_ptr, info_ptr, pal_ptr, pal->ncolors);
|
||||||
|
free(pal_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto depth = surface->format->BitsPerPixel;
|
||||||
|
|
||||||
|
// Set image attributes.
|
||||||
|
png_set_IHDR(png_ptr, info_ptr, surface->w, surface->h, depth, colortype,
|
||||||
|
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
|
||||||
|
PNG_FILTER_TYPE_DEFAULT);
|
||||||
|
|
||||||
|
png_set_bgr(png_ptr);
|
||||||
|
|
||||||
|
// Write the image data.
|
||||||
|
std::vector<png_bytep> row_pointers(surface->h);
|
||||||
|
for (int y = 0; y < surface->h; ++y) {
|
||||||
|
row_pointers[y] = (png_bytep)(surface->pixels) + y * surface->pitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
png_set_rows(png_ptr, info_ptr, row_pointers.data());
|
||||||
|
|
||||||
|
SDL_Log("Writing PNG image...");
|
||||||
|
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||||
|
SDL_Log("PNG image write complete");
|
||||||
|
|
||||||
|
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PngReadCallback(png_structp png_ptr, png_bytep outBytes,
|
||||||
|
png_size_t byteCountToRead) {
|
||||||
|
png_voidp io_ptr = png_get_io_ptr(png_ptr);
|
||||||
|
if (!io_ptr) return;
|
||||||
|
|
||||||
|
std::vector<uint8_t> *png_data =
|
||||||
|
reinterpret_cast<std::vector<uint8_t> *>(io_ptr);
|
||||||
|
size_t pos = png_data->size() - byteCountToRead;
|
||||||
|
memcpy(outBytes, png_data->data() + pos, byteCountToRead);
|
||||||
|
png_data->resize(pos); // Reduce the buffer size
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertPngToSurface(const std::vector<uint8_t> &png_data,
|
||||||
|
SDL_Surface **outSurface) {
|
||||||
|
std::vector<uint8_t> data(png_data);
|
||||||
|
png_structp png_ptr = png_create_read_struct("1.6.40", NULL, NULL, NULL);
|
||||||
|
if (!png_ptr) {
|
||||||
|
throw std::runtime_error("Failed to create PNG read struct");
|
||||||
|
}
|
||||||
|
|
||||||
|
png_infop info_ptr = png_create_info_struct(png_ptr);
|
||||||
|
if (!info_ptr) {
|
||||||
|
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
||||||
|
throw std::runtime_error("Failed to create PNG info struct");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
throw std::runtime_error("Error during PNG read");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set our custom read function
|
||||||
|
png_set_read_fn(png_ptr, &data, PngReadCallback);
|
||||||
|
|
||||||
|
// Read the PNG info
|
||||||
|
png_read_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
uint32_t width = png_get_image_width(png_ptr, info_ptr);
|
||||||
|
uint32_t height = png_get_image_height(png_ptr, info_ptr);
|
||||||
|
png_byte color_type = png_get_color_type(png_ptr, info_ptr);
|
||||||
|
png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
// Set up transformations, e.g., strip 16-bit PNGs down to 8-bit, expand
|
||||||
|
// palettes, etc.
|
||||||
|
if (bit_depth == 16) {
|
||||||
|
png_set_strip_16(png_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||||
|
png_set_palette_to_rgb(png_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// PNG files pack pixels, expand them
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
|
||||||
|
png_set_expand_gray_1_2_4_to_8(png_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||||
|
png_set_tRNS_to_alpha(png_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_GRAY ||
|
||||||
|
color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||||
|
png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color_type == PNG_COLOR_TYPE_GRAY ||
|
||||||
|
color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||||
|
png_set_gray_to_rgb(png_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update info structure with transformations
|
||||||
|
png_read_update_info(png_ptr, info_ptr);
|
||||||
|
|
||||||
|
// Read the file
|
||||||
|
std::vector<png_bytep> row_pointers(height);
|
||||||
|
std::vector<uint8_t> raw_data(width * height *
|
||||||
|
4); // Assuming 4 bytes per pixel (RGBA)
|
||||||
|
for (size_t y = 0; y < height; y++) {
|
||||||
|
row_pointers[y] = &raw_data[y * width * 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
png_read_image(png_ptr, row_pointers.data());
|
||||||
|
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
||||||
|
|
||||||
|
// Create SDL_Surface from raw pixel data
|
||||||
|
*outSurface = SDL_CreateRGBSurfaceWithFormatFrom(
|
||||||
|
raw_data.data(), width, height, 32, width * 4, SDL_PIXELFORMAT_RGBA32);
|
||||||
|
if (*outSurface == nullptr) {
|
||||||
|
SDL_Log("SDL_CreateRGBSurfaceWithFormatFrom failed: %s\n", SDL_GetError());
|
||||||
|
} else {
|
||||||
|
SDL_Log("Successfully created SDL_Surface from PNG data");
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Bitmap::Bitmap(int width, int height, int depth, int data_size) {
|
Bitmap::Bitmap(int width, int height, int depth, int data_size) {
|
||||||
@@ -143,6 +312,20 @@ void Bitmap::SetSurface(SDL_Surface *surface) {
|
|||||||
surface, SDL_Surface_Deleter());
|
surface, SDL_Surface_Deleter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> Bitmap::GetPngData() {
|
||||||
|
ConvertSurfaceToPNG(surface_.get(), png_data_);
|
||||||
|
return png_data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Bitmap::LoadFromPngData(const std::vector<uint8_t> &png_data, int width,
|
||||||
|
int height) {
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
SDL_Surface *surface = surface_.get();
|
||||||
|
ConvertPngToSurface(png_data, &surface);
|
||||||
|
surface_.reset(surface);
|
||||||
|
}
|
||||||
|
|
||||||
// Convert SNESPalette to SDL_Palette for surface.
|
// Convert SNESPalette to SDL_Palette for surface.
|
||||||
void Bitmap::ApplyPalette(const SNESPalette &palette) {
|
void Bitmap::ApplyPalette(const SNESPalette &palette) {
|
||||||
palette_ = palette;
|
palette_ = palette;
|
||||||
@@ -215,15 +398,6 @@ void Bitmap::InitializeFromData(uint32_t width, uint32_t height, uint32_t depth,
|
|||||||
GrayscalePalette(surface_->format->palette);
|
GrayscalePalette(surface_->format->palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bitmap::ReserveData(uint32_t width, uint32_t height, uint32_t depth,
|
|
||||||
uint32_t size) {
|
|
||||||
width_ = width;
|
|
||||||
height_ = height;
|
|
||||||
depth_ = depth;
|
|
||||||
data_.reserve(size);
|
|
||||||
pixel_data_ = data_.data();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
} // namespace app
|
} // namespace app
|
||||||
} // namespace yaze
|
} // namespace yaze
|
||||||
|
|||||||
@@ -27,24 +27,11 @@ class Bitmap {
|
|||||||
InitializeFromData(width, height, depth, data);
|
InitializeFromData(width, height, depth, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to create texture from pixel data
|
|
||||||
void CreateTextureFromData() {
|
|
||||||
active_ = true;
|
|
||||||
surface_ = std::shared_ptr<SDL_Surface>(
|
|
||||||
SDL_CreateRGBSurfaceWithFormat(0, width_, height_, depth_,
|
|
||||||
SDL_PIXELFORMAT_INDEX8),
|
|
||||||
SDL_Surface_Deleter());
|
|
||||||
surface_->pixels = data_.data();
|
|
||||||
data_size_ = data_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Create(int width, int height, int depth, int data_size);
|
void Create(int width, int height, int depth, int data_size);
|
||||||
void Create(int width, int height, int depth, const Bytes &data);
|
void Create(int width, int height, int depth, const Bytes &data);
|
||||||
|
|
||||||
void InitializeFromData(uint32_t width, uint32_t height, uint32_t depth,
|
void InitializeFromData(uint32_t width, uint32_t height, uint32_t depth,
|
||||||
const Bytes &data);
|
const Bytes &data);
|
||||||
void ReserveData(uint32_t width, uint32_t height, uint32_t depth,
|
|
||||||
uint32_t size);
|
|
||||||
|
|
||||||
void CreateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
void CreateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
||||||
void UpdateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
void UpdateTexture(std::shared_ptr<SDL_Renderer> renderer);
|
||||||
@@ -53,6 +40,9 @@ class Bitmap {
|
|||||||
|
|
||||||
void SaveSurfaceToFile(std::string_view filename);
|
void SaveSurfaceToFile(std::string_view filename);
|
||||||
void SetSurface(SDL_Surface *surface);
|
void SetSurface(SDL_Surface *surface);
|
||||||
|
std::vector<uint8_t> GetPngData();
|
||||||
|
void LoadFromPngData(const std::vector<uint8_t> &png_data, int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
void ApplyPalette(const SNESPalette &palette);
|
void ApplyPalette(const SNESPalette &palette);
|
||||||
void ApplyPaletteWithTransparent(const SNESPalette &palette, int index);
|
void ApplyPaletteWithTransparent(const SNESPalette &palette, int index);
|
||||||
@@ -75,6 +65,22 @@ class Bitmap {
|
|||||||
modified_ = true;
|
modified_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Get8x8Tile(int tile_index, int x, int y, std::vector<uint8_t> &tile_data,
|
||||||
|
int &tile_data_offset) {
|
||||||
|
int tile_offset = tile_index * 64;
|
||||||
|
int tile_x = x * 8;
|
||||||
|
int tile_y = y * 8;
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
int row_offset = tile_offset + (i * 8);
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
int pixel_offset = row_offset + j;
|
||||||
|
int pixel_value = data_[pixel_offset];
|
||||||
|
tile_data[tile_data_offset] = pixel_value;
|
||||||
|
tile_data_offset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Cleanup() {
|
void Cleanup() {
|
||||||
// Reset texture_
|
// Reset texture_
|
||||||
if (texture_) {
|
if (texture_) {
|
||||||
@@ -105,10 +111,11 @@ class Bitmap {
|
|||||||
auto depth() const { return depth_; }
|
auto depth() const { return depth_; }
|
||||||
auto size() const { return data_size_; }
|
auto size() const { return data_size_; }
|
||||||
auto data() const { return data_.data(); }
|
auto data() const { return data_.data(); }
|
||||||
auto mutable_data() { return data_; }
|
auto &mutable_data() { return data_; }
|
||||||
auto mutable_pixel_data() { return pixel_data_; }
|
auto mutable_pixel_data() { return pixel_data_; }
|
||||||
auto surface() const { return surface_.get(); }
|
auto surface() const { return surface_.get(); }
|
||||||
auto mutable_surface() { return surface_.get(); }
|
auto mutable_surface() { return surface_.get(); }
|
||||||
|
void set_data(const Bytes &data) { data_ = data; }
|
||||||
|
|
||||||
auto vector() const { return data_; }
|
auto vector() const { return data_; }
|
||||||
auto at(int i) const { return data_[i]; }
|
auto at(int i) const { return data_[i]; }
|
||||||
@@ -142,12 +149,17 @@ class Bitmap {
|
|||||||
int height_ = 0;
|
int height_ = 0;
|
||||||
int depth_ = 0;
|
int depth_ = 0;
|
||||||
int data_size_ = 0;
|
int data_size_ = 0;
|
||||||
|
|
||||||
bool freed_ = false;
|
bool freed_ = false;
|
||||||
bool active_ = false;
|
bool active_ = false;
|
||||||
bool modified_ = false;
|
bool modified_ = false;
|
||||||
void *texture_pixels = nullptr;
|
void *texture_pixels = nullptr;
|
||||||
|
|
||||||
uchar *pixel_data_;
|
uchar *pixel_data_;
|
||||||
Bytes data_;
|
Bytes data_;
|
||||||
|
|
||||||
|
std::vector<uint8_t> png_data_;
|
||||||
|
|
||||||
gfx::SNESPalette palette_;
|
gfx::SNESPalette palette_;
|
||||||
std::shared_ptr<SDL_Texture> texture_ = nullptr;
|
std::shared_ptr<SDL_Texture> texture_ = nullptr;
|
||||||
std::shared_ptr<SDL_Surface> surface_ = nullptr;
|
std::shared_ptr<SDL_Surface> surface_ = nullptr;
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ target_include_directories(
|
|||||||
../src/lib/
|
../src/lib/
|
||||||
# ../src/lib/asar/src/asar/
|
# ../src/lib/asar/src/asar/
|
||||||
${SDL2_INCLUDE_DIR}
|
${SDL2_INCLUDE_DIR}
|
||||||
|
${PNG_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
|
|||||||
Reference in New Issue
Block a user