OverworldMap sprite entities, canvas drawing updates
This commit is contained in:
@@ -253,9 +253,10 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar |
|
||||
ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
|
||||
gfx::Bitmap& current_bitmap =
|
||||
*rom()->mutable_bitmap_manager()->mutable_bitmap(sheet_id);
|
||||
|
||||
auto draw_tile_event = [&]() {
|
||||
gfx::Bitmap& current_bitmap =
|
||||
*rom()->mutable_bitmap_manager()->mutable_bitmap(sheet_id);
|
||||
current_sheet_canvas_.DrawTileOnBitmap(tile_size_, current_bitmap,
|
||||
current_color_);
|
||||
rom()->UpdateBitmap(¤t_bitmap);
|
||||
@@ -264,6 +265,8 @@ absl::Status GraphicsEditor::UpdateGfxTabView() {
|
||||
current_sheet_canvas_.UpdateColorPainter(
|
||||
*rom()->bitmap_manager()[sheet_id], current_color_, draw_tile_event,
|
||||
tile_size_, current_scale_);
|
||||
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ using ImGui::Text;
|
||||
absl::Status OverworldEditor::Update() {
|
||||
if (rom()->is_loaded() && !all_gfx_loaded_) {
|
||||
RETURN_IF_ERROR(tile16_editor_.InitBlockset(
|
||||
tile16_blockset_bmp_, current_gfx_bmp_, tile16_individual_));
|
||||
tile16_blockset_bmp_, current_gfx_bmp_, tile16_individual_,
|
||||
*overworld_.mutable_all_tiles_types()));
|
||||
gfx_group_editor_.InitBlockset(tile16_blockset_bmp_);
|
||||
all_gfx_loaded_ = true;
|
||||
} else if (!rom()->is_loaded() && all_gfx_loaded_) {
|
||||
@@ -286,15 +287,16 @@ void OverworldEditor::RefreshChildMap(int map_index) {
|
||||
} else {
|
||||
blockset = overworld_.map_tiles().special_world;
|
||||
}
|
||||
status_ = overworld_.mutable_overworld_map(map_index)->BuildBitmap(blockset);
|
||||
maps_bmp_[map_index].set_data(
|
||||
overworld_.mutable_overworld_map(map_index)->BitmapData());
|
||||
status_ = overworld_.mutable_overworld_map(map_index)->BuildBitmap(blockset);
|
||||
maps_bmp_[map_index].set_modified(true);
|
||||
PRINT_IF_ERROR(status_);
|
||||
rom()->UpdateBitmap(&maps_bmp_[map_index]);
|
||||
}
|
||||
|
||||
void OverworldEditor::RefreshOverworldMap() {
|
||||
std::vector<std::future<void>> futures;
|
||||
int indices[4];
|
||||
|
||||
auto refresh_map_async = [this](int map_index) {
|
||||
RefreshChildMap(map_index);
|
||||
@@ -302,50 +304,49 @@ void OverworldEditor::RefreshOverworldMap() {
|
||||
|
||||
if (overworld_.overworld_map(current_map_)->IsLargeMap()) {
|
||||
// We need to update the map and its siblings if it's a large map
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int i = 1; i < 4; i++) {
|
||||
int sibling_index = overworld_.overworld_map(current_map_)->Parent() + i;
|
||||
if (i >= 2) {
|
||||
sibling_index += 6;
|
||||
}
|
||||
if (i >= 2) sibling_index += 6;
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, refresh_map_async, sibling_index));
|
||||
indices[i] = sibling_index;
|
||||
}
|
||||
} else {
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, refresh_map_async, current_map_));
|
||||
}
|
||||
indices[0] = current_map_;
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, refresh_map_async, current_map_));
|
||||
|
||||
for (auto &each : futures) {
|
||||
each.get();
|
||||
}
|
||||
|
||||
// We do texture updating on the main thread
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
rom()->UpdateBitmap(&maps_bmp_[indices[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Palette throws out of bounds error unexpectedly.
|
||||
void OverworldEditor::RefreshMapPalette() {
|
||||
std::vector<std::future<void>> futures;
|
||||
|
||||
auto refresh_palette_async = [this](int map_index) {
|
||||
overworld_.mutable_overworld_map(map_index)->LoadPalette();
|
||||
maps_bmp_[map_index].ApplyPalette(
|
||||
*overworld_.mutable_overworld_map(map_index)
|
||||
->mutable_current_palette());
|
||||
rom()->UpdateBitmap(&maps_bmp_[map_index]);
|
||||
};
|
||||
|
||||
if (overworld_.overworld_map(current_map_)->IsLargeMap()) {
|
||||
// We need to update the map and its siblings if it's a large map
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int i = 1; i < 4; i++) {
|
||||
int sibling_index = overworld_.overworld_map(current_map_)->Parent() + i;
|
||||
if (i >= 2) {
|
||||
sibling_index += 6;
|
||||
}
|
||||
if (i >= 2) sibling_index += 6;
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, refresh_palette_async, sibling_index));
|
||||
}
|
||||
} else {
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, refresh_palette_async, current_map_));
|
||||
}
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, refresh_palette_async, current_map_));
|
||||
|
||||
for (auto &each : futures) {
|
||||
each.get();
|
||||
@@ -495,12 +496,16 @@ void HandleEntityDragging(zelda3::OverworldEntity *entity, ImVec2 canvas_p0,
|
||||
} else if (entity->type_ == zelda3::OverworldEntity::EntityType::kItem) {
|
||||
entity_type = "Item";
|
||||
}
|
||||
if (IsMouseHoveringOverEntity(*entity, canvas_p0, scrolling) &&
|
||||
ImGui::IsMouseDragging(ImGuiMouseButton_Left) && !is_dragging_entity) {
|
||||
const auto is_hovering =
|
||||
IsMouseHoveringOverEntity(*entity, canvas_p0, scrolling);
|
||||
|
||||
const auto drag_or_clicked = ImGui::IsMouseDragging(ImGuiMouseButton_Left) ||
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Left);
|
||||
|
||||
if (is_hovering && drag_or_clicked && !is_dragging_entity) {
|
||||
dragged_entity = entity;
|
||||
is_dragging_entity = true;
|
||||
} else if (IsMouseHoveringOverEntity(*entity, canvas_p0, scrolling) &&
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
} else if (is_hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
current_entity = entity;
|
||||
ImGui::OpenPopup(absl::StrFormat("%s editor", entity_type.c_str()).c_str());
|
||||
} else if (is_dragging_entity && dragged_entity == entity &&
|
||||
@@ -528,6 +533,24 @@ void HandleEntityDragging(zelda3::OverworldEntity *entity, ImVec2 canvas_p0,
|
||||
|
||||
namespace entrance_internal {
|
||||
|
||||
void DrawEntranceInserterPopup() {
|
||||
if (ImGui::BeginPopup("Entrance Inserter")) {
|
||||
static int entrance_id = 0;
|
||||
gui::InputHex("Entrance ID", &entrance_id);
|
||||
|
||||
if (ImGui::Button(ICON_MD_DONE)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_MD_CANCEL)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawOverworldEntrancePopup(zelda3::OverworldEntrance &entrance) {
|
||||
static bool set_done = false;
|
||||
if (set_done) {
|
||||
@@ -598,14 +621,42 @@ void OverworldEditor::DrawOverworldEntrances(ImVec2 canvas_p0, ImVec2 scrolling,
|
||||
i++;
|
||||
}
|
||||
|
||||
if (entrance_internal::DrawOverworldEntrancePopup(
|
||||
overworld_.Entrances()[current_entrance_id_])) {
|
||||
overworld_.Entrances()[current_entrance_id_] = current_entrance_;
|
||||
entrance_internal::DrawEntranceInserterPopup();
|
||||
if (current_mode == EditingMode::ENTRANCES) {
|
||||
const auto is_hovering = entity_internal::IsMouseHoveringOverEntity(
|
||||
current_entrance_, canvas_p0, scrolling);
|
||||
|
||||
if (!is_hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
ImGui::OpenPopup("Entrance Inserter");
|
||||
} else {
|
||||
if (entrance_internal::DrawOverworldEntrancePopup(
|
||||
overworld_.Entrances()[current_entrance_id_])) {
|
||||
overworld_.Entrances()[current_entrance_id_] = current_entrance_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace exit_internal {
|
||||
|
||||
void DrawExitInserterPopup() {
|
||||
if (ImGui::BeginPopup("Exit Inserter")) {
|
||||
static int exit_id = 0;
|
||||
gui::InputHex("Exit ID", &exit_id);
|
||||
|
||||
if (ImGui::Button(ICON_MD_DONE)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_MD_CANCEL)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawExitEditorPopup(zelda3::OverworldExit &exit) {
|
||||
static bool set_done = false;
|
||||
if (set_done) {
|
||||
@@ -661,7 +712,7 @@ bool DrawExitEditorPopup(zelda3::OverworldExit &exit) {
|
||||
static bool show_properties = false;
|
||||
ImGui::Checkbox("Show properties", &show_properties);
|
||||
if (show_properties) {
|
||||
ImGui::Text("Deleted? %s", exit.deleted ? "true" : "false");
|
||||
ImGui::Text("Deleted? %s", exit.deleted_ ? "true" : "false");
|
||||
ImGui::Text("Hole? %s", exit.is_hole_ ? "true" : "false");
|
||||
ImGui::Text("Large Map? %s", exit.large_map_ ? "true" : "false");
|
||||
}
|
||||
@@ -728,7 +779,7 @@ bool DrawExitEditorPopup(zelda3::OverworldExit &exit) {
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_MD_DELETE)) {
|
||||
exit.deleted = true;
|
||||
exit.deleted_ = true;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
@@ -744,7 +795,7 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
|
||||
int i = 0;
|
||||
for (auto &each : *overworld_.mutable_exits()) {
|
||||
if (each.map_id_ < 0x40 + (current_world_ * 0x40) &&
|
||||
each.map_id_ >= (current_world_ * 0x40) && !each.deleted) {
|
||||
each.map_id_ >= (current_world_ * 0x40) && !each.deleted_) {
|
||||
ow_map_canvas_.DrawRect(each.x_, each.y_, 16, 16,
|
||||
ImVec4(255, 255, 255, 150));
|
||||
if (current_mode == EditingMode::EXITS) {
|
||||
@@ -776,14 +827,55 @@ void OverworldEditor::DrawOverworldExits(ImVec2 canvas_p0, ImVec2 scrolling) {
|
||||
i++;
|
||||
}
|
||||
|
||||
if (exit_internal::DrawExitEditorPopup(
|
||||
overworld_.mutable_exits()->at(current_exit_id_))) {
|
||||
overworld_.mutable_exits()->at(current_exit_id_) = current_exit_;
|
||||
exit_internal::DrawExitInserterPopup();
|
||||
if (current_mode == EditingMode::EXITS) {
|
||||
const auto hovering = entity_internal::IsMouseHoveringOverEntity(
|
||||
overworld_.mutable_exits()->at(current_exit_id_),
|
||||
ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling());
|
||||
|
||||
if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
ImGui::OpenPopup("Exit Inserter");
|
||||
} else {
|
||||
if (exit_internal::DrawExitEditorPopup(
|
||||
overworld_.mutable_exits()->at(current_exit_id_))) {
|
||||
overworld_.mutable_exits()->at(current_exit_id_) = current_exit_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace item_internal {
|
||||
|
||||
void DrawItemInsertPopup() {
|
||||
// Contents of the Context Menu
|
||||
if (ImGui::BeginPopup("Item Inserter")) {
|
||||
static int new_item_id = 0;
|
||||
ImGui::Text("Add Item");
|
||||
ImGui::BeginChild("ScrollRegion", ImVec2(150, 150), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
for (int i = 0; i < zelda3::kSecretItemNames.size(); i++) {
|
||||
if (ImGui::Selectable(zelda3::kSecretItemNames[i].c_str(),
|
||||
i == new_item_id)) {
|
||||
new_item_id = i;
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::Button(ICON_MD_DONE)) {
|
||||
// Add the new item to the overworld
|
||||
new_item_id = 0;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(ICON_MD_CANCEL)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawItemEditorPopup(zelda3::OverworldItem &item) {
|
||||
static bool set_done = false;
|
||||
if (set_done) {
|
||||
@@ -791,7 +883,7 @@ bool DrawItemEditorPopup(zelda3::OverworldItem &item) {
|
||||
}
|
||||
if (ImGui::BeginPopupModal("Item editor", NULL,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::BeginChild("ScrollRegion", ImVec2(0, 150), true,
|
||||
ImGui::BeginChild("ScrollRegion", ImVec2(150, 150), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
ImGui::BeginGroup();
|
||||
for (int i = 0; i < zelda3::kSecretItemNames.size(); i++) {
|
||||
@@ -831,34 +923,203 @@ void OverworldEditor::DrawOverworldItems() {
|
||||
std::string item_name = zelda3::kSecretItemNames[item.id];
|
||||
|
||||
ow_map_canvas_.DrawRect(item.x_, item.y_, 16, 16, ImVec4(255, 0, 0, 150));
|
||||
if (current_mode == EditingMode::ITEMS) {
|
||||
if (entity_internal::IsMouseHoveringOverEntity(
|
||||
item, ow_map_canvas_.zero_point(),
|
||||
ow_map_canvas_.scrolling()) &&
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
current_item_id_ = i;
|
||||
current_item_ = item;
|
||||
}
|
||||
|
||||
if (current_mode == EditingMode::ITEMS) {
|
||||
// Check if this item is being clicked and dragged
|
||||
entity_internal::HandleEntityDragging(
|
||||
&item, ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling(),
|
||||
is_dragging_entity_, dragged_entity_, current_entity_);
|
||||
|
||||
const auto hovering = entity_internal::IsMouseHoveringOverEntity(
|
||||
item, ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling());
|
||||
if (hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
current_item_id_ = i;
|
||||
current_item_ = item;
|
||||
current_entity_ = &item;
|
||||
}
|
||||
}
|
||||
ow_map_canvas_.DrawText(item_name, item.x_, item.y_);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (item_internal::DrawItemEditorPopup(
|
||||
overworld_.mutable_all_items()->at(current_item_id_))) {
|
||||
overworld_.mutable_all_items()->at(current_item_id_) = current_item_;
|
||||
item_internal::DrawItemInsertPopup();
|
||||
if (current_mode == EditingMode::ITEMS) {
|
||||
const auto hovering = entity_internal::IsMouseHoveringOverEntity(
|
||||
overworld_.mutable_all_items()->at(current_item_id_),
|
||||
ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling());
|
||||
|
||||
if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
ImGui::OpenPopup("Item Inserter");
|
||||
} else {
|
||||
if (item_internal::DrawItemEditorPopup(
|
||||
overworld_.mutable_all_items()->at(current_item_id_))) {
|
||||
overworld_.mutable_all_items()->at(current_item_id_) = current_item_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
namespace sprite_internal {
|
||||
|
||||
enum MyItemColumnID {
|
||||
MyItemColumnID_ID,
|
||||
MyItemColumnID_Name,
|
||||
MyItemColumnID_Action,
|
||||
MyItemColumnID_Quantity,
|
||||
MyItemColumnID_Description
|
||||
};
|
||||
|
||||
struct SpriteItem {
|
||||
int id;
|
||||
const char *name;
|
||||
static const ImGuiTableSortSpecs *s_current_sort_specs;
|
||||
|
||||
static void SortWithSortSpecs(ImGuiTableSortSpecs *sort_specs,
|
||||
std::vector<SpriteItem> &items) {
|
||||
s_current_sort_specs =
|
||||
sort_specs; // Store for access by the compare function.
|
||||
if (items.size() > 1)
|
||||
std::sort(items.begin(), items.end(), SpriteItem::CompareWithSortSpecs);
|
||||
s_current_sort_specs = nullptr;
|
||||
}
|
||||
|
||||
static bool CompareWithSortSpecs(const SpriteItem &a, const SpriteItem &b) {
|
||||
for (int n = 0; n < s_current_sort_specs->SpecsCount; n++) {
|
||||
const ImGuiTableColumnSortSpecs *sort_spec =
|
||||
&s_current_sort_specs->Specs[n];
|
||||
int delta = 0;
|
||||
switch (sort_spec->ColumnUserID) {
|
||||
case MyItemColumnID_ID:
|
||||
delta = (a.id - b.id);
|
||||
break;
|
||||
case MyItemColumnID_Name:
|
||||
delta = strcmp(a.name + 2, b.name + 2);
|
||||
break;
|
||||
}
|
||||
if (delta != 0)
|
||||
return (sort_spec->SortDirection == ImGuiSortDirection_Ascending)
|
||||
? delta < 0
|
||||
: delta > 0;
|
||||
}
|
||||
return a.id < b.id; // Fallback
|
||||
}
|
||||
};
|
||||
const ImGuiTableSortSpecs *SpriteItem::s_current_sort_specs = nullptr;
|
||||
|
||||
void DrawSpriteTable(std::function<void(int)> onSpriteSelect) {
|
||||
static ImGuiTextFilter filter;
|
||||
static int selected_id = 0;
|
||||
static std::vector<SpriteItem> items;
|
||||
|
||||
// Initialize items if empty
|
||||
if (items.empty()) {
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
items.push_back(SpriteItem{i, core::kSpriteDefaultNames[i].data()});
|
||||
}
|
||||
}
|
||||
|
||||
filter.Draw("Filter", 180);
|
||||
|
||||
if (ImGui::BeginTable("##sprites", 2,
|
||||
ImGuiTableFlags_Sortable | ImGuiTableFlags_Resizable)) {
|
||||
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort, 0.0f,
|
||||
MyItemColumnID_ID);
|
||||
ImGui::TableSetupColumn("Name", 0, 0.0f, MyItemColumnID_Name);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
// Handle sorting
|
||||
if (ImGuiTableSortSpecs *sort_specs = ImGui::TableGetSortSpecs()) {
|
||||
if (sort_specs->SpecsDirty) {
|
||||
SpriteItem::SortWithSortSpecs(sort_specs, items);
|
||||
sort_specs->SpecsDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Display filtered and sorted items
|
||||
for (const auto &item : items) {
|
||||
if (filter.PassFilter(item.name)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::Text("%d", item.id);
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
|
||||
if (ImGui::Selectable(item.name, selected_id == item.id,
|
||||
ImGuiSelectableFlags_SpanAllColumns)) {
|
||||
selected_id = item.id;
|
||||
onSpriteSelect(item.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawSpriteInserterPopup() {
|
||||
if (ImGui::BeginPopup("Sprite Inserter")) {
|
||||
static int new_sprite_id = 0;
|
||||
ImGui::Text("Add Sprite");
|
||||
ImGui::BeginChild("ScrollRegion", ImVec2(250, 250), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
sprite_internal::DrawSpriteTable(
|
||||
[](int selected_id) { new_sprite_id = selected_id; });
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::Button(ICON_MD_DONE)) {
|
||||
// Add the new item to the overworld
|
||||
new_sprite_id = 0;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button(ICON_MD_CANCEL)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawSpriteEditorPopup(zelda3::Sprite &sprite) {
|
||||
static bool set_done = false;
|
||||
if (set_done) {
|
||||
set_done = false;
|
||||
}
|
||||
if (ImGui::BeginPopupModal("Sprite editor", NULL,
|
||||
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
ImGui::BeginChild("ScrollRegion", ImVec2(350, 350), true,
|
||||
ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text("%s", sprite.Name().c_str());
|
||||
|
||||
sprite_internal::DrawSpriteTable([&sprite](int selected_id) {
|
||||
sprite.set_id(selected_id);
|
||||
sprite.UpdateMapProperties(sprite.map_id());
|
||||
});
|
||||
ImGui::EndGroup();
|
||||
ImGui::EndChild();
|
||||
|
||||
if (ImGui::Button(ICON_MD_DONE)) ImGui::CloseCurrentPopup();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_MD_CLOSE)) {
|
||||
set_done = true;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_MD_DELETE)) {
|
||||
sprite.set_deleted(true);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
return set_done;
|
||||
}
|
||||
|
||||
} // namespace sprite_internal
|
||||
|
||||
void OverworldEditor::DrawOverworldSprites() {
|
||||
int i = 0;
|
||||
for (auto &sprite : *overworld_.mutable_sprites(game_state_)) {
|
||||
int map_id = sprite.map_id();
|
||||
int map_x = sprite.map_x();
|
||||
@@ -866,14 +1127,43 @@ void OverworldEditor::DrawOverworldSprites() {
|
||||
|
||||
if (map_id < 0x40 + (current_world_ * 0x40) &&
|
||||
map_id >= (current_world_ * 0x40) && !sprite.deleted()) {
|
||||
// auto globalx = (((map_id & 0x7) * 512) + (map_x * 16));
|
||||
// auto globaly = (((map_id & 0x3F) / 8 * 512) + (map_y * 16));
|
||||
|
||||
ow_map_canvas_.DrawRect(map_x, map_y, 16, 16,
|
||||
/*magenta*/ ImVec4(255, 0, 255, 150));
|
||||
if (current_mode == EditingMode::SPRITES) {
|
||||
entity_internal::HandleEntityDragging(
|
||||
&sprite, ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling(),
|
||||
is_dragging_entity_, dragged_entity_, current_entity_);
|
||||
if (entity_internal::IsMouseHoveringOverEntity(
|
||||
sprite, ow_map_canvas_.zero_point(),
|
||||
ow_map_canvas_.scrolling()) &&
|
||||
ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
current_sprite_id_ = i;
|
||||
current_sprite_ = sprite;
|
||||
}
|
||||
}
|
||||
|
||||
ow_map_canvas_.DrawText(absl::StrFormat("%s", sprite.Name()), map_x,
|
||||
map_y);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
sprite_internal::DrawSpriteInserterPopup();
|
||||
if (current_mode == EditingMode::SPRITES) {
|
||||
const auto hovering = entity_internal::IsMouseHoveringOverEntity(
|
||||
overworld_.mutable_sprites(game_state_)->at(current_sprite_id_),
|
||||
ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling());
|
||||
|
||||
if (!hovering && ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
ImGui::OpenPopup("Sprite Inserter");
|
||||
} else {
|
||||
if (sprite_internal::DrawSpriteEditorPopup(
|
||||
overworld_.mutable_sprites(game_state_)
|
||||
->at(current_sprite_id_))) {
|
||||
overworld_.mutable_sprites(game_state_)->at(current_sprite_id_) =
|
||||
current_sprite_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -904,11 +1194,11 @@ void OverworldEditor::DrawOverworldEdits() {
|
||||
int map_x = mouse_position.x / small_map_size;
|
||||
int map_y = mouse_position.y / small_map_size;
|
||||
current_map_ = map_x + map_y * 8;
|
||||
|
||||
// If the map has a parent, set the current_map_ to that parent map
|
||||
// if (overworld_.overworld_map(current_map_)->IsLargeMap()) {
|
||||
// current_map_ = overworld_.overworld_map(current_map_)->Parent();
|
||||
// }
|
||||
if (current_world_ == 1) {
|
||||
current_map_ += 0x40;
|
||||
} else if (current_world_ == 2) {
|
||||
current_map_ += 0x80;
|
||||
}
|
||||
|
||||
// Render the updated map bitmap.
|
||||
RenderUpdatedMapBitmap(mouse_position,
|
||||
@@ -930,17 +1220,17 @@ void OverworldEditor::DrawOverworldEdits() {
|
||||
uint8_t high_byte = (tile_value >> 8) & 0xFF;
|
||||
if (current_world_ == 0) {
|
||||
overworld_.mutable_map_tiles()->light_world[tile16_x][tile16_y] = low_byte;
|
||||
// overworld_.mutable_map_tiles()->light_world[tile16_x][tile16_y + 1] =
|
||||
// high_byte;
|
||||
overworld_.mutable_map_tiles()->light_world[tile16_x][tile16_y + 1] =
|
||||
high_byte;
|
||||
} else if (current_world_ == 1) {
|
||||
overworld_.mutable_map_tiles()->dark_world[tile16_x][tile16_y] = low_byte;
|
||||
// overworld_.mutable_map_tiles()->dark_world[tile16_x][tile16_y + 1] =
|
||||
// high_byte;
|
||||
overworld_.mutable_map_tiles()->dark_world[tile16_x][tile16_y + 1] =
|
||||
high_byte;
|
||||
} else {
|
||||
overworld_.mutable_map_tiles()->special_world[tile16_x][tile16_y] =
|
||||
low_byte;
|
||||
// overworld_.mutable_map_tiles()->special_world[tile16_x][tile16_y + 1] =
|
||||
// high_byte;
|
||||
overworld_.mutable_map_tiles()->special_world[tile16_x][tile16_y + 1] =
|
||||
high_byte;
|
||||
}
|
||||
|
||||
if (flags()->kLogToConsole) {
|
||||
@@ -978,8 +1268,10 @@ void OverworldEditor::RenderUpdatedMapBitmap(const ImVec2 &click_position,
|
||||
}
|
||||
}
|
||||
|
||||
// Render the updated bitmap to the canvas
|
||||
rom()->UpdateBitmap(¤t_bitmap);
|
||||
current_bitmap.set_modified(true);
|
||||
|
||||
// // Render the updated bitmap to the canvas
|
||||
// rom()->UpdateBitmap(¤t_bitmap);
|
||||
}
|
||||
|
||||
void OverworldEditor::CheckForOverworldEdits() {
|
||||
@@ -1001,8 +1293,7 @@ void OverworldEditor::CheckForCurrentMap() {
|
||||
// 4096x4096, 512x512 maps and some are larges maps 1024x1024
|
||||
auto mouse_position = ImGui::GetIO().MousePos;
|
||||
constexpr int small_map_size = 512;
|
||||
auto large_map_size = 1024;
|
||||
|
||||
const auto large_map_size = 1024;
|
||||
const auto canvas_zero_point = ow_map_canvas_.zero_point();
|
||||
|
||||
// Calculate which small map the mouse is currently over
|
||||
@@ -1011,6 +1302,16 @@ void OverworldEditor::CheckForCurrentMap() {
|
||||
|
||||
// Calculate the index of the map in the `maps_bmp_` vector
|
||||
current_map_ = map_x + map_y * 8;
|
||||
if (current_world_ == 1) {
|
||||
current_map_ += 0x40;
|
||||
} else if (current_world_ == 2) {
|
||||
current_map_ += 0x80;
|
||||
}
|
||||
|
||||
// If the map has a parent, set the current_map_ to that parent map
|
||||
if (overworld_.overworld_map(current_map_)->IsLargeMap()) {
|
||||
current_parent_ = overworld_.overworld_map(current_map_)->Parent();
|
||||
}
|
||||
|
||||
auto current_map_x = current_map_ % 8;
|
||||
auto current_map_y = current_map_ / 8;
|
||||
@@ -1027,6 +1328,31 @@ void OverworldEditor::CheckForCurrentMap() {
|
||||
current_map_y * small_map_size, small_map_size,
|
||||
small_map_size);
|
||||
}
|
||||
|
||||
if (maps_bmp_[current_map_].modified()) {
|
||||
rom()->UpdateBitmap(&maps_bmp_[current_map_]);
|
||||
maps_bmp_[current_map_].set_modified(false);
|
||||
}
|
||||
}
|
||||
|
||||
void OverworldEditor::CheckForSelectRectangle() {
|
||||
if (current_mode == EditingMode::DRAW_TILE) {
|
||||
ow_map_canvas_.DrawSelectRect(0x10);
|
||||
static std::vector<int> tile16_ids;
|
||||
if (ow_map_canvas_.selected_tiles().size() != 0) {
|
||||
// Get the tile16 IDs from the selected tile ID positions
|
||||
if (tile16_ids.size() != 0) {
|
||||
tile16_ids.clear();
|
||||
}
|
||||
for (auto &each : ow_map_canvas_.selected_tiles()) {
|
||||
int tile16_id = overworld_.GetTile16Id(each);
|
||||
tile16_ids.push_back(tile16_id);
|
||||
}
|
||||
ow_map_canvas_.mutable_selected_tiles()->clear();
|
||||
}
|
||||
// Create a composite image of all the tile16s selected
|
||||
ow_map_canvas_.DrawBitmapGroup(tile16_ids, tile16_individual_, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
// Overworld Editor canvas
|
||||
@@ -1047,9 +1373,9 @@ void OverworldEditor::DrawOverworldCanvas() {
|
||||
}
|
||||
if (overworld_.is_loaded()) {
|
||||
DrawOverworldMaps();
|
||||
DrawOverworldExits(ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling());
|
||||
DrawOverworldEntrances(ow_map_canvas_.zero_point(),
|
||||
ow_map_canvas_.scrolling());
|
||||
DrawOverworldExits(ow_map_canvas_.zero_point(), ow_map_canvas_.scrolling());
|
||||
DrawOverworldItems();
|
||||
DrawOverworldSprites();
|
||||
if (ImGui::IsItemHovered()) CheckForCurrentMap();
|
||||
@@ -1082,8 +1408,6 @@ void OverworldEditor::DrawTile16Selector() {
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
// Tile 8 Selector
|
||||
// Displays all the individual tiles that make up a tile16.
|
||||
void OverworldEditor::DrawTile8Selector() {
|
||||
graphics_bin_canvas_.DrawBackground();
|
||||
graphics_bin_canvas_.DrawContextMenu();
|
||||
@@ -1112,8 +1436,21 @@ void OverworldEditor::DrawAreaGraphics() {
|
||||
current_gfx_canvas_.DrawBackground();
|
||||
gui::EndPadding();
|
||||
current_gfx_canvas_.DrawContextMenu();
|
||||
current_gfx_canvas_.DrawBitmap(current_gfx_bmp_, /*border_offset=*/2,
|
||||
overworld_.is_loaded());
|
||||
if (current_graphics_set_.count(current_map_) == 0) {
|
||||
overworld_.SetCurrentMap(current_map_);
|
||||
palette_ = overworld_.AreaPalette();
|
||||
gfx::Bitmap bmp;
|
||||
gui::BuildAndRenderBitmapPipeline(
|
||||
0x80, 0x200, 0x08, overworld_.AreaGraphics(), *rom(), bmp, palette_);
|
||||
// int area_palette =
|
||||
// overworld_.overworld_map(current_map_)->area_palette();
|
||||
// gui::BuildAndRenderBitmapPipeline(0x80, 0x200, 0x40,
|
||||
// overworld_.AreaGraphics(), *rom(), bmp,
|
||||
// palettesets_[area_palette].main);
|
||||
current_graphics_set_[current_map_] = bmp;
|
||||
}
|
||||
current_gfx_canvas_.DrawBitmap(current_graphics_set_[current_map_],
|
||||
/*border_offset=*/2, overworld_.is_loaded());
|
||||
current_gfx_canvas_.DrawTileSelector(32.0f);
|
||||
current_gfx_canvas_.DrawGrid();
|
||||
current_gfx_canvas_.DrawOverlay();
|
||||
@@ -1168,8 +1505,6 @@ absl::Status OverworldEditor::LoadGraphics() {
|
||||
// Copy the tile16 data into individual tiles.
|
||||
auto tile16_data = overworld_.Tile16Blockset();
|
||||
|
||||
std::cout << tile16_data.size() << std::endl;
|
||||
|
||||
// Loop through the tiles and copy their pixel data into separate vectors
|
||||
for (int i = 0; i < 4096; i++) {
|
||||
// Create a new vector for the pixel data of the current tile
|
||||
@@ -1234,7 +1569,6 @@ void OverworldEditor::DrawOverworldProperties() {
|
||||
if (!init_properties) {
|
||||
for (int i = 0; i < 0x40; i++) {
|
||||
std::string area_graphics_str = absl::StrFormat(
|
||||
|
||||
"0x%02hX", overworld_.overworld_map(i)->area_graphics());
|
||||
properties_canvas_.mutable_labels(0)->push_back(area_graphics_str);
|
||||
}
|
||||
@@ -1437,11 +1771,11 @@ void OverworldEditor::DrawDebugWindow() {
|
||||
|
||||
// Print the size of the overworld map_tiles per world
|
||||
ImGui::Text("Light World Map Tiles: %d",
|
||||
overworld_.mutable_map_tiles()->light_world.size());
|
||||
(int)overworld_.mutable_map_tiles()->light_world.size());
|
||||
ImGui::Text("Dark World Map Tiles: %d",
|
||||
overworld_.mutable_map_tiles()->dark_world.size());
|
||||
(int)overworld_.mutable_map_tiles()->dark_world.size());
|
||||
ImGui::Text("Special World Map Tiles: %d",
|
||||
overworld_.mutable_map_tiles()->special_world.size());
|
||||
(int)overworld_.mutable_map_tiles()->special_world.size());
|
||||
|
||||
static bool view_lw_map_tiles = false;
|
||||
static MemoryEditor mem_edit;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define YAZE_APP_EDITOR_OVERWORLDEDITOR_H
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "app/core/common.h"
|
||||
#include "app/core/editor.h"
|
||||
#include "app/editor/context/gfx_context.h"
|
||||
#include "app/editor/modules/gfx_group_editor.h"
|
||||
#include "app/editor/modules/palette_editor.h"
|
||||
#include "app/editor/modules/tile16_editor.h"
|
||||
@@ -42,7 +44,8 @@ static constexpr absl::string_view kToolsetColumnNames[] = {
|
||||
"#transportTool", "#musicTool", "#separator3", "#tilemapTool",
|
||||
"propertiesTool"};
|
||||
|
||||
constexpr ImGuiTableFlags kOWMapFlags = ImGuiTableFlags_Borders;
|
||||
constexpr ImGuiTableFlags kOWMapFlags =
|
||||
ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable;
|
||||
constexpr ImGuiTableFlags kToolsetTableFlags = ImGuiTableFlags_SizingFixedFit;
|
||||
constexpr ImGuiTableFlags kOWEditFlags =
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable |
|
||||
@@ -60,6 +63,7 @@ constexpr absl::string_view kOWMapTable = "#MapSettingsTable";
|
||||
|
||||
class OverworldEditor : public Editor,
|
||||
public SharedROM,
|
||||
public GfxContext,
|
||||
public core::ExperimentFlags {
|
||||
public:
|
||||
absl::Status Update() final;
|
||||
@@ -75,16 +79,16 @@ class OverworldEditor : public Editor,
|
||||
int jump_to_tab_ = -1;
|
||||
|
||||
void Shutdown() {
|
||||
for (auto &bmp : tile16_individual_) {
|
||||
for (auto& bmp : tile16_individual_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
for (auto &[i, bmp] : maps_bmp_) {
|
||||
for (auto& [i, bmp] : maps_bmp_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
for (auto &[i, bmp] : graphics_bin_) {
|
||||
for (auto& [i, bmp] : graphics_bin_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
for (auto &[i, bmp] : current_graphics_set_) {
|
||||
for (auto& [i, bmp] : current_graphics_set_) {
|
||||
bmp.Cleanup();
|
||||
}
|
||||
}
|
||||
@@ -110,10 +114,11 @@ class OverworldEditor : public Editor,
|
||||
|
||||
void DrawOverworldMaps();
|
||||
void DrawOverworldEdits();
|
||||
void RenderUpdatedMapBitmap(const ImVec2 &click_position,
|
||||
const Bytes &tile_data);
|
||||
void RenderUpdatedMapBitmap(const ImVec2& click_position,
|
||||
const Bytes& tile_data);
|
||||
void CheckForOverworldEdits();
|
||||
void CheckForCurrentMap();
|
||||
void CheckForSelectRectangle();
|
||||
void DrawOverworldCanvas();
|
||||
|
||||
void DrawTile16Selector();
|
||||
@@ -152,9 +157,10 @@ class OverworldEditor : public Editor,
|
||||
|
||||
int current_world_ = 0;
|
||||
int current_map_ = 0;
|
||||
int current_parent_ = 0;
|
||||
int game_state_ = 1;
|
||||
int current_tile16_ = 0;
|
||||
int selected_tile_ = 0;
|
||||
int game_state_ = 0;
|
||||
|
||||
int selected_entrance_ = 0;
|
||||
int selected_usage_map_ = 0xFFFF;
|
||||
@@ -184,8 +190,8 @@ class OverworldEditor : public Editor,
|
||||
bool middle_mouse_dragging_ = false;
|
||||
|
||||
bool is_dragging_entity_ = false;
|
||||
zelda3::OverworldEntity *dragged_entity_;
|
||||
zelda3::OverworldEntity *current_entity_;
|
||||
zelda3::OverworldEntity* dragged_entity_;
|
||||
zelda3::OverworldEntity* current_entity_;
|
||||
|
||||
int current_entrance_id_ = 0;
|
||||
zelda3::OverworldEntrance current_entrance_;
|
||||
@@ -193,6 +199,8 @@ class OverworldEditor : public Editor,
|
||||
zelda3::OverworldExit current_exit_;
|
||||
int current_item_id_ = 0;
|
||||
zelda3::OverworldItem current_item_;
|
||||
int current_sprite_id_ = 0;
|
||||
zelda3::Sprite current_sprite_;
|
||||
|
||||
bool show_experimental = false;
|
||||
std::string ow_tilemap_filename_ = "";
|
||||
|
||||
@@ -32,7 +32,7 @@ void Canvas::Update(const gfx::Bitmap &bitmap, ImVec2 bg_size, int tile_size,
|
||||
DrawOverlay();
|
||||
}
|
||||
|
||||
void Canvas::UpdateColorPainter(const gfx::Bitmap &bitmap, const ImVec4 &color,
|
||||
void Canvas::UpdateColorPainter(gfx::Bitmap &bitmap, const ImVec4 &color,
|
||||
const std::function<void()> &event,
|
||||
int tile_size, float scale) {
|
||||
global_scale_ = scale;
|
||||
@@ -143,17 +143,7 @@ void Canvas::DrawContextMenu() {
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
// TODO: Add a menu item for selecting the palette
|
||||
// ImGui::Separator();
|
||||
// if (ImGui::BeginMenu("Palette")) {
|
||||
// for (const auto each : editor::kPaletteGroupAddressesKeys) {
|
||||
// if (ImGui::BeginMenu(each)) {
|
||||
// }
|
||||
// ImGui::EndMenu();
|
||||
// }
|
||||
// ImGui::EndMenu();
|
||||
// }
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -175,10 +165,13 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) {
|
||||
|
||||
// Calculate the coordinates of the mouse
|
||||
ImVec2 painter_pos;
|
||||
painter_pos.x = std::floor((double)mouse_pos.x / size) * size;
|
||||
painter_pos.y = std::floor((double)mouse_pos.y / size) * size;
|
||||
painter_pos.x =
|
||||
std::floor((double)mouse_pos.x / (size * scale)) * (size * scale);
|
||||
painter_pos.y =
|
||||
std::floor((double)mouse_pos.y / (size * scale)) * (size * scale);
|
||||
|
||||
auto painter_pos_end = ImVec2(painter_pos.x + size, painter_pos.y + size);
|
||||
auto painter_pos_end =
|
||||
ImVec2(painter_pos.x + (size * scale), painter_pos.y + (size * scale));
|
||||
points_.push_back(painter_pos);
|
||||
points_.push_back(painter_pos_end);
|
||||
|
||||
@@ -186,8 +179,8 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) {
|
||||
draw_list_->AddImage(
|
||||
(void *)bitmap.texture(),
|
||||
ImVec2(origin.x + painter_pos.x, origin.y + painter_pos.y),
|
||||
ImVec2(origin.x + painter_pos.x + bitmap.width() * scale,
|
||||
origin.y + painter_pos.y + bitmap.height() * scale));
|
||||
ImVec2(origin.x + painter_pos.x + (size)*scale,
|
||||
origin.y + painter_pos.y + size * scale));
|
||||
}
|
||||
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
@@ -195,8 +188,12 @@ bool Canvas::DrawTilePainter(const Bitmap &bitmap, int size, float scale) {
|
||||
// Save the coordinates of the selected tile.
|
||||
drawn_tile_pos_ = painter_pos;
|
||||
return true;
|
||||
} else if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
|
||||
// Draw the currently selected tile on the overworld here
|
||||
// Save the coordinates of the selected tile.
|
||||
drawn_tile_pos_ = painter_pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Erase the hover when the mouse is not in the canvas window.
|
||||
points_.clear();
|
||||
@@ -387,6 +384,26 @@ void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color) {
|
||||
IM_COL32(color.x, color.y, color.z, color.w));
|
||||
}
|
||||
|
||||
namespace {
|
||||
std::vector<int> GetTileIDsInGrid(int start_x, int start_y, int width,
|
||||
int height, int tile_size) {
|
||||
std::vector<int> tile_ids;
|
||||
|
||||
int num_tiles_x = width / tile_size;
|
||||
int num_tiles_y = height / tile_size;
|
||||
|
||||
for (int y = 0; y < num_tiles_y; y++) {
|
||||
for (int x = 0; x < num_tiles_x; x++) {
|
||||
int tile_id = (start_y / tile_size + y) * (width / tile_size) +
|
||||
(start_x / tile_size + x);
|
||||
tile_ids.push_back(tile_id);
|
||||
}
|
||||
}
|
||||
|
||||
return tile_ids;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void Canvas::DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color) {
|
||||
ImVec2 origin(canvas_p0_.x + scrolling_.x + x,
|
||||
canvas_p0_.y + scrolling_.y + y);
|
||||
@@ -400,12 +417,8 @@ void Canvas::DrawSelectRect(int tile_size, float scale) {
|
||||
static ImVec2 drag_start_pos;
|
||||
static bool dragging = false;
|
||||
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||
if (!points_.empty()) {
|
||||
points_.clear();
|
||||
}
|
||||
// Snap the start position to the nearest grid point with scaling
|
||||
// consideration
|
||||
if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
|
||||
// Start dragging and snap the start position to the nearest grid point
|
||||
drag_start_pos.x =
|
||||
std::floor(io.MousePos.x / (tile_size * scale)) * tile_size * scale;
|
||||
drag_start_pos.y =
|
||||
@@ -413,40 +426,81 @@ void Canvas::DrawSelectRect(int tile_size, float scale) {
|
||||
dragging = true;
|
||||
}
|
||||
|
||||
if (dragging) {
|
||||
ImVec2 current_pos = io.MousePos;
|
||||
ImVec2 grid_pos;
|
||||
grid_pos.x =
|
||||
std::floor(current_pos.x / (tile_size * scale)) * tile_size * scale;
|
||||
grid_pos.y =
|
||||
std::floor(current_pos.y / (tile_size * scale)) * tile_size * scale;
|
||||
|
||||
// Calculate rect_min and rect_max considering the drag direction
|
||||
ImVec2 rect_min, rect_max;
|
||||
rect_min.x =
|
||||
(grid_pos.x < drag_start_pos.x) ? grid_pos.x : drag_start_pos.x;
|
||||
rect_min.y =
|
||||
(grid_pos.y < drag_start_pos.y) ? grid_pos.y : drag_start_pos.y;
|
||||
rect_max.x = (grid_pos.x >= drag_start_pos.x)
|
||||
? grid_pos.x + tile_size * scale
|
||||
: drag_start_pos.x + tile_size * scale;
|
||||
rect_max.y = (grid_pos.y >= drag_start_pos.y)
|
||||
? grid_pos.y + tile_size * scale
|
||||
: drag_start_pos.y + tile_size * scale;
|
||||
ImVec2 current_pos = io.MousePos;
|
||||
// Snap current position to the nearest grid point
|
||||
ImVec2 snapped_current_pos;
|
||||
snapped_current_pos.x =
|
||||
std::floor(current_pos.x / (tile_size * scale)) * tile_size * scale;
|
||||
snapped_current_pos.y =
|
||||
std::floor(current_pos.y / (tile_size * scale)) * tile_size * scale;
|
||||
// Calculate rect_min and rect_max considering the drag direction
|
||||
ImVec2 rect_min = ImVec2(std::min(drag_start_pos.x, snapped_current_pos.x),
|
||||
std::min(drag_start_pos.y, snapped_current_pos.y));
|
||||
ImVec2 rect_max = ImVec2(
|
||||
std::max(drag_start_pos.x, snapped_current_pos.x) + tile_size * scale,
|
||||
std::max(drag_start_pos.y, snapped_current_pos.y) + tile_size * scale);
|
||||
|
||||
if (dragging && ImGui::IsMouseDragging(ImGuiMouseButton_Right)) {
|
||||
draw_list_->AddRect(rect_min, rect_max, kRectangleBorder);
|
||||
}
|
||||
|
||||
if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
|
||||
dragging = false;
|
||||
// Convert the coordinates to scale-independent form
|
||||
ImVec2 scaled_rect_min, scaled_rect_max;
|
||||
scaled_rect_min.x = rect_min.x * scale;
|
||||
scaled_rect_min.y = rect_min.y * scale;
|
||||
scaled_rect_max.x = rect_max.x * scale;
|
||||
scaled_rect_max.y = rect_max.y * scale;
|
||||
if (dragging && !ImGui::IsMouseDown(ImGuiMouseButton_Right)) {
|
||||
dragging = false;
|
||||
ImVec2 scaled_rect_min =
|
||||
ImVec2(drag_start_pos.x / scale, drag_start_pos.y / scale);
|
||||
ImVec2 scaled_rect_max = ImVec2(rect_max.x / scale, rect_max.y / scale);
|
||||
|
||||
points_.push_back(scaled_rect_min);
|
||||
points_.push_back(scaled_rect_max);
|
||||
// Here, calculate and store the tile16 IDs within the rectangle
|
||||
selected_tiles_ =
|
||||
GetTileIDsInGrid(scaled_rect_min.x, scaled_rect_min.y,
|
||||
scaled_rect_max.x - scaled_rect_min.x,
|
||||
scaled_rect_max.y - scaled_rect_min.y, tile_size);
|
||||
|
||||
// Clear and add the calculated rectangle points
|
||||
points_.clear();
|
||||
points_.push_back(scaled_rect_min);
|
||||
points_.push_back(scaled_rect_max);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::DrawBitmapGroup(std::vector<int> &group,
|
||||
std::vector<gfx::Bitmap> &tile16_individual_,
|
||||
int tile_size, float scale) {
|
||||
if (points_.size() != 2) {
|
||||
// Handle error: points_ should contain exactly two points
|
||||
return;
|
||||
}
|
||||
|
||||
// Top-left and bottom-right corners of the rectangle
|
||||
ImVec2 rect_top_left = points_[0];
|
||||
ImVec2 rect_bottom_right = points_[1];
|
||||
|
||||
// Calculate the start and end tiles in the grid
|
||||
int start_tile_x = static_cast<int>(rect_top_left.x / (tile_size * scale));
|
||||
int start_tile_y = static_cast<int>(rect_top_left.y / (tile_size * scale));
|
||||
int end_tile_x = static_cast<int>(rect_bottom_right.x / (tile_size * scale));
|
||||
int end_tile_y = static_cast<int>(rect_bottom_right.y / (tile_size * scale));
|
||||
|
||||
// Calculate the size of the rectangle in 16x16 grid form
|
||||
int rect_width = (end_tile_x - start_tile_x + 1) * tile_size;
|
||||
int rect_height = (end_tile_y - start_tile_y + 1) * tile_size;
|
||||
|
||||
const int tiles_per_row = rect_width / tile_size;
|
||||
|
||||
for (int i = 0; i < group.size(); ++i) {
|
||||
int tile_id = group[i];
|
||||
|
||||
// Check if tile_id is within the range of tile16_individual_
|
||||
if (tile_id >= 0 && tile_id < tile16_individual_.size()) {
|
||||
int x = i % tiles_per_row;
|
||||
int y = i / tiles_per_row;
|
||||
|
||||
// Calculate the position of the tile within the rectangle
|
||||
int tile_pos_x = x * tile_size * scale + start_tile_x * tile_size * scale;
|
||||
int tile_pos_y = y * tile_size * scale + start_tile_y * tile_size * scale;
|
||||
|
||||
// Draw the tile bitmap at the calculated position
|
||||
DrawBitmap(tile16_individual_[tile_id], tile_pos_x, tile_pos_y, scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class Canvas {
|
||||
void Update(const gfx::Bitmap& bitmap, ImVec2 bg_size, int tile_size,
|
||||
float scale = 1.0f, float grid_size = 64.0f);
|
||||
|
||||
void UpdateColorPainter(const gfx::Bitmap& bitmap, const ImVec4& color,
|
||||
void UpdateColorPainter(gfx::Bitmap& bitmap, const ImVec4& color,
|
||||
const std::function<void()>& event, int tile_size,
|
||||
float scale = 1.0f);
|
||||
|
||||
@@ -90,6 +90,11 @@ class Canvas {
|
||||
float scale = 1.0f);
|
||||
|
||||
void DrawBitmapTable(const BitmapTable& gfx_bin);
|
||||
|
||||
void DrawBitmapGroup(std::vector<int> &group,
|
||||
std::vector<gfx::Bitmap>& tile16_individual_,
|
||||
int tile_size, float scale = 1.0f);
|
||||
|
||||
void DrawOutline(int x, int y, int w, int h);
|
||||
void DrawOutlineWithColor(int x, int y, int w, int h, ImVec4 color);
|
||||
void DrawOutlineWithColor(int x, int y, int w, int h, uint32_t color);
|
||||
@@ -117,7 +122,7 @@ class Canvas {
|
||||
auto canvas_size() const { return canvas_sz_; }
|
||||
void set_global_scale(float scale) { global_scale_ = scale; }
|
||||
auto global_scale() const { return global_scale_; }
|
||||
auto custom_labels_enabled() const { return enable_custom_labels_; }
|
||||
auto custom_labels_enabled() { return &enable_custom_labels_; }
|
||||
auto custom_step() const { return custom_step_; }
|
||||
auto width() const { return canvas_sz_.x; }
|
||||
auto height() const { return canvas_sz_.y; }
|
||||
@@ -151,6 +156,9 @@ class Canvas {
|
||||
auto set_highlight_tile_id(int i) { highlight_tile_id = i; }
|
||||
auto set_draggable(bool value) { draggable_ = value; }
|
||||
|
||||
auto selected_tiles() const { return selected_tiles_; }
|
||||
auto mutable_selected_tiles() { return &selected_tiles_; }
|
||||
|
||||
private:
|
||||
bool draggable_ = false;
|
||||
bool enable_grid_ = true;
|
||||
@@ -175,6 +183,8 @@ class Canvas {
|
||||
ImVec2 canvas_p1_;
|
||||
ImVec2 mouse_pos_in_canvas_;
|
||||
ImVec2 drawn_tile_pos_;
|
||||
|
||||
std::vector<int> selected_tiles_;
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
|
||||
38
src/app/zelda3/common.h
Normal file
38
src/app/zelda3/common.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef YAZE_APP_ZELDA3_COMMON_H
|
||||
#define YAZE_APP_ZELDA3_COMMON_H
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace zelda3 {
|
||||
|
||||
class OverworldEntity {
|
||||
public:
|
||||
enum EntityType {
|
||||
kEntrance = 0,
|
||||
kExit = 1,
|
||||
kItem = 2,
|
||||
kSprite = 3,
|
||||
kTransport = 4,
|
||||
kMusic = 5,
|
||||
kTilemap = 6,
|
||||
kProperties = 7
|
||||
} type_;
|
||||
int x_;
|
||||
int y_;
|
||||
int game_x_;
|
||||
int game_y_;
|
||||
int entity_id_;
|
||||
int map_id_;
|
||||
|
||||
auto set_x(int x) { x_ = x; }
|
||||
auto set_y(int y) { y_ = y; }
|
||||
|
||||
OverworldEntity() = default;
|
||||
|
||||
virtual void UpdateMapProperties(short map_id) = 0;
|
||||
};
|
||||
} // namespace zelda3
|
||||
} // namespace app
|
||||
} // namespace yaze
|
||||
|
||||
#endif // YAZE_APP_ZELDA3_COMMON_H
|
||||
@@ -141,8 +141,8 @@ absl::Status Overworld::Load(ROM &rom) {
|
||||
FetchLargeMaps();
|
||||
LoadEntrances();
|
||||
LoadExits();
|
||||
LoadSprites();
|
||||
RETURN_IF_ERROR(LoadItems());
|
||||
RETURN_IF_ERROR(LoadSprites());
|
||||
RETURN_IF_ERROR(LoadOverworldMaps())
|
||||
|
||||
is_loaded_ = true;
|
||||
@@ -862,6 +862,12 @@ void Overworld::FetchLargeMaps() {
|
||||
}
|
||||
}
|
||||
|
||||
void Overworld::LoadTileTypes() {
|
||||
for (int i = 0; i < 0x200; i++) {
|
||||
all_tiles_types_[i] = rom()->data()[overworldTilesType + i];
|
||||
}
|
||||
}
|
||||
|
||||
void Overworld::LoadEntrances() {
|
||||
for (int i = 0; i < 129; i++) {
|
||||
short map_id = rom()->toint16(OWEntranceMap + (i * 2));
|
||||
@@ -939,6 +945,37 @@ absl::Status Overworld::SaveExits() {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool compareItemsArrays(std::vector<OverworldItem> itemArray1,
|
||||
std::vector<OverworldItem> itemArray2) {
|
||||
if (itemArray1.size() != itemArray2.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool match;
|
||||
for (int i = 0; i < itemArray1.size(); i++) {
|
||||
match = false;
|
||||
for (int j = 0; j < itemArray2.size(); j++) {
|
||||
// Check all sprite in 2nd array if one match
|
||||
if (itemArray1[i].x_ == itemArray2[j].x_ &&
|
||||
itemArray1[i].y_ == itemArray2[j].y_ &&
|
||||
itemArray1[i].id == itemArray2[j].id) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
absl::Status Overworld::SaveItems() {
|
||||
std::vector<std::vector<OverworldItem>> roomItems(128);
|
||||
|
||||
@@ -968,13 +1005,19 @@ absl::Status Overworld::SaveItems() {
|
||||
itemPointersReuse[i] = -2;
|
||||
break;
|
||||
}
|
||||
// Unclear: this.compareItemsArrays(roomItems[i].ToArray(),
|
||||
// roomItems[ci].ToArray()) Commenting out for now if
|
||||
// (this.compareItemsArrays(roomItems[i].ToArray(),
|
||||
// roomItems[ci].ToArray())) {
|
||||
// itemPointersReuse[i] = ci;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// Unclear:
|
||||
compareItemsArrays(
|
||||
std::vector<OverworldItem>(roomItems[i].begin(), roomItems[i].end()),
|
||||
std::vector<OverworldItem>(roomItems[ci].begin(),
|
||||
roomItems[ci].end()));
|
||||
if (compareItemsArrays(std::vector<OverworldItem>(roomItems[i].begin(),
|
||||
roomItems[i].end()),
|
||||
std::vector<OverworldItem>(roomItems[ci].begin(),
|
||||
roomItems[ci].end()))) {
|
||||
itemPointersReuse[i] = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1051,10 +1094,6 @@ void Overworld::LoadExits() {
|
||||
rom_data[OWExitYPlayer + (i * 2)]);
|
||||
ushort px = (ushort)((rom_data[OWExitXPlayer + (i * 2) + 1] << 8) +
|
||||
rom_data[OWExitXPlayer + (i * 2)]);
|
||||
OverworldExit exit(exit_room_id, exit_map_id, exit_vram, exit_y_scroll,
|
||||
exit_x_scroll, py, px, exit_y_camera, exit_x_camera,
|
||||
exit_scroll_mod_y, exit_scroll_mod_x, exit_door_type_1,
|
||||
exit_door_type_2);
|
||||
|
||||
if (rom()->flags()->kLogToConsole) {
|
||||
std::cout << "Exit: " << i << " RoomID: " << exit_room_id
|
||||
@@ -1069,22 +1108,24 @@ void Overworld::LoadExits() {
|
||||
<< " DoorType2: " << exit_door_type_2 << std::endl;
|
||||
}
|
||||
|
||||
if ((px & py) == 0xFFFF) {
|
||||
exit.deleted = true;
|
||||
}
|
||||
|
||||
exits.push_back(exit);
|
||||
exits.emplace_back(exit_room_id, exit_map_id, exit_vram, exit_y_scroll,
|
||||
exit_x_scroll, py, px, exit_y_camera, exit_x_camera,
|
||||
exit_scroll_mod_y, exit_scroll_mod_x, exit_door_type_1,
|
||||
exit_door_type_2, (px & py) == 0xFFFF);
|
||||
}
|
||||
all_exits_ = exits;
|
||||
}
|
||||
|
||||
absl::Status Overworld::LoadItems() {
|
||||
ASSIGN_OR_RETURN(int pointer, rom()->ReadLong(zelda3::overworldItemsAddress));
|
||||
int oointerPC = core::SnesToPc(pointer); // 1BC2F9 -> 0DC2F9
|
||||
int pointer_pc = core::SnesToPc(pointer); // 1BC2F9 -> 0DC2F9
|
||||
for (int i = 0; i < 128; i++) {
|
||||
int addr = (pointer & 0xFF0000) + // 1B
|
||||
(rom()->data()[oointerPC + (i * 2) + 1] << 8) + // F9
|
||||
rom()->data()[oointerPC + (i * 2)]; // 3C
|
||||
ASSIGN_OR_RETURN(uint16_t word_address,
|
||||
rom()->ReadWord(pointer_pc + i * 2));
|
||||
int addr = (pointer & 0xFF0000) | word_address; // 1B
|
||||
|
||||
// (rom()->data()[pointer_pc + (i * 2) + 1] << 8) + // F9
|
||||
// rom()->data()[pointer_pc + (i * 2)]; // 3C
|
||||
|
||||
addr = core::SnesToPc(addr);
|
||||
|
||||
@@ -1095,9 +1136,9 @@ absl::Status Overworld::LoadItems() {
|
||||
}
|
||||
|
||||
while (true) {
|
||||
uint8_t b1 = rom()->data()[addr];
|
||||
uint8_t b2 = rom()->data()[addr + 1];
|
||||
uint8_t b3 = rom()->data()[addr + 2];
|
||||
ASSIGN_OR_RETURN(uint8_t b1, rom()->ReadByte(addr));
|
||||
ASSIGN_OR_RETURN(uint8_t b2, rom()->ReadByte(addr + 1));
|
||||
ASSIGN_OR_RETURN(uint8_t b3, rom()->ReadByte(addr + 2));
|
||||
|
||||
if (b1 == 0xFF && b2 == 0xFF) {
|
||||
break;
|
||||
@@ -1116,51 +1157,41 @@ absl::Status Overworld::LoadItems() {
|
||||
int sy = fakeID / 8;
|
||||
int sx = fakeID - (sy * 8);
|
||||
|
||||
all_items_.emplace_back(zelda3::OverworldItem(
|
||||
b3, (ushort)i, (x * 16) + (sx * 512), (y * 16) + (sy * 512), false));
|
||||
all_items_.emplace_back(b3, (ushort)i, (x * 16) + (sx * 512),
|
||||
(y * 16) + (sy * 512), false);
|
||||
auto size = all_items_.size();
|
||||
all_items_.at(size - 1).game_x = (uint8_t)x;
|
||||
all_items_.at(size - 1).game_y = (uint8_t)y;
|
||||
|
||||
all_items_[size - 1].game_x = (uint8_t)x;
|
||||
all_items_[size - 1].game_y = (uint8_t)y;
|
||||
addr += 3;
|
||||
}
|
||||
}
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void Overworld::LoadSprites() {
|
||||
absl::Status Overworld::LoadSprites() {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
all_sprites_.emplace_back();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++) {
|
||||
all_sprites_[0].emplace_back();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 144; i++) {
|
||||
all_sprites_[1].emplace_back();
|
||||
}
|
||||
|
||||
for (int i = 0; i < 144; i++) {
|
||||
all_sprites_[2].emplace_back();
|
||||
}
|
||||
|
||||
LoadSpritesFromMap(overworldSpritesBegining, 64, 0);
|
||||
LoadSpritesFromMap(overworldSpritesZelda, 144, 1);
|
||||
LoadSpritesFromMap(overworldSpritesAgahnim, 144, 2);
|
||||
RETURN_IF_ERROR(LoadSpritesFromMap(overworldSpritesBegining, 64, 0));
|
||||
RETURN_IF_ERROR(LoadSpritesFromMap(overworldSpritesZelda, 144, 1));
|
||||
RETURN_IF_ERROR(LoadSpritesFromMap(overworldSpritesAgahnim, 144, 2));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
void Overworld::LoadSpritesFromMap(int sprite_start, int sprite_count,
|
||||
int sprite_index) {
|
||||
absl::Status Overworld::LoadSpritesFromMap(int sprite_start, int sprite_count,
|
||||
int sprite_index) {
|
||||
for (int i = 0; i < sprite_count; i++) {
|
||||
if (map_parent_[i] != i) continue;
|
||||
|
||||
int ptrPos = sprite_start + (i * 2);
|
||||
int sprite_address =
|
||||
core::SnesToPc((0x09 << 0x10) | rom()->toint16(ptrPos));
|
||||
ASSIGN_OR_RETURN(auto word_addr, rom()->ReadWord(ptrPos));
|
||||
int sprite_address = core::SnesToPc((0x09 << 0x10) | word_addr);
|
||||
while (true) {
|
||||
uchar b1 = rom_[sprite_address];
|
||||
uchar b2 = rom_[sprite_address + 1];
|
||||
uchar b3 = rom_[sprite_address + 2];
|
||||
ASSIGN_OR_RETURN(uint8_t b1, rom()->ReadByte(sprite_address));
|
||||
ASSIGN_OR_RETURN(uint8_t b2, rom()->ReadByte(sprite_address + 1));
|
||||
ASSIGN_OR_RETURN(uint8_t b3, rom()->ReadByte(sprite_address + 2));
|
||||
if (b1 == 0xFF) break;
|
||||
|
||||
int editor_map_index = i;
|
||||
@@ -1175,14 +1206,16 @@ void Overworld::LoadSpritesFromMap(int sprite_start, int sprite_count,
|
||||
|
||||
int realX = ((b2 & 0x3F) * 16) + mapX * 512;
|
||||
int realY = ((b1 & 0x3F) * 16) + mapY * 512;
|
||||
all_sprites_[sprite_index][i].InitSprite(
|
||||
overworld_maps_[i].AreaGraphics(), (uchar)i, b3, (uchar)(b2 & 0x3F),
|
||||
(uchar)(b1 & 0x3F), realX, realY);
|
||||
all_sprites_[sprite_index][i].Draw();
|
||||
all_sprites_[sprite_index].emplace_back(overworld_maps_[i].AreaGraphics(),
|
||||
(uchar)i, b3, (uchar)(b2 & 0x3F),
|
||||
(uchar)(b1 & 0x3F), realX, realY);
|
||||
// all_sprites_[sprite_index][i].Draw();
|
||||
|
||||
sprite_address += 3;
|
||||
}
|
||||
}
|
||||
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status Overworld::SaveMapProperties() {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/common.h"
|
||||
#include "app/zelda3/overworld_map.h"
|
||||
#include "app/zelda3/sprite/sprite.h"
|
||||
|
||||
@@ -21,33 +22,6 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace zelda3 {
|
||||
|
||||
class OverworldEntity {
|
||||
public:
|
||||
enum EntityType {
|
||||
kEntrance = 0,
|
||||
kExit = 1,
|
||||
kItem = 2,
|
||||
kSprite = 3,
|
||||
kTransport = 4,
|
||||
kMusic = 5,
|
||||
kTilemap = 6,
|
||||
kProperties = 7
|
||||
} type_;
|
||||
int x_;
|
||||
int y_;
|
||||
int game_x_;
|
||||
int game_y_;
|
||||
int entity_id_;
|
||||
int map_id_;
|
||||
|
||||
auto set_x(int x) { x_ = x; }
|
||||
auto set_y(int y) { y_ = y; }
|
||||
|
||||
OverworldEntity() = default;
|
||||
|
||||
virtual void UpdateMapProperties(short map_id) = 0;
|
||||
};
|
||||
|
||||
// List of secret item names
|
||||
const std::vector<std::string> kSecretItemNames = {
|
||||
"Nothing", // 0
|
||||
@@ -96,15 +70,6 @@ class OverworldItem : public OverworldEntity {
|
||||
bool deleted = false;
|
||||
OverworldItem() = default;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OverworldItem"/>
|
||||
/// class.
|
||||
/// </summary>
|
||||
/// <param name="id"> The ID. </param>
|
||||
/// <param name="room_map_id"> The dungeon room ID or overworld area ID.
|
||||
/// </param> <param name="x"> The in editor X position. </param> <param
|
||||
/// name="y"> The in editor Y position. </param> <param name="bg2"> Whether
|
||||
/// the Item is on BG2 or not. </param>
|
||||
OverworldItem(uint8_t id, uint16_t room_map_id, int x, int y, bool bg2) {
|
||||
this->id = id;
|
||||
this->x_ = x;
|
||||
@@ -123,12 +88,6 @@ class OverworldItem : public OverworldEntity {
|
||||
// this->unique_id = ROM.unique_item_id++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the item info when needed. Generally when moving items around
|
||||
/// in editor.
|
||||
/// </summary>
|
||||
/// <param name="room_map_id"> The dungeon room ID or overworld area ID where
|
||||
/// the item was moved to. </param>
|
||||
void UpdateMapProperties(int16_t room_map_id) override {
|
||||
this->room_map_id = static_cast<uint16_t>(room_map_id);
|
||||
|
||||
@@ -205,7 +164,7 @@ class OverworldExit : public OverworldEntity {
|
||||
uchar area_x_;
|
||||
uchar area_y_;
|
||||
bool is_hole_ = false;
|
||||
bool deleted = false;
|
||||
bool deleted_ = false;
|
||||
bool is_automatic_ = false;
|
||||
bool large_map_ = false;
|
||||
|
||||
@@ -214,7 +173,7 @@ class OverworldExit : public OverworldEntity {
|
||||
ushort y_scroll, ushort x_scroll, ushort player_y,
|
||||
ushort player_x, ushort camera_y, ushort camera_x,
|
||||
uchar scroll_mod_y, uchar scroll_mod_x, ushort door_type_1,
|
||||
ushort door_type_2)
|
||||
ushort door_type_2, bool deleted = false)
|
||||
: map_pos_(vram_location),
|
||||
entrance_id_(0),
|
||||
area_x_(0),
|
||||
@@ -230,7 +189,8 @@ class OverworldExit : public OverworldEntity {
|
||||
scroll_mod_y_(scroll_mod_y),
|
||||
scroll_mod_x_(scroll_mod_x),
|
||||
door_type_1_(door_type_1),
|
||||
door_type_2_(door_type_2) {
|
||||
door_type_2_(door_type_2),
|
||||
deleted_(deleted) {
|
||||
// Initialize entity variables
|
||||
this->x_ = player_x;
|
||||
this->y_ = player_y;
|
||||
@@ -494,6 +454,10 @@ class Overworld : public SharedROM, public core::ExperimentFlags {
|
||||
|
||||
absl::Status SaveMapProperties();
|
||||
|
||||
int GetTile16Id(int grid_id) const {
|
||||
return map_tiles_.light_world[game_state_][grid_id];
|
||||
}
|
||||
|
||||
auto overworld_maps() const { return overworld_maps_; }
|
||||
auto overworld_map(int i) const { return &overworld_maps_[i]; }
|
||||
auto mutable_overworld_map(int i) { return &overworld_maps_[i]; }
|
||||
@@ -528,6 +492,8 @@ class Overworld : public SharedROM, public core::ExperimentFlags {
|
||||
auto all_items() const { return all_items_; }
|
||||
auto mutable_all_items() { return &all_items_; }
|
||||
auto &ref_all_items() { return all_items_; }
|
||||
auto all_tiles_types() const { return all_tiles_types_; }
|
||||
auto mutable_all_tiles_types() { return &all_tiles_types_; }
|
||||
|
||||
absl::Status LoadPrototype(ROM &rom_, const std::string &tilemap_filename);
|
||||
|
||||
@@ -549,11 +515,13 @@ class Overworld : public SharedROM, public core::ExperimentFlags {
|
||||
absl::Status DecompressAllMapTiles();
|
||||
absl::Status DecompressProtoMapTiles(const std::string &filename);
|
||||
void FetchLargeMaps();
|
||||
void LoadTileTypes();
|
||||
void LoadEntrances();
|
||||
void LoadExits();
|
||||
absl::Status LoadItems();
|
||||
void LoadSprites();
|
||||
void LoadSpritesFromMap(int spriteStart, int spriteCount, int spriteIndex);
|
||||
absl::Status LoadSprites();
|
||||
absl::Status LoadSpritesFromMap(int spriteStart, int spriteCount,
|
||||
int spriteIndex);
|
||||
|
||||
bool is_loaded_ = false;
|
||||
|
||||
@@ -564,6 +532,8 @@ class Overworld : public SharedROM, public core::ExperimentFlags {
|
||||
ROM rom_;
|
||||
OWMapTiles map_tiles_;
|
||||
|
||||
uint8_t all_tiles_types_[0x200];
|
||||
|
||||
std::vector<gfx::Tile16> tiles16_;
|
||||
std::vector<gfx::Tile32> tiles32;
|
||||
std::vector<gfx::Tile32> tiles32_unique_;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "app/core/common.h"
|
||||
#include "app/editor/context/gfx_context.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/rom.h"
|
||||
@@ -18,138 +19,6 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace zelda3 {
|
||||
|
||||
namespace {
|
||||
|
||||
void CopyTile8bpp16(int x, int y, int tile, Bytes& bitmap, Bytes& blockset) {
|
||||
int src_pos =
|
||||
((tile - ((tile / 0x08) * 0x08)) * 0x10) + ((tile / 0x08) * 2048);
|
||||
int dest_pos = (x + (y * 0x200));
|
||||
for (int yy = 0; yy < 0x10; yy++) {
|
||||
for (int xx = 0; xx < 0x10; xx++) {
|
||||
bitmap[dest_pos + xx + (yy * 0x200)] =
|
||||
blockset[src_pos + xx + (yy * 0x80)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
||||
gfx::SNESPalette main, gfx::SNESPalette animated,
|
||||
gfx::SNESPalette aux1, gfx::SNESPalette aux2,
|
||||
gfx::SNESPalette hud, gfx::SNESColor bgrcolor,
|
||||
gfx::SNESPalette spr, gfx::SNESPalette spr2) {
|
||||
// Palettes infos, color 0 of a palette is always transparent (the arrays
|
||||
// contains 7 colors width wide) There is 16 color per line so 16*Y
|
||||
|
||||
// Left side of the palette - Main, Animated
|
||||
std::vector<gfx::SNESColor> new_palette(256);
|
||||
|
||||
// Main Palette, Location 0,2 : 35 colors [7x5]
|
||||
int k = 0;
|
||||
for (int y = 2; y < 7; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = main[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Animated Palette, Location 0,7 : 7colors
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[(16 * 7) + (x)] = animated[(x - 1)];
|
||||
}
|
||||
|
||||
// Right side of the palette - Aux1, Aux2
|
||||
|
||||
// Aux1 Palette, Location 8,2 : 21 colors [7x3]
|
||||
k = 0;
|
||||
for (int y = 2; y < 5; y++) {
|
||||
for (int x = 9; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = aux1[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Aux2 Palette, Location 8,5 : 21 colors [7x3]
|
||||
k = 0;
|
||||
for (int y = 5; y < 8; y++) {
|
||||
for (int x = 9; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = aux2[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Hud Palette, Location 0,0 : 32 colors [16x2]
|
||||
for (int i = 0; i < 32; i++) {
|
||||
new_palette[i] = hud[i];
|
||||
}
|
||||
|
||||
// Hardcoded grass color (that might change to become invisible instead)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
new_palette[(i * 16)] = bgrcolor;
|
||||
new_palette[(i * 16) + 8] = bgrcolor;
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 8; y < 9; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("sprites_aux1")[1][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 8; y < 9; y++) {
|
||||
for (int x = 9; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("sprites_aux3")[0][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 9; y < 13; y++) {
|
||||
for (int x = 1; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("global_sprites")[0][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 13; y < 14; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = spr[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 14; y < 15; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = spr2[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 15; y < 16; y++) {
|
||||
for (int x = 1; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("armors")[0][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
current.Create(new_palette);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
current[(i / 16) * 16].SetTransparent(true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
OverworldMap::OverworldMap(int index, ROM& rom,
|
||||
std::vector<gfx::Tile16>& tiles16)
|
||||
: parent_(index), index_(index), rom_(rom), tiles16_(tiles16) {
|
||||
@@ -322,14 +191,6 @@ void OverworldMap::DrawAnimatedTiles() {
|
||||
}
|
||||
static_graphics_[7] = 0x5B;
|
||||
}
|
||||
// if (static_graphics_[7] == 0x5A) {
|
||||
// static_graphics_[7] = 0x5B;
|
||||
// } else {
|
||||
// if (static_graphics_[7] == 0x58) {
|
||||
// static_graphics_[7] = 0x59;
|
||||
// }
|
||||
// static_graphics_[7] = 0x5A;
|
||||
// }
|
||||
}
|
||||
|
||||
void OverworldMap::LoadAreaGraphicsBlocksets() {
|
||||
@@ -359,6 +220,125 @@ void OverworldMap::LoadAreaGraphics() {
|
||||
LoadDeathMountainGFX();
|
||||
}
|
||||
|
||||
namespace palette_internal {
|
||||
|
||||
void SetColorsPalette(ROM& rom, int index, gfx::SNESPalette& current,
|
||||
gfx::SNESPalette main, gfx::SNESPalette animated,
|
||||
gfx::SNESPalette aux1, gfx::SNESPalette aux2,
|
||||
gfx::SNESPalette hud, gfx::SNESColor bgrcolor,
|
||||
gfx::SNESPalette spr, gfx::SNESPalette spr2) {
|
||||
// Palettes infos, color 0 of a palette is always transparent (the arrays
|
||||
// contains 7 colors width wide) There is 16 color per line so 16*Y
|
||||
|
||||
// Left side of the palette - Main, Animated
|
||||
std::vector<gfx::SNESColor> new_palette(256);
|
||||
|
||||
// Main Palette, Location 0,2 : 35 colors [7x5]
|
||||
int k = 0;
|
||||
for (int y = 2; y < 7; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = main[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Animated Palette, Location 0,7 : 7colors
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[(16 * 7) + (x)] = animated[(x - 1)];
|
||||
}
|
||||
|
||||
// Right side of the palette - Aux1, Aux2
|
||||
|
||||
// Aux1 Palette, Location 8,2 : 21 colors [7x3]
|
||||
k = 0;
|
||||
for (int y = 2; y < 5; y++) {
|
||||
for (int x = 9; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = aux1[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Aux2 Palette, Location 8,5 : 21 colors [7x3]
|
||||
k = 0;
|
||||
for (int y = 5; y < 8; y++) {
|
||||
for (int x = 9; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = aux2[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Hud Palette, Location 0,0 : 32 colors [16x2]
|
||||
for (int i = 0; i < 32; i++) {
|
||||
new_palette[i] = hud[i];
|
||||
}
|
||||
|
||||
// Hardcoded grass color (that might change to become invisible instead)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
new_palette[(i * 16)] = bgrcolor;
|
||||
new_palette[(i * 16) + 8] = bgrcolor;
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 8; y < 9; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("sprites_aux1")[1][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 8; y < 9; y++) {
|
||||
for (int x = 9; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("sprites_aux3")[0][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 9; y < 13; y++) {
|
||||
for (int x = 1; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("global_sprites")[0][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 13; y < 14; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = spr[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 14; y < 15; y++) {
|
||||
for (int x = 1; x < 8; x++) {
|
||||
new_palette[x + (16 * y)] = spr2[k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sprite Palettes
|
||||
k = 0;
|
||||
for (int y = 15; y < 16; y++) {
|
||||
for (int x = 1; x < 16; x++) {
|
||||
new_palette[x + (16 * y)] = rom.palette_group("armors")[0][k];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
current.Create(new_palette);
|
||||
for (int i = 0; i < 256; i++) {
|
||||
current[(i / 16) * 16].SetTransparent(true);
|
||||
}
|
||||
}
|
||||
} // namespace palette_internal
|
||||
|
||||
// New helper function to get a palette from the ROM.
|
||||
gfx::SNESPalette OverworldMap::GetPalette(const std::string& group, int index,
|
||||
int previousIndex, int limit) {
|
||||
@@ -427,8 +407,11 @@ void OverworldMap::LoadPalette() {
|
||||
gfx::SNESPalette spr2 =
|
||||
GetPalette("sprites_aux3", pal5, previousSprPalId, 24);
|
||||
|
||||
SetColorsPalette(rom_, parent_, current_palette_, main, animated, aux1, aux2,
|
||||
hud, bgr, spr, spr2);
|
||||
palette_internal::SetColorsPalette(rom_, parent_, current_palette_, main,
|
||||
animated, aux1, aux2, hud, bgr, spr, spr2);
|
||||
|
||||
gfx::Paletteset paletteset{main, animated, aux1, aux2, bgr, hud, spr, spr2};
|
||||
palettesets_[area_graphics_] = paletteset;
|
||||
}
|
||||
|
||||
// New helper function to process graphics buffer.
|
||||
@@ -450,7 +433,7 @@ void OverworldMap::ProcessGraphicsBuffer(int index, int static_graphics_offset,
|
||||
|
||||
absl::Status OverworldMap::BuildTileset() {
|
||||
all_gfx_ = rom_.graphics_buffer();
|
||||
current_gfx_.resize(0x10000, 0x00);
|
||||
if (current_gfx_.size() == 0) current_gfx_.resize(0x10000, 0x00);
|
||||
|
||||
for (int i = 0; i < 0x10; i++) {
|
||||
ProcessGraphicsBuffer(i, static_graphics_[i], 0x1000);
|
||||
@@ -460,13 +443,8 @@ absl::Status OverworldMap::BuildTileset() {
|
||||
}
|
||||
|
||||
absl::Status OverworldMap::BuildTiles16Gfx(int count) {
|
||||
if (current_blockset_.size() != 0) {
|
||||
current_blockset_.clear();
|
||||
}
|
||||
current_blockset_.reserve(0x100000);
|
||||
for (int i = 0; i < 0x100000; i++) {
|
||||
current_blockset_.push_back(0x00);
|
||||
}
|
||||
if (current_blockset_.size() == 0) current_blockset_.resize(0x100000, 0x00);
|
||||
|
||||
const int offsets[] = {0x00, 0x08, 0x400, 0x408};
|
||||
auto yy = 0;
|
||||
auto xx = 0;
|
||||
@@ -509,6 +487,22 @@ absl::Status OverworldMap::BuildTiles16Gfx(int count) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void CopyTile8bpp16(int x, int y, int tile, Bytes& bitmap, Bytes& blockset) {
|
||||
int src_pos =
|
||||
((tile - ((tile / 0x08) * 0x08)) * 0x10) + ((tile / 0x08) * 2048);
|
||||
int dest_pos = (x + (y * 0x200));
|
||||
for (int yy = 0; yy < 0x10; yy++) {
|
||||
for (int xx = 0; xx < 0x10; xx++) {
|
||||
bitmap[dest_pos + xx + (yy * 0x200)] =
|
||||
blockset[src_pos + xx + (yy * 0x80)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
absl::Status OverworldMap::BuildBitmap(OWBlockset& world_blockset) {
|
||||
if (bitmap_data_.size() != 0) {
|
||||
bitmap_data_.clear();
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "app/core/common.h"
|
||||
#include "app/editor/context/gfx_context.h"
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_palette.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
@@ -22,7 +23,9 @@ namespace zelda3 {
|
||||
|
||||
static constexpr int kTileOffsets[] = {0, 8, 4096, 4104};
|
||||
|
||||
class OverworldMap {
|
||||
using editor::GfxContext;
|
||||
|
||||
class OverworldMap : public GfxContext {
|
||||
public:
|
||||
OverworldMap() = default;
|
||||
OverworldMap(int index, ROM& rom, std::vector<gfx::Tile16>& tiles16);
|
||||
@@ -38,6 +41,7 @@ class OverworldMap {
|
||||
|
||||
void DrawAnimatedTiles();
|
||||
|
||||
|
||||
auto Tile16Blockset() const { return current_blockset_; }
|
||||
auto AreaGraphics() const { return current_gfx_; }
|
||||
auto AreaPalette() const { return current_palette_; }
|
||||
@@ -46,7 +50,7 @@ class OverworldMap {
|
||||
auto IsLargeMap() const { return large_map_; }
|
||||
auto IsInitialized() const { return initialized_; }
|
||||
auto Parent() const { return parent_; }
|
||||
|
||||
|
||||
auto mutable_current_palette() { return ¤t_palette_; }
|
||||
|
||||
auto area_graphics() const { return area_graphics_; }
|
||||
|
||||
@@ -4,39 +4,40 @@ namespace yaze {
|
||||
namespace app {
|
||||
namespace zelda3 {
|
||||
|
||||
Sprite::Sprite() {
|
||||
preview_gfx_.reserve(64 * 64);
|
||||
for (int i = 0; i < 64 * 64; i++) {
|
||||
preview_gfx_.push_back(0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::InitSprite(const Bytes& src, uchar mapid, uchar id, uchar x,
|
||||
uchar y, int map_x, int map_y) {
|
||||
current_gfx_ = src;
|
||||
overworld_ = true;
|
||||
map_id_ = mapid;
|
||||
map_id_ = static_cast<int>(mapid);
|
||||
id_ = id;
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
this->type_ = zelda3::OverworldEntity::EntityType::kSprite;
|
||||
this->entity_id_ = id;
|
||||
this->x_ = map_x_;
|
||||
this->y_ = map_y_;
|
||||
nx_ = x;
|
||||
ny_ = y;
|
||||
name_ = core::kSpriteDefaultNames[id];
|
||||
map_x_ = map_x;
|
||||
map_y_ = map_y;
|
||||
preview_gfx_.reserve(64 * 64);
|
||||
for (int i = 0; i < 64 * 64; i++) {
|
||||
preview_gfx_.push_back(0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
Sprite::Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x,
|
||||
int map_y)
|
||||
: current_gfx_(src),
|
||||
map_id_(mapid),
|
||||
map_id_(static_cast<int>(mapid)),
|
||||
id_(id),
|
||||
x_(x),
|
||||
y_(y),
|
||||
nx_(x),
|
||||
ny_(y),
|
||||
map_x_(map_x),
|
||||
map_y_(map_y) {
|
||||
this->type_ = zelda3::OverworldEntity::EntityType::kSprite;
|
||||
this->entity_id_ = id;
|
||||
this->x_ = map_x_;
|
||||
this->y_ = map_y_;
|
||||
current_gfx_ = src;
|
||||
overworld_ = true;
|
||||
|
||||
@@ -47,6 +48,12 @@ Sprite::Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x,
|
||||
}
|
||||
}
|
||||
|
||||
void Sprite::UpdateMapProperties(short map_id) {
|
||||
map_x_ = x_;
|
||||
map_y_ = y_;
|
||||
name_ = core::kSpriteDefaultNames[id_];
|
||||
}
|
||||
|
||||
void Sprite::updateCoordinates(int map_x, int map_y) {
|
||||
map_x_ = map_x;
|
||||
map_y_ = map_y;
|
||||
|
||||
@@ -13,14 +13,15 @@
|
||||
#include "app/gfx/bitmap.h"
|
||||
#include "app/gfx/snes_tile.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/zelda3/common.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace app {
|
||||
namespace zelda3 {
|
||||
|
||||
class Sprite {
|
||||
class Sprite : public OverworldEntity {
|
||||
public:
|
||||
Sprite();
|
||||
Sprite() = default;
|
||||
Sprite(Bytes src, uchar mapid, uchar id, uchar x, uchar y, int map_x,
|
||||
int map_y);
|
||||
void InitSprite(const Bytes& src, uchar mapid, uchar id, uchar x, uchar y,
|
||||
@@ -32,13 +33,14 @@ class Sprite {
|
||||
bool mirror_x = false, bool mirror_y = false,
|
||||
int sizex = 2, int sizey = 2);
|
||||
|
||||
void UpdateMapProperties(short map_id) override;
|
||||
|
||||
// New methods
|
||||
void updateCoordinates(int map_x, int map_y);
|
||||
|
||||
auto PreviewGraphics() const { return preview_gfx_; }
|
||||
auto GetRealX() const { return bounding_box_.x; }
|
||||
auto GetRealY() const { return bounding_box_.y; }
|
||||
auto id() const { return id_; }
|
||||
auto set_id(uchar id) { id_ = id; }
|
||||
auto x() const { return x_; }
|
||||
auto y() const { return y_; }
|
||||
auto nx() const { return nx_; }
|
||||
@@ -55,6 +57,7 @@ class Sprite {
|
||||
auto Height() const { return bounding_box_.h; }
|
||||
std::string& Name() { return name_; }
|
||||
auto deleted() const { return deleted_; }
|
||||
auto set_deleted(bool deleted) { deleted_ = deleted; }
|
||||
|
||||
private:
|
||||
Bytes current_gfx_;
|
||||
@@ -62,8 +65,8 @@ class Sprite {
|
||||
|
||||
uchar map_id_;
|
||||
uchar id_;
|
||||
uchar x_;
|
||||
uchar y_;
|
||||
// uchar x_;
|
||||
// uchar y_;
|
||||
uchar nx_;
|
||||
uchar ny_;
|
||||
uchar overlord_ = 0;
|
||||
|
||||
Reference in New Issue
Block a user