mirror of
https://github.com/opentibiabr/remeres-map-editor
synced 2026-08-15 18:26:04 -04:00
New Features: - Scene caching with render-to-texture and blitting for faster map redraws. - Explicit blend-mode controls and FBO-backed render-to-texture workflow. Bug Fixes: - More robust sprite-sheet reload and texture release behavior. - Safer editor/tab shutdown with ensured live-server closure and deferred deletion. Performance: - Reworked GPU batching/streaming and command-based flushing for fewer draw calls and efficient uploads. - Smarter scene invalidation to avoid unnecessary re-renders. UX: - Undo/redo now refreshes editor views more reliably.
230 lines
6.2 KiB
C++
230 lines
6.2 KiB
C++
//////////////////////////////////////////////////////////////////////
|
|
// This file is part of Canary Map Editor
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Canary Map Editor is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// Canary Map Editor is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef SPRITEAPPEARANCES_H
|
|
#define SPRITEAPPEARANCES_H
|
|
|
|
#include "definitions.h"
|
|
#include "main.h"
|
|
#include "graphics.h"
|
|
#include <chrono>
|
|
|
|
class GameSprite;
|
|
|
|
// APPEARANCES
|
|
#define LZMA_UNCOMPRESSED_SIZE BYTES_IN_SPRITE_SHEET + 122
|
|
#define LZMA_HEADER_SIZE LZMA_PROPS_SIZE + 8
|
|
|
|
#define SPRITE_SHEET_WIDTH 384
|
|
#define SPRITE_SHEET_HEIGHT 384
|
|
#define BYTES_IN_SPRITE_SHEET SPRITE_SHEET_WIDTH* SPRITE_SHEET_WIDTH * 4
|
|
#define SPRITE_SHEET_WIDTH_BYTES SPRITE_SHEET_WIDTH * 4
|
|
|
|
enum class SpriteLayout {
|
|
ONE_BY_ONE = 0,
|
|
ONE_BY_TWO = 1,
|
|
TWO_BY_ONE = 2,
|
|
TWO_BY_TWO = 3
|
|
};
|
|
|
|
struct SpritesSize {
|
|
public:
|
|
SpritesSize(int width, int height) :
|
|
height(height), width(width) { }
|
|
|
|
void resize(int width, int height) {
|
|
this->height = height;
|
|
this->width = width;
|
|
}
|
|
void setHeight(int height) {
|
|
this->height = height;
|
|
}
|
|
void setWidth(int width) {
|
|
this->width = width;
|
|
}
|
|
int area() const {
|
|
return width * height;
|
|
}
|
|
|
|
int height = 0;
|
|
int width = 0;
|
|
};
|
|
|
|
struct Sprites {
|
|
public:
|
|
Sprites(int32_t width, int32_t height) :
|
|
size(width, height) {
|
|
pixels.resize(width * height * 4, 0);
|
|
}
|
|
|
|
bool save(const std::string &file, bool fixMagenta = false) {
|
|
wxImage image(size.width, size.height);
|
|
|
|
for (int y = 0; y < size.height; ++y) {
|
|
for (int x = 0; x < size.width; ++x) {
|
|
const int index = (y * size.width + x) * 4;
|
|
const uint8_t r = pixels[index + 2];
|
|
const uint8_t g = pixels[index + 1];
|
|
const uint8_t b = pixels[index];
|
|
image.SetRGB(x, y, r, g, b);
|
|
}
|
|
}
|
|
|
|
return image.SaveFile(wxString(file), wxBITMAP_TYPE_PNG);
|
|
}
|
|
|
|
std::vector<uint8_t> pixels;
|
|
SpritesSize size;
|
|
};
|
|
|
|
class SpriteSheet {
|
|
public:
|
|
SpriteSheet(int firstId, int lastId, SpriteLayout spriteLayout, const std::string &path) :
|
|
firstId(firstId), lastId(lastId), spriteLayout(spriteLayout), path(path) { }
|
|
|
|
SpritesSize getSpriteSize() const {
|
|
SpritesSize size(rme::SpritePixels, rme::SpritePixels);
|
|
|
|
switch (spriteLayout) {
|
|
case SpriteLayout::ONE_BY_ONE:
|
|
break;
|
|
case SpriteLayout::ONE_BY_TWO:
|
|
size.setHeight(64);
|
|
break;
|
|
case SpriteLayout::TWO_BY_ONE:
|
|
size.setWidth(64);
|
|
break;
|
|
case SpriteLayout::TWO_BY_TWO:
|
|
size.resize(64, 64);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
int getTotalSprites() const {
|
|
return lastId - firstId + 1;
|
|
}
|
|
|
|
int getTotalRows() const {
|
|
auto spriteSize = getSpriteSize();
|
|
if (spriteSize.width == 0) {
|
|
return 0; // Avoid division by zero
|
|
}
|
|
|
|
int spritesPerRow = SPRITE_SHEET_WIDTH / spriteSize.width; // Use the actual sheet width
|
|
if (spritesPerRow == 0) {
|
|
return 0; // No rows if sprites don't fit in a line
|
|
}
|
|
|
|
// Calculate total sprites and round up division for rows
|
|
return (getTotalSprites() + spritesPerRow - 1) / spritesPerRow;
|
|
}
|
|
|
|
bool exportSheetImage(const std::string &file, bool fixMagenta = false) {
|
|
if (!data) {
|
|
return false;
|
|
}
|
|
wxImage image(384, 384, data.get(), true);
|
|
return image.SaveFile(wxString(file), wxBITMAP_TYPE_PNG);
|
|
};
|
|
|
|
GLuint getOrUploadGLTexture();
|
|
void releaseGLTexture();
|
|
SpriteUV getSpriteUVs(int spriteId) const;
|
|
|
|
int firstId = 0;
|
|
int lastId = 0;
|
|
SpriteLayout spriteLayout = SpriteLayout::ONE_BY_ONE;
|
|
std::unique_ptr<uint8_t[]> data;
|
|
std::string path;
|
|
bool loaded = false;
|
|
GLuint glTextureId = 0;
|
|
std::chrono::steady_clock::time_point lastaccess;
|
|
};
|
|
|
|
using SpritePtr = std::shared_ptr<Sprites>;
|
|
using SpriteSheetPtr = std::shared_ptr<SpriteSheet>;
|
|
|
|
//@bindsingleton g_spriteAppearances
|
|
class SpriteAppearances {
|
|
public:
|
|
void init();
|
|
void terminate();
|
|
|
|
void unload();
|
|
|
|
// sprites
|
|
void exportSpriteImage(int id, const std::string &path);
|
|
SpritePtr getSprite(int spriteId);
|
|
|
|
int getSpritesCount() {
|
|
return spritesCount;
|
|
}
|
|
|
|
void setSpritesCount(int count) {
|
|
spritesCount = count;
|
|
}
|
|
int getSpritesCount() const {
|
|
return spritesCount;
|
|
}
|
|
/**
|
|
Returns a wxImage object containing the sprite image data for a given sprite ID.
|
|
@param id The ID of the sprite to retrieve.
|
|
@param toSavePng Determines if the image should be saved as a PNG file.
|
|
@return A wxImage object containing the sprite image data.
|
|
@remarks The image data is retrieved from a sprite sheet using the provided ID.
|
|
If toSavePng is set to true, the black color (0, 0, 0) is set to transparent by default and the image will be saved as a PNG file (with transparent background).
|
|
Use to save image: image.SaveFile(g_gui.GetDataDirectory().ToStdString() + "image.png", wxBITMAP_TYPE_PNG);
|
|
*/
|
|
wxImage getWxImageBySpriteId(int id, bool toSavePng = false);
|
|
|
|
const std::string getAppearanceFileName() const {
|
|
return appearanceFile;
|
|
}
|
|
|
|
bool loadCatalogContent(const std::string &dir, bool loadData = true);
|
|
bool loadSpriteSheet(const SpriteSheetPtr &sheet);
|
|
void saveSheetToFileBySprite(int id, const std::string &file);
|
|
void saveSheetToFile(const SpriteSheetPtr &sheet, const std::string &file);
|
|
struct AtlasInfo {
|
|
GLuint textureId;
|
|
SpriteUV uvs;
|
|
};
|
|
AtlasInfo getAtlasInfo(int spriteId);
|
|
SpriteSheetPtr getSheetBySpriteId(int id, bool load = true);
|
|
std::vector<SpriteSheetPtr> &getSheets() {
|
|
return sheets;
|
|
}
|
|
|
|
void addSpriteSheet(SpriteSheetPtr sheet) {
|
|
sheets.push_back(sheet);
|
|
}
|
|
|
|
void saveSpriteToFile(int id, const std::string &file);
|
|
|
|
private:
|
|
int spritesCount = 0;
|
|
std::vector<SpriteSheetPtr> sheets;
|
|
std::map<int, SpritePtr> sprites;
|
|
std::string appearanceFile;
|
|
};
|
|
|
|
extern SpriteAppearances g_spriteAppearances;
|
|
|
|
#endif
|