Удалил слои, добавил древовидность объектов

Удалил структуру слоев. Теперь объекты хранятся непосредственно в документе, а вложенность реализуется через поле children структуры Object. Это упростило структуру документа и позволило создавать иерархические объекты.
This commit is contained in:
2026-02-23 19:33:51 +03:00
parent c73d710513
commit 6ae927c4b7

View File

@@ -7,44 +7,27 @@ const Document = @This();
size: Size, size: Size,
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
layers: std.ArrayList(Layer), /// Корневые объекты документа (вложенность через Object.children).
objects: std.ArrayList(Object),
pub fn init(allocator: std.mem.Allocator, size: Size) Document { pub fn init(allocator: std.mem.Allocator, size: Size) Document {
return .{ return .{
.size = size, .size = size,
.allocator = allocator,
.layers = std.ArrayList(Layer).empty,
};
}
pub fn deinit(self: *Document) void {
for (self.layers.items) |*layer| layer.deinit();
self.layers.deinit(self.allocator);
}
pub const Layer = struct {
name: [64:0]u8 = .{0} ** 64,
allocator: std.mem.Allocator,
objects: std.ArrayList(Object),
pub fn init(allocator: std.mem.Allocator) Layer {
return .{
.allocator = allocator, .allocator = allocator,
.objects = std.ArrayList(Object).empty, .objects = std.ArrayList(Object).empty,
}; };
} }
pub fn deinit(self: *Layer) void { pub fn deinit(self: *Document) void {
for (self.objects.items) |*obj| obj.deinit(self.allocator); for (self.objects.items) |*obj| obj.deinit(self.allocator);
self.objects.deinit(self.allocator); self.objects.deinit(self.allocator);
} }
/// Добавить объект в слой (клонирует свойства в allocator слоя). /// Добавить корневой объект в документ (клонирует в allocator документа).
pub fn addObject(self: *Layer, template: Object) !void { pub fn addObject(self: *Document, template: Object) !void {
const obj = try template.clone(self.allocator); const obj = try template.clone(self.allocator);
try self.objects.append(self.allocator, obj); try self.objects.append(self.allocator, obj);
} }
};
/// Тип фигуры: определяет, как RenderEngine интерпретирует свойства и рисует объект. /// Тип фигуры: определяет, как RenderEngine интерпретирует свойства и рисует объект.
pub const ShapeKind = enum { pub const ShapeKind = enum {
@@ -54,12 +37,13 @@ pub const ShapeKind = enum {
path, path,
}; };
/// Объект на слое: тип фигуры + список полиморфных свойств. /// Объект документа: тип фигуры, свойства и вложенные дочерние объекты.
/// Типы объектов (прямоугольник, эллипс, линия) задаются конструкторами, /// Типы объектов задаются конструкторами; UI и RenderEngine работают с union Property.
/// которые создают нужный набор свойств; UI и RenderEngine работают с union Property.
pub const Object = struct { pub const Object = struct {
shape: ShapeKind, shape: ShapeKind,
properties: std.ArrayList(Property), properties: std.ArrayList(Property),
/// Вложенные объекты (дерево).
children: std.ArrayList(Object),
/// Найти свойство по тегу и вернуть вариант union (caller делает switch). /// Найти свойство по тегу и вернуть вариант union (caller делает switch).
pub fn getProperty(self: Object, tag: std.meta.Tag(Property)) ?Property { pub fn getProperty(self: Object, tag: std.meta.Tag(Property)) ?Property {
@@ -80,15 +64,34 @@ pub const Object = struct {
try self.properties.append(allocator, prop); try self.properties.append(allocator, prop);
} }
/// Клонировать объект (в т.ч. список свойств) для вставки в другой слой/документ. /// Добавить дочерний объект (клонирует в переданный allocator).
pub fn addChild(self: *Object, allocator: std.mem.Allocator, template: Object) !void {
const obj = try template.clone(allocator);
try self.children.append(allocator, obj);
}
/// Клонировать объект рекурсивно (свойства и дети).
pub fn clone(self: Object, allocator: std.mem.Allocator) !Object { pub fn clone(self: Object, allocator: std.mem.Allocator) !Object {
var list = std.ArrayList(Property).empty; var properties_list = std.ArrayList(Property).empty;
errdefer list.deinit(allocator); errdefer properties_list.deinit(allocator);
try list.appendSlice(allocator, self.properties.items); try properties_list.appendSlice(allocator, self.properties.items);
return .{ .shape = self.shape, .properties = list };
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));
}
return .{
.shape = self.shape,
.properties = properties_list,
.children = children_list,
};
} }
pub fn deinit(self: *Object, allocator: std.mem.Allocator) void { pub fn deinit(self: *Object, allocator: std.mem.Allocator) void {
for (self.children.items) |*child| child.deinit(allocator);
self.children.deinit(allocator);
self.properties.deinit(allocator); self.properties.deinit(allocator);
self.* = undefined; self.* = undefined;
} }
@@ -99,7 +102,11 @@ pub const Object = struct {
var properties_list = std.ArrayList(Property).empty; var properties_list = std.ArrayList(Property).empty;
errdefer properties_list.deinit(allocator); errdefer properties_list.deinit(allocator);
try properties_list.appendSlice(allocator, &common); try properties_list.appendSlice(allocator, &common);
return .{ .shape = shape, .properties = properties_list }; return .{
.shape = shape,
.properties = properties_list,
.children = std.ArrayList(Object).empty,
};
} }
// --- Публичные конструкторы: базовый объект + одно свойство фигуры --- // --- Публичные конструкторы: базовый объект + одно свойство фигуры ---