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>
2025-11-25 21:42:33 -05:00
|
|
|
#pragma once
|
|
|
|
|
#include "Common.h"
|
|
|
|
|
#include "Python.h"
|
|
|
|
|
#include "structmember.h"
|
|
|
|
|
#include "UIDrawable.h"
|
|
|
|
|
#include "UIBase.h"
|
|
|
|
|
#include "PyDrawable.h"
|
|
|
|
|
#include "PyColor.h"
|
|
|
|
|
#include "PyVector.h"
|
|
|
|
|
#include "McRFPy_Doc.h"
|
|
|
|
|
|
|
|
|
|
// Forward declaration
|
|
|
|
|
class UICircle;
|
|
|
|
|
|
|
|
|
|
// Python object structure
|
|
|
|
|
typedef struct {
|
|
|
|
|
PyObject_HEAD
|
|
|
|
|
std::shared_ptr<UICircle> data;
|
|
|
|
|
PyObject* weakreflist;
|
|
|
|
|
} PyUICircleObject;
|
|
|
|
|
|
|
|
|
|
class UICircle : public UIDrawable
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
sf::CircleShape shape;
|
|
|
|
|
float radius;
|
|
|
|
|
sf::Color fill_color;
|
|
|
|
|
sf::Color outline_color;
|
|
|
|
|
float outline_thickness;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
UICircle();
|
|
|
|
|
UICircle(float radius, sf::Vector2f center = sf::Vector2f(0, 0),
|
|
|
|
|
sf::Color fillColor = sf::Color::White,
|
|
|
|
|
sf::Color outlineColor = sf::Color::Transparent,
|
|
|
|
|
float outlineThickness = 0.0f);
|
|
|
|
|
|
|
|
|
|
// Copy constructor and assignment
|
|
|
|
|
UICircle(const UICircle& other);
|
|
|
|
|
UICircle& operator=(const UICircle& other);
|
|
|
|
|
|
|
|
|
|
// Move constructor and assignment
|
|
|
|
|
UICircle(UICircle&& other) noexcept;
|
|
|
|
|
UICircle& operator=(UICircle&& other) noexcept;
|
|
|
|
|
|
|
|
|
|
// UIDrawable interface
|
|
|
|
|
void render(sf::Vector2f offset, sf::RenderTarget& target) override;
|
|
|
|
|
UIDrawable* click_at(sf::Vector2f point) override;
|
|
|
|
|
PyObjectsEnum derived_type() override;
|
|
|
|
|
|
|
|
|
|
// Getters and setters
|
|
|
|
|
float getRadius() const { return radius; }
|
|
|
|
|
void setRadius(float r);
|
|
|
|
|
|
|
|
|
|
sf::Vector2f getCenter() const { return position; }
|
|
|
|
|
void setCenter(sf::Vector2f c) { position = c; }
|
|
|
|
|
|
|
|
|
|
sf::Color getFillColor() const { return fill_color; }
|
|
|
|
|
void setFillColor(sf::Color c);
|
|
|
|
|
|
|
|
|
|
sf::Color getOutlineColor() const { return outline_color; }
|
|
|
|
|
void setOutlineColor(sf::Color c);
|
|
|
|
|
|
|
|
|
|
float getOutline() const { return outline_thickness; }
|
|
|
|
|
void setOutline(float t);
|
|
|
|
|
|
|
|
|
|
// Phase 1 virtual method implementations
|
|
|
|
|
sf::FloatRect get_bounds() const override;
|
|
|
|
|
void move(float dx, float dy) override;
|
|
|
|
|
void resize(float w, float h) override;
|
|
|
|
|
|
|
|
|
|
// Property system for animations
|
|
|
|
|
bool setProperty(const std::string& name, float value) override;
|
|
|
|
|
bool setProperty(const std::string& name, const sf::Color& value) override;
|
|
|
|
|
bool setProperty(const std::string& name, const sf::Vector2f& value) override;
|
|
|
|
|
bool getProperty(const std::string& name, float& value) const override;
|
|
|
|
|
bool getProperty(const std::string& name, sf::Color& value) const override;
|
|
|
|
|
bool getProperty(const std::string& name, sf::Vector2f& value) const override;
|
|
|
|
|
|
2026-01-04 15:32:14 -05:00
|
|
|
bool hasProperty(const std::string& name) const override;
|
|
|
|
|
|
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>
2025-11-25 21:42:33 -05:00
|
|
|
// Python API
|
|
|
|
|
static PyObject* get_radius(PyUICircleObject* self, void* closure);
|
|
|
|
|
static int set_radius(PyUICircleObject* self, PyObject* value, void* closure);
|
|
|
|
|
static PyObject* get_center(PyUICircleObject* self, void* closure);
|
|
|
|
|
static int set_center(PyUICircleObject* self, PyObject* value, void* closure);
|
|
|
|
|
static PyObject* get_fill_color(PyUICircleObject* self, void* closure);
|
|
|
|
|
static int set_fill_color(PyUICircleObject* self, PyObject* value, void* closure);
|
|
|
|
|
static PyObject* get_outline_color(PyUICircleObject* self, void* closure);
|
|
|
|
|
static int set_outline_color(PyUICircleObject* self, PyObject* value, void* closure);
|
|
|
|
|
static PyObject* get_outline(PyUICircleObject* self, void* closure);
|
|
|
|
|
static int set_outline(PyUICircleObject* self, PyObject* value, void* closure);
|
|
|
|
|
|
|
|
|
|
static PyGetSetDef getsetters[];
|
|
|
|
|
static PyObject* repr(PyUICircleObject* self);
|
|
|
|
|
static int init(PyUICircleObject* self, PyObject* args, PyObject* kwds);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Method definitions
|
|
|
|
|
extern PyMethodDef UICircle_methods[];
|
|
|
|
|
|
|
|
|
|
namespace mcrfpydef {
|
|
|
|
|
static PyTypeObject PyUICircleType = {
|
|
|
|
|
.ob_base = {.ob_base = {.ob_refcnt = 1, .ob_type = NULL}, .ob_size = 0},
|
|
|
|
|
.tp_name = "mcrfpy.Circle",
|
|
|
|
|
.tp_basicsize = sizeof(PyUICircleObject),
|
|
|
|
|
.tp_itemsize = 0,
|
|
|
|
|
.tp_dealloc = (destructor)[](PyObject* self) {
|
|
|
|
|
PyUICircleObject* obj = (PyUICircleObject*)self;
|
|
|
|
|
if (obj->weakreflist != NULL) {
|
|
|
|
|
PyObject_ClearWeakRefs(self);
|
|
|
|
|
}
|
|
|
|
|
obj->data.reset();
|
|
|
|
|
Py_TYPE(self)->tp_free(self);
|
|
|
|
|
},
|
|
|
|
|
.tp_repr = (reprfunc)UICircle::repr,
|
|
|
|
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
|
|
|
.tp_doc = PyDoc_STR(
|
|
|
|
|
"Circle(radius=0, center=None, fill_color=None, outline_color=None, outline=0, **kwargs)\n\n"
|
|
|
|
|
"A circle UI element for drawing filled or outlined circles.\n\n"
|
|
|
|
|
"Args:\n"
|
|
|
|
|
" radius (float, optional): Circle radius in pixels. Default: 0\n"
|
|
|
|
|
" center (tuple, optional): Center position as (x, y). Default: (0, 0)\n"
|
|
|
|
|
" fill_color (Color, optional): Fill color. Default: White\n"
|
|
|
|
|
" outline_color (Color, optional): Outline color. Default: Transparent\n"
|
|
|
|
|
" outline (float, optional): Outline thickness. Default: 0 (no outline)\n\n"
|
|
|
|
|
"Keyword Args:\n"
|
refactor: Rename click kwarg to on_click for API consistency (closes #126)
BREAKING CHANGE: Constructor keyword argument renamed from `click` to
`on_click` for all UIDrawable types (Frame, Caption, Sprite, Grid, Line,
Circle, Arc).
Before: Frame(pos=(0,0), size=(100,100), click=handler)
After: Frame(pos=(0,0), size=(100,100), on_click=handler)
The property name was already `on_click` - this makes the constructor
kwarg match, completing the callback naming standardization from #139.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-28 14:31:22 -05:00
|
|
|
" on_click (callable): Click handler. Default: None\n"
|
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>
2025-11-25 21:42:33 -05:00
|
|
|
" visible (bool): Visibility state. Default: True\n"
|
|
|
|
|
" opacity (float): Opacity (0.0-1.0). Default: 1.0\n"
|
|
|
|
|
" z_index (int): Rendering order. Default: 0\n"
|
|
|
|
|
" name (str): Element name for finding. Default: None\n\n"
|
|
|
|
|
"Attributes:\n"
|
|
|
|
|
" radius (float): Circle radius\n"
|
|
|
|
|
" center (Vector): Center position\n"
|
|
|
|
|
" fill_color (Color): Fill color\n"
|
|
|
|
|
" outline_color (Color): Outline color\n"
|
|
|
|
|
" outline (float): Outline thickness\n"
|
|
|
|
|
" visible (bool): Visibility state\n"
|
|
|
|
|
" opacity (float): Opacity value\n"
|
|
|
|
|
" z_index (int): Rendering order\n"
|
|
|
|
|
" name (str): Element name\n"
|
|
|
|
|
),
|
|
|
|
|
.tp_methods = UICircle_methods,
|
|
|
|
|
.tp_getset = UICircle::getsetters,
|
|
|
|
|
.tp_base = &mcrfpydef::PyDrawableType,
|
|
|
|
|
.tp_init = (initproc)UICircle::init,
|
|
|
|
|
.tp_new = [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* {
|
|
|
|
|
PyUICircleObject* self = (PyUICircleObject*)type->tp_alloc(type, 0);
|
|
|
|
|
if (self) {
|
|
|
|
|
self->data = std::make_shared<UICircle>();
|
|
|
|
|
self->weakreflist = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return (PyObject*)self;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|