support for Scene object as parent, from Python: closes #183
This commit is contained in:
parent
7e47050d6f
commit
2c20455003
6 changed files with 108 additions and 16 deletions
|
|
@ -879,9 +879,11 @@ PyObject* McRFPy_API::_sceneUI(PyObject* self, PyObject* args) {
|
|||
//Py_INCREF(Py_None);
|
||||
//return Py_None;
|
||||
PyUICollectionObject* o = (PyUICollectionObject*)PyUICollectionType.tp_alloc(&PyUICollectionType, 0);
|
||||
if (o)
|
||||
o->data = ui;
|
||||
return (PyObject*)o;
|
||||
if (o) {
|
||||
o->data = ui;
|
||||
o->scene_name = scene_cstr; // #183: Track scene ownership
|
||||
}
|
||||
return (PyObject*)o;
|
||||
}
|
||||
|
||||
// Internal use - called by PySceneObject::activate()
|
||||
|
|
|
|||
|
|
@ -519,6 +519,20 @@ PyMethodDef PySceneClass::methods[] = {
|
|||
{NULL}
|
||||
};
|
||||
|
||||
// #183: Lookup scene by name (returns new reference or nullptr)
|
||||
PyObject* PySceneClass::get_scene_by_name(const std::string& name)
|
||||
{
|
||||
if (name.empty()) return nullptr;
|
||||
|
||||
if (python_scenes.count(name) > 0) {
|
||||
PyObject* scene_obj = (PyObject*)python_scenes[name];
|
||||
Py_INCREF(scene_obj);
|
||||
return scene_obj;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Helper function to trigger lifecycle events
|
||||
void McRFPy_API::triggerSceneChange(const std::string& from_scene, const std::string& to_scene)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ public:
|
|||
static void call_update(PySceneObject* self, float dt);
|
||||
static void call_on_resize(PySceneObject* self, int width, int height);
|
||||
|
||||
// #183: Lookup scene by name (returns new reference or nullptr)
|
||||
static PyObject* get_scene_by_name(const std::string& name);
|
||||
|
||||
static PyGetSetDef getsetters[];
|
||||
static PyMethodDef methods[];
|
||||
};
|
||||
|
|
|
|||
|
|
@ -656,15 +656,19 @@ PyObject* UICollection::append(PyUICollectionObject* self, PyObject* o)
|
|||
|
||||
// Helper lambda to add drawable with parent tracking
|
||||
auto addDrawable = [&](std::shared_ptr<UIDrawable> drawable) {
|
||||
// #122: Remove from old parent if it has one
|
||||
if (auto old_parent = drawable->getParent()) {
|
||||
drawable->removeFromParent();
|
||||
}
|
||||
// #183: Remove from old parent (drawable or scene)
|
||||
drawable->removeFromParent();
|
||||
|
||||
drawable->z_index = new_z_index;
|
||||
|
||||
// #122: Set new parent (owner of this collection)
|
||||
drawable->setParent(owner_ptr);
|
||||
// #183: Set new parent - either scene or drawable
|
||||
if (!self->scene_name.empty()) {
|
||||
// This is a scene's children collection
|
||||
drawable->setParentScene(self->scene_name);
|
||||
} else {
|
||||
// This is a Frame/Grid's children collection
|
||||
drawable->setParent(owner_ptr);
|
||||
}
|
||||
|
||||
self->data->push_back(drawable);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include "Animation.h"
|
||||
#include "PyAnimation.h"
|
||||
#include "PyEasing.h"
|
||||
#include "PySceneObject.h" // #183: For scene parent lookup
|
||||
|
||||
UIDrawable::UIDrawable() : position(0.0f, 0.0f) { click_callable = NULL; }
|
||||
|
||||
|
|
@ -764,6 +765,12 @@ int UIDrawable::set_pos(PyObject* self, PyObject* value, void* closure) {
|
|||
// #122 - Parent-child hierarchy implementation
|
||||
void UIDrawable::setParent(std::shared_ptr<UIDrawable> new_parent) {
|
||||
parent = new_parent;
|
||||
parent_scene.clear(); // #183: Clear scene parent when setting drawable parent
|
||||
}
|
||||
|
||||
void UIDrawable::setParentScene(const std::string& scene_name) {
|
||||
parent.reset(); // #183: Clear drawable parent when setting scene parent
|
||||
parent_scene = scene_name;
|
||||
}
|
||||
|
||||
std::shared_ptr<UIDrawable> UIDrawable::getParent() const {
|
||||
|
|
@ -771,6 +778,22 @@ std::shared_ptr<UIDrawable> UIDrawable::getParent() const {
|
|||
}
|
||||
|
||||
void UIDrawable::removeFromParent() {
|
||||
// #183: Handle scene parent removal
|
||||
if (!parent_scene.empty()) {
|
||||
auto ui = Resources::game->scene_ui(parent_scene);
|
||||
if (ui) {
|
||||
for (auto it = ui->begin(); it != ui->end(); ++it) {
|
||||
if (it->get() == this) {
|
||||
ui->erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
parent_scene.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle drawable parent removal
|
||||
auto p = parent.lock();
|
||||
if (!p) return;
|
||||
|
||||
|
|
@ -899,6 +922,15 @@ PyObject* UIDrawable::get_parent(PyObject* self, void* closure) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// #183: Check for scene parent first
|
||||
if (!drawable->parent_scene.empty()) {
|
||||
PyObject* scene = PySceneClass::get_scene_by_name(drawable->parent_scene);
|
||||
if (scene) {
|
||||
return scene; // Already has new reference from get_scene_by_name
|
||||
}
|
||||
// Scene not found in python_scenes (shouldn't happen, but fall through to None)
|
||||
}
|
||||
|
||||
auto parent_ptr = drawable->getParent();
|
||||
if (!parent_ptr) {
|
||||
Py_RETURN_NONE;
|
||||
|
|
@ -1008,22 +1040,52 @@ int UIDrawable::set_parent(PyObject* self, PyObject* value, void* closure) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Value must be a Frame or Grid (things with children collections)
|
||||
// Check if it's a Frame
|
||||
// Value must be a Frame, Grid, or Scene (things with children collections)
|
||||
PyTypeObject* frame_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame");
|
||||
PyTypeObject* grid_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid");
|
||||
PyTypeObject* scene_type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Scene");
|
||||
|
||||
bool is_frame = frame_type && PyObject_IsInstance(value, (PyObject*)frame_type);
|
||||
bool is_grid = grid_type && PyObject_IsInstance(value, (PyObject*)grid_type);
|
||||
bool is_scene = scene_type && PyObject_IsInstance(value, (PyObject*)scene_type);
|
||||
|
||||
Py_XDECREF(frame_type);
|
||||
Py_XDECREF(grid_type);
|
||||
Py_XDECREF(scene_type);
|
||||
|
||||
if (!is_frame && !is_grid) {
|
||||
PyErr_SetString(PyExc_TypeError, "parent must be a Frame, Grid, or None");
|
||||
if (!is_frame && !is_grid && !is_scene) {
|
||||
PyErr_SetString(PyExc_TypeError, "parent must be a Frame, Grid, Scene, or None");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Handle Scene parent specially - add to scene's children
|
||||
if (is_scene) {
|
||||
PySceneObject* scene_obj = (PySceneObject*)value;
|
||||
std::string scene_name = scene_obj->name;
|
||||
|
||||
// Remove from old parent first
|
||||
drawable->removeFromParent();
|
||||
|
||||
// Get the scene's UI elements and add
|
||||
auto ui = Resources::game->scene_ui(scene_name);
|
||||
if (ui) {
|
||||
// Check if already in this scene (prevent duplicates)
|
||||
bool already_present = false;
|
||||
for (const auto& child : *ui) {
|
||||
if (child.get() == drawable.get()) {
|
||||
already_present = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!already_present) {
|
||||
ui->push_back(drawable);
|
||||
drawable->setParentScene(scene_name);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Remove from old parent first
|
||||
drawable->removeFromParent();
|
||||
|
||||
|
|
|
|||
|
|
@ -107,13 +107,19 @@ public:
|
|||
// Parent-child hierarchy (#122)
|
||||
std::weak_ptr<UIDrawable> parent;
|
||||
|
||||
// Scene parent tracking (#183) - name of scene if this is a top-level element
|
||||
std::string parent_scene;
|
||||
|
||||
// Set the parent of this drawable (called by collections when adding)
|
||||
void setParent(std::shared_ptr<UIDrawable> new_parent);
|
||||
|
||||
// Set the parent scene name (called by UICollection when adding to scene)
|
||||
void setParentScene(const std::string& scene_name);
|
||||
|
||||
// Get the parent drawable (returns nullptr if no parent or expired)
|
||||
std::shared_ptr<UIDrawable> getParent() const;
|
||||
|
||||
// Remove this drawable from its current parent's children
|
||||
// Remove this drawable from its current parent's children (or scene)
|
||||
void removeFromParent();
|
||||
|
||||
// Get the global (screen) position by walking up the parent chain (#102)
|
||||
|
|
@ -205,6 +211,7 @@ typedef struct {
|
|||
PyObject_HEAD
|
||||
std::shared_ptr<std::vector<std::shared_ptr<UIDrawable>>> data;
|
||||
std::weak_ptr<UIDrawable> owner; // #122: Parent drawable (for Frame.children, Grid.children)
|
||||
std::string scene_name; // #183: Scene name (for Scene.children) - empty if not scene-level
|
||||
} PyUICollectionObject;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue