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>
150 lines
5.9 KiB
C++
150 lines
5.9 KiB
C++
#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 UILine;
|
|
|
|
// Python object structure
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
std::shared_ptr<UILine> data;
|
|
PyObject* weakreflist;
|
|
} PyUILineObject;
|
|
|
|
class UILine : public UIDrawable
|
|
{
|
|
private:
|
|
sf::Vector2f start_pos; // Starting point
|
|
sf::Vector2f end_pos; // Ending point
|
|
sf::Color color; // Line color
|
|
float thickness; // Line thickness in pixels
|
|
|
|
// Cached vertex array for rendering
|
|
mutable sf::VertexArray vertices;
|
|
mutable bool vertices_dirty;
|
|
|
|
void updateVertices() const;
|
|
|
|
public:
|
|
UILine();
|
|
UILine(sf::Vector2f start, sf::Vector2f end, float thickness = 1.0f, sf::Color color = sf::Color::White);
|
|
|
|
// Copy constructor and assignment
|
|
UILine(const UILine& other);
|
|
UILine& operator=(const UILine& other);
|
|
|
|
// Move constructor and assignment
|
|
UILine(UILine&& other) noexcept;
|
|
UILine& operator=(UILine&& 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
|
|
sf::Vector2f getStart() const { return start_pos; }
|
|
void setStart(sf::Vector2f pos) { start_pos = pos; vertices_dirty = true; }
|
|
|
|
sf::Vector2f getEnd() const { return end_pos; }
|
|
void setEnd(sf::Vector2f pos) { end_pos = pos; vertices_dirty = true; }
|
|
|
|
sf::Color getColor() const { return color; }
|
|
void setColor(sf::Color c) { color = c; vertices_dirty = true; }
|
|
|
|
float getThickness() const { return thickness; }
|
|
void setThickness(float t) { thickness = t; vertices_dirty = true; }
|
|
|
|
// 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;
|
|
|
|
// Python API
|
|
static PyObject* get_start(PyUILineObject* self, void* closure);
|
|
static int set_start(PyUILineObject* self, PyObject* value, void* closure);
|
|
static PyObject* get_end(PyUILineObject* self, void* closure);
|
|
static int set_end(PyUILineObject* self, PyObject* value, void* closure);
|
|
static PyObject* get_color(PyUILineObject* self, void* closure);
|
|
static int set_color(PyUILineObject* self, PyObject* value, void* closure);
|
|
static PyObject* get_thickness(PyUILineObject* self, void* closure);
|
|
static int set_thickness(PyUILineObject* self, PyObject* value, void* closure);
|
|
|
|
static PyGetSetDef getsetters[];
|
|
static PyObject* repr(PyUILineObject* self);
|
|
static int init(PyUILineObject* self, PyObject* args, PyObject* kwds);
|
|
};
|
|
|
|
// Method definitions (extern to be defined in .cpp)
|
|
extern PyMethodDef UILine_methods[];
|
|
|
|
namespace mcrfpydef {
|
|
static PyTypeObject PyUILineType = {
|
|
.ob_base = {.ob_base = {.ob_refcnt = 1, .ob_type = NULL}, .ob_size = 0},
|
|
.tp_name = "mcrfpy.Line",
|
|
.tp_basicsize = sizeof(PyUILineObject),
|
|
.tp_itemsize = 0,
|
|
.tp_dealloc = (destructor)[](PyObject* self) {
|
|
PyUILineObject* obj = (PyUILineObject*)self;
|
|
if (obj->weakreflist != NULL) {
|
|
PyObject_ClearWeakRefs(self);
|
|
}
|
|
obj->data.reset();
|
|
Py_TYPE(self)->tp_free(self);
|
|
},
|
|
.tp_repr = (reprfunc)UILine::repr,
|
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
.tp_doc = PyDoc_STR(
|
|
"Line(start=None, end=None, thickness=1.0, color=None, **kwargs)\n\n"
|
|
"A line UI element for drawing straight lines between two points.\n\n"
|
|
"Args:\n"
|
|
" start (tuple, optional): Starting point as (x, y). Default: (0, 0)\n"
|
|
" end (tuple, optional): Ending point as (x, y). Default: (0, 0)\n"
|
|
" thickness (float, optional): Line thickness in pixels. Default: 1.0\n"
|
|
" color (Color, optional): Line color. Default: White\n\n"
|
|
"Keyword Args:\n"
|
|
" click (callable): Click handler. Default: None\n"
|
|
" 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"
|
|
" start (Vector): Starting point\n"
|
|
" end (Vector): Ending point\n"
|
|
" thickness (float): Line thickness\n"
|
|
" color (Color): Line color\n"
|
|
" visible (bool): Visibility state\n"
|
|
" opacity (float): Opacity value\n"
|
|
" z_index (int): Rendering order\n"
|
|
" name (str): Element name\n"
|
|
),
|
|
.tp_methods = UILine_methods,
|
|
.tp_getset = UILine::getsetters,
|
|
.tp_base = &mcrfpydef::PyDrawableType,
|
|
.tp_init = (initproc)UILine::init,
|
|
.tp_new = [](PyTypeObject* type, PyObject* args, PyObject* kwds) -> PyObject* {
|
|
PyUILineObject* self = (PyUILineObject*)type->tp_alloc(type, 0);
|
|
if (self) {
|
|
self->data = std::make_shared<UILine>();
|
|
self->weakreflist = nullptr;
|
|
}
|
|
return (PyObject*)self;
|
|
}
|
|
};
|
|
}
|