feat: Add UILine, UICircle, and UIArc drawing primitives
Implement new UIDrawable-derived classes for vector graphics: - UILine: Thick line segments using sf::ConvexShape for proper thickness - Properties: start, end, color, thickness - Supports click detection along the line - UICircle: Filled and outlined circles using sf::CircleShape - Properties: radius, center, fill_color, outline_color, outline - Full property system for animations - UIArc: Arc segments for orbital paths and partial circles - Properties: center, radius, start_angle, end_angle, color, thickness - Uses sf::VertexArray with TriangleStrip for smooth rendering - Supports arbitrary angle spans including negative (reverse) arcs All primitives integrate with the Python API through mcrfpy module: - Added to PyObjectsEnum for type identification - Full getter/setter support for all properties - Added to UICollection for scene management - Support for visibility, opacity, z_index, name, and click handling closes #128, closes #129 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
acef21593b
commit
311dc02f1d
10 changed files with 2261 additions and 28 deletions
|
|
@ -4,6 +4,9 @@
|
|||
#include "UICaption.h"
|
||||
#include "UISprite.h"
|
||||
#include "UIGrid.h"
|
||||
#include "UILine.h"
|
||||
#include "UICircle.h"
|
||||
#include "UIArc.h"
|
||||
#include "McRFPy_API.h"
|
||||
#include "PyObjectUtils.h"
|
||||
#include "PythonObjectCache.h"
|
||||
|
|
@ -79,6 +82,42 @@ static PyObject* convertDrawableToPython(std::shared_ptr<UIDrawable> drawable) {
|
|||
obj = (PyObject*)pyObj;
|
||||
break;
|
||||
}
|
||||
case PyObjectsEnum::UILINE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line");
|
||||
if (!type) return nullptr;
|
||||
auto pyObj = (PyUILineObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UILine>(drawable);
|
||||
pyObj->weakreflist = NULL;
|
||||
}
|
||||
obj = (PyObject*)pyObj;
|
||||
break;
|
||||
}
|
||||
case PyObjectsEnum::UICIRCLE:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle");
|
||||
if (!type) return nullptr;
|
||||
auto pyObj = (PyUICircleObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UICircle>(drawable);
|
||||
pyObj->weakreflist = NULL;
|
||||
}
|
||||
obj = (PyObject*)pyObj;
|
||||
break;
|
||||
}
|
||||
case PyObjectsEnum::UIARC:
|
||||
{
|
||||
type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc");
|
||||
if (!type) return nullptr;
|
||||
auto pyObj = (PyUIArcObject*)type->tp_alloc(type, 0);
|
||||
if (pyObj) {
|
||||
pyObj->data = std::static_pointer_cast<UIArc>(drawable);
|
||||
pyObj->weakreflist = NULL;
|
||||
}
|
||||
obj = (PyObject*)pyObj;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
PyErr_SetString(PyExc_TypeError, "Unknown UIDrawable derived type");
|
||||
return nullptr;
|
||||
|
|
@ -577,10 +616,13 @@ PyObject* UICollection::append(PyUICollectionObject* self, PyObject* o)
|
|||
if (!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid"))
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle")) &&
|
||||
!PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc"))
|
||||
)
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "Only Frame, Caption, Sprite, and Grid objects can be added to UICollection");
|
||||
PyErr_SetString(PyExc_TypeError, "Only Frame, Caption, Sprite, Grid, Line, Circle, and Arc objects can be added to UICollection");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -620,7 +662,25 @@ PyObject* UICollection::append(PyUICollectionObject* self, PyObject* o)
|
|||
grid->data->z_index = new_z_index;
|
||||
self->data->push_back(grid->data);
|
||||
}
|
||||
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line")))
|
||||
{
|
||||
PyUILineObject* line = (PyUILineObject*)o;
|
||||
line->data->z_index = new_z_index;
|
||||
self->data->push_back(line->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle")))
|
||||
{
|
||||
PyUICircleObject* circle = (PyUICircleObject*)o;
|
||||
circle->data->z_index = new_z_index;
|
||||
self->data->push_back(circle->data);
|
||||
}
|
||||
if (PyObject_IsInstance(o, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc")))
|
||||
{
|
||||
PyUIArcObject* arc = (PyUIArcObject*)o;
|
||||
arc->data->z_index = new_z_index;
|
||||
self->data->push_back(arc->data);
|
||||
}
|
||||
|
||||
// Mark scene as needing resort after adding element
|
||||
McRFPy_API::markSceneNeedsSort();
|
||||
|
||||
|
|
@ -656,11 +716,14 @@ PyObject* UICollection::extend(PyUICollectionObject* self, PyObject* iterable)
|
|||
if (!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Frame")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Sprite")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Caption")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid")))
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Grid")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle")) &&
|
||||
!PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc")))
|
||||
{
|
||||
Py_DECREF(item);
|
||||
Py_DECREF(iterator);
|
||||
PyErr_SetString(PyExc_TypeError, "All items must be Frame, Caption, Sprite, or Grid objects");
|
||||
PyErr_SetString(PyExc_TypeError, "All items must be Frame, Caption, Sprite, Grid, Line, Circle, or Arc objects");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -692,10 +755,25 @@ PyObject* UICollection::extend(PyUICollectionObject* self, PyObject* iterable)
|
|||
grid->data->z_index = current_z_index;
|
||||
self->data->push_back(grid->data);
|
||||
}
|
||||
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Line"))) {
|
||||
PyUILineObject* line = (PyUILineObject*)item;
|
||||
line->data->z_index = current_z_index;
|
||||
self->data->push_back(line->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Circle"))) {
|
||||
PyUICircleObject* circle = (PyUICircleObject*)item;
|
||||
circle->data->z_index = current_z_index;
|
||||
self->data->push_back(circle->data);
|
||||
}
|
||||
else if (PyObject_IsInstance(item, PyObject_GetAttrString(McRFPy_API::mcrf_module, "Arc"))) {
|
||||
PyUIArcObject* arc = (PyUIArcObject*)item;
|
||||
arc->data->z_index = current_z_index;
|
||||
self->data->push_back(arc->data);
|
||||
}
|
||||
|
||||
Py_DECREF(item);
|
||||
}
|
||||
|
||||
|
||||
Py_DECREF(iterator);
|
||||
|
||||
// Check if iteration ended due to an error
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue