diff --git a/src/GridChunk.cpp b/src/GridChunk.cpp index 2491c07..f1ff7f2 100644 --- a/src/GridChunk.cpp +++ b/src/GridChunk.cpp @@ -14,7 +14,7 @@ GridChunk::GridChunk(int chunk_x, int chunk_y, int width, int height, width(width), height(height), world_x(world_x), world_y(world_y), cells(width * height), - dirty(true), texture_initialized(false), + dirty(true), parent_grid(parent) {} @@ -30,60 +30,8 @@ void GridChunk::markDirty() { dirty = true; } -void GridChunk::ensureTexture(int cell_width, int cell_height) { - unsigned int required_width = width * cell_width; - unsigned int required_height = height * cell_height; - - if (texture_initialized && - cached_texture.getSize().x == required_width && - cached_texture.getSize().y == required_height) { - return; - } - - if (!cached_texture.create(required_width, required_height)) { - texture_initialized = false; - return; - } - - texture_initialized = true; - dirty = true; // Force re-render after resize - cached_sprite.setTexture(cached_texture.getTexture()); -} - -void GridChunk::renderToTexture(int cell_width, int cell_height, - std::shared_ptr texture) { - ensureTexture(cell_width, cell_height); - if (!texture_initialized) return; - - cached_texture.clear(sf::Color::Transparent); - - sf::RectangleShape rect; - rect.setSize(sf::Vector2f(cell_width, cell_height)); - rect.setOutlineThickness(0); - - // Render all cells in this chunk - for (int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) { - const auto& cell = at(x, y); - sf::Vector2f pixel_pos(x * cell_width, y * cell_height); - - // Draw background color - rect.setPosition(pixel_pos); - rect.setFillColor(cell.color); - cached_texture.draw(rect); - - // Draw tile sprite if available - if (texture && cell.tilesprite != -1) { - sf::Sprite sprite = texture->sprite(cell.tilesprite, pixel_pos, - sf::Vector2f(1.0f, 1.0f)); - cached_texture.draw(sprite); - } - } - } - - cached_texture.display(); - dirty = false; -} +// #150 - Removed ensureTexture/renderToTexture - base layer rendering removed +// GridChunk now only provides data storage for GridPoints sf::FloatRect GridChunk::getWorldBounds(int cell_width, int cell_height) const { return sf::FloatRect( diff --git a/src/GridChunk.h b/src/GridChunk.h index d590392..1360355 100644 --- a/src/GridChunk.h +++ b/src/GridChunk.h @@ -10,11 +10,11 @@ class UIGrid; class PyTexture; /** - * #123 - Grid chunk for sub-grid rendering system + * #123 - Grid chunk for sub-grid data storage + * #150 - Rendering removed; layers now handle all rendering * * Each chunk represents a CHUNK_SIZE x CHUNK_SIZE portion of the grid. - * Chunks have their own RenderTexture and dirty flag for efficient - * incremental rendering - only dirty chunks are re-rendered. + * Chunks store GridPoint data for pathfinding and game logic. */ class GridChunk { public: @@ -30,16 +30,13 @@ public: // World position (in cell coordinates) int world_x, world_y; - // Cell data for this chunk + // Cell data for this chunk (pathfinding properties only) std::vector cells; - // Cached rendering - sf::RenderTexture cached_texture; - sf::Sprite cached_sprite; + // Dirty flag (for layer sync if needed) bool dirty; - bool texture_initialized; - // Parent grid reference (for texture access) + // Parent grid reference UIGrid* parent_grid; // Constructor @@ -50,16 +47,9 @@ public: UIGridPoint& at(int local_x, int local_y); const UIGridPoint& at(int local_x, int local_y) const; - // Mark chunk as needing re-render + // Mark chunk as dirty void markDirty(); - // Ensure texture is properly sized - void ensureTexture(int cell_width, int cell_height); - - // Render chunk content to cached texture - void renderToTexture(int cell_width, int cell_height, - std::shared_ptr texture); - // Get pixel bounds of this chunk in world coordinates sf::FloatRect getWorldBounds(int cell_width, int cell_height) const; diff --git a/src/UIGrid.cpp b/src/UIGrid.cpp index ef5de71..2f88d39 100644 --- a/src/UIGrid.cpp +++ b/src/UIGrid.cpp @@ -407,9 +407,9 @@ std::shared_ptr UIGrid::getLayerByName(const std::string& name) { } bool UIGrid::isProtectedLayerName(const std::string& name) { - // #150 - These names are reserved for GridPoint properties + // #150 - These names are reserved for GridPoint pathfinding properties static const std::vector protected_names = { - "walkable", "transparent", "color", "color_overlay" + "walkable", "transparent" }; for (const auto& pn : protected_names) { if (name == pn) return true; @@ -896,8 +896,8 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { // Default: {"tilesprite": "tile"} when layers not provided // Empty dict: no rendering layers (entity storage + pathfinding only) if (layers_obj == nullptr) { - // Default layer: single TileLayer named "tilesprite" - self->data->addTileLayer(0, texture_ptr, "tilesprite"); + // Default layer: single TileLayer named "tilesprite" (z_index -1 = below entities) + self->data->addTileLayer(-1, texture_ptr, "tilesprite"); } else if (layers_obj != Py_None) { if (!PyDict_Check(layers_obj)) { PyErr_SetString(PyExc_TypeError, "layers must be a dict mapping names to types ('color' or 'tile')"); @@ -907,7 +907,7 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { PyObject* key; PyObject* value; Py_ssize_t pos = 0; - int layer_z = 0; // Auto-increment z_index for each layer + int layer_z = -1; // Start at -1 (below entities), decrement for each layer while (PyDict_Next(layers_obj, &pos, &key, &value)) { if (!PyUnicode_Check(key)) { @@ -929,9 +929,9 @@ int UIGrid::init(PyUIGridObject* self, PyObject* args, PyObject* kwds) { } if (strcmp(layer_type, "color") == 0) { - self->data->addColorLayer(layer_z++, layer_name); + self->data->addColorLayer(layer_z--, layer_name); } else if (strcmp(layer_type, "tile") == 0) { - self->data->addTileLayer(layer_z++, texture_ptr, layer_name); + self->data->addTileLayer(layer_z--, texture_ptr, layer_name); } else { PyErr_Format(PyExc_ValueError, "Unknown layer type '%s' (expected 'color' or 'tile')", layer_type); return -1; diff --git a/src/UIGridPoint.cpp b/src/UIGridPoint.cpp index a893651..df93fce 100644 --- a/src/UIGridPoint.cpp +++ b/src/UIGridPoint.cpp @@ -4,8 +4,7 @@ #include // #150 - for strcmp UIGridPoint::UIGridPoint() -: color(1.0f, 1.0f, 1.0f), color_overlay(0.0f, 0.0f, 0.0f), walkable(false), transparent(false), - tilesprite(-1), tile_overlay(-1), uisprite(-1), grid_x(-1), grid_y(-1), parent_grid(nullptr) +: walkable(false), transparent(false), grid_x(-1), grid_y(-1), parent_grid(nullptr) {} // Utility function to convert sf::Color to PyObject* @@ -53,28 +52,7 @@ sf::Color PyObject_to_sfColor(PyObject* obj) { return sf::Color(r, g, b, a); } -PyObject* UIGridPoint::get_color(PyUIGridPointObject* self, void* closure) { - if (reinterpret_cast(closure) == 0) { // color - return sfColor_to_PyObject(self->data->color); - } else { // color_overlay - return sfColor_to_PyObject(self->data->color_overlay); - } -} - -int UIGridPoint::set_color(PyUIGridPointObject* self, PyObject* value, void* closure) { - sf::Color color = PyObject_to_sfColor(value); - // Check if an error occurred during conversion - if (PyErr_Occurred()) { - return -1; - } - - if (reinterpret_cast(closure) == 0) { // color - self->data->color = color; - } else { // color_overlay - self->data->color_overlay = color; - } - return 0; -} +// #150 - Removed get_color/set_color - now handled by layers PyObject* UIGridPoint::get_bool_member(PyUIGridPointObject* self, void* closure) { if (reinterpret_cast(closure) == 0) { // walkable @@ -110,36 +88,11 @@ int UIGridPoint::set_bool_member(PyUIGridPointObject* self, PyObject* value, voi return 0; } -PyObject* UIGridPoint::get_int_member(PyUIGridPointObject* self, void* closure) { - switch(reinterpret_cast(closure)) { - case 0: return PyLong_FromLong(self->data->tilesprite); - case 1: return PyLong_FromLong(self->data->tile_overlay); - case 2: return PyLong_FromLong(self->data->uisprite); - default: PyErr_SetString(PyExc_RuntimeError, "Invalid closure"); return nullptr; - } -} - -int UIGridPoint::set_int_member(PyUIGridPointObject* self, PyObject* value, void* closure) { - long val = PyLong_AsLong(value); - if (PyErr_Occurred()) return -1; - - switch(reinterpret_cast(closure)) { - case 0: self->data->tilesprite = val; break; - case 1: self->data->tile_overlay = val; break; - case 2: self->data->uisprite = val; break; - default: PyErr_SetString(PyExc_RuntimeError, "Invalid closure"); return -1; - } - return 0; -} +// #150 - Removed get_int_member/set_int_member - now handled by layers PyGetSetDef UIGridPoint::getsetters[] = { - {"color", (getter)UIGridPoint::get_color, (setter)UIGridPoint::set_color, "GridPoint color", (void*)0}, - {"color_overlay", (getter)UIGridPoint::get_color, (setter)UIGridPoint::set_color, "GridPoint color overlay", (void*)1}, {"walkable", (getter)UIGridPoint::get_bool_member, (setter)UIGridPoint::set_bool_member, "Is the GridPoint walkable", (void*)0}, {"transparent", (getter)UIGridPoint::get_bool_member, (setter)UIGridPoint::set_bool_member, "Is the GridPoint transparent", (void*)1}, - {"tilesprite", (getter)UIGridPoint::get_int_member, (setter)UIGridPoint::set_int_member, "Tile sprite index", (void*)0}, - {"tile_overlay", (getter)UIGridPoint::get_int_member, (setter)UIGridPoint::set_int_member, "Tile overlay sprite index", (void*)1}, - {"uisprite", (getter)UIGridPoint::get_int_member, (setter)UIGridPoint::set_int_member, "UI sprite index", (void*)2}, {NULL} /* Sentinel */ }; @@ -148,9 +101,9 @@ PyObject* UIGridPoint::repr(PyUIGridPointObject* self) { if (!self->data) ss << ""; else { auto gp = self->data; - ss << ""; + ss << "grid_x << ", " << gp->grid_y << ")>"; } std::string repr_str = ss.str(); return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace"); diff --git a/src/UIGridPoint.h b/src/UIGridPoint.h index 0f117ff..1eee314 100644 --- a/src/UIGridPoint.h +++ b/src/UIGridPoint.h @@ -33,24 +33,20 @@ typedef struct { std::shared_ptr entity; } PyUIGridPointStateObject; -// UIGridPoint - revised grid data for each point +// UIGridPoint - grid cell data for pathfinding and layer access +// #150 - Layer-related properties (color, tilesprite, etc.) removed; now handled by layers class UIGridPoint { public: - sf::Color color, color_overlay; - bool walkable, transparent; - int tilesprite, tile_overlay, uisprite; - int grid_x, grid_y; // Position in parent grid - UIGrid* parent_grid; // Parent grid reference for TCOD sync + bool walkable, transparent; // Pathfinding/FOV properties + int grid_x, grid_y; // Position in parent grid + UIGrid* parent_grid; // Parent grid reference for TCOD sync UIGridPoint(); - static int set_int_member(PyUIGridPointObject* self, PyObject* value, void* closure); + // Built-in property accessors (walkable, transparent only) static PyGetSetDef getsetters[]; - static PyObject* get_color(PyUIGridPointObject* self, void* closure); - static PyObject* get_int_member(PyUIGridPointObject* self, void* closure); static int set_bool_member(PyUIGridPointObject* self, PyObject* value, void* closure); static PyObject* get_bool_member(PyUIGridPointObject* self, void* closure); - static int set_color(PyUIGridPointObject* self, PyObject* value, void* closure); static PyObject* repr(PyUIGridPointObject* self); // #150 - Dynamic property access for named layers diff --git a/src/UITestScene.cpp b/src/UITestScene.cpp index f505b75..d76b644 100644 --- a/src/UITestScene.cpp +++ b/src/UITestScene.cpp @@ -105,16 +105,16 @@ UITestScene::UITestScene(GameEngine* g) : Scene(g) */ // UIGrid test: (in grid cells) ( in screen pixels ) - // constructor args: w h texture x y w h + // constructor args: w h texture x y w h auto e5 = std::make_shared(4, 4, ptex, sf::Vector2f(550, 150), sf::Vector2f(200, 200)); e5->zoom=2.0; - e5->points[0].color = sf::Color(255, 0, 0); - e5->points[1].tilesprite = 1; - e5->points[5].color = sf::Color(0, 255, 0); - e5->points[6].tilesprite = 2; - e5->points[10].color = sf::Color(0, 0, 255); - e5->points[11].tilesprite = 3; - e5->points[15].color = sf::Color(255, 255, 255); + + // #150 - GridPoint no longer has color/tilesprite properties + // Use layers for visual rendering; GridPoint only has walkable/transparent + // The default "tilesprite" TileLayer is created automatically + // Example: e5->layers[0]->at(x, y) = tile_index for TileLayer + e5->points[0].walkable = true; + e5->points[0].transparent = true; ui_elements->push_back(e5); diff --git a/src/scripts/cos_level.py b/src/scripts/cos_level.py index d594f86..e10cca0 100644 --- a/src/scripts/cos_level.py +++ b/src/scripts/cos_level.py @@ -105,7 +105,9 @@ class Level: self.height = height #self.graph = [(0, 0, width, height)] self.graph = RoomGraph( (0, 0, width, height) ) - self.grid = mcrfpy.Grid(grid_size=(width, height), texture=t, pos=(10, 5), size=(1014, 700)) + # #150 - Create grid with explicit layers for color and tilesprite + self.grid = mcrfpy.Grid(grid_size=(width, height), texture=t, pos=(10, 5), size=(1014, 700), + layers={"color": "color", "tilesprite": "tile"}) self.highlighted = -1 #debug view feature self.walled_rooms = [] # for tracking "hallway rooms" vs "walled rooms"