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
|
|
|
#include "UILine.h"
|
|
|
|
|
#include "GameEngine.h"
|
|
|
|
|
#include "McRFPy_API.h"
|
|
|
|
|
#include "PyVector.h"
|
|
|
|
|
#include "PyColor.h"
|
|
|
|
|
#include "PythonObjectCache.h"
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
|
|
UILine::UILine()
|
|
|
|
|
: start_pos(0.0f, 0.0f),
|
|
|
|
|
end_pos(0.0f, 0.0f),
|
|
|
|
|
color(sf::Color::White),
|
|
|
|
|
thickness(1.0f),
|
|
|
|
|
vertices(sf::TriangleStrip, 4),
|
|
|
|
|
vertices_dirty(true)
|
|
|
|
|
{
|
|
|
|
|
position = sf::Vector2f(0.0f, 0.0f);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UILine::UILine(sf::Vector2f start, sf::Vector2f end, float thickness, sf::Color color)
|
|
|
|
|
: start_pos(start),
|
|
|
|
|
end_pos(end),
|
|
|
|
|
color(color),
|
|
|
|
|
thickness(thickness),
|
|
|
|
|
vertices(sf::TriangleStrip, 4),
|
|
|
|
|
vertices_dirty(true)
|
|
|
|
|
{
|
|
|
|
|
// Set position to the midpoint for consistency with other UIDrawables
|
|
|
|
|
position = (start + end) / 2.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UILine::UILine(const UILine& other)
|
|
|
|
|
: UIDrawable(other),
|
|
|
|
|
start_pos(other.start_pos),
|
|
|
|
|
end_pos(other.end_pos),
|
|
|
|
|
color(other.color),
|
|
|
|
|
thickness(other.thickness),
|
|
|
|
|
vertices(sf::TriangleStrip, 4),
|
|
|
|
|
vertices_dirty(true)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UILine& UILine::operator=(const UILine& other) {
|
|
|
|
|
if (this != &other) {
|
|
|
|
|
UIDrawable::operator=(other);
|
|
|
|
|
start_pos = other.start_pos;
|
|
|
|
|
end_pos = other.end_pos;
|
|
|
|
|
color = other.color;
|
|
|
|
|
thickness = other.thickness;
|
|
|
|
|
vertices_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UILine::UILine(UILine&& other) noexcept
|
|
|
|
|
: UIDrawable(std::move(other)),
|
|
|
|
|
start_pos(other.start_pos),
|
|
|
|
|
end_pos(other.end_pos),
|
|
|
|
|
color(other.color),
|
|
|
|
|
thickness(other.thickness),
|
|
|
|
|
vertices(std::move(other.vertices)),
|
|
|
|
|
vertices_dirty(other.vertices_dirty)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UILine& UILine::operator=(UILine&& other) noexcept {
|
|
|
|
|
if (this != &other) {
|
|
|
|
|
UIDrawable::operator=(std::move(other));
|
|
|
|
|
start_pos = other.start_pos;
|
|
|
|
|
end_pos = other.end_pos;
|
|
|
|
|
color = other.color;
|
|
|
|
|
thickness = other.thickness;
|
|
|
|
|
vertices = std::move(other.vertices);
|
|
|
|
|
vertices_dirty = other.vertices_dirty;
|
|
|
|
|
}
|
|
|
|
|
return *this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UILine::updateVertices() const {
|
|
|
|
|
if (!vertices_dirty) return;
|
|
|
|
|
|
|
|
|
|
// Calculate direction and perpendicular
|
|
|
|
|
sf::Vector2f direction = end_pos - start_pos;
|
|
|
|
|
float length = std::sqrt(direction.x * direction.x + direction.y * direction.y);
|
|
|
|
|
|
|
|
|
|
if (length < 0.0001f) {
|
|
|
|
|
// Zero-length line - make a small dot
|
|
|
|
|
float half = thickness / 2.0f;
|
|
|
|
|
vertices[0].position = start_pos + sf::Vector2f(-half, -half);
|
|
|
|
|
vertices[1].position = start_pos + sf::Vector2f(half, -half);
|
|
|
|
|
vertices[2].position = start_pos + sf::Vector2f(-half, half);
|
|
|
|
|
vertices[3].position = start_pos + sf::Vector2f(half, half);
|
|
|
|
|
} else {
|
|
|
|
|
// Normalize direction
|
|
|
|
|
direction /= length;
|
|
|
|
|
|
|
|
|
|
// Perpendicular vector
|
|
|
|
|
sf::Vector2f perpendicular(-direction.y, direction.x);
|
|
|
|
|
perpendicular *= thickness / 2.0f;
|
|
|
|
|
|
|
|
|
|
// Create a quad (triangle strip) for the thick line
|
|
|
|
|
vertices[0].position = start_pos + perpendicular;
|
|
|
|
|
vertices[1].position = start_pos - perpendicular;
|
|
|
|
|
vertices[2].position = end_pos + perpendicular;
|
|
|
|
|
vertices[3].position = end_pos - perpendicular;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set colors
|
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
|
vertices[i].color = color;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vertices_dirty = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UILine::render(sf::Vector2f offset, sf::RenderTarget& target) {
|
|
|
|
|
if (!visible) return;
|
|
|
|
|
|
|
|
|
|
updateVertices();
|
|
|
|
|
|
|
|
|
|
// Apply opacity to color
|
|
|
|
|
sf::Color render_color = color;
|
|
|
|
|
render_color.a = static_cast<sf::Uint8>(color.a * opacity);
|
|
|
|
|
|
|
|
|
|
// Use ConvexShape to draw the line as a quad
|
|
|
|
|
sf::ConvexShape line_shape(4);
|
|
|
|
|
// Vertices are: 0=start+perp, 1=start-perp, 2=end+perp, 3=end-perp
|
|
|
|
|
// ConvexShape needs points in clockwise/counter-clockwise order
|
|
|
|
|
line_shape.setPoint(0, vertices[0].position + offset); // start + perp
|
|
|
|
|
line_shape.setPoint(1, vertices[2].position + offset); // end + perp
|
|
|
|
|
line_shape.setPoint(2, vertices[3].position + offset); // end - perp
|
|
|
|
|
line_shape.setPoint(3, vertices[1].position + offset); // start - perp
|
|
|
|
|
line_shape.setFillColor(render_color);
|
|
|
|
|
line_shape.setOutlineThickness(0);
|
|
|
|
|
|
|
|
|
|
target.draw(line_shape);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UIDrawable* UILine::click_at(sf::Vector2f point) {
|
|
|
|
|
if (!click_callable) return nullptr;
|
|
|
|
|
|
|
|
|
|
// Check if point is close enough to the line
|
|
|
|
|
// Using a simple bounding box check plus distance-to-line calculation
|
|
|
|
|
sf::FloatRect bounds = get_bounds();
|
|
|
|
|
bounds.left -= thickness;
|
|
|
|
|
bounds.top -= thickness;
|
|
|
|
|
bounds.width += thickness * 2;
|
|
|
|
|
bounds.height += thickness * 2;
|
|
|
|
|
|
|
|
|
|
if (!bounds.contains(point)) return nullptr;
|
|
|
|
|
|
|
|
|
|
// Calculate distance from point to line segment
|
|
|
|
|
sf::Vector2f line_vec = end_pos - start_pos;
|
|
|
|
|
sf::Vector2f point_vec = point - start_pos;
|
|
|
|
|
|
|
|
|
|
float line_len_sq = line_vec.x * line_vec.x + line_vec.y * line_vec.y;
|
|
|
|
|
float t = 0.0f;
|
|
|
|
|
|
|
|
|
|
if (line_len_sq > 0.0001f) {
|
|
|
|
|
t = std::max(0.0f, std::min(1.0f,
|
|
|
|
|
(point_vec.x * line_vec.x + point_vec.y * line_vec.y) / line_len_sq));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sf::Vector2f closest = start_pos + t * line_vec;
|
|
|
|
|
sf::Vector2f diff = point - closest;
|
|
|
|
|
float distance = std::sqrt(diff.x * diff.x + diff.y * diff.y);
|
|
|
|
|
|
|
|
|
|
// Click is valid if within thickness + some margin
|
|
|
|
|
if (distance <= thickness / 2.0f + 2.0f) {
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObjectsEnum UILine::derived_type() {
|
|
|
|
|
return PyObjectsEnum::UILINE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sf::FloatRect UILine::get_bounds() const {
|
|
|
|
|
float min_x = std::min(start_pos.x, end_pos.x);
|
|
|
|
|
float min_y = std::min(start_pos.y, end_pos.y);
|
|
|
|
|
float max_x = std::max(start_pos.x, end_pos.x);
|
|
|
|
|
float max_y = std::max(start_pos.y, end_pos.y);
|
|
|
|
|
|
|
|
|
|
return sf::FloatRect(min_x, min_y, max_x - min_x, max_y - min_y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UILine::move(float dx, float dy) {
|
|
|
|
|
start_pos.x += dx;
|
|
|
|
|
start_pos.y += dy;
|
|
|
|
|
end_pos.x += dx;
|
|
|
|
|
end_pos.y += dy;
|
|
|
|
|
position.x += dx;
|
|
|
|
|
position.y += dy;
|
|
|
|
|
vertices_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void UILine::resize(float w, float h) {
|
|
|
|
|
// For a line, resize adjusts the end point relative to start
|
|
|
|
|
end_pos = start_pos + sf::Vector2f(w, h);
|
|
|
|
|
vertices_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Animation property system
|
|
|
|
|
bool UILine::setProperty(const std::string& name, float value) {
|
|
|
|
|
if (name == "thickness") {
|
|
|
|
|
thickness = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "x") {
|
|
|
|
|
float dx = value - position.x;
|
|
|
|
|
move(dx, 0);
|
2025-11-28 19:30:24 -05:00
|
|
|
markCompositeDirty(); // #144 - Position change, texture still valid
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "y") {
|
|
|
|
|
float dy = value - position.y;
|
|
|
|
|
move(0, dy);
|
2025-11-28 19:30:24 -05:00
|
|
|
markCompositeDirty(); // #144 - Position change, texture still valid
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "start_x") {
|
|
|
|
|
start_pos.x = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "start_y") {
|
|
|
|
|
start_pos.y = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "end_x") {
|
|
|
|
|
end_pos.x = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "end_y") {
|
|
|
|
|
end_pos.y = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UILine::setProperty(const std::string& name, const sf::Color& value) {
|
|
|
|
|
if (name == "color") {
|
|
|
|
|
color = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UILine::setProperty(const std::string& name, const sf::Vector2f& value) {
|
|
|
|
|
if (name == "start") {
|
|
|
|
|
start_pos = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "end") {
|
|
|
|
|
end_pos = value;
|
|
|
|
|
vertices_dirty = true;
|
feat: Add dirty flag propagation to all UIDrawables and expand metrics API (#144, #104)
- Add markDirty() calls to setProperty() methods in:
- UISprite: position, scale, sprite_index changes
- UICaption: position, font_size, colors, text changes
- UIGrid: position, size, center, zoom, color changes
- UILine: thickness, position, endpoints, color changes
- UICircle: radius, position, colors changes
- UIArc: radius, angles, position, color changes
- UIEntity: position changes propagate to parent grid
- Expand getMetrics() Python API to include detailed timing breakdown:
- grid_render_time, entity_render_time, fov_overlay_time
- python_time, animation_time
- grid_cells_rendered, entities_rendered, total_entities
- Add comprehensive benchmark suite (tests/benchmarks/benchmark_suite.py):
- 6 scenarios: empty, static UI, animated UI, mixed, deep hierarchy, grid stress
- Automated metrics collection and performance assessment
- Timing breakdown percentages
This enables proper dirty flag propagation for the upcoming texture caching
system (#144) and provides infrastructure for performance benchmarking (#104).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 15:44:09 -05:00
|
|
|
markDirty(); // #144 - Content change
|
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
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UILine::getProperty(const std::string& name, float& value) const {
|
|
|
|
|
if (name == "thickness") {
|
|
|
|
|
value = thickness;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "x") {
|
|
|
|
|
value = position.x;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "y") {
|
|
|
|
|
value = position.y;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "start_x") {
|
|
|
|
|
value = start_pos.x;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "start_y") {
|
|
|
|
|
value = start_pos.y;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "end_x") {
|
|
|
|
|
value = end_pos.x;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "end_y") {
|
|
|
|
|
value = end_pos.y;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UILine::getProperty(const std::string& name, sf::Color& value) const {
|
|
|
|
|
if (name == "color") {
|
|
|
|
|
value = color;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool UILine::getProperty(const std::string& name, sf::Vector2f& value) const {
|
|
|
|
|
if (name == "start") {
|
|
|
|
|
value = start_pos;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
else if (name == "end") {
|
|
|
|
|
value = end_pos;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Python API implementation
|
|
|
|
|
PyObject* UILine::get_start(PyUILineObject* self, void* closure) {
|
|
|
|
|
auto vec = self->data->getStart();
|
|
|
|
|
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
|
|
|
|
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
|
|
|
|
Py_DECREF(type);
|
|
|
|
|
if (obj) {
|
|
|
|
|
obj->data = vec;
|
|
|
|
|
}
|
|
|
|
|
return (PyObject*)obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UILine::set_start(PyUILineObject* self, PyObject* value, void* closure) {
|
|
|
|
|
PyVectorObject* vec = PyVector::from_arg(value);
|
|
|
|
|
if (!vec) {
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "start must be a Vector or tuple (x, y)");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
self->data->setStart(vec->data);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObject* UILine::get_end(PyUILineObject* self, void* closure) {
|
|
|
|
|
auto vec = self->data->getEnd();
|
|
|
|
|
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Vector");
|
|
|
|
|
auto obj = (PyVectorObject*)type->tp_alloc(type, 0);
|
|
|
|
|
Py_DECREF(type);
|
|
|
|
|
if (obj) {
|
|
|
|
|
obj->data = vec;
|
|
|
|
|
}
|
|
|
|
|
return (PyObject*)obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UILine::set_end(PyUILineObject* self, PyObject* value, void* closure) {
|
|
|
|
|
PyVectorObject* vec = PyVector::from_arg(value);
|
|
|
|
|
if (!vec) {
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "end must be a Vector or tuple (x, y)");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
self->data->setEnd(vec->data);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObject* UILine::get_color(PyUILineObject* self, void* closure) {
|
|
|
|
|
auto color = self->data->getColor();
|
|
|
|
|
auto type = (PyTypeObject*)PyObject_GetAttrString(McRFPy_API::mcrf_module, "Color");
|
|
|
|
|
PyObject* args = Py_BuildValue("(iiii)", color.r, color.g, color.b, color.a);
|
|
|
|
|
PyObject* obj = PyObject_CallObject((PyObject*)type, args);
|
|
|
|
|
Py_DECREF(args);
|
|
|
|
|
Py_DECREF(type);
|
|
|
|
|
return obj;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UILine::set_color(PyUILineObject* self, PyObject* value, void* closure) {
|
|
|
|
|
auto color = PyColor::from_arg(value);
|
|
|
|
|
if (!color) {
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "color must be a Color or tuple (r, g, b) or (r, g, b, a)");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
self->data->setColor(color->data);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyObject* UILine::get_thickness(PyUILineObject* self, void* closure) {
|
|
|
|
|
return PyFloat_FromDouble(self->data->getThickness());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UILine::set_thickness(PyUILineObject* self, PyObject* value, void* closure) {
|
|
|
|
|
float thickness;
|
|
|
|
|
if (PyFloat_Check(value)) {
|
|
|
|
|
thickness = PyFloat_AsDouble(value);
|
|
|
|
|
} else if (PyLong_Check(value)) {
|
|
|
|
|
thickness = PyLong_AsLong(value);
|
|
|
|
|
} else {
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "thickness must be a number");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (thickness < 0.0f) {
|
|
|
|
|
PyErr_SetString(PyExc_ValueError, "thickness must be non-negative");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self->data->setThickness(thickness);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Define the Python type alias for macros
|
|
|
|
|
typedef PyUILineObject PyObjectType;
|
|
|
|
|
|
|
|
|
|
// Method definitions
|
|
|
|
|
PyMethodDef UILine_methods[] = {
|
|
|
|
|
UIDRAWABLE_METHODS,
|
|
|
|
|
{NULL} // Sentinel
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
PyGetSetDef UILine::getsetters[] = {
|
|
|
|
|
{"start", (getter)UILine::get_start, (setter)UILine::set_start,
|
|
|
|
|
MCRF_PROPERTY(start, "Starting point of the line as a Vector."), NULL},
|
|
|
|
|
{"end", (getter)UILine::get_end, (setter)UILine::set_end,
|
|
|
|
|
MCRF_PROPERTY(end, "Ending point of the line as a Vector."), NULL},
|
|
|
|
|
{"color", (getter)UILine::get_color, (setter)UILine::set_color,
|
|
|
|
|
MCRF_PROPERTY(color, "Line color as a Color object."), NULL},
|
|
|
|
|
{"thickness", (getter)UILine::get_thickness, (setter)UILine::set_thickness,
|
|
|
|
|
MCRF_PROPERTY(thickness, "Line thickness in pixels."), NULL},
|
2025-11-27 22:31:53 -05:00
|
|
|
{"on_click", (getter)UIDrawable::get_click, (setter)UIDrawable::set_click,
|
|
|
|
|
MCRF_PROPERTY(on_click, "Callable executed when line is clicked."),
|
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
|
|
|
(void*)PyObjectsEnum::UILINE},
|
|
|
|
|
{"z_index", (getter)UIDrawable::get_int, (setter)UIDrawable::set_int,
|
|
|
|
|
MCRF_PROPERTY(z_index, "Z-order for rendering (lower values rendered first)."),
|
|
|
|
|
(void*)PyObjectsEnum::UILINE},
|
|
|
|
|
{"name", (getter)UIDrawable::get_name, (setter)UIDrawable::set_name,
|
|
|
|
|
MCRF_PROPERTY(name, "Name for finding this element."),
|
|
|
|
|
(void*)PyObjectsEnum::UILINE},
|
|
|
|
|
{"pos", (getter)UIDrawable::get_pos, (setter)UIDrawable::set_pos,
|
|
|
|
|
MCRF_PROPERTY(pos, "Position as a Vector (midpoint of line)."),
|
|
|
|
|
(void*)PyObjectsEnum::UILINE},
|
|
|
|
|
UIDRAWABLE_GETSETTERS,
|
2025-11-27 16:33:17 -05:00
|
|
|
UIDRAWABLE_PARENT_GETSETTERS(PyObjectsEnum::UILINE),
|
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
|
|
|
{NULL}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
PyObject* UILine::repr(PyUILineObject* self) {
|
|
|
|
|
std::ostringstream ss;
|
|
|
|
|
if (!self->data) {
|
|
|
|
|
ss << "<Line (invalid internal object)>";
|
|
|
|
|
} else {
|
|
|
|
|
auto start = self->data->getStart();
|
|
|
|
|
auto end = self->data->getEnd();
|
|
|
|
|
auto color = self->data->getColor();
|
|
|
|
|
ss << "<Line start=(" << start.x << ", " << start.y << ") "
|
|
|
|
|
<< "end=(" << end.x << ", " << end.y << ") "
|
|
|
|
|
<< "thickness=" << self->data->getThickness() << " "
|
|
|
|
|
<< "color=(" << (int)color.r << ", " << (int)color.g << ", "
|
|
|
|
|
<< (int)color.b << ", " << (int)color.a << ")>";
|
|
|
|
|
}
|
|
|
|
|
std::string repr_str = ss.str();
|
|
|
|
|
return PyUnicode_DecodeUTF8(repr_str.c_str(), repr_str.size(), "replace");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int UILine::init(PyUILineObject* self, PyObject* args, PyObject* kwds) {
|
|
|
|
|
// Arguments
|
|
|
|
|
PyObject* start_obj = nullptr;
|
|
|
|
|
PyObject* end_obj = nullptr;
|
|
|
|
|
float thickness = 1.0f;
|
|
|
|
|
PyObject* color_obj = nullptr;
|
|
|
|
|
PyObject* click_handler = nullptr;
|
|
|
|
|
int visible = 1;
|
|
|
|
|
float opacity = 1.0f;
|
|
|
|
|
int z_index = 0;
|
|
|
|
|
const char* name = nullptr;
|
|
|
|
|
|
|
|
|
|
static const char* kwlist[] = {
|
|
|
|
|
"start", "end", "thickness", "color",
|
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", "visible", "opacity", "z_index", "name",
|
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
|
|
|
nullptr
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOfOOifiz", const_cast<char**>(kwlist),
|
|
|
|
|
&start_obj, &end_obj, &thickness, &color_obj,
|
|
|
|
|
&click_handler, &visible, &opacity, &z_index, &name)) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse start position
|
|
|
|
|
sf::Vector2f start(0.0f, 0.0f);
|
|
|
|
|
if (start_obj) {
|
|
|
|
|
PyVectorObject* vec = PyVector::from_arg(start_obj);
|
|
|
|
|
if (vec) {
|
|
|
|
|
start = vec->data;
|
|
|
|
|
} else {
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "start must be a Vector or tuple (x, y)");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse end position
|
|
|
|
|
sf::Vector2f end(0.0f, 0.0f);
|
|
|
|
|
if (end_obj) {
|
|
|
|
|
PyVectorObject* vec = PyVector::from_arg(end_obj);
|
|
|
|
|
if (vec) {
|
|
|
|
|
end = vec->data;
|
|
|
|
|
} else {
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "end must be a Vector or tuple (x, y)");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Parse color
|
|
|
|
|
sf::Color color = sf::Color::White;
|
|
|
|
|
if (color_obj && color_obj != Py_None) {
|
|
|
|
|
auto pycolor = PyColor::from_arg(color_obj);
|
|
|
|
|
if (pycolor) {
|
|
|
|
|
color = pycolor->data;
|
|
|
|
|
} else {
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
PyErr_SetString(PyExc_TypeError, "color must be a Color or tuple");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Validate thickness
|
|
|
|
|
if (thickness < 0.0f) {
|
|
|
|
|
PyErr_SetString(PyExc_ValueError, "thickness must be non-negative");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create the line
|
|
|
|
|
self->data = std::make_shared<UILine>(start, end, thickness, color);
|
|
|
|
|
self->data->visible = visible;
|
|
|
|
|
self->data->opacity = opacity;
|
|
|
|
|
self->data->z_index = z_index;
|
|
|
|
|
|
|
|
|
|
if (name) {
|
|
|
|
|
self->data->name = std::string(name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle click handler
|
|
|
|
|
if (click_handler && click_handler != Py_None) {
|
|
|
|
|
if (!PyCallable_Check(click_handler)) {
|
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
|
|
|
PyErr_SetString(PyExc_TypeError, "on_click must be callable");
|
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
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
self->data->click_register(click_handler);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize weak reference list
|
|
|
|
|
self->weakreflist = NULL;
|
|
|
|
|
|
|
|
|
|
// Register in Python object cache
|
|
|
|
|
if (self->data->serial_number == 0) {
|
|
|
|
|
self->data->serial_number = PythonObjectCache::getInstance().assignSerial();
|
|
|
|
|
PyObject* weakref = PyWeakref_NewRef((PyObject*)self, NULL);
|
|
|
|
|
if (weakref) {
|
|
|
|
|
PythonObjectCache::getInstance().registerObject(self->data->serial_number, weakref);
|
|
|
|
|
Py_DECREF(weakref);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|