const std = @import("std"); const Property = @import("Property.zig").Property; const PropertyData = @import("Property.zig").Data; const Object = @This(); pub const ShapeKind = enum { line, ellipse, broken, }; const default_common_data = [_]PropertyData{ .{ .position = .{ .x = 0, .y = 0 } }, .{ .angle = 0 }, .{ .scale = .{ .scale_x = 1, .scale_y = 1 } }, .{ .visible = true }, .{ .opacity = 1.0 }, .{ .locked = false }, .{ .stroke_rgba = 0x000000FF }, // чёрный, полная непрозрачность .{ .thickness = 2.0 }, }; pub const defaultCommonProperties: [default_common_data.len]Property = blk: { var result: [default_common_data.len]Property = undefined; for (default_common_data, &result) |d, *p| { p.* = .{ .data = d }; } break :blk result; }; id: u64, shape: ShapeKind, properties: std.ArrayList(Property), children: std.ArrayList(Object), pub fn getProperty(self: Object, tag: std.meta.Tag(PropertyData)) ?*const PropertyData { for (self.properties.items) |*prop| { if (std.meta.activeTag(prop.data) == tag) return &prop.data; } return null; } /// Забирает владение Property pub fn setProperty(self: *Object, allocator: std.mem.Allocator, prop: Property) !void { for (self.properties.items, 0..) |*p, i| { if (std.meta.activeTag(p.data) == std.meta.activeTag(prop.data)) { if (p.data == .points) p.data.points.deinit(allocator); self.properties.items[i] = prop; return; } } return error.PropertyNotFound; } pub fn addChild(self: *Object, allocator: std.mem.Allocator, template: Object, next_id: *u64) !void { const obj = try template.clone(allocator, next_id); try self.children.append(allocator, obj); } pub fn clone(self: Object, allocator: std.mem.Allocator, next_id: *u64) !Object { var properties_list = std.ArrayList(Property).empty; errdefer properties_list.deinit(allocator); for (self.properties.items) |prop| { try properties_list.append(allocator, try prop.clone(allocator)); } var children_list = std.ArrayList(Object).empty; errdefer children_list.deinit(allocator); for (self.children.items) |child| { try children_list.append(allocator, try child.clone(allocator, next_id)); } return .{ .id = allocId(next_id), .shape = self.shape, .properties = properties_list, .children = children_list, }; } fn allocId(next_id: *u64) u64 { const id = next_id.*; next_id.* += 1; return id; } pub fn deinit(self: *Object, allocator: std.mem.Allocator) void { for (self.children.items) |*child| child.deinit(allocator); self.children.deinit(allocator); for (self.properties.items) |*prop| prop.deinit(allocator); self.properties.deinit(allocator); self.* = undefined; }