Compare commits
2 Commits
8ca31bf479
...
b692539a30
| Author | SHA1 | Date | |
|---|---|---|---|
| b692539a30 | |||
| 9fa13fa913 |
@@ -24,17 +24,20 @@ scroll: dvui.ScrollInfo = .{
|
|||||||
.horizontal = .auto,
|
.horizontal = .auto,
|
||||||
},
|
},
|
||||||
native_scaling: bool = true,
|
native_scaling: bool = true,
|
||||||
redraw_throttle_ms: u32 = 50,
|
|
||||||
_visible_rect: ?Rect_i = null,
|
|
||||||
_zoom: f32 = 1,
|
|
||||||
_redraw_pending: bool = false,
|
|
||||||
_last_redraw_time_ms: i64 = 0,
|
|
||||||
cursor_document_point: ?Point2_f = null,
|
cursor_document_point: ?Point2_f = null,
|
||||||
draw_document: bool = true,
|
draw_document: bool = true,
|
||||||
|
show_render_stats: bool = true,
|
||||||
/// Rect тулбара (из предыдущего кадра) для исключения кликов по нему из handleCanvasMouse.
|
/// Rect тулбара (из предыдущего кадра) для исключения кликов по нему из handleCanvasMouse.
|
||||||
toolbar_rect_scale: ?dvui.RectScale = null,
|
toolbar_rect_scale: ?dvui.RectScale = null,
|
||||||
/// Rect панели свойств (из предыдущего кадра) для исключения кликов по нему из handleCanvasMouse.
|
/// Rect панели свойств (из предыдущего кадра) для исключения кликов по нему из handleCanvasMouse.
|
||||||
properties_rect_scale: ?dvui.RectScale = null,
|
properties_rect_scale: ?dvui.RectScale = null,
|
||||||
|
redraw_throttle_ms: u32 = 50,
|
||||||
|
frame_index: u64 = 0,
|
||||||
|
|
||||||
|
_zoom: f32 = 1,
|
||||||
|
_last_redraw_time_ms: i64 = 0, // Метка последней перерисовки чтобы ограничить частоту
|
||||||
|
_visible_rect: ?Rect_i = null,
|
||||||
|
_redraw_pending: bool = false,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator, document: *Document, engine: RenderEngine) Canvas {
|
pub fn init(allocator: std.mem.Allocator, document: *Document, engine: RenderEngine) Canvas {
|
||||||
return .{
|
return .{
|
||||||
@@ -80,6 +83,7 @@ fn redraw(self: *Canvas) !void {
|
|||||||
self.texture = tex;
|
self.texture = tex;
|
||||||
}
|
}
|
||||||
self._last_redraw_time_ms = std.time.milliTimestamp();
|
self._last_redraw_time_ms = std.time.milliTimestamp();
|
||||||
|
self.frame_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exampleReset(self: *Canvas) !void {
|
pub fn exampleReset(self: *Canvas) !void {
|
||||||
|
|||||||
@@ -45,17 +45,14 @@ pub const OpenDocument = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
frame_index: u64,
|
|
||||||
documents: std.ArrayList(*OpenDocument),
|
documents: std.ArrayList(*OpenDocument),
|
||||||
active_document_index: ?usize,
|
active_document_index: ?usize,
|
||||||
|
|
||||||
pub fn init(allocator: std.mem.Allocator) !WindowContext {
|
pub fn init(allocator: std.mem.Allocator) !WindowContext {
|
||||||
const frame_index: u64 = 0;
|
|
||||||
const documents = std.ArrayList(*OpenDocument).empty;
|
const documents = std.ArrayList(*OpenDocument).empty;
|
||||||
const active_document_index: ?usize = null;
|
const active_document_index: ?usize = null;
|
||||||
return .{
|
return .{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.frame_index = frame_index,
|
|
||||||
.documents = documents,
|
.documents = documents,
|
||||||
.active_document_index = active_document_index,
|
.active_document_index = active_document_index,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const RenderEngine = @import("RenderEngine.zig").RenderEngine;
|
|||||||
const Document = @import("../models/Document.zig");
|
const Document = @import("../models/Document.zig");
|
||||||
const basic_models = @import("../models/basic_models.zig");
|
const basic_models = @import("../models/basic_models.zig");
|
||||||
const cpu_draw = @import("cpu/draw.zig");
|
const cpu_draw = @import("cpu/draw.zig");
|
||||||
|
const RenderStats = @import("RenderStats.zig");
|
||||||
const Size_i = basic_models.Size_i;
|
const Size_i = basic_models.Size_i;
|
||||||
const Rect_i = basic_models.Rect_i;
|
const Rect_i = basic_models.Rect_i;
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
@@ -17,14 +18,18 @@ const Type = enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type: Type,
|
type: Type,
|
||||||
_allocator: Allocator,
|
|
||||||
gradient_start: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 },
|
gradient_start: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 },
|
||||||
gradient_end: Color.PMA = .{ .r = 255, .g = 255, .b = 255, .a = 255 },
|
gradient_end: Color.PMA = .{ .r = 255, .g = 255, .b = 255, .a = 255 },
|
||||||
|
_allocator: Allocator,
|
||||||
|
_renderStats: RenderStats,
|
||||||
|
|
||||||
pub fn init(allocator: Allocator, render_type: Type) CpuRenderEngine {
|
pub fn init(allocator: Allocator, render_type: Type) CpuRenderEngine {
|
||||||
return .{
|
return .{
|
||||||
._allocator = allocator,
|
._allocator = allocator,
|
||||||
.type = render_type,
|
.type = render_type,
|
||||||
|
._renderStats = .{
|
||||||
|
.render_time_ns = 0,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,7 +187,13 @@ pub fn renderDocument(self: *CpuRenderEngine, document: *const Document, canvas_
|
|||||||
defer self._allocator.free(pixels);
|
defer self._allocator.free(pixels);
|
||||||
|
|
||||||
for (pixels) |*p| p.* = .{ .r = 255, .g = 255, .b = 255, .a = 255 };
|
for (pixels) |*p| p.* = .{ .r = 255, .g = 255, .b = 255, .a = 255 };
|
||||||
|
var t = try std.time.Timer.start();
|
||||||
try cpu_draw.drawDocument(pixels, width, height, visible_rect, document, canvas_size, self._allocator);
|
try cpu_draw.drawDocument(pixels, width, height, visible_rect, document, canvas_size, self._allocator);
|
||||||
|
self._renderStats.render_time_ns = t.read();
|
||||||
|
|
||||||
return try dvui.textureCreate(pixels, width, height, .nearest);
|
return try dvui.textureCreate(pixels, width, height, .nearest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getStats(self: CpuRenderEngine) RenderStats {
|
||||||
|
return self._renderStats;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ const dvui = @import("dvui");
|
|||||||
const CpuRenderEngine = @import("CpuRenderEngine.zig");
|
const CpuRenderEngine = @import("CpuRenderEngine.zig");
|
||||||
const Document = @import("../models/Document.zig");
|
const Document = @import("../models/Document.zig");
|
||||||
const basic_models = @import("../models/basic_models.zig");
|
const basic_models = @import("../models/basic_models.zig");
|
||||||
|
const RenderStats = @import("RenderStats.zig");
|
||||||
|
|
||||||
pub const RenderEngine = union(enum) {
|
pub const RenderEngine = union(enum) {
|
||||||
cpu: *CpuRenderEngine,
|
cpu: *CpuRenderEngine,
|
||||||
@@ -18,6 +19,12 @@ pub const RenderEngine = union(enum) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getStats(self: RenderEngine) RenderStats {
|
||||||
|
return switch (self) {
|
||||||
|
.cpu => |cpu_r| cpu_r.getStats(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/// Растеризует документ в текстуру.
|
/// Растеризует документ в текстуру.
|
||||||
pub fn render(self: RenderEngine, document: *const Document, canvas_size: basic_models.Size_i, visible_rect: basic_models.Rect_i) !?dvui.Texture {
|
pub fn render(self: RenderEngine, document: *const Document, canvas_size: basic_models.Size_i, visible_rect: basic_models.Rect_i) !?dvui.Texture {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
|
|||||||
3
src/render/RenderStats.zig
Normal file
3
src/render/RenderStats.zig
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
const RenderStats = @This();
|
||||||
|
|
||||||
|
render_time_ns: u64, // Время рендера кадра в микросекундах
|
||||||
@@ -7,6 +7,7 @@ const Property = @import("../models/Property.zig").Property;
|
|||||||
const PropertyData = @import("../models/Property.zig").Data;
|
const PropertyData = @import("../models/Property.zig").Data;
|
||||||
const Rect_i = @import("../models/basic_models.zig").Rect_i;
|
const Rect_i = @import("../models/basic_models.zig").Rect_i;
|
||||||
const Tool = @import("../toolbar/Tool.zig");
|
const Tool = @import("../toolbar/Tool.zig");
|
||||||
|
const RenderStats = @import("../render/RenderStats.zig");
|
||||||
|
|
||||||
pub fn canvasView(canvas: *Canvas, selected_object_id: ?u64, content_rect_scale: dvui.RectScale) void {
|
pub fn canvasView(canvas: *Canvas, selected_object_id: ?u64, content_rect_scale: dvui.RectScale) void {
|
||||||
var textured = dvui_ext.texturedBox(content_rect_scale, dvui.Rect.all(20));
|
var textured = dvui_ext.texturedBox(content_rect_scale, dvui.Rect.all(20));
|
||||||
@@ -36,23 +37,27 @@ pub fn canvasView(canvas: *Canvas, selected_object_id: ?u64, content_rect_scale:
|
|||||||
const scroll_parent = dvui.parentGet();
|
const scroll_parent = dvui.parentGet();
|
||||||
dvui.parentSet(overlay_parent);
|
dvui.parentSet(overlay_parent);
|
||||||
|
|
||||||
|
const vbar = scroll.vbar;
|
||||||
|
const hbar = scroll.hbar;
|
||||||
|
if (vbar != null) {
|
||||||
|
|
||||||
|
// std.debug.print("{any}", .{vbar.?.data()});
|
||||||
|
}
|
||||||
|
if (hbar != null) {
|
||||||
|
// std.debug.print("{any}", .{hbar.?.data()});
|
||||||
|
}
|
||||||
|
|
||||||
// Тулбар поверх scroll
|
// Тулбар поверх scroll
|
||||||
var toolbar_box = dvui.box(
|
var toolbar_box = dvui.box(
|
||||||
@src(),
|
@src(),
|
||||||
.{ .dir = .horizontal },
|
.{ .dir = .horizontal },
|
||||||
.{
|
.{},
|
||||||
.expand = .none,
|
|
||||||
.background = false,
|
|
||||||
.gravity_x = 0.0,
|
|
||||||
.gravity_y = 0.0,
|
|
||||||
.margin = dvui.Rect{ .x = 16, .y = 16 },
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
drawToolbar(canvas);
|
drawToolbar(canvas);
|
||||||
}
|
|
||||||
// Сохраняем rect тулбара для следующего кадра — в handleCanvasMouse исключаем из него клики
|
// Сохраняем rect тулбара для следующего кадра — в handleCanvasMouse исключаем из него клики
|
||||||
canvas.toolbar_rect_scale = toolbar_box.data().contentRectScale();
|
canvas.toolbar_rect_scale = toolbar_box.data().contentRectScale();
|
||||||
|
}
|
||||||
toolbar_box.deinit();
|
toolbar_box.deinit();
|
||||||
|
|
||||||
// Панель свойств поверх scroll (правый верхний угол)
|
// Панель свойств поверх scroll (правый верхний угол)
|
||||||
@@ -61,24 +66,20 @@ pub fn canvasView(canvas: *Canvas, selected_object_id: ?u64, content_rect_scale:
|
|||||||
var properties_box = dvui.box(
|
var properties_box = dvui.box(
|
||||||
@src(),
|
@src(),
|
||||||
.{ .dir = .horizontal },
|
.{ .dir = .horizontal },
|
||||||
.{
|
.{},
|
||||||
.expand = .none,
|
|
||||||
.background = false,
|
|
||||||
.gravity_x = 1.0,
|
|
||||||
.gravity_y = 0.0,
|
|
||||||
.margin = dvui.Rect{ .w = 32, .y = 16, .h = 100 },
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
drawPropertiesPanel(canvas, obj);
|
drawPropertiesPanel(canvas, obj);
|
||||||
}
|
|
||||||
// Сохраняем rect панели свойств для следующего кадра — в handleCanvasMouse исключаем из него клики
|
// Сохраняем rect панели свойств для следующего кадра — в handleCanvasMouse исключаем из него клики
|
||||||
canvas.properties_rect_scale = properties_box.data().contentRectScale();
|
canvas.properties_rect_scale = properties_box.data().contentRectScale();
|
||||||
|
}
|
||||||
properties_box.deinit();
|
properties_box.deinit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dvui.label(@src(), "Canvas", .{}, .{ .gravity_x = 0.5, .gravity_y = 0.0 });
|
drawCanvasLabelPanel();
|
||||||
|
if (canvas.show_render_stats)
|
||||||
|
drawStatsPanel(canvas.render_engine.getStats(), canvas.frame_index);
|
||||||
|
|
||||||
if (canvas.properties_rect_scale) |prs| {
|
if (canvas.properties_rect_scale) |prs| {
|
||||||
for (dvui.events()) |*e| {
|
for (dvui.events()) |*e| {
|
||||||
@@ -278,6 +279,7 @@ fn drawToolbar(canvas: *Canvas) void {
|
|||||||
.corner_radius = dvui.Rect.all(8),
|
.corner_radius = dvui.Rect.all(8),
|
||||||
.background = true,
|
.background = true,
|
||||||
.color_fill = dvui.Color.black.opacity(0.2),
|
.color_fill = dvui.Color.black.opacity(0.2),
|
||||||
|
.margin = dvui.Rect{ .x = 16, .y = 16 },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
@@ -312,6 +314,7 @@ fn drawPropertiesPanel(canvas: *Canvas, selected_object: *Document.Object) void
|
|||||||
.background = true,
|
.background = true,
|
||||||
.color_fill = dvui.Color.black.opacity(0.2),
|
.color_fill = dvui.Color.black.opacity(0.2),
|
||||||
.min_size_content = .{ .w = 220 },
|
.min_size_content = .{ .w = 220 },
|
||||||
|
.margin = dvui.Rect{ .w = 32, .y = 16, .h = 100 },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
{
|
{
|
||||||
@@ -332,6 +335,47 @@ fn drawPropertiesPanel(canvas: *Canvas, selected_object: *Document.Object) void
|
|||||||
panel.deinit();
|
panel.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn drawCanvasLabelPanel() void {
|
||||||
|
var panel = dvui.box(
|
||||||
|
@src(),
|
||||||
|
.{ .dir = .vertical },
|
||||||
|
.{
|
||||||
|
.gravity_x = 0.5,
|
||||||
|
.gravity_y = 0.0,
|
||||||
|
.padding = dvui.Rect.all(8),
|
||||||
|
.corner_radius = dvui.Rect.all(8),
|
||||||
|
.background = true,
|
||||||
|
.color_fill = dvui.Color.black.opacity(0.2),
|
||||||
|
.margin = dvui.Rect{ .x = 16, .y = 16 },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
{
|
||||||
|
dvui.label(@src(), "Canvas", .{}, .{});
|
||||||
|
}
|
||||||
|
panel.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drawStatsPanel(stats: RenderStats, frame_index: u64) void {
|
||||||
|
var panel = dvui.box(
|
||||||
|
@src(),
|
||||||
|
.{ .dir = .vertical },
|
||||||
|
.{
|
||||||
|
.gravity_x = 0.0,
|
||||||
|
.gravity_y = 1.0,
|
||||||
|
.padding = dvui.Rect.all(8),
|
||||||
|
.corner_radius = dvui.Rect.all(8),
|
||||||
|
.background = true,
|
||||||
|
.color_fill = dvui.Color.black.opacity(0.2),
|
||||||
|
.margin = dvui.Rect{ .x = 16, .h = 16 },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
{
|
||||||
|
dvui.label(@src(), "Frame time: {d:.2}ms", .{@as(f32, @floatFromInt(stats.render_time_ns)) / std.time.ns_per_ms}, .{});
|
||||||
|
dvui.label(@src(), "Frame index: {}", .{frame_index}, .{});
|
||||||
|
}
|
||||||
|
panel.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Property, row_index: usize) void {
|
fn drawPropertyEditor(canvas: *Canvas, obj: *Document.Object, prop: *const Property, row_index: usize) void {
|
||||||
const row_id: usize = row_index * 16;
|
const row_id: usize = row_index * 16;
|
||||||
var row = dvui.box(
|
var row = dvui.box(
|
||||||
|
|||||||
@@ -30,6 +30,5 @@ pub fn guiFrame(ctx: *WindowContext) bool {
|
|||||||
}
|
}
|
||||||
root.deinit();
|
root.deinit();
|
||||||
|
|
||||||
ctx.frame_index += 1;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ pub fn leftPanel(ctx: *WindowContext) void {
|
|||||||
if (dvui.checkbox(@src(), &canvas.draw_document, "Draw document", .{})) {
|
if (dvui.checkbox(@src(), &canvas.draw_document, "Draw document", .{})) {
|
||||||
canvas.requestRedraw();
|
canvas.requestRedraw();
|
||||||
}
|
}
|
||||||
|
if (dvui.checkbox(@src(), &canvas.show_render_stats, "Show stats", .{})) {}
|
||||||
if (!canvas.draw_document) {
|
if (!canvas.draw_document) {
|
||||||
if (dvui.button(@src(), if (doc.cpu_render.type == .Gradient) "Gradient" else "Squares", .{}, .{})) {
|
if (dvui.button(@src(), if (doc.cpu_render.type == .Gradient) "Gradient" else "Squares", .{}, .{})) {
|
||||||
if (doc.cpu_render.type == .Gradient) {
|
if (doc.cpu_render.type == .Gradient) {
|
||||||
@@ -188,6 +189,9 @@ pub fn leftPanel(ctx: *WindowContext) void {
|
|||||||
if (dvui.button(@src(), "Add random shapes", .{}, .{})) {
|
if (dvui.button(@src(), "Add random shapes", .{}, .{})) {
|
||||||
canvas.addRandomShapes() catch {};
|
canvas.addRandomShapes() catch {};
|
||||||
}
|
}
|
||||||
|
if (dvui.button(@src(), "Request redraw", .{}, .{})) {
|
||||||
|
canvas.requestRedraw();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dvui.label(@src(), "No document", .{}, .{});
|
dvui.label(@src(), "No document", .{}, .{});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user