mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 13:02:07 +03:00
Display object refactoring (#3877)
This commit is contained in:
parent
4e30b3036d
commit
d60e3835f2
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -2373,6 +2373,7 @@ dependencies = [
|
|||||||
name = "enso-types"
|
name = "enso-types"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"enso-prelude",
|
||||||
"enso-reflect",
|
"enso-reflect",
|
||||||
"nalgebra",
|
"nalgebra",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
@ -180,7 +180,7 @@ impl EntryData {
|
|||||||
|
|
||||||
fn update_layout(&self, contour: Contour, text_size: text::Size, text_padding: f32) {
|
fn update_layout(&self, contour: Contour, text_size: text::Size, text_padding: f32) {
|
||||||
let size = contour.size;
|
let size = contour.size;
|
||||||
self.text.set_position_xy(Vector2(text_padding - size.x / 2.0, text_size.value / 2.0));
|
self.text.set_xy(Vector2(text_padding - size.x / 2.0, text_size.value / 2.0));
|
||||||
self.separator.size.set(size);
|
self.separator.size.set(size);
|
||||||
self.ellipsis.size.set(size);
|
self.ellipsis.size.set(size);
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ impl Model {
|
|||||||
fn update_layout(&self, content_size: Vector2, size: Vector2) {
|
fn update_layout(&self, content_size: Vector2, size: Vector2) {
|
||||||
self.mask.size.set(size);
|
self.mask.size.set(size);
|
||||||
let grid_view_center = Vector2(size.x / 2.0, -size.y / 2.0);
|
let grid_view_center = Vector2(size.x / 2.0, -size.y / 2.0);
|
||||||
self.mask.set_position_xy(grid_view_center);
|
self.mask.set_xy(grid_view_center);
|
||||||
let offset = self.offset(content_size, size);
|
let offset = self.offset(content_size, size);
|
||||||
// Additional padding is added to the viewport width to avoid rare glitches when the last
|
// Additional padding is added to the viewport width to avoid rare glitches when the last
|
||||||
// entry is cropped because it is placed right on the border of the viewport. Even 1px seems
|
// entry is cropped because it is placed right on the border of the viewport. Even 1px seems
|
||||||
@ -505,7 +505,7 @@ impl Breadcrumbs {
|
|||||||
model.offset(*content_size, *size)
|
model.offset(*content_size, *size)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
eval scroll_anim.value((offset) model.grid.set_position_x(-offset));
|
eval scroll_anim.value((offset) model.grid.set_x(-offset));
|
||||||
eval_ input.move_up(model.move_up());
|
eval_ input.move_up(model.move_up());
|
||||||
eval_ input.move_down(model.move_down());
|
eval_ input.move_down(model.move_down());
|
||||||
entries_height <- all(&entries_height, &init)._0();
|
entries_height <- all(&entries_height, &init)._0();
|
||||||
|
@ -18,7 +18,6 @@ use ensogl_core::data::color;
|
|||||||
use ensogl_core::display;
|
use ensogl_core::display;
|
||||||
use ensogl_core::display::scene::Layer;
|
use ensogl_core::display::scene::Layer;
|
||||||
use ensogl_core::display::shape::StyleWatchFrp;
|
use ensogl_core::display::shape::StyleWatchFrp;
|
||||||
use ensogl_core::display::Scene;
|
|
||||||
use ensogl_grid_view as grid_view;
|
use ensogl_grid_view as grid_view;
|
||||||
use ensogl_grid_view::entry::Contour;
|
use ensogl_grid_view::entry::Contour;
|
||||||
use ensogl_grid_view::entry::MovedHeaderPosition;
|
use ensogl_grid_view::entry::MovedHeaderPosition;
|
||||||
@ -267,7 +266,7 @@ impl CurrentIcon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for CurrentIcon {
|
impl display::Object for CurrentIcon {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.display_object
|
&self.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,16 +331,16 @@ impl Data {
|
|||||||
let shadow_addition = self.background.size.get().y - self.background.height.get();
|
let shadow_addition = self.background.size.get().y - self.background.height.get();
|
||||||
let bg_sprite_height = bg_height + shadow_addition;
|
let bg_sprite_height = bg_height + shadow_addition;
|
||||||
let bg_y = -gap_over_header / 2.0 + overlap / 2.0 + local_scope_offset;
|
let bg_y = -gap_over_header / 2.0 + overlap / 2.0 + local_scope_offset;
|
||||||
self.background.set_position_y(bg_y);
|
self.background.set_y(bg_y);
|
||||||
self.background.size.set(Vector2(bg_width, bg_sprite_height));
|
self.background.size.set(Vector2(bg_width, bg_sprite_height));
|
||||||
self.background.height.set(bg_height);
|
self.background.height.set(bg_height);
|
||||||
let left = -entry_size.x / 2.0 + style.padding;
|
let left = -entry_size.x / 2.0 + style.padding;
|
||||||
let icon_x = left + style.icon_size / 2.0;
|
let icon_x = left + style.icon_size / 2.0;
|
||||||
let icon_y = local_scope_offset;
|
let icon_y = local_scope_offset;
|
||||||
self.icon.borrow().set_position_xy(Vector2(icon_x, icon_y));
|
self.icon.borrow().set_xy(Vector2(icon_x, icon_y));
|
||||||
let text_x = Self::text_x_position(kind, style, grid_style);
|
let text_x = Self::text_x_position(kind, style, grid_style);
|
||||||
let text_y = style.text_size / 2.0 + local_scope_offset;
|
let text_y = style.text_size / 2.0 + local_scope_offset;
|
||||||
self.label.set_position_xy(Vector2(text_x, text_y));
|
self.label.set_xy(Vector2(text_x, text_y));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contour(kind: Kind, grid_style: &GridStyle, entry_size: Vector2) -> Contour {
|
fn contour(kind: Kind, grid_style: &GridStyle, entry_size: Vector2) -> Contour {
|
||||||
@ -517,7 +516,7 @@ impl grid_view::Entry for View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for View {
|
impl display::Object for View {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.data.display_object
|
&self.data.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -658,7 +658,7 @@ impl component::Frp<Model> for Frp {
|
|||||||
selection_entries_style.map(f!((input) model.selection_entries_params(input)));
|
selection_entries_style.map(f!((input) model.selection_entries_params(input)));
|
||||||
grid_scroll_frp.resize <+ style_and_content_size.map(Model::grid_size);
|
grid_scroll_frp.resize <+ style_and_content_size.map(Model::grid_size);
|
||||||
grid_position <- style_and_content_size.map(Model::grid_position);
|
grid_position <- style_and_content_size.map(Model::grid_position);
|
||||||
eval grid_position ((pos) model.grid.set_position_xy(*pos));
|
eval grid_position ((pos) model.grid.set_xy(*pos));
|
||||||
grid_scroll_frp.set_corner_radius_bottom_right <+ all(&corners_radius, &style.init)._0();
|
grid_scroll_frp.set_corner_radius_bottom_right <+ all(&corners_radius, &style.init)._0();
|
||||||
grid.set_entries_size <+ style.update.map(|s| s.entry_size());
|
grid.set_entries_size <+ style.update.map(|s| s.entry_size());
|
||||||
grid.set_column_width <+ style.update.map(|s| (column::CENTER, s.middle_column_width()));
|
grid.set_column_width <+ style.update.map(|s| (column::CENTER, s.middle_column_width()));
|
||||||
|
@ -282,13 +282,13 @@ impl Model {
|
|||||||
self.section_navigator.update_layout(style);
|
self.section_navigator.update_layout(style);
|
||||||
|
|
||||||
let navigator_shadow_x = -style.grid.width / 2.0;
|
let navigator_shadow_x = -style.grid.width / 2.0;
|
||||||
self.navigator_shadow.set_position_x(navigator_shadow_x);
|
self.navigator_shadow.set_x(navigator_shadow_x);
|
||||||
let section_navigator_shadow_size = Vector2(style.navigator.width, style.size().y);
|
let section_navigator_shadow_size = Vector2(style.navigator.width, style.size().y);
|
||||||
self.navigator_shadow.size.set(section_navigator_shadow_size);
|
self.navigator_shadow.size.set(section_navigator_shadow_size);
|
||||||
|
|
||||||
self.breadcrumbs.set_position_xy(style.breadcrumbs_pos());
|
self.breadcrumbs.set_xy(style.breadcrumbs_pos());
|
||||||
self.breadcrumbs.set_size(style.breadcrumbs_size());
|
self.breadcrumbs.set_size(style.breadcrumbs_size());
|
||||||
self.grid.set_position_xy(style.grid_pos());
|
self.grid.set_xy(style.grid_pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the navigator so it can be disabled on hover.
|
/// Set the navigator so it can be disabled on hover.
|
||||||
|
@ -220,8 +220,8 @@ impl Navigator {
|
|||||||
let x_pos = -style.grid.width / 2.0;
|
let x_pos = -style.grid.width / 2.0;
|
||||||
let top_buttons_y = top - top_buttons_height / 2.0 - top_padding;
|
let top_buttons_y = top - top_buttons_height / 2.0 - top_padding;
|
||||||
let bottom_buttons_y = bottom + bottom_buttons_height / 2.0 + bottom_padding;
|
let bottom_buttons_y = bottom + bottom_buttons_height / 2.0 + bottom_padding;
|
||||||
self.top_buttons.set_position_xy(Vector2(x_pos, top_buttons_y));
|
self.top_buttons.set_xy(Vector2(x_pos, top_buttons_y));
|
||||||
self.bottom_buttons.set_position_xy(Vector2(x_pos, bottom_buttons_y));
|
self.bottom_buttons.set_xy(Vector2(x_pos, bottom_buttons_y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ pub fn entry_point_searcher_icons() {
|
|||||||
let shape = id.create_shape(Vector2(icon::SIZE, icon::SIZE));
|
let shape = id.create_shape(Vector2(icon::SIZE, icon::SIZE));
|
||||||
shape.set_vivid_color(color::Rgba(0.243, 0.541, 0.160, 1.0).into());
|
shape.set_vivid_color(color::Rgba(0.243, 0.541, 0.160, 1.0).into());
|
||||||
shape.set_dull_color(color::Rgba(0.655, 0.788, 0.624, 1.0).into());
|
shape.set_dull_color(color::Rgba(0.655, 0.788, 0.624, 1.0).into());
|
||||||
shape.set_position_x(x);
|
shape.set_x(x);
|
||||||
x += 20.0;
|
x += 20.0;
|
||||||
world.add_child(&shape);
|
world.add_child(&shape);
|
||||||
mem::forget(shape);
|
mem::forget(shape);
|
||||||
|
@ -86,7 +86,7 @@ mod entry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_position_and_size(&self, pos: &Vector2, size: &Vector2) {
|
fn set_position_and_size(&self, pos: &Vector2, size: &Vector2) {
|
||||||
self.text.set_position_xy(*pos);
|
self.text.set_xy(*pos);
|
||||||
|
|
||||||
self.text.set_style_or_warn("left", format!("{}px", pos.x - size.x / 2.0));
|
self.text.set_style_or_warn("left", format!("{}px", pos.x - size.x / 2.0));
|
||||||
self.text.set_style_or_warn("top", format!("{}px", -pos.y - size.y / 2.0));
|
self.text.set_style_or_warn("top", format!("{}px", -pos.y - size.y / 2.0));
|
||||||
@ -205,10 +205,10 @@ impl<T: TextProvider> Model<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_size(&self, size: Vector2) {
|
fn set_size(&self, size: Vector2) {
|
||||||
self.scroll_bar_horizontal.set_position_y(-size.y / 2.0);
|
self.scroll_bar_horizontal.set_y(-size.y / 2.0);
|
||||||
self.scroll_bar_horizontal.set_length(size.x);
|
self.scroll_bar_horizontal.set_length(size.x);
|
||||||
|
|
||||||
self.scroll_bar_vertical.set_position_x(size.x / 2.0);
|
self.scroll_bar_vertical.set_x(size.x / 2.0);
|
||||||
self.scroll_bar_vertical.set_length(size.y);
|
self.scroll_bar_vertical.set_length(size.y);
|
||||||
|
|
||||||
self.clipping_div.set_size(size);
|
self.clipping_div.set_size(size);
|
||||||
|
@ -129,8 +129,8 @@ impl AddNodeButton {
|
|||||||
let screen = camera.screen();
|
let screen = camera.screen();
|
||||||
let x = -screen.width / 2.0 + margin + size / 2.0;
|
let x = -screen.width / 2.0 + margin + size / 2.0;
|
||||||
let y = -screen.height / 2.0 + margin + size / 2.0;
|
let y = -screen.height / 2.0 + margin + size / 2.0;
|
||||||
view.set_position_x(x.round());
|
view.set_x(x.round());
|
||||||
view.set_position_y(y.round());
|
view.set_y(y.round());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,8 +264,8 @@ impl BreadcrumbsModel {
|
|||||||
let gap_width = self.gap_width.get();
|
let gap_width = self.gap_width.get();
|
||||||
let project_name_width = self.project_name.width.value().round();
|
let project_name_width = self.project_name.width.value().round();
|
||||||
|
|
||||||
self.project_name.set_position_x(gap_width);
|
self.project_name.set_x(gap_width);
|
||||||
self.breadcrumbs_container.set_position_x(gap_width + project_name_width);
|
self.breadcrumbs_container.set_x(gap_width + project_name_width);
|
||||||
|
|
||||||
let width = gap_width + project_name_width + self.breadcrumbs_container_width();
|
let width = gap_width + project_name_width + self.breadcrumbs_container_width();
|
||||||
let background_width = width + 2.0 * BACKGROUND_PADDING;
|
let background_width = width + 2.0 * BACKGROUND_PADDING;
|
||||||
@ -274,8 +274,8 @@ impl BreadcrumbsModel {
|
|||||||
let width_with_shadow = background_width + MAGIC_SHADOW_MARGIN * 2.0;
|
let width_with_shadow = background_width + MAGIC_SHADOW_MARGIN * 2.0;
|
||||||
let height_with_shadow = background_height + MAGIC_SHADOW_MARGIN * 2.0;
|
let height_with_shadow = background_height + MAGIC_SHADOW_MARGIN * 2.0;
|
||||||
self.background.size.set(Vector2(width_with_shadow, height_with_shadow));
|
self.background.size.set(Vector2(width_with_shadow, height_with_shadow));
|
||||||
self.background.set_position_x(width / 2.0);
|
self.background.set_x(width / 2.0);
|
||||||
self.background.set_position_y(-HEIGHT / 2.0);
|
self.background.set_y(-HEIGHT / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_breadcrumb(&self, index: usize) -> Option<Breadcrumb> {
|
fn get_breadcrumb(&self, index: usize) -> Option<Breadcrumb> {
|
||||||
@ -352,7 +352,7 @@ impl BreadcrumbsModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug!("Pushing {} breadcrumb.", breadcrumb.info.method_pointer.name);
|
debug!("Pushing {} breadcrumb.", breadcrumb.info.method_pointer.name);
|
||||||
breadcrumb.set_position_x(self.breadcrumbs_container_width().round());
|
breadcrumb.set_x(self.breadcrumbs_container_width().round());
|
||||||
self.breadcrumbs_container.add_child(&breadcrumb);
|
self.breadcrumbs_container.add_child(&breadcrumb);
|
||||||
self.breadcrumbs.borrow_mut().push(breadcrumb);
|
self.breadcrumbs.borrow_mut().push(breadcrumb);
|
||||||
}
|
}
|
||||||
|
@ -341,8 +341,8 @@ impl BreadcrumbModel {
|
|||||||
self.label.set_property_default(color);
|
self.label.set_property_default(color);
|
||||||
self.label.set_property_default(text::formatting::Size::from(TEXT_SIZE));
|
self.label.set_property_default(text::formatting::Size::from(TEXT_SIZE));
|
||||||
self.label.set_single_line_mode(true);
|
self.label.set_single_line_mode(true);
|
||||||
self.label.set_position_x(ICON_RADIUS + ICON_RIGHT_MARGIN);
|
self.label.set_x(ICON_RADIUS + ICON_RIGHT_MARGIN);
|
||||||
self.label.set_position_y(TEXT_SIZE / 2.0);
|
self.label.set_y(TEXT_SIZE / 2.0);
|
||||||
self.label.set_content(&self.info.method_pointer.name);
|
self.label.set_content(&self.info.method_pointer.name);
|
||||||
|
|
||||||
let width = self.width();
|
let width = self.width();
|
||||||
@ -354,10 +354,10 @@ impl BreadcrumbModel {
|
|||||||
let separator_size = (SEPARATOR_SIZE + PADDING * 2.0).max(0.0);
|
let separator_size = (SEPARATOR_SIZE + PADDING * 2.0).max(0.0);
|
||||||
let icon_size = (ICON_SIZE + PADDING * 2.0).max(0.0);
|
let icon_size = (ICON_SIZE + PADDING * 2.0).max(0.0);
|
||||||
self.separator.size.set(Vector2::new(separator_size, separator_size));
|
self.separator.size.set(Vector2::new(separator_size, separator_size));
|
||||||
self.separator.set_position_x((offset - width / 2.0).round());
|
self.separator.set_x((offset - width / 2.0).round());
|
||||||
self.icon.size.set(Vector2::new(icon_size, icon_size));
|
self.icon.size.set(Vector2::new(icon_size, icon_size));
|
||||||
let x_position = offset + PADDING + ICON_SIZE / 2.0 + LEFT_MARGIN + ICON_LEFT_MARGIN;
|
let x_position = offset + PADDING + ICON_SIZE / 2.0 + LEFT_MARGIN + ICON_LEFT_MARGIN;
|
||||||
self.icon.set_position_x(x_position.round());
|
self.icon.set_x(x_position.round());
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -680,25 +680,25 @@ impl LayoutLine for front::line::View {
|
|||||||
let pos = Vector2(start.x, start.y + len / 2.0);
|
let pos = Vector2(start.x, start.y + len / 2.0);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
fn layout_h(&self, start: Vector2<f32>, len: f32) {
|
fn layout_h(&self, start: Vector2<f32>, len: f32) {
|
||||||
let pos = Vector2(start.x + len / 2.0, start.y);
|
let pos = Vector2(start.x + len / 2.0, start.y);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
fn layout_v_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
fn layout_v_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
||||||
let pos = Vector2(start.x, start.y + len / 2.0);
|
let pos = Vector2(start.x, start.y + len / 2.0);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
fn layout_h_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
fn layout_h_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
||||||
let pos = Vector2(start.x + len / 2.0, start.y);
|
let pos = Vector2(start.x + len / 2.0, start.y);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,25 +707,25 @@ impl LayoutLine for back::line::View {
|
|||||||
let pos = Vector2(start.x, start.y + len / 2.0);
|
let pos = Vector2(start.x, start.y + len / 2.0);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
fn layout_h(&self, start: Vector2<f32>, len: f32) {
|
fn layout_h(&self, start: Vector2<f32>, len: f32) {
|
||||||
let pos = Vector2(start.x + len / 2.0, start.y);
|
let pos = Vector2(start.x + len / 2.0, start.y);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs() + LINE_SIDES_OVERLAP);
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
fn layout_v_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
fn layout_v_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
||||||
let pos = Vector2(start.x, start.y + len / 2.0);
|
let pos = Vector2(start.x, start.y + len / 2.0);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
fn layout_h_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
fn layout_h_no_overlap(&self, start: Vector2<f32>, len: f32) {
|
||||||
let pos = Vector2(start.x + len / 2.0, start.y);
|
let pos = Vector2(start.x + len / 2.0, start.y);
|
||||||
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
let size = Vector2(LINE_SHAPE_WIDTH, len.abs());
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.set_position_xy(pos);
|
self.set_xy(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1398,7 +1398,7 @@ impl EdgeModelData {
|
|||||||
self.try_enable_focus_split(hover_position, hover_target, focus_part);
|
self.try_enable_focus_split(hover_position, hover_target, focus_part);
|
||||||
if let Ok(snap_data) = focus_split_result {
|
if let Ok(snap_data) = focus_split_result {
|
||||||
let joint_position = snap_data.position - self.display_object.position().xy();
|
let joint_position = snap_data.position - self.display_object.position().xy();
|
||||||
self.joint.set_position_xy(joint_position);
|
self.joint.set_xy(joint_position);
|
||||||
let joint_size = LINE_WIDTH + PADDING;
|
let joint_size = LINE_WIDTH + PADDING;
|
||||||
self.joint.size.set(Vector2(joint_size, joint_size));
|
self.joint.size.set(Vector2(joint_size, joint_size));
|
||||||
}
|
}
|
||||||
@ -1541,7 +1541,7 @@ impl EdgeModelData {
|
|||||||
bg.corner.angle.set(corner1_angle);
|
bg.corner.angle.set(corner1_angle);
|
||||||
bg.corner.radius.set(corner1_radius);
|
bg.corner.radius.set(corner1_radius);
|
||||||
bg.corner.pos.set(corner1);
|
bg.corner.pos.set(corner1);
|
||||||
bg.corner.set_position_xy(corner1);
|
bg.corner.set_xy(corner1);
|
||||||
if !fully_attached {
|
if !fully_attached {
|
||||||
bg.corner.dim.set(Vector2(node_half_width, source_node_half_height));
|
bg.corner.dim.set(Vector2(node_half_width, source_node_half_height));
|
||||||
fg.corner.size.set(corner1_size);
|
fg.corner.size.set(corner1_size);
|
||||||
@ -1550,7 +1550,7 @@ impl EdgeModelData {
|
|||||||
fg.corner.radius.set(corner1_radius);
|
fg.corner.radius.set(corner1_radius);
|
||||||
fg.corner.pos.set(corner1);
|
fg.corner.pos.set(corner1);
|
||||||
fg.corner.dim.set(Vector2(node_half_width, source_node_half_height));
|
fg.corner.dim.set(Vector2(node_half_width, source_node_half_height));
|
||||||
fg.corner.set_position_xy(corner1);
|
fg.corner.set_xy(corner1);
|
||||||
} else {
|
} else {
|
||||||
fg.corner.size.set(zero());
|
fg.corner.size.set(zero());
|
||||||
bg.corner.dim.set(Vector2(INFINITE, INFINITE));
|
bg.corner.dim.set(Vector2(INFINITE, INFINITE));
|
||||||
@ -1687,7 +1687,7 @@ impl EdgeModelData {
|
|||||||
bg.corner3.radius.set(corner3_radius);
|
bg.corner3.radius.set(corner3_radius);
|
||||||
bg.corner3.pos.set(corner3);
|
bg.corner3.pos.set(corner3);
|
||||||
bg.corner3.dim.set(Vector2(INFINITE, INFINITE));
|
bg.corner3.dim.set(Vector2(INFINITE, INFINITE));
|
||||||
bg.corner3.set_position_xy(corner3);
|
bg.corner3.set_xy(corner3);
|
||||||
} else {
|
} else {
|
||||||
bg.corner3.size.set(zero());
|
bg.corner3.size.set(zero());
|
||||||
fg.corner3.size.set(corner3_size);
|
fg.corner3.size.set(corner3_size);
|
||||||
@ -1696,7 +1696,7 @@ impl EdgeModelData {
|
|||||||
fg.corner3.radius.set(corner3_radius);
|
fg.corner3.radius.set(corner3_radius);
|
||||||
fg.corner3.pos.set(corner3);
|
fg.corner3.pos.set(corner3);
|
||||||
fg.corner3.dim.set(zero());
|
fg.corner3.dim.set(zero());
|
||||||
fg.corner3.set_position_xy(corner3);
|
fg.corner3.set_xy(corner3);
|
||||||
}
|
}
|
||||||
|
|
||||||
let corner2_x = corner1_target.x + corner_2_3_side * corner2_radius;
|
let corner2_x = corner1_target.x + corner_2_3_side * corner2_radius;
|
||||||
@ -1711,7 +1711,7 @@ impl EdgeModelData {
|
|||||||
bg.corner2.radius.set(corner2_radius);
|
bg.corner2.radius.set(corner2_radius);
|
||||||
bg.corner2.pos.set(corner2);
|
bg.corner2.pos.set(corner2);
|
||||||
bg.corner2.dim.set(Vector2(INFINITE, INFINITE));
|
bg.corner2.dim.set(Vector2(INFINITE, INFINITE));
|
||||||
bg.corner2.set_position_xy(corner2);
|
bg.corner2.set_xy(corner2);
|
||||||
} else {
|
} else {
|
||||||
bg.corner2.size.set(zero());
|
bg.corner2.size.set(zero());
|
||||||
fg.corner2.size.set(corner1_size);
|
fg.corner2.size.set(corner1_size);
|
||||||
@ -1720,7 +1720,7 @@ impl EdgeModelData {
|
|||||||
fg.corner2.radius.set(corner2_radius);
|
fg.corner2.radius.set(corner2_radius);
|
||||||
fg.corner2.pos.set(corner2);
|
fg.corner2.pos.set(corner2);
|
||||||
fg.corner2.dim.set(zero());
|
fg.corner2.dim.set(zero());
|
||||||
fg.corner2.set_position_xy(corner2);
|
fg.corner2.set_xy(corner2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1751,11 +1751,11 @@ impl EdgeModelData {
|
|||||||
if fully_attached {
|
if fully_attached {
|
||||||
fg.arrow.size.set(zero());
|
fg.arrow.size.set(zero());
|
||||||
bg.arrow.size.set(arrow_size);
|
bg.arrow.size.set(arrow_size);
|
||||||
bg.arrow.set_position_xy(arrow_pos);
|
bg.arrow.set_xy(arrow_pos);
|
||||||
} else {
|
} else {
|
||||||
bg.arrow.size.set(zero());
|
bg.arrow.size.set(zero());
|
||||||
fg.arrow.size.set(arrow_size);
|
fg.arrow.size.set(arrow_size);
|
||||||
fg.arrow.set_position_xy(arrow_pos);
|
fg.arrow.set_xy(arrow_pos);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bg.arrow.size.set(zero());
|
bg.arrow.size.set(zero());
|
||||||
|
@ -629,11 +629,11 @@ impl NodeModel {
|
|||||||
self.error_indicator.size.set(padded_size);
|
self.error_indicator.size.set(padded_size);
|
||||||
self.vcs_indicator.set_size(padded_size);
|
self.vcs_indicator.set_size(padded_size);
|
||||||
let x_offset_to_node_center = x_offset_to_node_center(width);
|
let x_offset_to_node_center = x_offset_to_node_center(width);
|
||||||
self.backdrop.set_position_x(x_offset_to_node_center);
|
self.backdrop.set_x(x_offset_to_node_center);
|
||||||
self.background.set_position_x(x_offset_to_node_center);
|
self.background.set_x(x_offset_to_node_center);
|
||||||
self.drag_area.set_position_x(x_offset_to_node_center);
|
self.drag_area.set_x(x_offset_to_node_center);
|
||||||
self.error_indicator.set_position_x(x_offset_to_node_center);
|
self.error_indicator.set_x(x_offset_to_node_center);
|
||||||
self.vcs_indicator.set_position_x(x_offset_to_node_center);
|
self.vcs_indicator.set_x(x_offset_to_node_center);
|
||||||
|
|
||||||
let action_bar_width = ACTION_BAR_WIDTH;
|
let action_bar_width = ACTION_BAR_WIDTH;
|
||||||
self.action_bar.mod_position(|t| {
|
self.action_bar.mod_position(|t| {
|
||||||
@ -642,8 +642,8 @@ impl NodeModel {
|
|||||||
self.action_bar.frp.set_size(Vector2::new(action_bar_width, ACTION_BAR_HEIGHT));
|
self.action_bar.frp.set_size(Vector2::new(action_bar_width, ACTION_BAR_HEIGHT));
|
||||||
|
|
||||||
let visualization_offset = visualization_offset(width);
|
let visualization_offset = visualization_offset(width);
|
||||||
self.error_visualization.set_position_xy(visualization_offset);
|
self.error_visualization.set_xy(visualization_offset);
|
||||||
self.visualization.set_position_xy(visualization_offset);
|
self.visualization.set_xy(visualization_offset);
|
||||||
|
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
@ -688,6 +688,7 @@ impl Node {
|
|||||||
let input = &frp.private.input;
|
let input = &frp.private.input;
|
||||||
let model = Rc::new(NodeModel::new(app, registry));
|
let model = Rc::new(NodeModel::new(app, registry));
|
||||||
let selection = Animation::<f32>::new(network);
|
let selection = Animation::<f32>::new(network);
|
||||||
|
let display_object = &model.display_object;
|
||||||
|
|
||||||
// TODO[ao] The comment color should be animated, but this is currently slow. Will be fixed
|
// TODO[ao] The comment color should be animated, but this is currently slow. Will be fixed
|
||||||
// in https://github.com/enso-org/ide/issues/1031
|
// in https://github.com/enso-org/ide/issues/1031
|
||||||
@ -696,12 +697,13 @@ impl Node {
|
|||||||
let style = StyleWatch::new(&app.display.default_scene.style_sheet);
|
let style = StyleWatch::new(&app.display.default_scene.style_sheet);
|
||||||
let style_frp = &model.style;
|
let style_frp = &model.style;
|
||||||
let action_bar = &model.action_bar.frp;
|
let action_bar = &model.action_bar.frp;
|
||||||
// Hook up the display object position updates to the node's FRP. Required to calculate the
|
|
||||||
// bounding box.
|
|
||||||
model.display_object.set_on_updated(f!((p) out.position.emit(p.position().xy())));
|
|
||||||
|
|
||||||
frp::extend! { network
|
frp::extend! { network
|
||||||
|
|
||||||
|
// Hook up the display object position updates to the node's FRP. Required to calculate
|
||||||
|
// the bounding box.
|
||||||
|
out.position <+ display_object.on_updated.map(f_!(display_object.position().xy()));
|
||||||
|
|
||||||
// === Hover ===
|
// === Hover ===
|
||||||
// The hover discovery of a node is an interesting process. First, we discover whether
|
// The hover discovery of a node is an interesting process. First, we discover whether
|
||||||
// ths user hovers the drag area. The input port manager merges this information with
|
// ths user hovers the drag area. The input port manager merges this information with
|
||||||
@ -758,9 +760,9 @@ impl Node {
|
|||||||
eval comment_color ((value) model.comment.set_property(.., color::Rgba::from(value)));
|
eval comment_color ((value) model.comment.set_property(.., color::Rgba::from(value)));
|
||||||
|
|
||||||
eval model.comment.width ([model](width)
|
eval model.comment.width ([model](width)
|
||||||
model.comment.set_position_x(-*width - COMMENT_MARGIN));
|
model.comment.set_x(-*width - COMMENT_MARGIN));
|
||||||
eval model.comment.height ([model](height)
|
eval model.comment.height ([model](height)
|
||||||
model.comment.set_position_y(*height / 2.0));
|
model.comment.set_y(*height / 2.0));
|
||||||
model.comment.set_content <+ input.set_comment;
|
model.comment.set_content <+ input.set_comment;
|
||||||
out.comment <+ model.comment.content.map(|text| text.to_im_string());
|
out.comment <+ model.comment.content.map(|text| text.to_im_string());
|
||||||
|
|
||||||
|
@ -192,12 +192,12 @@ impl Model {
|
|||||||
self.hover_area.size.set(hover_ara_size);
|
self.hover_area.size.set(hover_ara_size);
|
||||||
let center_offset = -size.x / 2.0 + hover_ara_size.x / 2.0;
|
let center_offset = -size.x / 2.0 + hover_ara_size.x / 2.0;
|
||||||
let padding_offset = -0.5 * hover_padding * button_width - HOVER_EXTENSION_X / 2.0;
|
let padding_offset = -0.5 * hover_padding * button_width - HOVER_EXTENSION_X / 2.0;
|
||||||
self.hover_area.set_position_x(center_offset + padding_offset);
|
self.hover_area.set_x(center_offset + padding_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_size(&self, size: Vector2) {
|
fn set_size(&self, size: Vector2) {
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.icons.set_position_x(-size.x / 2.0);
|
self.icons.set_x(-size.x / 2.0);
|
||||||
|
|
||||||
// Note: Disabled for https://github.com/enso-org/ide/issues/1397
|
// Note: Disabled for https://github.com/enso-org/ide/issues/1397
|
||||||
// Should be re-enabled when https://github.com/enso-org/ide/issues/862 as been implemented.
|
// Should be re-enabled when https://github.com/enso-org/ide/issues/862 as been implemented.
|
||||||
|
@ -230,8 +230,8 @@ impl Model {
|
|||||||
self.label.remove_all_cursors();
|
self.label.remove_all_cursors();
|
||||||
|
|
||||||
let origin = Vector2(TEXT_OFFSET, 0.0);
|
let origin = Vector2(TEXT_OFFSET, 0.0);
|
||||||
self.ports.set_position_xy(origin);
|
self.ports.set_xy(origin);
|
||||||
self.label.set_position_xy(origin);
|
self.label.set_xy(origin);
|
||||||
self.label.mod_position(|t| t.y += TEXT_SIZE / 2.0);
|
self.label.mod_position(|t| t.y += TEXT_SIZE / 2.0);
|
||||||
|
|
||||||
self
|
self
|
||||||
|
@ -239,7 +239,7 @@ impl Model {
|
|||||||
fn set_label(&self, content: impl Into<String>) {
|
fn set_label(&self, content: impl Into<String>) {
|
||||||
let str = if ARGS.node_labels.unwrap_or(true) { content.into() } else { default() };
|
let str = if ARGS.node_labels.unwrap_or(true) { content.into() } else { default() };
|
||||||
self.label.set_content(str);
|
self.label.set_content(str);
|
||||||
self.label.set_position_x(-self.label.width.value() - input::area::TEXT_OFFSET);
|
self.label.set_x(-self.label.width.value() - input::area::TEXT_OFFSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update expression type for the particular `ast::Id`.
|
/// Update expression type for the particular `ast::Id`.
|
||||||
@ -329,7 +329,7 @@ impl Model {
|
|||||||
|
|
||||||
#[profile(Debug)]
|
#[profile(Debug)]
|
||||||
fn set_size(&self, size: Vector2) {
|
fn set_size(&self, size: Vector2) {
|
||||||
self.ports.set_position_x(size.x / 2.0);
|
self.ports.set_x(size.x / 2.0);
|
||||||
self.traverse_borrowed_expression_mut(|is_a_port, node, _| {
|
self.traverse_borrowed_expression_mut(|is_a_port, node, _| {
|
||||||
if is_a_port {
|
if is_a_port {
|
||||||
node.payload_mut().set_size(size)
|
node.payload_mut().set_size(size)
|
||||||
|
@ -485,7 +485,7 @@ impl Model {
|
|||||||
let type_label = app.new_view::<text::Text>();
|
let type_label = app.new_view::<text::Text>();
|
||||||
let offset_y =
|
let offset_y =
|
||||||
styles.get_number(ensogl_hardcoded_theme::graph_editor::node::type_label::offset_y);
|
styles.get_number(ensogl_hardcoded_theme::graph_editor::node::type_label::offset_y);
|
||||||
type_label.set_position_y(offset_y);
|
type_label.set_y(offset_y);
|
||||||
self.type_label = Some(type_label.clone());
|
self.type_label = Some(type_label.clone());
|
||||||
|
|
||||||
let display_object = display::object::Instance::new();
|
let display_object = display::object::Instance::new();
|
||||||
@ -549,7 +549,7 @@ impl Model {
|
|||||||
let label_center_x = port_center_x;
|
let label_center_x = port_center_x;
|
||||||
label_center_x - type_label_width / 2.0
|
label_center_x - type_label_width / 2.0
|
||||||
}));
|
}));
|
||||||
eval set_type_label_x ((&t) type_label.set_position_x(t));
|
eval set_type_label_x ((&t) type_label.set_x(t));
|
||||||
eval frp.set_size_multiplier ((t) shape.set_size_multiplier(*t));
|
eval frp.set_size_multiplier ((t) shape.set_size_multiplier(*t));
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ impl ProfilingLabel {
|
|||||||
|
|
||||||
let label = text::Text::new(app);
|
let label = text::Text::new(app);
|
||||||
root.add_child(&label);
|
root.add_child(&label);
|
||||||
label.set_position_y(crate::component::node::input::area::TEXT_SIZE / 2.0);
|
label.set_y(crate::component::node::input::area::TEXT_SIZE / 2.0);
|
||||||
scene.layers.main.remove(&label);
|
scene.layers.main.remove(&label);
|
||||||
label.add_to_scene_layer(&scene.layers.label);
|
label.add_to_scene_layer(&scene.layers.label);
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ impl ProfilingLabel {
|
|||||||
// === Position ===
|
// === Position ===
|
||||||
|
|
||||||
let x_offset = crate::component::node::input::area::TEXT_OFFSET;
|
let x_offset = crate::component::node::input::area::TEXT_OFFSET;
|
||||||
eval label.width((&width) label.set_position_x(-width-x_offset));
|
eval label.width((&width) label.set_x(-width-x_offset));
|
||||||
|
|
||||||
|
|
||||||
// === Content ===
|
// === Content ===
|
||||||
|
@ -167,8 +167,8 @@ impl Button {
|
|||||||
|
|
||||||
eval scene.frp.camera_changed([button,scene](_) {
|
eval scene.frp.camera_changed([button,scene](_) {
|
||||||
let screen = scene.camera().screen();
|
let screen = scene.camera().screen();
|
||||||
button.set_position_x(screen.width/2.0 - 16.0);
|
button.set_x(screen.width/2.0 - 16.0);
|
||||||
button.set_position_y(screen.height/2.0 - 16.0);
|
button.set_y(screen.height/2.0 - 16.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -414,7 +414,7 @@ impl ContainerModel {
|
|||||||
self.action_bar.frp.set_size.emit(action_bar_size);
|
self.action_bar.frp.set_size.emit(action_bar_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.action_bar.set_position_y((size.y - ACTION_BAR_HEIGHT) / 2.0);
|
self.action_bar.set_y((size.y - ACTION_BAR_HEIGHT) / 2.0);
|
||||||
|
|
||||||
if let Some(viz) = &*self.visualization.borrow() {
|
if let Some(viz) = &*self.visualization.borrow() {
|
||||||
viz.set_size.emit(size);
|
viz.set_size.emit(size);
|
||||||
@ -649,9 +649,9 @@ impl Container {
|
|||||||
// === Action bar actions ===
|
// === Action bar actions ===
|
||||||
|
|
||||||
frp::extend! { network
|
frp::extend! { network
|
||||||
eval_ action_bar.on_container_reset_position(model.drag_root.set_position_xy(Vector2::zero()));
|
eval_ action_bar.on_container_reset_position(model.drag_root.set_xy(Vector2::zero()));
|
||||||
drag_action <- app.cursor.frp.scene_position_delta.gate(&action_bar.container_drag_state);
|
drag_action <- app.cursor.frp.scene_position_delta.gate(&action_bar.container_drag_state);
|
||||||
eval drag_action ((mouse) model.drag_root.mod_position_xy(|pos| pos - mouse.xy()));
|
eval drag_action ((mouse) model.drag_root.mod_xy(|pos| pos - mouse.xy()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME[mm]: If we set the size right here, we will see spurious shapes in some
|
// FIXME[mm]: If we set the size right here, we will see spurious shapes in some
|
||||||
|
@ -198,7 +198,7 @@ impl Icons {
|
|||||||
|
|
||||||
fn set_size(&self, size: Vector2) {
|
fn set_size(&self, size: Vector2) {
|
||||||
self.size.set(size);
|
self.size.set(size);
|
||||||
self.icon_root.set_position_x(-size.x / 2.0);
|
self.icon_root.set_x(-size.x / 2.0);
|
||||||
self.place_shape_in_slot(&self.drag_icon, 0);
|
self.place_shape_in_slot(&self.drag_icon, 0);
|
||||||
self.place_shape_in_slot(&self.reset_position_icon, 1);
|
self.place_shape_in_slot(&self.reset_position_icon, 1);
|
||||||
}
|
}
|
||||||
@ -298,7 +298,7 @@ impl Model {
|
|||||||
let right_padding = height / 2.0;
|
let right_padding = height / 2.0;
|
||||||
self.visualization_chooser.frp.set_icon_size(Vector2::new(height, height));
|
self.visualization_chooser.frp.set_icon_size(Vector2::new(height, height));
|
||||||
self.visualization_chooser.frp.set_icon_padding(Vector2::new(height / 3.0, height / 3.0));
|
self.visualization_chooser.frp.set_icon_padding(Vector2::new(height / 3.0, height / 3.0));
|
||||||
self.visualization_chooser.set_position_x((width / 2.0) - right_padding);
|
self.visualization_chooser.set_x((width / 2.0) - right_padding);
|
||||||
self.visualization_chooser.frp.set_menu_offset_y(MENU_GAP);
|
self.visualization_chooser.frp.set_menu_offset_y(MENU_GAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1468,7 +1468,7 @@ impl GraphEditorModelWithNetwork {
|
|||||||
) -> (NodeId, Option<NodeSource>, bool) {
|
) -> (NodeId, Option<NodeSource>, bool) {
|
||||||
let position = new_node_position::new_node_position(self, way, mouse_position);
|
let position = new_node_position::new_node_position(self, way, mouse_position);
|
||||||
let node = self.new_node(ctx);
|
let node = self.new_node(ctx);
|
||||||
node.set_position_xy(position);
|
node.set_xy(position);
|
||||||
let should_edit = !matches!(way, WayOfCreatingNode::AddNodeEvent);
|
let should_edit = !matches!(way, WayOfCreatingNode::AddNodeEvent);
|
||||||
if should_edit {
|
if should_edit {
|
||||||
node.view.set_expression(node::Expression::default());
|
node.view.set_expression(node::Expression::default());
|
||||||
@ -1741,8 +1741,8 @@ impl GraphEditorModel {
|
|||||||
self.add_child(&self.breadcrumbs);
|
self.add_child(&self.breadcrumbs);
|
||||||
let x_offset = MACOS_TRAFFIC_LIGHTS_SIDE_OFFSET;
|
let x_offset = MACOS_TRAFFIC_LIGHTS_SIDE_OFFSET;
|
||||||
let y_offset = MACOS_TRAFFIC_LIGHTS_VERTICAL_CENTER + component::breadcrumbs::HEIGHT / 2.0;
|
let y_offset = MACOS_TRAFFIC_LIGHTS_VERTICAL_CENTER + component::breadcrumbs::HEIGHT / 2.0;
|
||||||
self.breadcrumbs.set_position_x(x_offset);
|
self.breadcrumbs.set_x(x_offset);
|
||||||
self.breadcrumbs.set_position_y(y_offset);
|
self.breadcrumbs.set_y(y_offset);
|
||||||
self.breadcrumbs.gap_width(traffic_lights_gap_width());
|
self.breadcrumbs.gap_width(traffic_lights_gap_width());
|
||||||
self.scene().add_child(&self.tooltip);
|
self.scene().add_child(&self.tooltip);
|
||||||
self.add_child(&self.profiling_button);
|
self.add_child(&self.profiling_button);
|
||||||
@ -3877,7 +3877,7 @@ mod tests {
|
|||||||
camera_pos: Vector2,
|
camera_pos: Vector2,
|
||||||
) {
|
) {
|
||||||
let camera = &scene.camera();
|
let camera = &scene.camera();
|
||||||
camera.set_position_xy(camera_pos);
|
camera.set_xy(camera_pos);
|
||||||
camera.update(scene);
|
camera.update(scene);
|
||||||
click_add_node_button(editor);
|
click_add_node_button(editor);
|
||||||
}
|
}
|
||||||
@ -3941,12 +3941,12 @@ mod tests {
|
|||||||
// Create 2nd node below the 1st one and move it slightly to the right.
|
// Create 2nd node below the 1st one and move it slightly to the right.
|
||||||
graph_editor.nodes().select(node_1_id);
|
graph_editor.nodes().select(node_1_id);
|
||||||
let (node_2_id, node_2) = graph_editor.add_node_by(&press_add_node_shortcut);
|
let (node_2_id, node_2) = graph_editor.add_node_by(&press_add_node_shortcut);
|
||||||
node_2.mod_position_x(|x| x + 16.0);
|
node_2.mod_x(|x| x + 16.0);
|
||||||
|
|
||||||
// Create 3rd node below the 2nd one and move it slightly down and far to the right.
|
// Create 3rd node below the 2nd one and move it slightly down and far to the right.
|
||||||
graph_editor.nodes().select(node_2_id);
|
graph_editor.nodes().select(node_2_id);
|
||||||
let (_, node_3) = graph_editor.add_node_by(&press_add_node_shortcut);
|
let (_, node_3) = graph_editor.add_node_by(&press_add_node_shortcut);
|
||||||
node_2.mod_position_xy(|pos| pos + Vector2(800.0, -7.0));
|
node_2.mod_xy(|pos| pos + Vector2(800.0, -7.0));
|
||||||
|
|
||||||
// Create 4th node by clicking (+) button when camera is roughly centered at the 1st node.
|
// Create 4th node by clicking (+) button when camera is roughly centered at the 1st node.
|
||||||
let small_displacement = Vector2(8.0, 9.0);
|
let small_displacement = Vector2(8.0, 9.0);
|
||||||
@ -3987,7 +3987,7 @@ mod tests {
|
|||||||
fn add_node_by_api_at_pos(&self, position: Vector2) -> (NodeId, Node) {
|
fn add_node_by_api_at_pos(&self, position: Vector2) -> (NodeId, Node) {
|
||||||
let (node_id, node) = self.add_node_by_api();
|
let (node_id, node) = self.add_node_by_api();
|
||||||
self.stop_editing();
|
self.stop_editing();
|
||||||
node.set_position_xy(position);
|
node.set_xy(position);
|
||||||
(node_id, node)
|
(node_id, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ impl View {
|
|||||||
let model = app.new_view::<text::Text>();
|
let model = app.new_view::<text::Text>();
|
||||||
let height_fraction = DEPRECATED_Animation::<f32>::new(network);
|
let height_fraction = DEPRECATED_Animation::<f32>::new(network);
|
||||||
|
|
||||||
model.set_position_x(PADDING_LEFT);
|
model.set_x(PADDING_LEFT);
|
||||||
scene.layers.main.remove(&model);
|
scene.layers.main.remove(&model);
|
||||||
model.add_to_scene_layer(&scene.layers.panel_text);
|
model.add_to_scene_layer(&scene.layers.panel_text);
|
||||||
// TODO[ao]: To have code editor usable we treat it as constantly mouse-hovered, but this
|
// TODO[ao]: To have code editor usable we treat it as constantly mouse-hovered, but this
|
||||||
@ -108,7 +108,7 @@ impl View {
|
|||||||
let y = -scene_size.height / 2.0 + height;
|
let y = -scene_size.height / 2.0 + height;
|
||||||
Vector2(x,y)
|
Vector2(x,y)
|
||||||
});
|
});
|
||||||
eval position ((pos) model.set_position_xy(*pos));
|
eval position ((pos) model.set_xy(*pos));
|
||||||
|
|
||||||
let color = styles.get_color(ensogl_hardcoded_theme::code::syntax::base);
|
let color = styles.get_color(ensogl_hardcoded_theme::code::syntax::base);
|
||||||
eval color ((color) model.set_property_default(color));
|
eval color ((color) model.set_property_default(color));
|
||||||
|
@ -125,8 +125,8 @@ impl component::Frp<Model> for Frp {
|
|||||||
list_position_x <-
|
list_position_x <-
|
||||||
all_with3(&size, &list_panel.size, &snap, |sz, list_sz, snap| list_sz.x / 2.0 - sz.x / 2.0 + snap.x);
|
all_with3(&size, &list_panel.size, &snap, |sz, list_sz, snap| list_sz.x / 2.0 - sz.x / 2.0 + snap.x);
|
||||||
doc_position_x <- all_with3(&size, &doc_size, &snap, |sz, doc_sz, snap| sz.x / 2.0 - doc_sz.x / 2.0 + snap.x);
|
doc_position_x <- all_with3(&size, &doc_size, &snap, |sz, doc_sz, snap| sz.x / 2.0 - doc_sz.x / 2.0 + snap.x);
|
||||||
eval list_position_x ((x) model.list.set_position_x(*x));
|
eval list_position_x ((x) model.list.set_x(*x));
|
||||||
eval doc_position_x ((x) model.documentation.set_position_x(*x));
|
eval doc_position_x ((x) model.documentation.set_x(*x));
|
||||||
|
|
||||||
model.list.input.show <+ input.show;
|
model.list.input.show <+ input.show;
|
||||||
model.list.input.hide <+ input.hide;
|
model.list.input.hide <+ input.hide;
|
||||||
|
@ -8,7 +8,6 @@ use enso_frp as frp;
|
|||||||
use ensogl::animation::delayed::DelayedAnimation;
|
use ensogl::animation::delayed::DelayedAnimation;
|
||||||
use ensogl::application::Application;
|
use ensogl::application::Application;
|
||||||
use ensogl::display;
|
use ensogl::display;
|
||||||
use ensogl::display::scene::Scene;
|
|
||||||
use ensogl::Animation;
|
use ensogl::Animation;
|
||||||
use ensogl_component::label::Label;
|
use ensogl_component::label::Label;
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ pub struct PopupLabel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for PopupLabel {
|
impl display::Object for PopupLabel {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
self.label.display_object()
|
self.label.display_object()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,7 +179,7 @@ impl View {
|
|||||||
let half_height = scene_size.height / 2.0;
|
let half_height = scene_size.height / 2.0;
|
||||||
let label_height = model.label_height();
|
let label_height = model.label_height();
|
||||||
let pos_y = half_height - LABEL_PADDING_TOP - label_height / 2.0;
|
let pos_y = half_height - LABEL_PADDING_TOP - label_height / 2.0;
|
||||||
model.display_object.set_position_y(pos_y);
|
model.display_object.set_y(pos_y);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
eval_ frp.enabled(model.show_enabled_label());
|
eval_ frp.enabled(model.show_enabled_label());
|
||||||
@ -198,7 +197,7 @@ impl View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for View {
|
impl display::Object for View {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.model.display_object
|
&self.model.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,8 +67,8 @@ impl OpenDialog {
|
|||||||
project_list_x <- all_with(&width,&project_list_width,|w,pw| - *w / 2.0 + *pw / 2.0);
|
project_list_x <- all_with(&width,&project_list_width,|w,pw| - *w / 2.0 + *pw / 2.0);
|
||||||
file_browser_x <- all_with(&width,&file_browser_width, |w,fw| w / 2.0 - *fw / 2.0);
|
file_browser_x <- all_with(&width,&file_browser_width, |w,fw| w / 2.0 - *fw / 2.0);
|
||||||
|
|
||||||
eval project_list_x ((x) project_list.set_position_x(*x));
|
eval project_list_x ((x) project_list.set_x(*x));
|
||||||
eval file_browser_x ((x) file_browser.set_position_x(*x));
|
eval file_browser_x ((x) file_browser.set_x(*x));
|
||||||
}
|
}
|
||||||
init.emit(());
|
init.emit(());
|
||||||
Self { logger, network, project_list, file_browser, display_object, style_watch }
|
Self { logger, network, project_list, file_browser, display_object, style_watch }
|
||||||
|
@ -130,8 +130,8 @@ impl ProjectList {
|
|||||||
|
|
||||||
eval size ((size) background.size.set(*size));
|
eval size ((size) background.size.set(*size));
|
||||||
eval list_size ((size) list.resize(*size));
|
eval list_size ((size) list.resize(*size));
|
||||||
eval list_y ((y) list.set_position_y(*y));
|
eval list_y ((y) list.set_y(*y));
|
||||||
eval caption_xy ((xy) caption.set_position_xy(*xy));
|
eval caption_xy ((xy) caption.set_xy(*xy));
|
||||||
eval color ((color) caption.set_property_default(color));
|
eval color ((color) caption.set_property_default(color));
|
||||||
eval label_size ((size) caption.set_property_default(text::Size(*size)));
|
eval label_size ((size) caption.set_property_default(text::Size(*size)));
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,6 @@ use ensogl::application::shortcut;
|
|||||||
use ensogl::application::Application;
|
use ensogl::application::Application;
|
||||||
use ensogl::display;
|
use ensogl::display;
|
||||||
use ensogl::display::navigation::navigator::Navigator;
|
use ensogl::display::navigation::navigator::Navigator;
|
||||||
use ensogl::display::Scene;
|
|
||||||
use ensogl::system::web;
|
use ensogl::system::web;
|
||||||
use ensogl::system::web::dom;
|
use ensogl::system::web::dom;
|
||||||
use ensogl::Animation;
|
use ensogl::Animation;
|
||||||
@ -223,7 +222,7 @@ impl SearcherVariant {
|
|||||||
SearcherVariant::ComponentBrowser(view) => {
|
SearcherVariant::ComponentBrowser(view) => {
|
||||||
frp::extend! {network
|
frp::extend! {network
|
||||||
cb_position <- all_with(anchor, &view.expression_input_position, |anchor, pos| anchor - pos);
|
cb_position <- all_with(anchor, &view.expression_input_position, |anchor, pos| anchor - pos);
|
||||||
eval cb_position ((pos) view.set_position_xy(*pos));
|
eval cb_position ((pos) view.set_xy(*pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SearcherVariant::OldNodeSearcher(view) => {
|
SearcherVariant::OldNodeSearcher(view) => {
|
||||||
@ -233,7 +232,7 @@ impl SearcherVariant {
|
|||||||
let y = anchor.y - node::HEIGHT / 2.0 - size.y / 2.0;
|
let y = anchor.y - node::HEIGHT / 2.0 - size.y / 2.0;
|
||||||
Vector2(x, y)
|
Vector2(x, y)
|
||||||
});
|
});
|
||||||
eval searcher_pos ((pos) view.set_position_xy(*pos));
|
eval searcher_pos ((pos) view.set_xy(*pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,7 +240,7 @@ impl SearcherVariant {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for SearcherVariant {
|
impl display::Object for SearcherVariant {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
match self {
|
match self {
|
||||||
SearcherVariant::ComponentBrowser(view) => view.display_object(),
|
SearcherVariant::ComponentBrowser(view) => view.display_object(),
|
||||||
SearcherVariant::OldNodeSearcher(view) => view.display_object(),
|
SearcherVariant::OldNodeSearcher(view) => view.display_object(),
|
||||||
@ -391,7 +390,7 @@ impl Model {
|
|||||||
// Top buttons must always stay in top-left corner.
|
// Top buttons must always stay in top-left corner.
|
||||||
if let Some(window_control_buttons) = &*self.window_control_buttons {
|
if let Some(window_control_buttons) = &*self.window_control_buttons {
|
||||||
let pos = Vector2(-shape.width, shape.height) / 2.0;
|
let pos = Vector2(-shape.width, shape.height) / 2.0;
|
||||||
window_control_buttons.set_position_xy(pos);
|
window_control_buttons.set_xy(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,7 +551,7 @@ impl View {
|
|||||||
let move_to_edited_node = searcher_pos * (1.0 - zoom);
|
let move_to_edited_node = searcher_pos * (1.0 - zoom);
|
||||||
preserve_zoom + move_to_edited_node
|
preserve_zoom + move_to_edited_node
|
||||||
});
|
});
|
||||||
eval searcher_cam_pos ((pos) searcher_cam.set_position_xy(*pos));
|
eval searcher_cam_pos ((pos) searcher_cam.set_xy(*pos));
|
||||||
|
|
||||||
eval searcher.is_visible ([model](is_visible) {
|
eval searcher.is_visible ([model](is_visible) {
|
||||||
let is_attached = model.searcher.has_parent();
|
let is_attached = model.searcher.has_parent();
|
||||||
@ -737,7 +736,7 @@ impl View {
|
|||||||
);
|
);
|
||||||
_eval <- all_with3(&model.prompt.width,&prompt_size,&prompt_bg_padding,
|
_eval <- all_with3(&model.prompt.width,&prompt_size,&prompt_bg_padding,
|
||||||
f!([model](width,size,padding) {
|
f!([model](width,size,padding) {
|
||||||
model.prompt.set_position_x(- *width / 2.0);
|
model.prompt.set_x(- *width / 2.0);
|
||||||
model.prompt_background.size.set(Vector2(*width + padding, *size + padding));
|
model.prompt_background.size.set(Vector2(*width + padding, *size + padding));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -135,10 +135,10 @@ impl Model {
|
|||||||
let action_list_gap_path = ensogl_hardcoded_theme::application::searcher::action_list_gap;
|
let action_list_gap_path = ensogl_hardcoded_theme::application::searcher::action_list_gap;
|
||||||
let action_list_gap = style.get_number_or(action_list_gap_path, 0.0);
|
let action_list_gap = style.get_number_or(action_list_gap_path, 0.0);
|
||||||
list.set_label_layer(&scene.layers.node_searcher_text);
|
list.set_label_layer(&scene.layers.node_searcher_text);
|
||||||
list.set_position_y(-action_list_gap);
|
list.set_y(-action_list_gap);
|
||||||
list.set_position_x(ACTION_LIST_X);
|
list.set_x(ACTION_LIST_X);
|
||||||
documentation.set_position_x(DOCUMENTATION_X);
|
documentation.set_x(DOCUMENTATION_X);
|
||||||
documentation.set_position_y(-action_list_gap);
|
documentation.set_y(-action_list_gap);
|
||||||
Self { app, logger, display_object, list, documentation, doc_provider }
|
Self { app, logger, display_object, list, documentation, doc_provider }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@ use ensogl::application::Application;
|
|||||||
use ensogl::display;
|
use ensogl::display;
|
||||||
use ensogl::display::camera::Camera2d;
|
use ensogl::display::camera::Camera2d;
|
||||||
use ensogl::display::style;
|
use ensogl::display::style;
|
||||||
use ensogl::display::Scene;
|
|
||||||
use ensogl_component::shadow;
|
use ensogl_component::shadow;
|
||||||
use ensogl_hardcoded_theme as theme;
|
use ensogl_hardcoded_theme as theme;
|
||||||
use ensogl_text as text;
|
use ensogl_text as text;
|
||||||
@ -209,13 +208,13 @@ impl Model {
|
|||||||
fn camera_changed(&self) {
|
fn camera_changed(&self) {
|
||||||
let screen = self.camera.screen();
|
let screen = self.camera.screen();
|
||||||
let y = screen.height / 2.0 - MARGIN;
|
let y = screen.height / 2.0 - MARGIN;
|
||||||
self.root.set_position_y(y.round());
|
self.root.set_y(y.round());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_layout(&self) {
|
fn update_layout(&self) {
|
||||||
let label_width = self.label.width.value();
|
let label_width = self.label.width.value();
|
||||||
self.label.set_position_x(-label_width / 2.0);
|
self.label.set_x(-label_width / 2.0);
|
||||||
self.label.set_position_y(-HEIGHT / 2.0 + TEXT_SIZE / 2.0);
|
self.label.set_y(-HEIGHT / 2.0 + TEXT_SIZE / 2.0);
|
||||||
|
|
||||||
let bg_width = if label_width > 0.0 {
|
let bg_width = if label_width > 0.0 {
|
||||||
label_width + 2.0 * PADDING + 2.0 * MAGIC_SHADOW_MARGIN
|
label_width + 2.0 * PADDING + 2.0 * MAGIC_SHADOW_MARGIN
|
||||||
@ -224,7 +223,7 @@ impl Model {
|
|||||||
};
|
};
|
||||||
let bg_height = HEIGHT + 2.0 * MAGIC_SHADOW_MARGIN;
|
let bg_height = HEIGHT + 2.0 * MAGIC_SHADOW_MARGIN;
|
||||||
self.background.size.set(Vector2(bg_width, bg_height));
|
self.background.size.set(Vector2(bg_width, bg_height));
|
||||||
self.background.set_position_y(-HEIGHT / 2.0);
|
self.background.set_y(-HEIGHT / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_event(&self, label: &event::Label) -> event::Id {
|
fn add_event(&self, label: &event::Label) -> event::Id {
|
||||||
@ -350,7 +349,7 @@ impl View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for View {
|
impl display::Object for View {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.model.display_object
|
&self.model.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,16 +176,16 @@ impl Model {
|
|||||||
let padding_offset = Vector2(padding_left, -padding_top);
|
let padding_offset = Vector2(padding_left, -padding_top);
|
||||||
let origin_offset = |size: Vector2| Vector2(size.x / 2.0, -size.y / 2.0);
|
let origin_offset = |size: Vector2| Vector2(size.x / 2.0, -size.y / 2.0);
|
||||||
|
|
||||||
self.close.set_position_xy(padding_offset + origin_offset(close_size));
|
self.close.set_xy(padding_offset + origin_offset(close_size));
|
||||||
let fullscreen_x = padding_left + close_size.x + spacing;
|
let fullscreen_x = padding_left + close_size.x + spacing;
|
||||||
self.fullscreen
|
self.fullscreen
|
||||||
.set_position_xy(Vector2(fullscreen_x, -padding_top) + origin_offset(fullscreen_size));
|
.set_xy(Vector2(fullscreen_x, -padding_top) + origin_offset(fullscreen_size));
|
||||||
|
|
||||||
let width = fullscreen_x + fullscreen_size.x + padding_right;
|
let width = fullscreen_x + fullscreen_size.x + padding_right;
|
||||||
let height = padding_top + max(close_size.y, fullscreen_size.y) + padding_bottom;
|
let height = padding_top + max(close_size.y, fullscreen_size.y) + padding_bottom;
|
||||||
|
|
||||||
let size = Vector2(width, height);
|
let size = Vector2(width, height);
|
||||||
self.shape.set_position_xy(Vector2(size.x, -size.y) / 2.0);
|
self.shape.set_xy(Vector2(size.x, -size.y) / 2.0);
|
||||||
self.shape.size.set(size);
|
self.shape.size.set(size);
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ async fn adding_node_with_add_node_button() {
|
|||||||
|
|
||||||
// If there is a free space, the new node is created in the center of screen.
|
// If there is a free space, the new node is created in the center of screen.
|
||||||
let camera = scene.layers.main.camera();
|
let camera = scene.layers.main.camera();
|
||||||
camera.mod_position_xy(|pos| pos + Vector2(1000.0, 1000.0));
|
camera.mod_xy(|pos| pos + Vector2(1000.0, 1000.0));
|
||||||
wait_a_frame().await;
|
wait_a_frame().await;
|
||||||
graph_editor.nodes().deselect_all();
|
graph_editor.nodes().deselect_all();
|
||||||
let (node_id, node_source, _) = add_node_with_add_node_button(&graph_editor, "1").await;
|
let (node_id, node_source, _) = add_node_with_add_node_button(&graph_editor, "1").await;
|
||||||
|
@ -265,24 +265,24 @@ impl DropDownMenu {
|
|||||||
resize_menu <- all(model.selection_menu.size,frp.input.set_icon_size,frp.input.set_menu_offset_y);
|
resize_menu <- all(model.selection_menu.size,frp.input.set_icon_size,frp.input.set_menu_offset_y);
|
||||||
eval resize_menu (((menu_size,icon_size,menu_offset_y)) {
|
eval resize_menu (((menu_size,icon_size,menu_offset_y)) {
|
||||||
// Align the top of the menu to the bottom of the icon.
|
// Align the top of the menu to the bottom of the icon.
|
||||||
model.selection_menu.set_position_y(-menu_size.y/2.0-icon_size.y/2.0-menu_offset_y);
|
model.selection_menu.set_y(-menu_size.y/2.0-icon_size.y/2.0-menu_offset_y);
|
||||||
// Align the right of the menu to the right of the icon.
|
// Align the right of the menu to the right of the icon.
|
||||||
let offfset_y = -menu_size.x/2.0+icon_size.x/2.0-list_view::SHADOW_PX/2.0;
|
let offfset_y = -menu_size.x/2.0+icon_size.x/2.0-list_view::SHADOW_PX/2.0;
|
||||||
model.selection_menu.set_position_x(offfset_y);
|
model.selection_menu.set_x(offfset_y);
|
||||||
});
|
});
|
||||||
|
|
||||||
label_position <- all(model.label.frp.width,frp.input.set_icon_size);
|
label_position <- all(model.label.frp.width,frp.input.set_icon_size);
|
||||||
eval label_position (((text_width,icon_size)) {
|
eval label_position (((text_width,icon_size)) {
|
||||||
model.label.set_position_x(-text_width-icon_size.x/2.0);
|
model.label.set_x(-text_width-icon_size.x/2.0);
|
||||||
// Adjust for text offset, so this appears more centered.
|
// Adjust for text offset, so this appears more centered.
|
||||||
model.label.set_position_y(0.25 * icon_size.y);
|
model.label.set_y(0.25 * icon_size.y);
|
||||||
});
|
});
|
||||||
|
|
||||||
overlay_size <- all(model.label.frp.width,frp.input.set_icon_size);
|
overlay_size <- all(model.label.frp.width,frp.input.set_icon_size);
|
||||||
eval overlay_size ([model]((text_width,icon_size)) {
|
eval overlay_size ([model]((text_width,icon_size)) {
|
||||||
let size = Vector2::new(text_width + icon_size.x,icon_size.y);
|
let size = Vector2::new(text_width + icon_size.x,icon_size.y);
|
||||||
model.icon_overlay.size.set(size);
|
model.icon_overlay.size.set(size);
|
||||||
model.icon_overlay.set_position_x(-text_width/2.0);
|
model.icon_overlay.set_x(-text_width/2.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ use crate::prelude::*;
|
|||||||
use crate::model::AnyFolderContent;
|
use crate::model::AnyFolderContent;
|
||||||
|
|
||||||
use ensogl_core::display;
|
use ensogl_core::display;
|
||||||
use ensogl_core::display::Scene;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
|
||||||
@ -108,7 +107,7 @@ impl Default for FileBrowser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for FileBrowser {
|
impl display::Object for FileBrowser {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.display_object
|
&self.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ pub fn shape_from_block<BlockType: IntoThemePath>(
|
|||||||
|
|
||||||
component.set_content.emit(block.label);
|
component.set_content.emit(block.label);
|
||||||
component.set_size.emit(size);
|
component.set_size.emit(size);
|
||||||
component.set_position_xy(pos);
|
component.set_xy(pos);
|
||||||
|
|
||||||
component
|
component
|
||||||
}
|
}
|
||||||
@ -151,7 +151,7 @@ fn shape_from_mark(mark: profiler_flame_graph::Mark, app: &Application) -> Mark
|
|||||||
let label = format!("{} ({:.1}ms)", mark.label, mark.position);
|
let label = format!("{} ({:.1}ms)", mark.label, mark.position);
|
||||||
|
|
||||||
component.set_content.emit(label);
|
component.set_content.emit(label);
|
||||||
component.set_position_xy(pos);
|
component.set_xy(pos);
|
||||||
|
|
||||||
component
|
component
|
||||||
}
|
}
|
||||||
@ -267,8 +267,8 @@ impl FlameGraph {
|
|||||||
/// position as the root display object).
|
/// position as the root display object).
|
||||||
pub fn set_origin(&mut self, new_origin: f64) {
|
pub fn set_origin(&mut self, new_origin: f64) {
|
||||||
let delta = (self.origin_x - new_origin) as f32;
|
let delta = (self.origin_x - new_origin) as f32;
|
||||||
self.marks.iter().for_each(|mark| mark.mod_position_x(|pos| pos - delta));
|
self.marks.iter().for_each(|mark| mark.mod_x(|pos| pos - delta));
|
||||||
self.blocks.iter().for_each(|block| block.mod_position_x(|pos| pos - delta));
|
self.blocks.iter().for_each(|block| block.mod_x(|pos| pos - delta));
|
||||||
self.origin_x = new_origin
|
self.origin_x = new_origin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ where EntryParams: frp::node::Data
|
|||||||
contour <- all(init, entry_frp.contour)._1();
|
contour <- all(init, entry_frp.contour)._1();
|
||||||
eval contour ((c) overlay.set_contour(*c));
|
eval contour ((c) overlay.set_contour(*c));
|
||||||
contour_offset <- all(init, entry_frp.contour_offset)._1();
|
contour_offset <- all(init, entry_frp.contour_offset)._1();
|
||||||
eval contour_offset ((off) overlay.set_position_xy(*off));
|
eval contour_offset ((off) overlay.set_xy(*off));
|
||||||
|
|
||||||
let events = &overlay.events;
|
let events = &overlay.events;
|
||||||
let disabled = &entry_frp.disabled;
|
let disabled = &entry_frp.disabled;
|
||||||
@ -173,7 +173,7 @@ pub fn set_position<E: Entry>(
|
|||||||
column_widths: &ColumnWidths,
|
column_widths: &ColumnWidths,
|
||||||
) {
|
) {
|
||||||
let pos = position(row, col, entry_size, column_widths);
|
let pos = position(row, col, entry_size, column_widths);
|
||||||
entry.set_position_xy(pos);
|
entry.set_xy(pos);
|
||||||
entry.frp().position_set(pos);
|
entry.frp().position_set(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +231,7 @@ impl<InnerGrid, HeaderEntry: Entry> Model<InnerGrid, HeaderEntry, HeaderEntry::P
|
|||||||
let updated_positions = visible_headers.iter().filter_map(|(col, header)| {
|
let updated_positions = visible_headers.iter().filter_map(|(col, header)| {
|
||||||
let new_position = header.header_position(*col, entries_size, viewport, widths);
|
let new_position = header.header_position(*col, entries_size, viewport, widths);
|
||||||
(header.entry.position().xy() != new_position.position).as_some_from(|| {
|
(header.entry.position().xy() != new_position.position).as_some_from(|| {
|
||||||
header.entry.set_position_xy(new_position.position);
|
header.entry.set_xy(new_position.position);
|
||||||
header.entry.entry.frp().moved_as_header(&new_position);
|
header.entry.entry.frp().moved_as_header(&new_position);
|
||||||
(header.section_rows.start, *col, new_position.position)
|
(header.section_rows.start, *col, new_position.position)
|
||||||
})
|
})
|
||||||
@ -295,7 +295,7 @@ impl<InnerGrid, HeaderEntry: Entry> Model<InnerGrid, HeaderEntry, HeaderEntry::P
|
|||||||
let width_offset = self.column_widths.width_diff(col);
|
let width_offset = self.column_widths.width_diff(col);
|
||||||
entry_frp.set_size(entry_size + Vector2(width_offset, 0.0));
|
entry_frp.set_size(entry_size + Vector2(width_offset, 0.0));
|
||||||
let position = entry.header_position(col, entry_size, viewport, widths);
|
let position = entry.header_position(col, entry_size, viewport, widths);
|
||||||
entry.entry.set_position_xy(position.position);
|
entry.entry.set_xy(position.position);
|
||||||
entry_frp.moved_as_header(&position);
|
entry_frp.moved_as_header(&position);
|
||||||
(entry.section_rows.start, col, position.position)
|
(entry.section_rows.start, col, position.position)
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,6 @@ mod tests {
|
|||||||
use ensogl_core::application::frp::API;
|
use ensogl_core::application::frp::API;
|
||||||
use ensogl_core::data::color;
|
use ensogl_core::data::color;
|
||||||
use ensogl_core::display::scene::Layer;
|
use ensogl_core::display::scene::Layer;
|
||||||
use ensogl_core::display::Scene;
|
|
||||||
use ensogl_scroll_area::Viewport;
|
use ensogl_scroll_area::Viewport;
|
||||||
use itertools::iproduct;
|
use itertools::iproduct;
|
||||||
|
|
||||||
@ -355,7 +354,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for TestEntry {
|
impl display::Object for TestEntry {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.display_object
|
&self.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ ensogl_core::shape! {
|
|||||||
/// [module's docs](mod@self) for more info.
|
/// [module's docs](mod@self) for more info.
|
||||||
pub fn set_viewport(shape: &View, viewport: Viewport) {
|
pub fn set_viewport(shape: &View, viewport: Viewport) {
|
||||||
shape.size.set(viewport.size());
|
shape.size.set(viewport.size());
|
||||||
shape.set_position_xy(viewport.center_point());
|
shape.set_xy(viewport.center_point());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ impl EntryData {
|
|||||||
fn update_layout(&self, contour: entry::Contour, text_size: text::Size, text_offset: f32) {
|
fn update_layout(&self, contour: entry::Contour, text_size: text::Size, text_offset: f32) {
|
||||||
self.background.set_contour(contour);
|
self.background.set_contour(contour);
|
||||||
let size = contour.size;
|
let size = contour.size;
|
||||||
self.label.set_position_xy(Vector2(text_offset - size.x / 2.0, text_size.value / 2.0));
|
self.label.set_xy(Vector2(text_offset - size.x / 2.0, text_size.value / 2.0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ impl Model {
|
|||||||
let padded_size = size + padding * 2.0;
|
let padded_size = size + padding * 2.0;
|
||||||
self.background.size.set(padded_size);
|
self.background.size.set(padded_size);
|
||||||
let text_origin = Vector2(text_offset - size.x / 2.0, text_size / 2.0);
|
let text_origin = Vector2(text_offset - size.x / 2.0, text_size / 2.0);
|
||||||
self.label.set_position_xy(text_origin);
|
self.label.set_xy(text_origin);
|
||||||
padded_size
|
padded_size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +125,7 @@ impl Label {
|
|||||||
label.set_property_default <+ color.ref_into_some();
|
label.set_property_default <+ color.ref_into_some();
|
||||||
label.set_font <+ font;
|
label.set_font <+ font;
|
||||||
label.set_property_default <+ size.map(|v| text::Size(*v)).ref_into_some();
|
label.set_property_default <+ size.map(|v| text::Size(*v)).ref_into_some();
|
||||||
eval size ((size) label.set_position_y(size/2.0));
|
eval size ((size) label.set_y(size/2.0));
|
||||||
|
|
||||||
label.set_content <+ text;
|
label.set_content <+ text;
|
||||||
label.set_view_width <+ max_width_px.some();
|
label.set_view_width <+ max_width_px.some();
|
||||||
|
@ -288,7 +288,7 @@ impl<E: Entry> ListData<E, E::Params> {
|
|||||||
entry.entry.update(&default());
|
entry.entry.update(&default());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
entry.entry.set_position_y(Self::position_y_of_entry(id));
|
entry.entry.set_y(Self::position_y_of_entry(id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,10 +235,10 @@ impl<E: Entry> Model<E> {
|
|||||||
let margin = Vector2(2.0 * SHAPE_MARGIN, 2.0 * SHAPE_MARGIN);
|
let margin = Vector2(2.0 * SHAPE_MARGIN, 2.0 * SHAPE_MARGIN);
|
||||||
let shadow = Vector2(2.0 * SHADOW_PX, 2.0 * SHADOW_PX);
|
let shadow = Vector2(2.0 * SHADOW_PX, 2.0 * SHADOW_PX);
|
||||||
let entry_width = view.size.x - 2.0 * entry_padding;
|
let entry_width = view.size.x - 2.0 * entry_padding;
|
||||||
self.entries.set_position_x(-view.size.x / 2.0 + entry_padding);
|
self.entries.set_x(-view.size.x / 2.0 + entry_padding);
|
||||||
self.background.size.set(view.size + padding + shadow + margin);
|
self.background.size.set(view.size + padding + shadow + margin);
|
||||||
self.overlay.size.set(view.size + padding + shadow + margin);
|
self.overlay.size.set(view.size + padding + shadow + margin);
|
||||||
self.scrolled_area.set_position_y(view.size.y / 2.0 - view.position_y);
|
self.scrolled_area.set_y(view.size.y / 2.0 - view.position_y);
|
||||||
self.entries.update_entries(visible_entries, entry_width, style_prefix);
|
self.entries.update_entries(visible_entries, entry_width, style_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +594,7 @@ where E::Model: Default
|
|||||||
selection_sprite_y <- all_with3(&selection_y.value, &selection_height.value, &style.selection_height,
|
selection_sprite_y <- all_with3(&selection_y.value, &selection_height.value, &style.selection_height,
|
||||||
|y, h, max_h| y + (max_h - h) / 2.0
|
|y, h, max_h| y + (max_h - h) / 2.0
|
||||||
);
|
);
|
||||||
eval selection_sprite_y ((y) model.selection.set_position_y(*y));
|
eval selection_sprite_y ((y) model.selection.set_y(*y));
|
||||||
frp.source.selection_size <+ all_with3(&frp.size, &style.padding, &selection_height.value, f!([](size, padding, height) {
|
frp.source.selection_size <+ all_with3(&frp.size, &style.padding, &selection_height.value, f!([](size, padding, height) {
|
||||||
let width = size.x - 2.0 * padding;
|
let width = size.x - 2.0 * padding;
|
||||||
Vector2(width,*height)
|
Vector2(width,*height)
|
||||||
|
@ -199,14 +199,14 @@ struct Model {
|
|||||||
|
|
||||||
impl Model {
|
impl Model {
|
||||||
fn resize(&self, size: Vector2) {
|
fn resize(&self, size: Vector2) {
|
||||||
self.h_scrollbar.set_position_y(-size.y + scrollbar::WIDTH / 2.0);
|
self.h_scrollbar.set_y(-size.y + scrollbar::WIDTH / 2.0);
|
||||||
let scrollbar_y = size.x - scrollbar::WIDTH / 2.0 + scrollbar::PADDING / 2.0 + 1.0;
|
let scrollbar_y = size.x - scrollbar::WIDTH / 2.0 + scrollbar::PADDING / 2.0 + 1.0;
|
||||||
self.v_scrollbar.set_position_x(scrollbar_y);
|
self.v_scrollbar.set_x(scrollbar_y);
|
||||||
self.h_scrollbar.set_position_x(size.x / 2.0);
|
self.h_scrollbar.set_x(size.x / 2.0);
|
||||||
self.v_scrollbar.set_position_y(-size.y / 2.0);
|
self.v_scrollbar.set_y(-size.y / 2.0);
|
||||||
self.mask.size.set(size);
|
self.mask.size.set(size);
|
||||||
self.mask.set_position_x(size.x / 2.0);
|
self.mask.set_x(size.x / 2.0);
|
||||||
self.mask.set_position_y(-size.y / 2.0);
|
self.mask.set_y(-size.y / 2.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,8 +335,8 @@ impl ScrollArea {
|
|||||||
frp.source.scroll_position_target_x <+ model.h_scrollbar.thumb_position_target.map(|x| -x);
|
frp.source.scroll_position_target_x <+ model.h_scrollbar.thumb_position_target.map(|x| -x);
|
||||||
frp.source.scroll_position_target_y <+ model.v_scrollbar.thumb_position_target;
|
frp.source.scroll_position_target_y <+ model.v_scrollbar.thumb_position_target;
|
||||||
|
|
||||||
eval frp.scroll_position_x((&pos) model.content.set_position_x(pos));
|
eval frp.scroll_position_x((&pos) model.content.set_x(pos));
|
||||||
eval frp.scroll_position_y((&pos) model.content.set_position_y(pos));
|
eval frp.scroll_position_y((&pos) model.content.set_y(pos));
|
||||||
|
|
||||||
scroll_position <- all(&frp.scroll_position_x, &frp.scroll_position_y);
|
scroll_position <- all(&frp.scroll_position_x, &frp.scroll_position_y);
|
||||||
scroll_position <- scroll_position.map(|(x,y)| Vector2::new(*x,*y));
|
scroll_position <- scroll_position.map(|(x,y)| Vector2::new(*x,*y));
|
||||||
|
@ -83,7 +83,7 @@ impl Frp {
|
|||||||
model.label_full.set_content <+ formatted;
|
model.label_full.set_content <+ formatted;
|
||||||
|
|
||||||
eval model.label_left.width((offset)
|
eval model.label_left.width((offset)
|
||||||
model.label_full.set_position_x(-offset-LABEL_OFFSET));
|
model.label_full.set_x(-offset-LABEL_OFFSET));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,11 +91,11 @@ impl Frp {
|
|||||||
let track_click = relative_shape_down_position(net, scene, &model.track);
|
let track_click = relative_shape_down_position(net, scene, &model.track);
|
||||||
|
|
||||||
// Initialisation of components. Required for correct layout on startup.
|
// Initialisation of components. Required for correct layout on startup.
|
||||||
model.label_right.set_position_y(text_size.value() / 2.0);
|
model.label_right.set_y(text_size.value() / 2.0);
|
||||||
model.label_left.set_position_y(text_size.value() / 2.0);
|
model.label_left.set_y(text_size.value() / 2.0);
|
||||||
model.label.set_position_y(text_size.value() / 2.0);
|
model.label.set_y(text_size.value() / 2.0);
|
||||||
model.caption_left.set_position_y(text_size.value() / 2.0);
|
model.caption_left.set_y(text_size.value() / 2.0);
|
||||||
model.caption_center.set_position_y(text_size.value() / 2.0);
|
model.caption_center.set_y(text_size.value() / 2.0);
|
||||||
|
|
||||||
let bg_color = style.get_color(theme::component::slider::background);
|
let bg_color = style.get_color(theme::component::slider::background);
|
||||||
model.set_background_color(bg_color.value());
|
model.set_background_color(bg_color.value());
|
||||||
@ -106,9 +106,9 @@ impl Frp {
|
|||||||
init_shadow_padding <- source::<()>();
|
init_shadow_padding <- source::<()>();
|
||||||
shadow_padding <- all_with(&shadow.size,&init_shadow_padding,|&v,_| Vector2(v,v));
|
shadow_padding <- all_with(&shadow.size,&init_shadow_padding,|&v,_| Vector2(v,v));
|
||||||
eval text_size ((size) {
|
eval text_size ((size) {
|
||||||
model.label.set_position_y(size / 2.0);
|
model.label.set_y(size / 2.0);
|
||||||
model.label_right.set_position_y(size / 2.0);
|
model.label_right.set_y(size / 2.0);
|
||||||
model.label_left.set_position_y(size / 2.0);
|
model.label_left.set_y(size / 2.0);
|
||||||
});
|
});
|
||||||
eval bg_color ((color) model.set_background_color(*color) );
|
eval bg_color ((color) model.set_background_color(*color) );
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ impl Frp {
|
|||||||
update_caption_position <- all(&size,&text_size);
|
update_caption_position <- all(&size,&text_size);
|
||||||
eval update_caption_position((args) model.update_caption_position(args));
|
eval update_caption_position((args) model.update_caption_position(args));
|
||||||
eval model.caption_center.frp.width((width)
|
eval model.caption_center.frp.width((width)
|
||||||
model.caption_center.set_position_x(-width/2.0)
|
model.caption_center.set_x(-width/2.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Size updates
|
// Size updates
|
||||||
|
@ -152,12 +152,12 @@ impl Model {
|
|||||||
let overflow_icon_size = size.y;
|
let overflow_icon_size = size.y;
|
||||||
let label_offset = size.x / 2.0 - overflow_icon_size + left_padding;
|
let label_offset = size.x / 2.0 - overflow_icon_size + left_padding;
|
||||||
|
|
||||||
self.label_left.set_position_x(-label_offset);
|
self.label_left.set_x(-label_offset);
|
||||||
self.label_right.set_position_x(label_offset - self.label_right.width.value());
|
self.label_right.set_x(label_offset - self.label_right.width.value());
|
||||||
|
|
||||||
let overflow_icon_offset = size.x / 2.0 - overflow_icon_size / 2.0;
|
let overflow_icon_offset = size.x / 2.0 - overflow_icon_size / 2.0;
|
||||||
self.left_overflow.set_position_x(-overflow_icon_offset);
|
self.left_overflow.set_x(-overflow_icon_offset);
|
||||||
self.right_overflow.set_position_x(overflow_icon_offset);
|
self.right_overflow.set_x(overflow_icon_offset);
|
||||||
|
|
||||||
let track_handle_size = Vector2::new(size.y / 2.0, size.y);
|
let track_handle_size = Vector2::new(size.y / 2.0, size.y);
|
||||||
self.track_handle_left.size.set(track_handle_size);
|
self.track_handle_left.size.set(track_handle_size);
|
||||||
@ -171,9 +171,9 @@ impl Model {
|
|||||||
let left_padding = LABEL_OFFSET;
|
let left_padding = LABEL_OFFSET;
|
||||||
let overflow_icon_size = size.y / 2.0;
|
let overflow_icon_size = size.y / 2.0;
|
||||||
let caption_offset = size.x / 2.0 - overflow_icon_size - left_padding;
|
let caption_offset = size.x / 2.0 - overflow_icon_size - left_padding;
|
||||||
self.caption_left.set_position_x(-caption_offset);
|
self.caption_left.set_x(-caption_offset);
|
||||||
self.caption_left.set_position_y(text_size / 2.0);
|
self.caption_left.set_y(text_size / 2.0);
|
||||||
self.caption_center.set_position_y(text_size / 2.0);
|
self.caption_center.set_y(text_size / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set whether to allow interactions with the edges of the track shape. If this is set to
|
/// Set whether to allow interactions with the edges of the track shape. If this is set to
|
||||||
@ -208,8 +208,8 @@ impl Model {
|
|||||||
self.track.left.set(value.start);
|
self.track.left.set(value.start);
|
||||||
self.track.right.set(value.end);
|
self.track.right.set(value.end);
|
||||||
|
|
||||||
self.track_handle_left.set_position_x(value.start * size.x - size.x / 2.0);
|
self.track_handle_left.set_x(value.start * size.x - size.x / 2.0);
|
||||||
self.track_handle_right.set_position_x(value.end * size.x - size.x / 2.0);
|
self.track_handle_right.set_x(value.end * size.x - size.x / 2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the label in the center of the background to show the given numeric value.
|
/// Set the label in the center of the background to show the given numeric value.
|
||||||
|
@ -126,7 +126,7 @@ impl Model {
|
|||||||
self.display_object.add_child(&line);
|
self.display_object.add_child(&line);
|
||||||
line.set_content(process.to_string());
|
line.set_content(process.to_string());
|
||||||
line.set_size(Vector2::new(LINE_WIDTH, INFINITE));
|
line.set_size(Vector2::new(LINE_WIDTH, INFINITE));
|
||||||
line.set_position_y(ROW_HEIGHT * ix as f32);
|
line.set_y(ROW_HEIGHT * ix as f32);
|
||||||
line.set_rotation_z(90.0_f32.to_radians());
|
line.set_rotation_z(90.0_f32.to_radians());
|
||||||
line
|
line
|
||||||
})
|
})
|
||||||
@ -156,8 +156,8 @@ impl Model {
|
|||||||
let start = message.recipient.id.min(message.sender.id) as u32;
|
let start = message.recipient.id.min(message.sender.id) as u32;
|
||||||
line.set_size(Vector2::new(LINE_WIDTH, height_px));
|
line.set_size(Vector2::new(LINE_WIDTH, height_px));
|
||||||
|
|
||||||
line.set_position_x(message.time as f32);
|
line.set_x(message.time as f32);
|
||||||
line.set_position_y(ROW_HEIGHT * start as f32 + height_px / 2.0);
|
line.set_y(ROW_HEIGHT * start as f32 + height_px / 2.0);
|
||||||
line
|
line
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -195,7 +195,7 @@ impl Model {
|
|||||||
.borrow()
|
.borrow()
|
||||||
.deref()
|
.deref()
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|line| line.mod_position_x(|x| x + delta))
|
.for_each(|line| line.mod_x(|x| x + delta))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,16 +320,16 @@ impl Slider {
|
|||||||
&model.value_text_dot.width,
|
&model.value_text_dot.width,
|
||||||
);
|
);
|
||||||
value_text_left_pos_x <- value_text_left_pos_x.map(|(left, dot)| -*left - *dot / 2.0);
|
value_text_left_pos_x <- value_text_left_pos_x.map(|(left, dot)| -*left - *dot / 2.0);
|
||||||
eval value_text_left_pos_x((x) model.value_text_left.set_position_x(*x));
|
eval value_text_left_pos_x((x) model.value_text_left.set_x(*x));
|
||||||
eval model.value_text_left.height((h) model.value_text_left.set_position_y(*h / 2.0));
|
eval model.value_text_left.height((h) model.value_text_left.set_y(*h / 2.0));
|
||||||
eval model.value_text_dot.width((w) model.value_text_dot.set_position_x(-*w / 2.0));
|
eval model.value_text_dot.width((w) model.value_text_dot.set_x(-*w / 2.0));
|
||||||
eval model.value_text_dot.height((h) model.value_text_dot.set_position_y(*h / 2.0));
|
eval model.value_text_dot.height((h) model.value_text_dot.set_y(*h / 2.0));
|
||||||
eval model.value_text_dot.width((w) model.value_text_right.set_position_x(*w / 2.0));
|
eval model.value_text_dot.width((w) model.value_text_right.set_x(*w / 2.0));
|
||||||
eval model.value_text_right.height((h) model.value_text_right.set_position_y(*h / 2.0));
|
eval model.value_text_right.height((h) model.value_text_right.set_y(*h / 2.0));
|
||||||
|
|
||||||
model.label.set_content <+ input.set_label;
|
model.label.set_content <+ input.set_label;
|
||||||
eval input.set_label_hidden((v) model.set_label_hidden(*v));
|
eval input.set_label_hidden((v) model.set_label_hidden(*v));
|
||||||
eval model.label.height((h) model.label.set_position_y(*h / 2.0));
|
eval model.label.height((h) model.label.set_y(*h / 2.0));
|
||||||
label_pos_x <- all4(
|
label_pos_x <- all4(
|
||||||
&input.set_width,
|
&input.set_width,
|
||||||
&input.set_height,
|
&input.set_height,
|
||||||
@ -341,7 +341,7 @@ impl Slider {
|
|||||||
LabelPosition::Outside => -comp_width / 2.0 - comp_height / 2.0 - lab_width,
|
LabelPosition::Outside => -comp_width / 2.0 - comp_height / 2.0 - lab_width,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
eval label_pos_x((x) model.label.set_position_x(*x));
|
eval label_pos_x((x) model.label.set_x(*x));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,7 +270,7 @@ impl View {
|
|||||||
|
|
||||||
baseline_anim.target <+ frp.set_baseline;
|
baseline_anim.target <+ frp.set_baseline;
|
||||||
baseline_anim.skip <+ frp.skip_baseline_animation;
|
baseline_anim.skip <+ frp.skip_baseline_animation;
|
||||||
eval baseline_anim.value ((y) display_object.set_position_y(*y));
|
eval baseline_anim.value ((y) display_object.set_y(*y));
|
||||||
|
|
||||||
new_baseline <- baseline_anim.value.on_change();
|
new_baseline <- baseline_anim.value.on_change();
|
||||||
frp.private.output.baseline <+ new_baseline;
|
frp.private.output.baseline <+ new_baseline;
|
||||||
@ -307,7 +307,7 @@ impl View {
|
|||||||
let truncation = TruncationData::new(size, ellipsis);
|
let truncation = TruncationData::new(size, ellipsis);
|
||||||
let x = self.glyphs.last().map(|g| g.position().x + g.x_advance.get()).unwrap_or(0.0);
|
let x = self.glyphs.last().map(|g| g.position().x + g.x_advance.get()).unwrap_or(0.0);
|
||||||
let x = x + truncation.x_after_last_glyph();
|
let x = x + truncation.x_after_last_glyph();
|
||||||
truncation.ellipsis.set_position_xy(Vector2(x, truncation.y()));
|
truncation.ellipsis.set_xy(Vector2(x, truncation.y()));
|
||||||
truncation.ellipsis.scale.set(truncation.scale);
|
truncation.ellipsis.scale.set(truncation.scale);
|
||||||
truncation.ellipsis.size.set(truncation.dim());
|
truncation.ellipsis.size.set(truncation.dim());
|
||||||
let was_truncated = self.truncation.borrow().is_some();
|
let was_truncated = self.truncation.borrow().is_some();
|
||||||
|
@ -182,7 +182,7 @@ impl Selection {
|
|||||||
_eval <- all_with(&ascender.value, &descender.value,
|
_eval <- all_with(&ascender.value, &descender.value,
|
||||||
f!([model](ascender,descender) {
|
f!([model](ascender,descender) {
|
||||||
let height = ascender - descender;
|
let height = ascender - descender;
|
||||||
model.view.set_position_y(height / 2.0 + descender);
|
model.view.set_y(height / 2.0 + descender);
|
||||||
model.view.size.modify(|t| Vector2(t.x, CURSOR_PADDING * 2.0 + height));
|
model.view.size.modify(|t| Vector2(t.x, CURSOR_PADDING * 2.0 + height));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@ -217,10 +217,10 @@ impl Selection {
|
|||||||
let width = max(CURSOR_WIDTH, abs_width - CURSORS_SPACING);
|
let width = max(CURSOR_WIDTH, abs_width - CURSORS_SPACING);
|
||||||
let view_width = CURSOR_PADDING * 2.0 + width;
|
let view_width = CURSOR_PADDING * 2.0 + width;
|
||||||
let view_x = (abs_width/2.0) * side;
|
let view_x = (abs_width/2.0) * side;
|
||||||
model.display_object.set_position_xy(*p);
|
model.display_object.set_xy(*p);
|
||||||
model.right_side.set_position_x(abs_width);
|
model.right_side.set_x(abs_width);
|
||||||
model.view.size.modify(|t| Vector2(view_width,t.y));
|
model.view.size.modify(|t| Vector2(view_width,t.y));
|
||||||
model.view.set_position_x(view_x);
|
model.view.set_x(view_x);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
eval frp.set_color((color) model.view.color_rgb.set(color.into()));
|
eval frp.set_color((color) model.view.color_rgb.set(color.into()));
|
||||||
|
@ -807,7 +807,7 @@ impl TextModel {
|
|||||||
let camera = self.layer.get().camera();
|
let camera = self.layer.get().camera();
|
||||||
let origin_world_space = Vector4(0.0, 0.0, 0.0, 1.0);
|
let origin_world_space = Vector4(0.0, 0.0, 0.0, 1.0);
|
||||||
let origin_clip_space = camera.view_projection_matrix() * origin_world_space;
|
let origin_clip_space = camera.view_projection_matrix() * origin_world_space;
|
||||||
let inv_object_matrix = self.transform_matrix().try_inverse().unwrap();
|
let inv_object_matrix = self.transformation_matrix().try_inverse().unwrap();
|
||||||
|
|
||||||
let shape = self.app.display.default_scene.frp.shape.value();
|
let shape = self.app.display.default_scene.frp.shape.value();
|
||||||
let clip_space_z = origin_clip_space.z;
|
let clip_space_z = origin_clip_space.z;
|
||||||
@ -1369,8 +1369,8 @@ impl TextModel {
|
|||||||
glyph.set_properties(shaped_glyph_set.non_variable_variations);
|
glyph.set_properties(shaped_glyph_set.non_variable_variations);
|
||||||
glyph.set_glyph_id(shaped_glyph.id());
|
glyph.set_glyph_id(shaped_glyph.id());
|
||||||
glyph.x_advance.set(x_advance);
|
glyph.x_advance.set(x_advance);
|
||||||
glyph.view.set_position_xy(glyph_render_offset * magic_scale);
|
glyph.view.set_xy(glyph_render_offset * magic_scale);
|
||||||
glyph.set_position_xy(Vector2(glyph_offset_x, 0.0));
|
glyph.set_xy(Vector2(glyph_offset_x, 0.0));
|
||||||
|
|
||||||
glyph_offset_x += x_advance;
|
glyph_offset_x += x_advance;
|
||||||
divs.push(glyph_offset_x);
|
divs.push(glyph_offset_x);
|
||||||
@ -1469,7 +1469,7 @@ impl TextModel {
|
|||||||
if let Some(cursor) = &last_cursor {
|
if let Some(cursor) = &last_cursor {
|
||||||
cursor.right_side().add_child(glyph);
|
cursor.right_side().add_child(glyph);
|
||||||
glyph.attached_to_cursor.set(true);
|
glyph.attached_to_cursor.set(true);
|
||||||
glyph.mod_position_x(|p| p - last_cursor_target_x);
|
glyph.mod_x(|p| p - last_cursor_target_x);
|
||||||
attached_glyphs.push(glyph.downgrade());
|
attached_glyphs.push(glyph.downgrade());
|
||||||
}
|
}
|
||||||
column += Column(1);
|
column += Column(1);
|
||||||
@ -1491,7 +1491,7 @@ impl TextModel {
|
|||||||
if let Some(glyph) = glyph.upgrade() {
|
if let Some(glyph) = glyph.upgrade() {
|
||||||
self.lines.borrow_mut()[line].add_child(&glyph);
|
self.lines.borrow_mut()[line].add_child(&glyph);
|
||||||
let pos_x = selection.position_target.value().x;
|
let pos_x = selection.position_target.value().x;
|
||||||
glyph.mod_position_xy(|pos| Vector2(pos.x + pos_x, 0.0));
|
glyph.mod_xy(|pos| Vector2(pos.x + pos_x, 0.0));
|
||||||
glyph.attached_to_cursor.set(false);
|
glyph.attached_to_cursor.set(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ impl Model {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let base_positions = position.xy();
|
let base_positions = position.xy();
|
||||||
self.tooltip.set_position_xy(base_positions + layout_offset)
|
self.tooltip.set_xy(base_positions + layout_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_style(&self, update: &Style) {
|
fn set_style(&self, update: &Style) {
|
||||||
|
@ -46,7 +46,7 @@ impl BoundingBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return a bounding box given by the position and size. The position interpreted as the
|
/// Return a bounding box given by the position and size. The position interpreted as the
|
||||||
/// top-right corner and size as the extend along the positive x and y-axis. Negative sizes
|
/// top-right corner and size as the extension along the positive x and y-axis. Negative sizes
|
||||||
/// are valid.
|
/// are valid.
|
||||||
pub fn from_position_and_size(position: Vector2, size: Vector2) -> Self {
|
pub fn from_position_and_size(position: Vector2, size: Vector2) -> Self {
|
||||||
Self::from_corners(position, position + size)
|
Self::from_corners(position, position + size)
|
||||||
|
@ -4,9 +4,6 @@
|
|||||||
//! a set of changed indexes and bulk-update the GPU-buffers every animation frame. You can think
|
//! a set of changed indexes and bulk-update the GPU-buffers every animation frame. You can think
|
||||||
//! of dirty flags like about a way to introduce laziness to the program evaluation mechanisms.
|
//! of dirty flags like about a way to introduce laziness to the program evaluation mechanisms.
|
||||||
|
|
||||||
// === Non-Standard Linter Configuration ===
|
|
||||||
#![allow(missing_docs)]
|
|
||||||
|
|
||||||
use crate::data::function::traits::*;
|
use crate::data::function::traits::*;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
@ -20,75 +17,140 @@ use std::mem;
|
|||||||
// === Operations ===
|
// === Operations ===
|
||||||
// ==================
|
// ==================
|
||||||
|
|
||||||
|
/// Common traits for dirty flags.
|
||||||
pub mod traits {
|
pub mod traits {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
// === Arg ===
|
// === Arg ===
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which accept an argument.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasArg {
|
pub trait HasArg {
|
||||||
type Arg;
|
type Arg;
|
||||||
}
|
}
|
||||||
|
/// The argument type-level getter.
|
||||||
pub type Arg<T> = <T as HasArg>::Arg;
|
pub type Arg<T> = <T as HasArg>::Arg;
|
||||||
|
|
||||||
|
|
||||||
// === Global Operations ===
|
// === Global Operations ===
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be checked for being dirty.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasCheckAll {
|
pub trait HasCheckAll {
|
||||||
fn check_all(&self) -> bool;
|
fn check_all(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be unset (set to clean).
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasUnsetAll {
|
pub trait HasUnsetAll {
|
||||||
fn unset_all(&mut self);
|
fn unset_all(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === Arity-0 Operations ===
|
// === Arity-0 Operations ===
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can perform a dirty check without requiring an argument.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasCheck0 {
|
pub trait HasCheck0 {
|
||||||
fn check(&self) -> bool;
|
fn check(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be set without requiring an argument.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasSet0 {
|
pub trait HasSet0 {
|
||||||
fn set(&mut self);
|
fn set(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be unset without requiring an argument.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasUnset0 {
|
pub trait HasUnset0 {
|
||||||
fn unset(&mut self);
|
fn unset(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === Arity-1 Operations ===
|
// === Arity-1 Operations ===
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can perform a dirty check by providing a single argument.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasCheck1: HasArg {
|
pub trait HasCheck1: HasArg {
|
||||||
fn check(&self, arg: &Self::Arg) -> bool;
|
fn check(&self, arg: &Self::Arg) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be set by providing a single argument.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasSet1: HasArg {
|
pub trait HasSet1: HasArg {
|
||||||
fn set(&mut self, arg: Self::Arg);
|
fn set(&mut self, arg: Self::Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be unset by providing a single argument.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait HasUnset1: HasArg {
|
pub trait HasUnset1: HasArg {
|
||||||
fn unset(&mut self, arg: &Self::Arg);
|
fn unset(&mut self, arg: &Self::Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Shared Operations ===
|
|
||||||
|
// === Shared Global Operations ===
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be unset (set to clean) without requiring mutable
|
||||||
|
/// access to self.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait SharedHasUnsetAll {
|
pub trait SharedHasUnsetAll {
|
||||||
fn unset_all(&self);
|
fn unset_all(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// === Shared Arity-0 Operations ===
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be set without requiring an argument and without
|
||||||
|
/// requiring mutable access to self.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait SharedHasSet0 {
|
pub trait SharedHasSet0 {
|
||||||
fn set(&self);
|
fn set(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be unset without requiring an argument and without
|
||||||
|
/// requiring mutable access to self.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait SharedHasUnset0 {
|
pub trait SharedHasUnset0 {
|
||||||
fn unset(&self);
|
fn unset(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// === Shared Arity-1 Operations ===
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be set by providing a single argument without
|
||||||
|
/// requiring mutable access to self.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait SharedHasSet1: HasArg {
|
pub trait SharedHasSet1: HasArg {
|
||||||
fn set(&self, arg: Self::Arg);
|
fn set(&self, arg: Self::Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Abstraction for dirty flags which can be unset by providing a single argument without
|
||||||
|
/// requiring mutable access to self.
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub trait SharedHasUnset1: HasArg {
|
pub trait SharedHasUnset1: HasArg {
|
||||||
fn unset(&self, arg: &Self::Arg);
|
fn unset(&self, arg: &Self::Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Type Aliases ===
|
// === Type Aliases ===
|
||||||
pub trait DirtyFlagOps = Debug + HasCheckAll + HasUnsetAll;
|
|
||||||
pub trait DirtyFlagOps0 = DirtyFlagOps + HasCheck0 + HasSet0;
|
/// Trait alias for bounds required by all dirty flags.
|
||||||
pub trait DirtyFlagOps1 = DirtyFlagOps + HasCheck1 + HasSet1 where Arg<Self>: Debug;
|
pub trait FlagOps = Debug + HasCheckAll + HasUnsetAll;
|
||||||
|
|
||||||
|
/// Trait alias for bounds required by all dirty flags which does not accept an argument.
|
||||||
|
pub trait FlagOps0 = FlagOps + HasCheck0 + HasSet0;
|
||||||
|
|
||||||
|
/// Trait alias for bounds required by all dirty flags which accept an argument.
|
||||||
|
pub trait FlagOps1 = FlagOps + HasCheck1 + HasSet1 where Arg<Self>: Debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use traits::*;
|
pub use traits::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =================
|
// ============
|
||||||
// === DirtyFlag ===
|
// === Flag ===
|
||||||
// =================
|
// ============
|
||||||
|
|
||||||
// === Definition ===
|
// === Definition ===
|
||||||
|
|
||||||
@ -97,7 +159,8 @@ pub use traits::*;
|
|||||||
/// implements public API for working with dirty flags.
|
/// implements public API for working with dirty flags.
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Debug(bound = "T:Debug"))]
|
#[derivative(Debug(bound = "T:Debug"))]
|
||||||
pub struct DirtyFlag<T, OnMut> {
|
#[allow(missing_docs)]
|
||||||
|
pub struct Flag<T, OnMut> {
|
||||||
pub data: T,
|
pub data: T,
|
||||||
#[derivative(Debug = "ignore")]
|
#[derivative(Debug = "ignore")]
|
||||||
on_set: OnMut,
|
on_set: OnMut,
|
||||||
@ -106,12 +169,14 @@ pub struct DirtyFlag<T, OnMut> {
|
|||||||
|
|
||||||
// === Basics ===
|
// === Basics ===
|
||||||
|
|
||||||
impl<OnMut, T: Default> DirtyFlag<T, OnMut> {
|
impl<OnMut, T: Default> Flag<T, OnMut> {
|
||||||
|
/// Constructor.
|
||||||
pub fn new(on_set: OnMut) -> Self {
|
pub fn new(on_set: OnMut) -> Self {
|
||||||
let data = default();
|
let data = default();
|
||||||
Self { data, on_set }
|
Self { data, on_set }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unsets the flag and returns its dirty value.
|
||||||
pub fn take(&mut self) -> T {
|
pub fn take(&mut self) -> T {
|
||||||
mem::take(&mut self.data)
|
mem::take(&mut self.data)
|
||||||
}
|
}
|
||||||
@ -120,20 +185,20 @@ impl<OnMut, T: Default> DirtyFlag<T, OnMut> {
|
|||||||
|
|
||||||
// === Arguments ===
|
// === Arguments ===
|
||||||
|
|
||||||
impl<T: HasArg, OnMut> HasArg for DirtyFlag<T, OnMut> {
|
impl<T: HasArg, OnMut> HasArg for Flag<T, OnMut> {
|
||||||
type Arg = Arg<T>;
|
type Arg = Arg<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === Global Operations ===
|
// === Global Operations ===
|
||||||
|
|
||||||
impl<T: HasCheckAll, OnMut> HasCheckAll for DirtyFlag<T, OnMut> {
|
impl<T: HasCheckAll, OnMut> HasCheckAll for Flag<T, OnMut> {
|
||||||
fn check_all(&self) -> bool {
|
fn check_all(&self) -> bool {
|
||||||
self.data.check_all()
|
self.data.check_all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasUnsetAll, OnMut> HasUnsetAll for DirtyFlag<T, OnMut> {
|
impl<T: HasUnsetAll, OnMut> HasUnsetAll for Flag<T, OnMut> {
|
||||||
fn unset_all(&mut self) {
|
fn unset_all(&mut self) {
|
||||||
self.data.unset_all()
|
self.data.unset_all()
|
||||||
}
|
}
|
||||||
@ -142,13 +207,13 @@ impl<T: HasUnsetAll, OnMut> HasUnsetAll for DirtyFlag<T, OnMut> {
|
|||||||
|
|
||||||
// === Check ===
|
// === Check ===
|
||||||
|
|
||||||
impl<T: DirtyFlagOps0, OnMut> HasCheck0 for DirtyFlag<T, OnMut> {
|
impl<T: FlagOps0, OnMut> HasCheck0 for Flag<T, OnMut> {
|
||||||
fn check(&self) -> bool {
|
fn check(&self) -> bool {
|
||||||
self.data.check()
|
self.data.check()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DirtyFlagOps1, OnMut> HasCheck1 for DirtyFlag<T, OnMut> {
|
impl<T: FlagOps1, OnMut> HasCheck1 for Flag<T, OnMut> {
|
||||||
fn check(&self, arg: &Self::Arg) -> bool {
|
fn check(&self, arg: &Self::Arg) -> bool {
|
||||||
self.data.check(arg)
|
self.data.check(arg)
|
||||||
}
|
}
|
||||||
@ -157,7 +222,7 @@ impl<T: DirtyFlagOps1, OnMut> HasCheck1 for DirtyFlag<T, OnMut> {
|
|||||||
|
|
||||||
// === Set ===
|
// === Set ===
|
||||||
|
|
||||||
impl<T: DirtyFlagOps0, OnMut: FnMut0> HasSet0 for DirtyFlag<T, OnMut> {
|
impl<T: FlagOps0, OnMut: FnMut0> HasSet0 for Flag<T, OnMut> {
|
||||||
fn set(&mut self) {
|
fn set(&mut self) {
|
||||||
let is_set = self.data.check_all();
|
let is_set = self.data.check_all();
|
||||||
if !is_set {
|
if !is_set {
|
||||||
@ -169,7 +234,7 @@ impl<T: DirtyFlagOps0, OnMut: FnMut0> HasSet0 for DirtyFlag<T, OnMut> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DirtyFlagOps1, OnMut: FnMut0> HasSet1 for DirtyFlag<T, OnMut> {
|
impl<T: FlagOps1, OnMut: FnMut0> HasSet1 for Flag<T, OnMut> {
|
||||||
fn set(&mut self, arg: Self::Arg) {
|
fn set(&mut self, arg: Self::Arg) {
|
||||||
let first_set = !self.check_all();
|
let first_set = !self.check_all();
|
||||||
let is_set = self.data.check(&arg);
|
let is_set = self.data.check(&arg);
|
||||||
@ -187,14 +252,14 @@ impl<T: DirtyFlagOps1, OnMut: FnMut0> HasSet1 for DirtyFlag<T, OnMut> {
|
|||||||
|
|
||||||
// === Unset ===
|
// === Unset ===
|
||||||
|
|
||||||
impl<T: HasUnset0, OnMut> HasUnset0 for DirtyFlag<T, OnMut> {
|
impl<T: HasUnset0, OnMut> HasUnset0 for Flag<T, OnMut> {
|
||||||
fn unset(&mut self) {
|
fn unset(&mut self) {
|
||||||
trace!("Unsetting.");
|
trace!("Unsetting.");
|
||||||
self.data.unset()
|
self.data.unset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasUnset1, OnMut> HasUnset1 for DirtyFlag<T, OnMut>
|
impl<T: HasUnset1, OnMut> HasUnset1 for Flag<T, OnMut>
|
||||||
where Arg<T>: Display
|
where Arg<T>: Display
|
||||||
{
|
{
|
||||||
fn unset(&mut self, arg: &Self::Arg) {
|
fn unset(&mut self, arg: &Self::Arg) {
|
||||||
@ -205,181 +270,307 @@ where Arg<T>: Display
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =======================
|
// ==================
|
||||||
// === SharedDirtyFlag ===
|
// === RefCellFlag ===
|
||||||
// =======================
|
// ==================
|
||||||
|
|
||||||
// === Definition ===
|
// === Definition ===
|
||||||
|
|
||||||
/// A version of `DirtyFlag` which uses internal mutability pattern. It is meant to expose the same
|
/// A version of `Flag` which uses internal mutability pattern. It is meant to expose the same
|
||||||
/// API but without requiring `self` reference to be mutable.
|
/// API but without requiring `self` reference to be mutable. This version does not allow for
|
||||||
#[derive(Derivative)]
|
/// cloning the flag. If you want to clone it you either need to put it in something like [`Rc`] or
|
||||||
|
/// use the [`SharedFlag`] instead.
|
||||||
|
#[derive(Derivative, From)]
|
||||||
#[derivative(Debug(bound = "T:Debug"))]
|
#[derivative(Debug(bound = "T:Debug"))]
|
||||||
#[derivative(Clone(bound = ""))]
|
#[repr(transparent)]
|
||||||
pub struct SharedDirtyFlag<T, OnMut> {
|
pub struct RefCellFlag<T, OnMut> {
|
||||||
rc: Rc<RefCell<DirtyFlag<T, OnMut>>>,
|
data: RefCell<Flag<T, OnMut>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === API ===
|
// === API ===
|
||||||
|
|
||||||
impl<T: Default, OnMut> SharedDirtyFlag<T, OnMut> {
|
impl<T: Default, OnMut> RefCellFlag<T, OnMut> {
|
||||||
|
/// Constructor.
|
||||||
pub fn new(on_set: OnMut) -> Self {
|
pub fn new(on_set: OnMut) -> Self {
|
||||||
Self { rc: Rc::new(RefCell::new(DirtyFlag::new(on_set))) }
|
Self { data: RefCell::new(Flag::new(on_set)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unsets the flag and returns its dirty value.
|
||||||
pub fn take(&self) -> T {
|
pub fn take(&self) -> T {
|
||||||
self.rc.borrow_mut().take()
|
self.data.borrow_mut().take()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, OnMut> SharedDirtyFlag<T, OnMut> {
|
impl<T, OnMut> RefCellFlag<T, OnMut> {
|
||||||
pub fn clone_ref(&self) -> Self {
|
/// Replace the callback of the flag.
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, OnMut> SharedDirtyFlag<T, OnMut> {
|
|
||||||
pub fn set_callback(&self, on_set: OnMut) {
|
pub fn set_callback(&self, on_set: OnMut) {
|
||||||
self.rc.borrow_mut().on_set = on_set;
|
self.data.borrow_mut().on_set = on_set;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, OnMut> From<Rc<RefCell<DirtyFlag<T, OnMut>>>> for SharedDirtyFlag<T, OnMut> {
|
|
||||||
fn from(rc: Rc<RefCell<DirtyFlag<T, OnMut>>>) -> Self {
|
|
||||||
Self { rc }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === Arg ===
|
// === Arg ===
|
||||||
|
|
||||||
impl<T: HasArg, OnMut> HasArg for SharedDirtyFlag<T, OnMut> {
|
impl<T: HasArg, OnMut> HasArg for RefCellFlag<T, OnMut> {
|
||||||
type Arg = Arg<T>;
|
type Arg = Arg<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === Global Operations ===
|
// === Global Operations ===
|
||||||
|
|
||||||
impl<T: HasUnsetAll, OnMut> SharedHasUnsetAll for SharedDirtyFlag<T, OnMut> {
|
impl<T: HasUnsetAll, OnMut> SharedHasUnsetAll for RefCellFlag<T, OnMut> {
|
||||||
fn unset_all(&self) {
|
fn unset_all(&self) {
|
||||||
self.rc.borrow_mut().unset_all()
|
self.data.borrow_mut().unset_all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasCheckAll, OnMut> HasCheckAll for SharedDirtyFlag<T, OnMut> {
|
impl<T: HasCheckAll, OnMut> HasCheckAll for RefCellFlag<T, OnMut> {
|
||||||
fn check_all(&self) -> bool {
|
fn check_all(&self) -> bool {
|
||||||
self.rc.borrow().check_all()
|
self.data.borrow().check_all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Check ===
|
// === Check ===
|
||||||
|
|
||||||
impl<T: DirtyFlagOps0, OnMut> HasCheck0 for SharedDirtyFlag<T, OnMut> {
|
impl<T: FlagOps0, OnMut> HasCheck0 for RefCellFlag<T, OnMut> {
|
||||||
fn check(&self) -> bool {
|
fn check(&self) -> bool {
|
||||||
self.rc.borrow().check()
|
self.data.borrow().check()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DirtyFlagOps1, OnMut> HasCheck1 for SharedDirtyFlag<T, OnMut> {
|
impl<T: FlagOps1, OnMut> HasCheck1 for RefCellFlag<T, OnMut> {
|
||||||
fn check(&self, arg: &Arg<T>) -> bool {
|
fn check(&self, arg: &Arg<T>) -> bool {
|
||||||
self.rc.borrow().check(arg)
|
self.data.borrow().check(arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Set ===
|
// === Set ===
|
||||||
|
|
||||||
impl<T: DirtyFlagOps0, OnMut: FnMut0> SharedHasSet0 for SharedDirtyFlag<T, OnMut> {
|
impl<T: FlagOps0, OnMut: FnMut0> SharedHasSet0 for RefCellFlag<T, OnMut> {
|
||||||
fn set(&self) {
|
fn set(&self) {
|
||||||
self.rc.borrow_mut().set()
|
self.data.borrow_mut().set()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DirtyFlagOps1, OnMut: FnMut0> SharedHasSet1 for SharedDirtyFlag<T, OnMut> {
|
impl<T: FlagOps1, OnMut: FnMut0> SharedHasSet1 for RefCellFlag<T, OnMut> {
|
||||||
fn set(&self, arg: Arg<T>) {
|
fn set(&self, arg: Arg<T>) {
|
||||||
self.rc.borrow_mut().set(arg)
|
self.data.borrow_mut().set(arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Unset ===
|
// === Unset ===
|
||||||
|
|
||||||
impl<T: HasUnset0, OnMut> SharedHasUnset0 for SharedDirtyFlag<T, OnMut> {
|
impl<T: HasUnset0, OnMut> SharedHasUnset0 for RefCellFlag<T, OnMut> {
|
||||||
fn unset(&self) {
|
fn unset(&self) {
|
||||||
self.rc.borrow_mut().unset()
|
self.data.borrow_mut().unset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: HasUnset1, OnMut> SharedHasUnset1 for SharedDirtyFlag<T, OnMut>
|
impl<T: HasUnset1, OnMut> SharedHasUnset1 for RefCellFlag<T, OnMut>
|
||||||
where Arg<T>: Display
|
where Arg<T>: Display
|
||||||
{
|
{
|
||||||
fn unset(&self, arg: &Self::Arg) {
|
fn unset(&self, arg: &Self::Arg) {
|
||||||
self.rc.borrow_mut().unset(arg)
|
self.data.borrow_mut().unset(arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// === Weak References ===
|
|
||||||
|
|
||||||
|
// ==================
|
||||||
|
// === SharedFlag ===
|
||||||
|
// ==================
|
||||||
|
|
||||||
|
// === Definition ===
|
||||||
|
|
||||||
|
/// A version of `Flag` which uses internal mutability pattern. It is meant to expose the same
|
||||||
|
/// API but without requiring `self` reference to be mutable. This version implements cloning. If
|
||||||
|
/// you don't need it, or you want to store a bunch of flags enclosed in a single [`Rc`], use the
|
||||||
|
/// [`RefCellFlag`] instead.
|
||||||
|
#[derive(Derivative, CloneRef, From, Deref)]
|
||||||
|
#[derivative(Debug(bound = "T:Debug"))]
|
||||||
|
#[derivative(Clone(bound = ""))]
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct SharedFlag<T, OnMut> {
|
||||||
|
rc: Rc<RefCellFlag<T, OnMut>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// === API ===
|
||||||
|
|
||||||
|
impl<T: Default, OnMut> SharedFlag<T, OnMut> {
|
||||||
|
/// Constructor.
|
||||||
|
pub fn new(on_set: OnMut) -> Self {
|
||||||
|
Self { rc: Rc::new(RefCellFlag::new(on_set)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// === Arg ===
|
||||||
|
|
||||||
|
impl<T: HasArg, OnMut> HasArg for SharedFlag<T, OnMut> {
|
||||||
|
type Arg = Arg<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// === Global Operations ===
|
||||||
|
|
||||||
|
impl<T: HasUnsetAll, OnMut> SharedHasUnsetAll for SharedFlag<T, OnMut> {
|
||||||
|
fn unset_all(&self) {
|
||||||
|
self.rc.unset_all()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: HasCheckAll, OnMut> HasCheckAll for SharedFlag<T, OnMut> {
|
||||||
|
fn check_all(&self) -> bool {
|
||||||
|
self.rc.check_all()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Check ===
|
||||||
|
|
||||||
|
impl<T: FlagOps0, OnMut> HasCheck0 for SharedFlag<T, OnMut> {
|
||||||
|
fn check(&self) -> bool {
|
||||||
|
self.rc.check()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FlagOps1, OnMut> HasCheck1 for SharedFlag<T, OnMut> {
|
||||||
|
fn check(&self, arg: &Arg<T>) -> bool {
|
||||||
|
self.rc.check(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Set ===
|
||||||
|
|
||||||
|
impl<T: FlagOps0, OnMut: FnMut0> SharedHasSet0 for SharedFlag<T, OnMut> {
|
||||||
|
fn set(&self) {
|
||||||
|
self.rc.set()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: FlagOps1, OnMut: FnMut0> SharedHasSet1 for SharedFlag<T, OnMut> {
|
||||||
|
fn set(&self, arg: Arg<T>) {
|
||||||
|
self.rc.set(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Unset ===
|
||||||
|
|
||||||
|
impl<T: HasUnset0, OnMut> SharedHasUnset0 for SharedFlag<T, OnMut> {
|
||||||
|
fn unset(&self) {
|
||||||
|
self.rc.unset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: HasUnset1, OnMut> SharedHasUnset1 for SharedFlag<T, OnMut>
|
||||||
|
where Arg<T>: Display
|
||||||
|
{
|
||||||
|
fn unset(&self, arg: &Self::Arg) {
|
||||||
|
self.rc.unset(arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// === WeakSharedFlag ===
|
||||||
|
// ======================
|
||||||
|
|
||||||
|
/// A weak version of [`SharedFlag`].
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Debug(bound = "T:Debug"))]
|
#[derivative(Debug(bound = "T:Debug"))]
|
||||||
#[derivative(Clone(bound = ""))]
|
#[derivative(Clone(bound = ""))]
|
||||||
pub struct WeakSharedDirtyFlag<T, OnMut> {
|
#[repr(transparent)]
|
||||||
weak: Weak<RefCell<DirtyFlag<T, OnMut>>>,
|
pub struct WeakSharedFlag<T, OnMut> {
|
||||||
|
weak: Weak<RefCellFlag<T, OnMut>>,
|
||||||
}
|
}
|
||||||
impl<T, OnMut> SharedDirtyFlag<T, OnMut> {
|
impl<T, OnMut> SharedFlag<T, OnMut> {
|
||||||
pub fn downgrade(&self) -> WeakSharedDirtyFlag<T, OnMut> {
|
/// Downgrade the flag to its weak version.
|
||||||
|
pub fn downgrade(&self) -> WeakSharedFlag<T, OnMut> {
|
||||||
let weak = self.rc.downgrade();
|
let weak = self.rc.downgrade();
|
||||||
WeakSharedDirtyFlag { weak }
|
WeakSharedFlag { weak }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T, OnMut> WeakSharedDirtyFlag<T, OnMut> {
|
impl<T, OnMut> WeakSharedFlag<T, OnMut> {
|
||||||
pub fn upgrade(&self) -> Option<SharedDirtyFlag<T, OnMut>> {
|
/// Upgrade the flag to its strong version.
|
||||||
self.weak.upgrade().map(|rc| SharedDirtyFlag { rc })
|
pub fn upgrade(&self) -> Option<SharedFlag<T, OnMut>> {
|
||||||
|
self.weak.upgrade().map(|rc| SharedFlag { rc })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =============================================================================
|
// =================================================================================================
|
||||||
// === Flags ===================================================================
|
// === Flag Definitions ============================================================================
|
||||||
// =============================================================================
|
// =================================================================================================
|
||||||
|
|
||||||
|
macro_rules! define_flag {
|
||||||
|
($(#$meta:tt)* $name:ident $(< $($param:tt),* $(,)? >)?) => { paste! {
|
||||||
|
$(#$meta)*
|
||||||
|
pub type $name< $($($param,)*)? OnMut = ()> =
|
||||||
|
Flag<[<$name Data>] $(<$($param,)*>)?, OnMut>;
|
||||||
|
|
||||||
|
/// A version with an internal mutability pattern.
|
||||||
|
$(#$meta)*
|
||||||
|
pub type [<RefCell $name>]< $($($param,)*)? OnMut = ()> =
|
||||||
|
RefCellFlag<[<$name Data>] $(<$($param,)*>)?, OnMut>;
|
||||||
|
|
||||||
|
/// A version with an internal mutability pattern and a reference counting mechanism.
|
||||||
|
/// Can be cloned and downgraded to a weak reference.
|
||||||
|
$(#$meta)*
|
||||||
|
pub type [<Shared $name>]< $($($param,)*)? OnMut = ()> =
|
||||||
|
SharedFlag<[<$name Data>] $(<$($param,)*>)?, OnMut>;
|
||||||
|
|
||||||
|
/// A weak version of the shared flag.
|
||||||
|
$(#$meta)*
|
||||||
|
pub type [<WeakShared $name>]< $($($param,)*)? OnMut = ()> =
|
||||||
|
WeakSharedFlag<[<$name Data>] $(<$($param,)*>)?, OnMut>;
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ============
|
// ============
|
||||||
// === Bool ===
|
// === Bool ===
|
||||||
// ============
|
// ============
|
||||||
|
|
||||||
|
define_flag! {
|
||||||
/// The on / off dirty flag. If you need a simple dirty / clean switch, this one
|
/// The on / off dirty flag. If you need a simple dirty / clean switch, this one
|
||||||
/// is the right choice.
|
/// is the right choice.
|
||||||
|
Bool
|
||||||
|
}
|
||||||
|
|
||||||
pub type Bool<OnMut = ()> = DirtyFlag<BoolData, OnMut>;
|
/// Internal representation of the [`Bool`] flag.
|
||||||
pub type SharedBool<OnMut = ()> = SharedDirtyFlag<BoolData, OnMut>;
|
|
||||||
pub type WeakSharedBool<OnMut = ()> = WeakSharedDirtyFlag<BoolData, OnMut>;
|
|
||||||
pub trait BoolCtx<OnMut> = where OnMut: FnMut0;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Display, Default)]
|
#[derive(Clone, Copy, Debug, Display, Default)]
|
||||||
pub struct BoolData {
|
pub struct BoolData {
|
||||||
is_dirty: bool,
|
is_dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasCheckAll for BoolData {
|
impl HasCheckAll for BoolData {
|
||||||
fn check_all(&self) -> bool {
|
fn check_all(&self) -> bool {
|
||||||
self.is_dirty
|
self.is_dirty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasUnsetAll for BoolData {
|
impl HasUnsetAll for BoolData {
|
||||||
fn unset_all(&mut self) {
|
fn unset_all(&mut self) {
|
||||||
self.is_dirty = false
|
self.is_dirty = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasCheck0 for BoolData {
|
impl HasCheck0 for BoolData {
|
||||||
fn check(&self) -> bool {
|
fn check(&self) -> bool {
|
||||||
self.is_dirty
|
self.is_dirty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasSet0 for BoolData {
|
impl HasSet0 for BoolData {
|
||||||
fn set(&mut self) {
|
fn set(&mut self) {
|
||||||
self.is_dirty = true
|
self.is_dirty = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HasUnset0 for BoolData {
|
impl HasUnset0 for BoolData {
|
||||||
fn unset(&mut self) {
|
fn unset(&mut self) {
|
||||||
self.is_dirty = false
|
self.is_dirty = false
|
||||||
@ -392,15 +583,17 @@ impl HasUnset0 for BoolData {
|
|||||||
// === Range ===
|
// === Range ===
|
||||||
// =============
|
// =============
|
||||||
|
|
||||||
|
define_flag! {
|
||||||
/// Dirty flag which keeps information about a range of dirty items. It does not track items
|
/// Dirty flag which keeps information about a range of dirty items. It does not track items
|
||||||
/// separately, nor you are allowed to keep multiple ranges in it. Just a single value range.
|
/// separately, nor you are allowed to keep multiple ranges in it. Just a single value range.
|
||||||
|
Range<Ix>
|
||||||
|
}
|
||||||
|
|
||||||
pub type Range<Ix, OnMut> = DirtyFlag<RangeData<Ix>, OnMut>;
|
|
||||||
pub type SharedRange<Ix, OnMut> = SharedDirtyFlag<RangeData<Ix>, OnMut>;
|
|
||||||
pub trait RangeCtx<OnMut> = where OnMut: FnMut0;
|
|
||||||
pub trait RangeIx = PartialOrd + Copy + Debug;
|
pub trait RangeIx = PartialOrd + Copy + Debug;
|
||||||
|
|
||||||
|
/// Internal representation of the [`Range`] flag.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct RangeData<Ix = usize> {
|
pub struct RangeData<Ix = usize> {
|
||||||
pub range: Option<RangeInclusive<Ix>>,
|
pub range: Option<RangeInclusive<Ix>>,
|
||||||
}
|
}
|
||||||
@ -408,11 +601,13 @@ pub struct RangeData<Ix = usize> {
|
|||||||
impl<Ix> HasArg for RangeData<Ix> {
|
impl<Ix> HasArg for RangeData<Ix> {
|
||||||
type Arg = Ix;
|
type Arg = Ix;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Ix> HasCheckAll for RangeData<Ix> {
|
impl<Ix> HasCheckAll for RangeData<Ix> {
|
||||||
fn check_all(&self) -> bool {
|
fn check_all(&self) -> bool {
|
||||||
self.range.is_some()
|
self.range.is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Ix> HasUnsetAll for RangeData<Ix> {
|
impl<Ix> HasUnsetAll for RangeData<Ix> {
|
||||||
fn unset_all(&mut self) {
|
fn unset_all(&mut self) {
|
||||||
self.range = None
|
self.range = None
|
||||||
@ -464,18 +659,20 @@ impl<Ix: RangeIx> Display for RangeData<Ix> {
|
|||||||
// === Set ===
|
// === Set ===
|
||||||
// ===========
|
// ===========
|
||||||
|
|
||||||
/// Dirty flag which keeps a set of dirty values. The `HashSet` dirty flag
|
define_flag! {
|
||||||
/// counterpart. Please note that it uses `FxHashSet` under the hood, so there
|
/// Dirty flag which keeps a set of dirty values. The `HashSet` dirty flag counterpart. Please
|
||||||
/// are no guarantees regarding attack-proof hashing algorithm here.
|
/// note that it uses `FxHashSet` under the hood, so there are no guarantees regarding
|
||||||
|
/// attack-proof hashing algorithm here.
|
||||||
|
Set<Ix>
|
||||||
|
}
|
||||||
|
|
||||||
pub type Set<Ix, OnMut = ()> = DirtyFlag<SetData<Ix>, OnMut>;
|
|
||||||
pub type SharedSet<Ix, OnMut = ()> = SharedDirtyFlag<SetData<Ix>, OnMut>;
|
|
||||||
pub trait SetCtx<OnMut> = where OnMut: FnMut0;
|
|
||||||
pub trait SetItem = Eq + Hash + Debug;
|
pub trait SetItem = Eq + Hash + Debug;
|
||||||
|
|
||||||
|
/// Internal representation of the [`Set`] flag.
|
||||||
#[derive(Derivative, Shrinkwrap)]
|
#[derive(Derivative, Shrinkwrap)]
|
||||||
#[derivative(Debug(bound = "Item:SetItem"))]
|
#[derivative(Debug(bound = "Item:SetItem"))]
|
||||||
#[derivative(Default(bound = "Item:SetItem"))]
|
#[derivative(Default(bound = "Item:SetItem"))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct SetData<Item> {
|
pub struct SetData<Item> {
|
||||||
pub set: FxHashSet<Item>,
|
pub set: FxHashSet<Item>,
|
||||||
}
|
}
|
||||||
@ -534,13 +731,17 @@ impl<'t, Item: SetItem> IntoIterator for &'t SetData<Item> {
|
|||||||
// === Vector ===
|
// === Vector ===
|
||||||
// ==============
|
// ==============
|
||||||
|
|
||||||
|
define_flag! {
|
||||||
/// Dirty flag which keeps a vector of dirty values.
|
/// Dirty flag which keeps a vector of dirty values.
|
||||||
pub type Vector<Item, OnMut = ()> = DirtyFlag<VectorData<Item>, OnMut>;
|
Vector<Item>
|
||||||
pub type SharedVector<Item, OnMut = ()> = SharedDirtyFlag<VectorData<Item>, OnMut>;
|
}
|
||||||
|
|
||||||
pub trait VectorItem = Debug + PartialEq;
|
pub trait VectorItem = Debug + PartialEq;
|
||||||
|
|
||||||
|
/// Internal representation of the [`Vector`] flag.
|
||||||
#[derive(Derivative, Debug, Shrinkwrap)]
|
#[derive(Derivative, Debug, Shrinkwrap)]
|
||||||
#[derivative(Default(bound = ""))]
|
#[derivative(Default(bound = ""))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct VectorData<Item> {
|
pub struct VectorData<Item> {
|
||||||
pub vec: Vec<Item>,
|
pub vec: Vec<Item>,
|
||||||
}
|
}
|
||||||
@ -548,11 +749,13 @@ pub struct VectorData<Item> {
|
|||||||
impl<Item> HasArg for VectorData<Item> {
|
impl<Item> HasArg for VectorData<Item> {
|
||||||
type Arg = Item;
|
type Arg = Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Item> HasCheckAll for VectorData<Item> {
|
impl<Item> HasCheckAll for VectorData<Item> {
|
||||||
fn check_all(&self) -> bool {
|
fn check_all(&self) -> bool {
|
||||||
!self.vec.is_empty()
|
!self.vec.is_empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Item> HasUnsetAll for VectorData<Item> {
|
impl<Item> HasUnsetAll for VectorData<Item> {
|
||||||
fn unset_all(&mut self) {
|
fn unset_all(&mut self) {
|
||||||
self.vec.clear();
|
self.vec.clear();
|
||||||
@ -599,24 +802,27 @@ impl<'t, Item> IntoIterator for &'t VectorData<Item> {
|
|||||||
|
|
||||||
use bit_field::BitField as BF;
|
use bit_field::BitField as BF;
|
||||||
|
|
||||||
/// Dirty flag which keeps information about a set of enumerator values. The
|
define_flag! {
|
||||||
/// items must be a plain enumerator implementing `Into<usize>`. The data is
|
/// Dirty flag which keeps information about a set of enumerator values. The items must be a
|
||||||
/// stored as an efficient `BitField` under the hood.
|
/// plain enumerators implementing `Into<usize>`. The data is stored as an efficient `BitField`
|
||||||
|
/// under the hood.
|
||||||
|
Enum<Prim, T>
|
||||||
|
}
|
||||||
|
|
||||||
pub type Enum<Prim, T, OnMut> = DirtyFlag<EnumData<Prim, T>, OnMut>;
|
|
||||||
pub type SharedEnum<Prim, T, OnMut> = SharedDirtyFlag<EnumData<Prim, T>, OnMut>;
|
|
||||||
pub trait EnumCtx<OnMut> = where OnMut: FnMut0;
|
|
||||||
pub trait EnumBase = Default + PartialEq + Copy + BF;
|
pub trait EnumBase = Default + PartialEq + Copy + BF;
|
||||||
pub trait EnumElem = Copy + Into<usize>;
|
pub trait EnumElem = Copy + Into<usize>;
|
||||||
|
|
||||||
/// Dirty flag which keeps dirty indexes in a `BitField` under the hood.
|
/// Dirty flag which keeps dirty indexes in a `BitField` under the hood.
|
||||||
|
|
||||||
pub type BitField<Prim, OnMut> = Enum<Prim, usize, OnMut>;
|
pub type BitField<Prim, OnMut> = Enum<Prim, usize, OnMut>;
|
||||||
|
|
||||||
|
/// Shared version of the [`BitField`] flag.
|
||||||
pub type SharedBitField<Prim, OnMut> = SharedEnum<Prim, usize, OnMut>;
|
pub type SharedBitField<Prim, OnMut> = SharedEnum<Prim, usize, OnMut>;
|
||||||
|
|
||||||
|
/// Internal representation of the [`Enum`] flag.
|
||||||
#[derive(Derivative)]
|
#[derive(Derivative)]
|
||||||
#[derivative(Debug(bound = "Prim:Debug"))]
|
#[derivative(Debug(bound = "Prim:Debug"))]
|
||||||
#[derivative(Default(bound = "Prim:Default"))]
|
#[derivative(Default(bound = "Prim:Default"))]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub struct EnumData<Prim = u32, T = usize> {
|
pub struct EnumData<Prim = u32, T = usize> {
|
||||||
pub bits: Prim,
|
pub bits: Prim,
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
|
@ -197,7 +197,7 @@ type ProjectionDirty = dirty::SharedBool<()>;
|
|||||||
type TransformDirty = dirty::SharedBool<()>;
|
type TransformDirty = dirty::SharedBool<()>;
|
||||||
|
|
||||||
impl Camera2dData {
|
impl Camera2dData {
|
||||||
fn new(display_object: &display::object::Instance) -> Self {
|
fn new() -> Self {
|
||||||
let screen = Screen::new();
|
let screen = Screen::new();
|
||||||
let projection = default();
|
let projection = default();
|
||||||
let clipping = default();
|
let clipping = default();
|
||||||
@ -205,10 +205,9 @@ impl Camera2dData {
|
|||||||
let z_zoom_1 = 1.0;
|
let z_zoom_1 = 1.0;
|
||||||
let matrix = default();
|
let matrix = default();
|
||||||
let dirty = Dirty::new();
|
let dirty = Dirty::new();
|
||||||
let display_object = display_object.clone_ref();
|
let display_object = display::object::Instance::new();
|
||||||
let zoom_update_registry = default();
|
let zoom_update_registry = default();
|
||||||
let screen_update_registry = default();
|
let screen_update_registry = default();
|
||||||
display_object.set_on_updated(f_!(dirty.transform.set()));
|
|
||||||
display_object.mod_position(|p| p.z = 1.0);
|
display_object.mod_position(|p| p.z = 1.0);
|
||||||
dirty.projection.set();
|
dirty.projection.set();
|
||||||
let network = frp::Network::new("Camera2d");
|
let network = frp::Network::new("Camera2d");
|
||||||
@ -216,6 +215,7 @@ impl Camera2dData {
|
|||||||
frp_position <- source();
|
frp_position <- source();
|
||||||
frp_zoom <- source();
|
frp_zoom <- source();
|
||||||
frp_screen <- source();
|
frp_screen <- source();
|
||||||
|
eval_ display_object.on_updated (dirty.transform.set());
|
||||||
}
|
}
|
||||||
let frp = Frp { network, position: frp_position, zoom: frp_zoom, screen: frp_screen };
|
let frp = Frp { network, position: frp_position, zoom: frp_zoom, screen: frp_screen };
|
||||||
Self {
|
Self {
|
||||||
@ -248,7 +248,7 @@ impl Camera2dData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn recompute_view_matrix(&mut self) {
|
fn recompute_view_matrix(&mut self) {
|
||||||
let transform = self.display_object.matrix();
|
let transform = self.display_object.transformation_matrix();
|
||||||
self.matrix.view_inversed = transform;
|
self.matrix.view_inversed = transform;
|
||||||
self.matrix.view = transform.try_inverse().unwrap()
|
self.matrix.view = transform.try_inverse().unwrap()
|
||||||
}
|
}
|
||||||
@ -402,8 +402,8 @@ impl Camera2d {
|
|||||||
/// Creates new [`Camera2d`] instance. Please note that the camera will be of zero-size and in
|
/// Creates new [`Camera2d`] instance. Please note that the camera will be of zero-size and in
|
||||||
/// order for it to work properly, you have to initialize it by using the `set_screen` method.
|
/// order for it to work properly, you have to initialize it by using the `set_screen` method.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let display_object = display::object::Instance::new();
|
let data = Camera2dData::new();
|
||||||
let data = Camera2dData::new(&display_object);
|
let display_object = data.display_object.clone_ref();
|
||||||
let data = Rc::new(RefCell::new(data));
|
let data = Rc::new(RefCell::new(data));
|
||||||
Self { display_object, data }
|
Self { display_object, data }
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,12 @@ use crate::display::scene::layer::Layer;
|
|||||||
// === Export ===
|
// === Export ===
|
||||||
// ==============
|
// ==============
|
||||||
|
|
||||||
pub mod class;
|
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod transform;
|
pub mod instance;
|
||||||
|
pub mod transformation;
|
||||||
|
|
||||||
pub use class::Any;
|
pub use instance::Any;
|
||||||
pub use class::*;
|
pub use instance::*;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -64,14 +64,17 @@ impl<L: CloneRef + AsRef<Layer> + 'static> InstanceWithLayer<L> {
|
|||||||
/// callback ensures that the `layer` will always be attached to the same layer the
|
/// callback ensures that the `layer` will always be attached to the same layer the
|
||||||
/// `instance` is attached to.
|
/// `instance` is attached to.
|
||||||
pub fn new(instance: Instance, layer: L) -> Self {
|
pub fn new(instance: Instance, layer: L) -> Self {
|
||||||
instance.set_on_scene_layer_changed(f!([layer](_, source, destination) {
|
let network = &instance.network;
|
||||||
|
frp::extend! { network
|
||||||
|
eval instance.on_layer_change ([layer] ((_, source, destination)) {
|
||||||
if let Some(src_layer) = source {
|
if let Some(src_layer) = source {
|
||||||
src_layer.remove_sublayer(layer.as_ref());
|
src_layer.remove_sublayer(layer.as_ref());
|
||||||
}
|
}
|
||||||
if let Some(dst_layer) = destination {
|
if let Some(dst_layer) = destination {
|
||||||
dst_layer.add_sublayer(layer.as_ref());
|
dst_layer.add_sublayer(layer.as_ref());
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
}
|
||||||
Self { instance, layer }
|
Self { instance, layer }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::display::object::class::Instance;
|
use crate::display::object::instance::Instance;
|
||||||
use crate::display::object::class::WeakInstance;
|
use crate::display::object::instance::WeakInstance;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -47,8 +47,8 @@ pub struct SomeEvent {
|
|||||||
|
|
||||||
impl SomeEvent {
|
impl SomeEvent {
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
pub fn new<Host: 'static, T: 'static>(target: Option<&Instance<Host>>, payload: T) -> Self {
|
pub fn new<T: 'static>(target: Option<WeakInstance>, payload: T) -> Self {
|
||||||
let event = Event::new(target.map(|t| t.downgrade()), payload);
|
let event = Event::new(target, payload);
|
||||||
let state = event.state.clone_ref();
|
let state = event.state.clone_ref();
|
||||||
let captures = Rc::new(Cell::new(true));
|
let captures = Rc::new(Cell::new(true));
|
||||||
let bubbles = Rc::new(Cell::new(true));
|
let bubbles = Rc::new(Cell::new(true));
|
||||||
@ -68,7 +68,7 @@ impl SomeEvent {
|
|||||||
|
|
||||||
impl Default for SomeEvent {
|
impl Default for SomeEvent {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new::<(), ()>(None, ())
|
Self::new::<()>(None, ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,23 +93,23 @@ impl Default for SomeEvent {
|
|||||||
#[derivative(Clone(bound = ""))]
|
#[derivative(Clone(bound = ""))]
|
||||||
#[derivative(Debug(bound = "T: Debug"))]
|
#[derivative(Debug(bound = "T: Debug"))]
|
||||||
#[derivative(Default(bound = "T: Default"))]
|
#[derivative(Default(bound = "T: Default"))]
|
||||||
pub struct Event<Host: 'static, T> {
|
pub struct Event<T> {
|
||||||
data: Rc<EventData<Host, T>>,
|
data: Rc<EventData<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal representation of [`Event`].
|
/// Internal representation of [`Event`].
|
||||||
#[derive(Deref, Derivative)]
|
#[derive(Deref, Derivative)]
|
||||||
#[derivative(Debug(bound = "T: Debug"))]
|
#[derivative(Debug(bound = "T: Debug"))]
|
||||||
#[derivative(Default(bound = "T: Default"))]
|
#[derivative(Default(bound = "T: Default"))]
|
||||||
pub struct EventData<Host: 'static, T> {
|
pub struct EventData<T> {
|
||||||
#[deref]
|
#[deref]
|
||||||
payload: T,
|
payload: T,
|
||||||
target: Option<WeakInstance<Host>>,
|
target: Option<WeakInstance>,
|
||||||
state: Rc<Cell<State>>,
|
state: Rc<Cell<State>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Host, T> Event<Host, T> {
|
impl<T> Event<T> {
|
||||||
fn new(target: Option<WeakInstance<Host>>, payload: T) -> Self {
|
fn new(target: Option<WeakInstance>, payload: T) -> Self {
|
||||||
let state = default();
|
let state = default();
|
||||||
let data = Rc::new(EventData { payload, target, state });
|
let data = Rc::new(EventData { payload, target, state });
|
||||||
Self { data }
|
Self { data }
|
||||||
@ -130,7 +130,7 @@ impl<Host, T> Event<Host, T> {
|
|||||||
/// A reference to the object onto which the event was dispatched.
|
/// A reference to the object onto which the event was dispatched.
|
||||||
///
|
///
|
||||||
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Event/target.
|
/// See: https://developer.mozilla.org/en-US/docs/Web/API/Event/target.
|
||||||
pub fn target(&self) -> Option<Instance<Host>> {
|
pub fn target(&self) -> Option<Instance> {
|
||||||
self.data.target.as_ref().and_then(|t| t.upgrade())
|
self.data.target.as_ref().and_then(|t| t.upgrade())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -11,8 +11,9 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
/// Defines the order in which particular axis coordinates are processed. Used for example to define
|
/// Defines the order in which particular axis coordinates are processed. Used for example to define
|
||||||
/// the rotation order in `DisplayObject`.
|
/// the rotation order in `DisplayObject`.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub enum AxisOrder {
|
pub enum AxisOrder {
|
||||||
|
#[default]
|
||||||
XYZ,
|
XYZ,
|
||||||
XZY,
|
XZY,
|
||||||
YXZ,
|
YXZ,
|
||||||
@ -21,22 +22,17 @@ pub enum AxisOrder {
|
|||||||
ZYX,
|
ZYX,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AxisOrder {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::XYZ
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===========================
|
||||||
// ======================
|
// === TransformationOrder ===
|
||||||
// === TransformOrder ===
|
// ===========================
|
||||||
// ======================
|
|
||||||
|
|
||||||
/// Defines the order in which transformations (scale, rotate, translate) are applied to a
|
/// Defines the order in which transformations (scale, rotate, translate) are applied to a
|
||||||
/// particular object.
|
/// particular object.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
pub enum TransformOrder {
|
pub enum TransformationOrder {
|
||||||
|
#[default]
|
||||||
ScaleRotateTranslate,
|
ScaleRotateTranslate,
|
||||||
ScaleTranslateRotate,
|
ScaleTranslateRotate,
|
||||||
RotateScaleTranslate,
|
RotateScaleTranslate,
|
||||||
@ -45,32 +41,26 @@ pub enum TransformOrder {
|
|||||||
TranslateScaleRotate,
|
TranslateScaleRotate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TransformOrder {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::ScaleRotateTranslate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
// ======================
|
||||||
// =================
|
// === Transformation ===
|
||||||
// === Transform ===
|
// ======================
|
||||||
// =================
|
|
||||||
|
|
||||||
/// Structure describing transform of an object, in particular its position, scale, and rotation.
|
/// Structure describing transform of an object, in particular its position, scale, and rotation.
|
||||||
/// You can use methods like `matrix` to get a combined transformation matrix. Bear in mind that
|
/// You can use methods like `matrix` to get a combined transformation matrix. Bear in mind that
|
||||||
/// the matrix will always be recomputed from scratch. This structure does not contain any caching
|
/// the matrix will always be recomputed from scratch. This structure does not contain any caching
|
||||||
/// mechanisms.
|
/// mechanisms.
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Transform {
|
pub struct Transformation {
|
||||||
pub position: Vector3<f32>,
|
pub position: Vector3<f32>,
|
||||||
pub scale: Vector3<f32>,
|
pub scale: Vector3<f32>,
|
||||||
pub rotation: Vector3<f32>,
|
pub rotation: Vector3<f32>,
|
||||||
pub transform_order: TransformOrder,
|
pub transform_order: TransformationOrder,
|
||||||
pub rotation_order: AxisOrder,
|
pub rotation_order: AxisOrder,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Transform {
|
impl Default for Transformation {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let position = Vector3::new(0.0, 0.0, 0.0);
|
let position = Vector3::new(0.0, 0.0, 0.0);
|
||||||
let scale = Vector3::new(1.0, 1.0, 1.0);
|
let scale = Vector3::new(1.0, 1.0, 1.0);
|
||||||
@ -81,7 +71,7 @@ impl Default for Transform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Transform {
|
impl Transformation {
|
||||||
/// Creates a new transformation object.
|
/// Creates a new transformation object.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
default()
|
default()
|
||||||
@ -93,32 +83,32 @@ impl Transform {
|
|||||||
let mut matrix = Matrix4::identity();
|
let mut matrix = Matrix4::identity();
|
||||||
let matrix_ref = &mut matrix;
|
let matrix_ref = &mut matrix;
|
||||||
match self.transform_order {
|
match self.transform_order {
|
||||||
TransformOrder::ScaleRotateTranslate => {
|
TransformationOrder::ScaleRotateTranslate => {
|
||||||
self.append_scale(matrix_ref);
|
self.append_scale(matrix_ref);
|
||||||
self.append_rotation(matrix_ref);
|
self.append_rotation(matrix_ref);
|
||||||
self.append_translation(matrix_ref);
|
self.append_translation(matrix_ref);
|
||||||
}
|
}
|
||||||
TransformOrder::ScaleTranslateRotate => {
|
TransformationOrder::ScaleTranslateRotate => {
|
||||||
self.append_scale(matrix_ref);
|
self.append_scale(matrix_ref);
|
||||||
self.append_translation(matrix_ref);
|
self.append_translation(matrix_ref);
|
||||||
self.append_rotation(matrix_ref);
|
self.append_rotation(matrix_ref);
|
||||||
}
|
}
|
||||||
TransformOrder::RotateScaleTranslate => {
|
TransformationOrder::RotateScaleTranslate => {
|
||||||
self.append_rotation(matrix_ref);
|
self.append_rotation(matrix_ref);
|
||||||
self.append_scale(matrix_ref);
|
self.append_scale(matrix_ref);
|
||||||
self.append_translation(matrix_ref);
|
self.append_translation(matrix_ref);
|
||||||
}
|
}
|
||||||
TransformOrder::RotateTranslateScale => {
|
TransformationOrder::RotateTranslateScale => {
|
||||||
self.append_rotation(matrix_ref);
|
self.append_rotation(matrix_ref);
|
||||||
self.append_translation(matrix_ref);
|
self.append_translation(matrix_ref);
|
||||||
self.append_scale(matrix_ref);
|
self.append_scale(matrix_ref);
|
||||||
}
|
}
|
||||||
TransformOrder::TranslateRotateScale => {
|
TransformationOrder::TranslateRotateScale => {
|
||||||
self.append_translation(matrix_ref);
|
self.append_translation(matrix_ref);
|
||||||
self.append_rotation(matrix_ref);
|
self.append_rotation(matrix_ref);
|
||||||
self.append_scale(matrix_ref);
|
self.append_scale(matrix_ref);
|
||||||
}
|
}
|
||||||
TransformOrder::TranslateScaleRotate => {
|
TransformationOrder::TranslateScaleRotate => {
|
||||||
self.append_translation(matrix_ref);
|
self.append_translation(matrix_ref);
|
||||||
self.append_scale(matrix_ref);
|
self.append_scale(matrix_ref);
|
||||||
self.append_rotation(matrix_ref);
|
self.append_rotation(matrix_ref);
|
||||||
@ -158,24 +148,24 @@ impl Transform {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =======================
|
// ============================
|
||||||
// === CachedTransform ===
|
// === CachedTransformation ===
|
||||||
// =======================
|
// ============================
|
||||||
|
|
||||||
/// The same as `Transform` but with caching. It contains cached transformation matrix and dirty
|
/// The same as `Transformation` but with caching. It contains cached transformation matrix and
|
||||||
/// flags which are set after fields are modified. You can use the `update` function to recompute
|
/// dirty flags which are set after fields are modified. You can use the `update` function to
|
||||||
/// the matrix.
|
/// recompute the matrix.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[allow(missing_copy_implementations)]
|
#[allow(missing_copy_implementations)]
|
||||||
pub struct CachedTransform {
|
pub struct CachedTransformation {
|
||||||
transform: Transform,
|
transform: Transformation,
|
||||||
transform_matrix: Matrix4<f32>,
|
transform_matrix: Matrix4<f32>,
|
||||||
origin: Matrix4<f32>,
|
origin: Matrix4<f32>,
|
||||||
pub matrix: Matrix4<f32>,
|
pub matrix: Matrix4<f32>,
|
||||||
pub dirty: bool,
|
pub dirty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CachedTransform {
|
impl Default for CachedTransformation {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let transform = default();
|
let transform = default();
|
||||||
let transform_matrix = Matrix4::identity();
|
let transform_matrix = Matrix4::identity();
|
||||||
@ -186,16 +176,16 @@ impl Default for CachedTransform {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CachedTransform {
|
impl CachedTransformation {
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
default()
|
default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the transformation matrix and return information if the data was really updated.
|
/// Update the transformation matrix if it was out of date. Returns [`true`] if the update was
|
||||||
|
/// needed.
|
||||||
pub fn update(&mut self, new_origin: Option<Matrix4<f32>>) -> bool {
|
pub fn update(&mut self, new_origin: Option<Matrix4<f32>>) -> bool {
|
||||||
let origin_changed = new_origin.is_some();
|
let changed = self.dirty || new_origin.is_some();
|
||||||
let changed = self.dirty || origin_changed;
|
|
||||||
if changed {
|
if changed {
|
||||||
if self.dirty {
|
if self.dirty {
|
||||||
self.transform_matrix = self.transform.matrix();
|
self.transform_matrix = self.transform.matrix();
|
||||||
@ -211,7 +201,7 @@ impl CachedTransform {
|
|||||||
|
|
||||||
// === Getters ===
|
// === Getters ===
|
||||||
|
|
||||||
impl CachedTransform {
|
impl CachedTransformation {
|
||||||
pub fn position(&self) -> Vector3<f32> {
|
pub fn position(&self) -> Vector3<f32> {
|
||||||
self.transform.position
|
self.transform.position
|
||||||
}
|
}
|
||||||
@ -236,7 +226,7 @@ impl CachedTransform {
|
|||||||
|
|
||||||
// === Setters ===
|
// === Setters ===
|
||||||
|
|
||||||
impl CachedTransform {
|
impl CachedTransformation {
|
||||||
pub fn position_mut(&mut self) -> &mut Vector3<f32> {
|
pub fn position_mut(&mut self) -> &mut Vector3<f32> {
|
||||||
self.dirty = true;
|
self.dirty = true;
|
||||||
&mut self.transform.position
|
&mut self.transform.position
|
@ -15,6 +15,7 @@ use crate::display;
|
|||||||
use crate::display::camera::Camera2d;
|
use crate::display::camera::Camera2d;
|
||||||
use crate::display::render;
|
use crate::display::render;
|
||||||
use crate::display::scene::dom::DomScene;
|
use crate::display::scene::dom::DomScene;
|
||||||
|
use crate::display::shape::primitive::glsl;
|
||||||
use crate::display::style;
|
use crate::display::style;
|
||||||
use crate::display::style::data::DataMatch;
|
use crate::display::style::data::DataMatch;
|
||||||
use crate::display::symbol::registry::SymbolRegistry;
|
use crate::display::symbol::registry::SymbolRegistry;
|
||||||
@ -122,6 +123,7 @@ pub struct Mouse {
|
|||||||
pub mouse_manager: MouseManager,
|
pub mouse_manager: MouseManager,
|
||||||
pub last_position: Rc<Cell<Vector2<i32>>>,
|
pub last_position: Rc<Cell<Vector2<i32>>>,
|
||||||
pub position: Uniform<Vector2<i32>>,
|
pub position: Uniform<Vector2<i32>>,
|
||||||
|
pub click_count: Uniform<i32>,
|
||||||
pub hover_rgba: Uniform<Vector4<u32>>,
|
pub hover_rgba: Uniform<Vector4<u32>>,
|
||||||
pub target: Rc<Cell<PointerTargetId>>,
|
pub target: Rc<Cell<PointerTargetId>>,
|
||||||
pub handles: Rc<[callback::Handle; 4]>,
|
pub handles: Rc<[callback::Handle; 4]>,
|
||||||
@ -135,17 +137,19 @@ impl Mouse {
|
|||||||
root: &web::dom::WithKnownShape<web::HtmlDivElement>,
|
root: &web::dom::WithKnownShape<web::HtmlDivElement>,
|
||||||
variables: &UniformScope,
|
variables: &UniformScope,
|
||||||
current_js_event: &CurrentJsEvent,
|
current_js_event: &CurrentJsEvent,
|
||||||
|
display_mode: &Rc<Cell<glsl::codes::DisplayModes>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let scene_frp = scene_frp.clone_ref();
|
let scene_frp = scene_frp.clone_ref();
|
||||||
let target = PointerTargetId::default();
|
let target = PointerTargetId::default();
|
||||||
let last_position = Rc::new(Cell::new(Vector2::new(0, 0)));
|
let last_position = Rc::new(Cell::new(Vector2::new(0, 0)));
|
||||||
let position = variables.add_or_panic("mouse_position", Vector2(0, 0));
|
let position = variables.add_or_panic("mouse_position", Vector2(0, 0));
|
||||||
|
let click_count = variables.add_or_panic("mouse_click_count", 0);
|
||||||
let hover_rgba = variables.add_or_panic("mouse_hover_ids", Vector4(0, 0, 0, 0));
|
let hover_rgba = variables.add_or_panic("mouse_hover_ids", Vector4(0, 0, 0, 0));
|
||||||
let target = Rc::new(Cell::new(target));
|
let target = Rc::new(Cell::new(target));
|
||||||
let mouse_manager = MouseManager::new_separated(&root.clone_ref().into(), &web::window);
|
let mouse_manager = MouseManager::new_separated(&root.clone_ref().into(), &web::window);
|
||||||
let frp = frp::io::Mouse::new();
|
let frp = frp::io::Mouse::new();
|
||||||
let on_move = mouse_manager.on_move.add(current_js_event.make_event_handler(
|
let on_move = mouse_manager.on_move.add(current_js_event.make_event_handler(
|
||||||
f!([frp,scene_frp,position,last_position] (event:&mouse::OnMove) {
|
f!([frp, scene_frp, position, last_position, display_mode] (event: &mouse::OnMove) {
|
||||||
let shape = scene_frp.shape.value();
|
let shape = scene_frp.shape.value();
|
||||||
let pixel_ratio = shape.pixel_ratio;
|
let pixel_ratio = shape.pixel_ratio;
|
||||||
let screen_x = event.client_x();
|
let screen_x = event.client_x();
|
||||||
@ -158,24 +162,46 @@ impl Mouse {
|
|||||||
let new_canvas_position = new_pos.map(|v| (v as f32 * pixel_ratio) as i32);
|
let new_canvas_position = new_pos.map(|v| (v as f32 * pixel_ratio) as i32);
|
||||||
position.set(new_canvas_position);
|
position.set(new_canvas_position);
|
||||||
let position = Vector2(new_pos.x as f32,new_pos.y as f32) - shape.center();
|
let position = Vector2(new_pos.x as f32,new_pos.y as f32) - shape.center();
|
||||||
|
if display_mode.get().allow_mouse_events() {
|
||||||
frp.position.emit(position);
|
frp.position.emit(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
}),
|
||||||
|
));
|
||||||
|
let on_down = mouse_manager.on_down.add(current_js_event.make_event_handler(
|
||||||
|
f!([frp, click_count, display_mode] (event:&mouse::OnDown) {
|
||||||
|
click_count.modify(|v| *v += 1);
|
||||||
|
if display_mode.get().allow_mouse_events() {
|
||||||
|
frp.down.emit(event.button());
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
let on_up = mouse_manager.on_up.add(current_js_event.make_event_handler(
|
||||||
|
f!([frp, display_mode] (event:&mouse::OnUp) {
|
||||||
|
if display_mode.get().allow_mouse_events() {
|
||||||
|
frp.up.emit(event.button())
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
let on_wheel = mouse_manager.on_wheel.add(current_js_event.make_event_handler(
|
||||||
|
f_!([frp, display_mode] {
|
||||||
|
if display_mode.get().allow_mouse_events() {
|
||||||
|
frp.wheel.emit(())
|
||||||
|
}
|
||||||
|
}),
|
||||||
));
|
));
|
||||||
let on_down = mouse_manager.on_down.add(
|
|
||||||
current_js_event
|
|
||||||
.make_event_handler(f!((event:&mouse::OnDown) frp.down.emit(event.button()))),
|
|
||||||
);
|
|
||||||
let on_up = mouse_manager.on_up.add(
|
|
||||||
current_js_event
|
|
||||||
.make_event_handler(f!((event:&mouse::OnUp) frp.up.emit(event.button()))),
|
|
||||||
);
|
|
||||||
let on_wheel = mouse_manager
|
|
||||||
.on_wheel
|
|
||||||
.add(current_js_event.make_event_handler(f_!(frp.wheel.emit(()))));
|
|
||||||
let handles = Rc::new([on_move, on_down, on_up, on_wheel]);
|
let handles = Rc::new([on_move, on_down, on_up, on_wheel]);
|
||||||
Self { mouse_manager, last_position, position, hover_rgba, target, handles, frp, scene_frp }
|
Self {
|
||||||
|
mouse_manager,
|
||||||
|
last_position,
|
||||||
|
position,
|
||||||
|
click_count,
|
||||||
|
hover_rgba,
|
||||||
|
target,
|
||||||
|
handles,
|
||||||
|
frp,
|
||||||
|
scene_frp,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Re-emits FRP mouse changed position event with the last mouse position value.
|
/// Re-emits FRP mouse changed position event with the last mouse position value.
|
||||||
@ -688,7 +714,7 @@ pub struct UpdateStatus {
|
|||||||
|
|
||||||
#[derive(Clone, CloneRef, Debug)]
|
#[derive(Clone, CloneRef, Debug)]
|
||||||
pub struct SceneData {
|
pub struct SceneData {
|
||||||
pub display_object: display::object::Instance,
|
pub display_object: display::object::Root,
|
||||||
pub dom: Dom,
|
pub dom: Dom,
|
||||||
pub context: Rc<RefCell<Option<Context>>>,
|
pub context: Rc<RefCell<Option<Context>>>,
|
||||||
pub context_lost_handler: Rc<RefCell<Option<ContextLostHandler>>>,
|
pub context_lost_handler: Rc<RefCell<Option<ContextLostHandler>>>,
|
||||||
@ -710,17 +736,22 @@ pub struct SceneData {
|
|||||||
pub frp: Frp,
|
pub frp: Frp,
|
||||||
pub pointer_position_changed: Rc<Cell<bool>>,
|
pub pointer_position_changed: Rc<Cell<bool>>,
|
||||||
pub shader_compiler: shader::compiler::Controller,
|
pub shader_compiler: shader::compiler::Controller,
|
||||||
|
display_mode: Rc<Cell<glsl::codes::DisplayModes>>,
|
||||||
extensions: Extensions,
|
extensions: Extensions,
|
||||||
disable_context_menu: Rc<EventListenerHandle>,
|
disable_context_menu: Rc<EventListenerHandle>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SceneData {
|
impl SceneData {
|
||||||
/// Create new instance with the provided on-dirty callback.
|
/// Create new instance with the provided on-dirty callback.
|
||||||
pub fn new<OnMut: Fn() + Clone + 'static>(stats: &Stats, on_mut: OnMut) -> Self {
|
pub fn new<OnMut: Fn() + Clone + 'static>(
|
||||||
|
stats: &Stats,
|
||||||
|
on_mut: OnMut,
|
||||||
|
display_mode: &Rc<Cell<glsl::codes::DisplayModes>>,
|
||||||
|
) -> Self {
|
||||||
debug!("Initializing.");
|
debug!("Initializing.");
|
||||||
|
let display_mode = display_mode.clone_ref();
|
||||||
let dom = Dom::new();
|
let dom = Dom::new();
|
||||||
let display_object = display::object::Instance::new();
|
let display_object = display::object::Root::new();
|
||||||
display_object.force_set_visibility(true);
|
|
||||||
let variables = UniformScope::new();
|
let variables = UniformScope::new();
|
||||||
let dirty = Dirty::new(on_mut);
|
let dirty = Dirty::new(on_mut);
|
||||||
let symbols_dirty = &dirty.symbols;
|
let symbols_dirty = &dirty.symbols;
|
||||||
@ -734,7 +765,7 @@ impl SceneData {
|
|||||||
let style_sheet = style::Sheet::new();
|
let style_sheet = style::Sheet::new();
|
||||||
let current_js_event = CurrentJsEvent::new();
|
let current_js_event = CurrentJsEvent::new();
|
||||||
let frp = Frp::new(&dom.root.shape);
|
let frp = Frp::new(&dom.root.shape);
|
||||||
let mouse = Mouse::new(&frp, &dom.root, &variables, ¤t_js_event);
|
let mouse = Mouse::new(&frp, &dom.root, &variables, ¤t_js_event, &display_mode);
|
||||||
let disable_context_menu = Rc::new(web::ignore_context_menu(&dom.root));
|
let disable_context_menu = Rc::new(web::ignore_context_menu(&dom.root));
|
||||||
let keyboard = Keyboard::new(¤t_js_event);
|
let keyboard = Keyboard::new(¤t_js_event);
|
||||||
let network = &frp.network;
|
let network = &frp.network;
|
||||||
@ -759,6 +790,7 @@ impl SceneData {
|
|||||||
let shader_compiler = default();
|
let shader_compiler = default();
|
||||||
Self {
|
Self {
|
||||||
display_object,
|
display_object,
|
||||||
|
display_mode,
|
||||||
dom,
|
dom,
|
||||||
context,
|
context,
|
||||||
context_lost_handler,
|
context_lost_handler,
|
||||||
@ -927,10 +959,10 @@ impl SceneData {
|
|||||||
screen_pos: Vector2,
|
screen_pos: Vector2,
|
||||||
) -> Vector2 {
|
) -> Vector2 {
|
||||||
let origin_world_space = Vector4(0.0, 0.0, 0.0, 1.0);
|
let origin_world_space = Vector4(0.0, 0.0, 0.0, 1.0);
|
||||||
let layer = object.display_layer().and_then(|t| t.upgrade());
|
let layer = object.display_layer();
|
||||||
let camera = layer.map_or(self.camera(), |l| l.camera());
|
let camera = layer.map_or(self.camera(), |l| l.camera());
|
||||||
let origin_clip_space = camera.view_projection_matrix() * origin_world_space;
|
let origin_clip_space = camera.view_projection_matrix() * origin_world_space;
|
||||||
let inv_object_matrix = object.transform_matrix().try_inverse().unwrap();
|
let inv_object_matrix = object.transformation_matrix().try_inverse().unwrap();
|
||||||
|
|
||||||
let shape = camera.screen();
|
let shape = camera.screen();
|
||||||
let clip_space_z = origin_clip_space.z;
|
let clip_space_z = origin_clip_space.z;
|
||||||
@ -1017,8 +1049,12 @@ pub struct Scene {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
pub fn new<OnMut: Fn() + Clone + 'static>(stats: &Stats, on_mut: OnMut) -> Self {
|
pub fn new<OnMut: Fn() + Clone + 'static>(
|
||||||
let no_mut_access = SceneData::new(stats, on_mut);
|
stats: &Stats,
|
||||||
|
on_mut: OnMut,
|
||||||
|
display_mode: &Rc<Cell<glsl::codes::DisplayModes>>,
|
||||||
|
) -> Self {
|
||||||
|
let no_mut_access = SceneData::new(stats, on_mut, display_mode);
|
||||||
let this = Self { no_mut_access };
|
let this = Self { no_mut_access };
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
@ -210,15 +210,8 @@ impl DomScene {
|
|||||||
/// Creates a new instance of DomSymbol and adds it to parent.
|
/// Creates a new instance of DomSymbol and adds it to parent.
|
||||||
pub fn manage(&self, object: &DomSymbol) {
|
pub fn manage(&self, object: &DomSymbol) {
|
||||||
let dom = object.dom();
|
let dom = object.dom();
|
||||||
let data = &self.data;
|
|
||||||
if object.is_visible() {
|
|
||||||
self.view_projection_dom.append_or_warn(dom);
|
self.view_projection_dom.append_or_warn(dom);
|
||||||
}
|
}
|
||||||
object.display_object().set_on_hide(f_!(dom.remove()));
|
|
||||||
object.display_object().set_on_show(f__!([data,dom] {
|
|
||||||
data.view_projection_dom.append_or_warn(&dom)
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update the objects to match the new camera's point of view. This function should be called
|
/// Update the objects to match the new camera's point of view. This function should be called
|
||||||
/// only after camera position change.
|
/// only after camera position change.
|
||||||
@ -227,7 +220,7 @@ impl DomScene {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let trans_cam = camera.transform_matrix().try_inverse();
|
let trans_cam = camera.transformation_matrix().try_inverse();
|
||||||
let trans_cam = trans_cam.expect("Camera's matrix is not invertible.");
|
let trans_cam = trans_cam.expect("Camera's matrix is not invertible.");
|
||||||
let trans_cam = trans_cam.map(eps);
|
let trans_cam = trans_cam.map(eps);
|
||||||
let trans_cam = inverse_y_translation(trans_cam);
|
let trans_cam = inverse_y_translation(trans_cam);
|
||||||
|
@ -154,30 +154,11 @@ use std::any::TypeId;
|
|||||||
/// Please note that the current implementation does not allow for hierarchical masks (masks applied
|
/// Please note that the current implementation does not allow for hierarchical masks (masks applied
|
||||||
/// to already masked area or masks applied to masks). If you try using masks in hierarchical way,
|
/// to already masked area or masks applied to masks). If you try using masks in hierarchical way,
|
||||||
/// the nested masks will be skipped and a warning will be emitted to the console.
|
/// the nested masks will be skipped and a warning will be emitted to the console.
|
||||||
#[derive(Clone, CloneRef)]
|
#[derive(Clone, CloneRef, Deref)]
|
||||||
pub struct Layer {
|
pub struct Layer {
|
||||||
model: Rc<LayerModel>,
|
model: Rc<LayerModel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Layer {
|
|
||||||
type Target = LayerModel;
|
|
||||||
fn deref(&self) -> &Self::Target {
|
|
||||||
&self.model
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<Layer> for Layer {
|
|
||||||
fn as_ref(&self) -> &Layer {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Debug for Layer {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
Debug::fmt(&*self.model, f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Layer {
|
impl Layer {
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
pub fn new(name: impl Into<String>) -> Self {
|
pub fn new(name: impl Into<String>) -> Self {
|
||||||
@ -207,7 +188,7 @@ impl Layer {
|
|||||||
|
|
||||||
/// Remove the display object from a layer it was assigned to, if any.
|
/// Remove the display object from a layer it was assigned to, if any.
|
||||||
pub fn remove(&self, object: impl display::Object) {
|
pub fn remove(&self, object: impl display::Object) {
|
||||||
object.display_object().remove_from_scene_layer(self);
|
object.display_object().remove_from_display_layer(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Instantiate the provided [`ShapeProxy`].
|
/// Instantiate the provided [`ShapeProxy`].
|
||||||
@ -258,12 +239,31 @@ impl Layer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Layer> for Layer {
|
||||||
|
fn as_ref(&self) -> &Layer {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Layer {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
Debug::fmt(&*self.model, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<&Layer> for LayerId {
|
impl From<&Layer> for LayerId {
|
||||||
fn from(t: &Layer) -> Self {
|
fn from(t: &Layer) -> Self {
|
||||||
t.id()
|
t.id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for Layer {}
|
||||||
|
impl PartialEq for Layer {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
Rc::ptr_eq(&self.model, &other.model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =================
|
// =================
|
||||||
@ -315,6 +315,7 @@ impl PartialEq for WeakLayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ==================
|
// ==================
|
||||||
// === LayerModel ===
|
// === LayerModel ===
|
||||||
// ==================
|
// ==================
|
||||||
|
@ -3,21 +3,13 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::control::io::mouse;
|
use crate::control::io::mouse;
|
||||||
|
use crate::display::shape::primitive::glsl;
|
||||||
use crate::display::symbol;
|
use crate::display::symbol;
|
||||||
|
|
||||||
use enso_frp as frp;
|
use enso_frp as frp;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =================
|
|
||||||
// === Constants ===
|
|
||||||
// =================
|
|
||||||
|
|
||||||
const ID_ENCODING_OVERFLOW_ERR: u32 =
|
|
||||||
include!("../shape/primitive/glsl/error_codes/id_encoding_overflow.txt");
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =====================
|
// =====================
|
||||||
// === PointerTarget ===
|
// === PointerTarget ===
|
||||||
// =====================
|
// =====================
|
||||||
@ -175,7 +167,7 @@ impl PointerTargetId {
|
|||||||
Ok(Self::Symbol { id })
|
Ok(Self::Symbol { id })
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let err = if alpha == ID_ENCODING_OVERFLOW_ERR {
|
let err = if alpha == glsl::codes::ID_ENCODING_OVERFLOW_ERROR {
|
||||||
DecodeError::Overflow
|
DecodeError::Overflow
|
||||||
} else {
|
} else {
|
||||||
DecodeError::WrongAlpha(alpha)
|
DecodeError::WrongAlpha(alpha)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
// ==============
|
// ==============
|
||||||
|
|
||||||
pub mod def;
|
pub mod def;
|
||||||
|
pub mod glsl;
|
||||||
pub mod shader;
|
pub mod shader;
|
||||||
pub mod style_watch;
|
pub mod style_watch;
|
||||||
pub mod system;
|
pub mod system;
|
||||||
|
@ -206,7 +206,7 @@ define_sdf_shapes! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Line (width:f32) {
|
Line (width:f32) {
|
||||||
return bound_sdf(abs(position.y)-width, bounding_box(0.0,width));
|
return bound_sdf(abs(position.y) - width/2.0, bounding_box(0.0,width));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ use crate::data::color;
|
|||||||
use crate::display::shape::primitive::def::unit::PixelDistance;
|
use crate::display::shape::primitive::def::unit::PixelDistance;
|
||||||
use crate::system::gpu::shader::glsl::Glsl;
|
use crate::system::gpu::shader::glsl::Glsl;
|
||||||
|
|
||||||
|
use enso_types;
|
||||||
use nalgebra::Scalar;
|
use nalgebra::Scalar;
|
||||||
|
|
||||||
|
|
||||||
@ -192,123 +193,6 @@ where T: Max + Into<Glsl>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! dim_impl {
|
|
||||||
($trait:ident for $tp:ty {
|
|
||||||
type $dim_ty_name:ident = $dim_ty:ty;
|
|
||||||
args = [$($single_arg:ident),* $(,)?];
|
|
||||||
$(swizzling = $multi_ty:ident [$($multi_arg:ident),* $(,)?];)*
|
|
||||||
}) => {
|
|
||||||
impl<T: Scalar + Copy> $trait for $tp {
|
|
||||||
type $dim_ty_name = $dim_ty;
|
|
||||||
$(
|
|
||||||
fn $single_arg(&self) -> Self::Dim1Type {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => Var::Static(t.$single_arg.clone()),
|
|
||||||
Self::Dynamic(t) => {
|
|
||||||
let code = format!("{}.{}", t, stringify!($single_arg));
|
|
||||||
Var::Dynamic(code.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*
|
|
||||||
$($(
|
|
||||||
fn $multi_arg(&self) -> Self::$multi_ty {
|
|
||||||
match self {
|
|
||||||
Self::Static(t) => Var::Static(t.$multi_arg()),
|
|
||||||
Self::Dynamic(t) => {
|
|
||||||
let code = format!("{}.{}", t, stringify!($multi_arg));
|
|
||||||
Var::Dynamic(code.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)*)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
dim_impl! ( Dim1 for Var<Vector2<T>> {
|
|
||||||
type Dim1Type = Var<T>;
|
|
||||||
args = [x];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim2 for Var<Vector2<T>> {
|
|
||||||
type Dim2Type = Var<Vector2<T>>;
|
|
||||||
args = [y];
|
|
||||||
swizzling = Dim2Type [xx, xy, yx, yy];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim1 for Var<Vector3<T>> {
|
|
||||||
type Dim1Type = Var<T>;
|
|
||||||
args = [x];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim2 for Var<Vector3<T>> {
|
|
||||||
type Dim2Type = Var<Vector2<T>>;
|
|
||||||
args = [y];
|
|
||||||
swizzling = Dim2Type [xx, xy, yx, yy];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim3 for Var<Vector3<T>> {
|
|
||||||
type Dim3Type = Var<Vector3<T>>;
|
|
||||||
args = [z];
|
|
||||||
swizzling = Dim2Type [zz, xz, zx, yz, zy];
|
|
||||||
swizzling = Dim3Type [
|
|
||||||
xxx, xxy, xxz, xyx, xyy, xyz, xzx, xzy, xzz, yxx, yxy, yxz, yyx, yyy, yyz, yzx, yzy, yzz,
|
|
||||||
zxx, zxy, zxz, zyx, zyy, zyz, zzx, zzy, zzz
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim1 for Var<Vector4<T>> {
|
|
||||||
type Dim1Type = Var<T>;
|
|
||||||
args = [x];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim2 for Var<Vector4<T>> {
|
|
||||||
type Dim2Type = Var<Vector2<T>>;
|
|
||||||
args = [y];
|
|
||||||
swizzling = Dim2Type [xx, xy, yx, yy];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim3 for Var<Vector4<T>> {
|
|
||||||
type Dim3Type = Var<Vector3<T>>;
|
|
||||||
args = [z];
|
|
||||||
swizzling = Dim2Type [zz, xz, zx, yz, zy];
|
|
||||||
swizzling = Dim3Type [
|
|
||||||
xxx, xxy, xxz, xyx, xyy, xyz, xzx, xzy, xzz, yxx, yxy, yxz, yyx, yyy, yyz, yzx, yzy, yzz,
|
|
||||||
zxx, zxy, zxz, zyx, zyy, zyz, zzx, zzy, zzz
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
dim_impl! ( Dim4 for Var<Vector4<T>> {
|
|
||||||
type Dim4Type = Var<Vector4<T>>;
|
|
||||||
args = [w];
|
|
||||||
swizzling = Dim2Type [ww, xw, wx, yw, wy, zw, wz];
|
|
||||||
swizzling = Dim3Type [
|
|
||||||
xxw, xyw, xzw, yxw, yyw, yzw, zxw, zyw, zzw, xwx, xwy, xwz, ywx, ywy, ywz, zwx, zwy, zwz,
|
|
||||||
wxx, wxy, wxz, wyx, wyy, wyz, wzx, wzy, wzz
|
|
||||||
];
|
|
||||||
swizzling = Dim4Type [
|
|
||||||
xxxx, xxxy, xxxz, xxxw, xxyx, xxyy, xxyz, xxyw, xxzx, xxzy, xxzz, xxzw, xxwx, xxwy, xxwz,
|
|
||||||
xxww, xyxx, xyxy, xyxz, xyxw, xyyx, xyyy, xyyz, xyyw, xyzx, xyzy, xyzz, xyzw, xywx, xywy,
|
|
||||||
xywz, xyww, xzxx, xzxy, xzxz, xzxw, xzyx, xzyy, xzyz, xzyw, xzzx, xzzy, xzzz, xzzw, xzwx,
|
|
||||||
xzwy, xzwz, xzww, xwxx, xwxy, xwxz, xwxw, xwyx, xwyy, xwyz, xwyw, xwzx, xwzy, xwzz, xwzw,
|
|
||||||
xwwx, xwwy, xwwz, xwww, yxxx, yxxy, yxxz, yxxw, yxyx, yxyy, yxyz, yxyw, yxzx, yxzy, yxzz,
|
|
||||||
yxzw, yxwx, yxwy, yxwz, yxww, yyxx, yyxy, yyxz, yyxw, yyyx, yyyy, yyyz, yyyw, yyzx, yyzy,
|
|
||||||
yyzz, yyzw, yywx, yywy, yywz, yyww, yzxx, yzxy, yzxz, yzxw, yzyx, yzyy, yzyz, yzyw, yzzx,
|
|
||||||
yzzy, yzzz, yzzw, yzwx, yzwy, yzwz, yzww, ywxx, ywxy, ywxz, ywxw, ywyx, ywyy, ywyz, ywyw,
|
|
||||||
ywzx, ywzy, ywzz, ywzw, ywwx, ywwy, ywwz, ywww, zxxx, zxxy, zxxz, zxxw, zxyx, zxyy, zxyz,
|
|
||||||
zxyw, zxzx, zxzy, zxzz, zxzw, zxwx, zxwy, zxwz, zxww, zyxx, zyxy, zyxz, zyxw, zyyx, zyyy,
|
|
||||||
zyyz, zyyw, zyzx, zyzy, zyzz, zyzw, zywx, zywy, zywz, zyww, zzxx, zzxy, zzxz, zzxw, zzyx,
|
|
||||||
zzyy, zzyz, zzyw, zzzx, zzzy, zzzz, zzzw, zzwx, zzwy, zzwz, zzww, zwxx, zwxy, zwxz, zwxw,
|
|
||||||
zwyx, zwyy, zwyz, zwyw, zwzx, zwzy, zwzz, zwzw, zwwx, zwwy, zwwz, zwww, wxxx, wxxy, wxxz,
|
|
||||||
wxxw, wxyx, wxyy, wxyz, wxyw, wxzx, wxzy, wxzz, wxzw, wxwx, wxwy, wxwz, wxww, wyxx, wyxy,
|
|
||||||
wyxz, wyxw, wyyx, wyyy, wyyz, wyyw, wyzx, wyzy, wyzz, wyzw, wywx, wywy, wywz, wyww, wzxx,
|
|
||||||
wzxy, wzxz, wzxw, wzyx, wzyy, wzyz, wzyw, wzzx, wzzy, wzzz, wzzw, wzwx, wzwy, wzwz, wzww,
|
|
||||||
wwxx, wwxy, wwxz, wwxw, wwyx, wwyy, wwyz, wwyw, wwzx, wwzy, wwzz, wwzw, wwwx, wwwy, wwwz,
|
|
||||||
wwww
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
impl PixelDistance for Var<Vector2<f32>> {
|
impl PixelDistance for Var<Vector2<f32>> {
|
||||||
type Output = Var<Vector2<Pixels>>;
|
type Output = Var<Vector2<Pixels>>;
|
||||||
fn px(&self) -> Self::Output {
|
fn px(&self) -> Self::Output {
|
||||||
@ -571,6 +455,46 @@ define_shape_data_string_operator! { Mul mul (*) }
|
|||||||
define_shape_data_string_operator! { Div div (/) }
|
define_shape_data_string_operator! { Div div (/) }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ============
|
||||||
|
// === Dim* ===
|
||||||
|
// ============
|
||||||
|
|
||||||
|
macro_rules! gen_dim_impl_for_vector {
|
||||||
|
([$vec:tt] $dim:tt $( $name:ident $swizzling_dim:tt [$($dim_ix:tt)*] [$($dim_ord:tt)*] )*) => {
|
||||||
|
paste! {
|
||||||
|
impl<T: Scalar + Copy> [<Dim $dim>] for Var<$vec<T>> {
|
||||||
|
type [<Dim $dim Type>] = Var<[<Vector $dim>]<T>>;
|
||||||
|
$(
|
||||||
|
fn $name(&self) -> Self::[<Dim $swizzling_dim Type>] {
|
||||||
|
match self {
|
||||||
|
Self::Static(t) => Var::Static(t.$name()),
|
||||||
|
Self::Dynamic(t) => {
|
||||||
|
let code = format!("{}.{}", t, stringify!($name));
|
||||||
|
Var::Dynamic(code.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
enso_types::with_swizzling_for_dim!(1, gen_dim_impl_for_vector, Vector2);
|
||||||
|
enso_types::with_swizzling_for_dim!(2, gen_dim_impl_for_vector, Vector2);
|
||||||
|
|
||||||
|
enso_types::with_swizzling_for_dim!(1, gen_dim_impl_for_vector, Vector3);
|
||||||
|
enso_types::with_swizzling_for_dim!(2, gen_dim_impl_for_vector, Vector3);
|
||||||
|
enso_types::with_swizzling_for_dim!(3, gen_dim_impl_for_vector, Vector3);
|
||||||
|
|
||||||
|
enso_types::with_swizzling_for_dim!(1, gen_dim_impl_for_vector, Vector4);
|
||||||
|
enso_types::with_swizzling_for_dim!(2, gen_dim_impl_for_vector, Vector4);
|
||||||
|
enso_types::with_swizzling_for_dim!(3, gen_dim_impl_for_vector, Vector4);
|
||||||
|
enso_types::with_swizzling_for_dim!(4, gen_dim_impl_for_vector, Vector4);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =========================
|
// =========================
|
||||||
// === Utility Functions ===
|
// === Utility Functions ===
|
||||||
// =========================
|
// =========================
|
||||||
|
8
lib/rust/ensogl/core/src/display/shape/primitive/glsl.rs
Normal file
8
lib/rust/ensogl/core/src/display/shape/primitive/glsl.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
//! GLSL constants and utilities.
|
||||||
|
|
||||||
|
|
||||||
|
// ==============
|
||||||
|
// === Export ===
|
||||||
|
// ==============
|
||||||
|
|
||||||
|
pub mod codes;
|
@ -0,0 +1,81 @@
|
|||||||
|
//! GLSL codes, numbers which are used to identify errors and display modes. These are shared
|
||||||
|
//! between Rust and GLSL code.
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use inflector::Inflector;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =============
|
||||||
|
// === Codes ===
|
||||||
|
// =============
|
||||||
|
|
||||||
|
/// The error code used for ID encoding errors.
|
||||||
|
pub const ID_ENCODING_OVERFLOW_ERROR: u32 = 100;
|
||||||
|
|
||||||
|
/// Enum describing possible GLSL display modes.
|
||||||
|
#[derive(Clone, Copy, Debug, num_enum::IntoPrimitive, num_enum::TryFromPrimitive)]
|
||||||
|
#[repr(u32)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub enum DisplayModes {
|
||||||
|
Normal,
|
||||||
|
DebugSpriteUv,
|
||||||
|
DebugSpriteOverview,
|
||||||
|
DebugSpriteGrid,
|
||||||
|
DebugSdf,
|
||||||
|
DebugShapeAaSpan,
|
||||||
|
DebugInstanceId,
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is not derived, as then [`num_enum::TryFromPrimitive`] will return the default value for
|
||||||
|
// not matched numbers.
|
||||||
|
impl Default for DisplayModes {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Normal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisplayModes {
|
||||||
|
/// The numeric representation of the code.
|
||||||
|
pub const fn value(self) -> u32 {
|
||||||
|
self as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Conversion from the numeric representation of the code to the code variant.
|
||||||
|
pub fn from_value(number: u32) -> Option<Self> {
|
||||||
|
Self::try_from(number).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Name of the code.
|
||||||
|
pub fn name(self) -> String {
|
||||||
|
format!("display_mode_{:?}", self).to_snake_case()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the display mode allows mouse interactions in GUI. The display modes that do not
|
||||||
|
/// allow it use mouse for debug purposes (like changing object hue on click).
|
||||||
|
pub fn allow_mouse_events(self) -> bool {
|
||||||
|
match self {
|
||||||
|
DisplayModes::Normal => true,
|
||||||
|
DisplayModes::DebugSpriteUv => true,
|
||||||
|
DisplayModes::DebugSpriteOverview => false,
|
||||||
|
DisplayModes::DebugSpriteGrid => false,
|
||||||
|
DisplayModes::DebugSdf => true,
|
||||||
|
DisplayModes::DebugShapeAaSpan => true,
|
||||||
|
DisplayModes::DebugInstanceId => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All registered codes.
|
||||||
|
pub fn all() -> Vec<Self> {
|
||||||
|
let mut codes = vec![];
|
||||||
|
for i in 0.. {
|
||||||
|
if let Some(code) = Self::from_value(i) {
|
||||||
|
codes.push(code);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
codes
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
// =================================================================================================
|
// =================================================================================================
|
||||||
// === Colorspaces Definition ======================================================================
|
// === Color spaces definition =====================================================================
|
||||||
// =================================================================================================
|
// =================================================================================================
|
||||||
|
|
||||||
/// Helper for colors definition.
|
/// Helper for colors definition.
|
||||||
@ -12,7 +12,7 @@
|
|||||||
/// All component values are in range 0.0..1.0.
|
/// All component values are in range 0.0..1.0.
|
||||||
|
|
||||||
|
|
||||||
#define DEF_COLOR(type_name3,type_name4,name3,name4,t1,t2,t3) \
|
#define DEF_COLOR(TYPE_NAME_3, TYPE_NAME_4, NAME_3, NAME_4, T_1, T_2, T_3) \
|
||||||
\
|
\
|
||||||
/* ============================= */ \
|
/* ============================= */ \
|
||||||
/* === Non Transparent Color === */ \
|
/* === Non Transparent Color === */ \
|
||||||
@ -20,30 +20,30 @@
|
|||||||
\
|
\
|
||||||
/* === Definition === */ \
|
/* === Definition === */ \
|
||||||
\
|
\
|
||||||
struct type_name3 { \
|
struct TYPE_NAME_3 { \
|
||||||
vec3 raw; \
|
vec3 raw; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/* === Getters === */ \
|
/* === Getters === */ \
|
||||||
\
|
\
|
||||||
float t1 (type_name3 color) { return color.raw.x; } \
|
float T_1 (TYPE_NAME_3 color) { return color.raw.x; } \
|
||||||
float t2 (type_name3 color) { return color.raw.y; } \
|
float T_2 (TYPE_NAME_3 color) { return color.raw.y; } \
|
||||||
float t3 (type_name3 color) { return color.raw.z; } \
|
float T_3 (TYPE_NAME_3 color) { return color.raw.z; } \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/* === Constructors === */ \
|
/* === Constructors === */ \
|
||||||
\
|
\
|
||||||
type_name3 name3(type_name3 identity) { \
|
TYPE_NAME_3 NAME_3(TYPE_NAME_3 identity) { \
|
||||||
return identity; \
|
return identity; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name3 name3(vec3 raw) { \
|
TYPE_NAME_3 NAME_3(vec3 raw) { \
|
||||||
return type_name3(raw); \
|
return TYPE_NAME_3(raw); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name3 name3(float t1, float t2, float t3) { \
|
TYPE_NAME_3 NAME_3(float T_1, float T_2, float T_3) { \
|
||||||
return name3(vec3(t1,t2,t3)); \
|
return NAME_3(vec3(T_1, T_2, T_3)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
@ -54,58 +54,58 @@ type_name3 name3(float t1, float t2, float t3) { \
|
|||||||
\
|
\
|
||||||
/* === Definition === */ \
|
/* === Definition === */ \
|
||||||
\
|
\
|
||||||
struct type_name4 { \
|
struct TYPE_NAME_4 { \
|
||||||
vec4 raw; \
|
vec4 raw; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/* === Getters === */ \
|
/* === Getters === */ \
|
||||||
\
|
\
|
||||||
float t1 (type_name4 name4) { return name4.raw.x; } \
|
float T_1 (TYPE_NAME_4 NAME_4) { return NAME_4.raw.x; } \
|
||||||
float t2 (type_name4 name4) { return name4.raw.y; } \
|
float T_2 (TYPE_NAME_4 NAME_4) { return NAME_4.raw.y; } \
|
||||||
float t3 (type_name4 name4) { return name4.raw.z; } \
|
float T_3 (TYPE_NAME_4 NAME_4) { return NAME_4.raw.z; } \
|
||||||
float a (type_name4 name4) { return name4.raw.a; } \
|
float a (TYPE_NAME_4 NAME_4) { return NAME_4.raw.a; } \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/* === Constructors === */ \
|
/* === Constructors === */ \
|
||||||
\
|
\
|
||||||
type_name4 name4 (type_name4 identity) { \
|
TYPE_NAME_4 NAME_4 (TYPE_NAME_4 identity) { \
|
||||||
return identity; \
|
return identity; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name4 name4 (vec4 raw) { \
|
TYPE_NAME_4 NAME_4 (vec4 raw) { \
|
||||||
return type_name4(raw); \
|
return TYPE_NAME_4(raw); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name4 name4 (vec3 raw) { \
|
TYPE_NAME_4 NAME_4 (vec3 raw) { \
|
||||||
return name4(vec4(raw,1.0)); \
|
return NAME_4(vec4(raw,1.0)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name4 name4 (vec3 raw, float a) { \
|
TYPE_NAME_4 NAME_4 (vec3 raw, float a) { \
|
||||||
return name4(vec4(raw,a)); \
|
return NAME_4(vec4(raw,a)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name4 name4 (type_name3 name3) { \
|
TYPE_NAME_4 NAME_4 (TYPE_NAME_3 NAME_3) { \
|
||||||
return name4(name3.raw); \
|
return NAME_4(NAME_3.raw); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name4 name4 (type_name3 name3, float a) { \
|
TYPE_NAME_4 NAME_4 (TYPE_NAME_3 NAME_3, float a) { \
|
||||||
return name4(name3.raw,a); \
|
return NAME_4(NAME_3.raw, a); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name4 name4 (float t1, float t2, float t3) { \
|
TYPE_NAME_4 NAME_4 (float T_1, float T_2, float T_3) { \
|
||||||
return name4(vec3(t1,t2,t3)); \
|
return NAME_4(vec3(T_1, T_2, T_3)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
type_name4 name4 (float t1, float t2, float t3, float a) { \
|
TYPE_NAME_4 NAME_4 (float T_1, float T_2, float T_3, float a) { \
|
||||||
return name4(vec4(t1,t2,t3,a)); \
|
return NAME_4(vec4(T_1, T_2, T_3, a)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/* === Conversions === */ \
|
/* === Conversions === */ \
|
||||||
\
|
\
|
||||||
type_name3 name3 (type_name4 a) { \
|
TYPE_NAME_3 NAME_3 (TYPE_NAME_4 a) { \
|
||||||
return name3(a.raw.xyz); \
|
return NAME_3(a.raw.xyz); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -117,30 +117,34 @@ DEF_COLOR(Lch , Lcha , lch , lcha , l , c ,h)
|
|||||||
|
|
||||||
|
|
||||||
// =================================================================================================
|
// =================================================================================================
|
||||||
// === Colorpsace Conversion =======================================================================
|
// === Color space conversion ======================================================================
|
||||||
// =================================================================================================
|
// =================================================================================================
|
||||||
|
|
||||||
#define DEF_TRANSITIVE_CONVERSIONS_1_WAY( \
|
#define DEF_TRANSITIVE_CONVERSIONS_1_WAY( \
|
||||||
a_type_name3,a_type_name4,a_name3,a_name4,b_type_name3,b_type_name4,b_name3,b_name4) \
|
A_TYPE_NAME_3, A_TYPE_NAME_4, A_NAME_3, A_NAME_4, B_TYPE_NAME_3, B_TYPE_NAME_4, B_NAME_3, B_NAME_4)\
|
||||||
\
|
\
|
||||||
a_type_name3 a_name3(b_type_name4 b_name4) { \
|
A_TYPE_NAME_3 A_NAME_3(B_TYPE_NAME_4 B_NAME_4) { \
|
||||||
return a_name3(b_name3(b_name4)); \
|
return A_NAME_3(B_NAME_3(B_NAME_4)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
a_type_name4 a_name4(b_type_name4 b_name4) { \
|
A_TYPE_NAME_4 A_NAME_4(B_TYPE_NAME_4 B_NAME_4) { \
|
||||||
return a_name4(a_name3(b_name3(b_name4)),a(b_name4)); \
|
return A_NAME_4(A_NAME_3(B_NAME_3(B_NAME_4)), a(B_NAME_4)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
a_type_name4 a_name4(b_type_name3 b_name3) { \
|
A_TYPE_NAME_4 A_NAME_4(B_TYPE_NAME_3 B_NAME_3) { \
|
||||||
return a_name4(a_name3(b_name3)); \
|
return A_NAME_4(A_NAME_3(B_NAME_3)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
A_TYPE_NAME_4 A_NAME_4(B_TYPE_NAME_3 B_NAME_3, float alpha) { \
|
||||||
|
return A_NAME_4(A_NAME_3(B_NAME_3), alpha); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEF_TRANSITIVE_CONVERSIONS( \
|
#define DEF_TRANSITIVE_CONVERSIONS( \
|
||||||
a_type_name3,a_type_name4,a_name3,a_name4,b_type_name3,b_type_name4,b_name3,b_name4) \
|
A_TYPE_NAME_3, A_TYPE_NAME_4, A_NAME_3, A_NAME_4, B_TYPE_NAME_3, B_TYPE_NAME_4, B_NAME_3, B_NAME_4)\
|
||||||
DEF_TRANSITIVE_CONVERSIONS_1_WAY( \
|
DEF_TRANSITIVE_CONVERSIONS_1_WAY( \
|
||||||
a_type_name3,a_type_name4,a_name3,a_name4,b_type_name3,b_type_name4,b_name3,b_name4) \
|
A_TYPE_NAME_3, A_TYPE_NAME_4, A_NAME_3, A_NAME_4, B_TYPE_NAME_3, B_TYPE_NAME_4, B_NAME_3, B_NAME_4)\
|
||||||
DEF_TRANSITIVE_CONVERSIONS_1_WAY( \
|
DEF_TRANSITIVE_CONVERSIONS_1_WAY( \
|
||||||
b_type_name3,b_type_name4,b_name3,b_name4,a_type_name3,a_type_name4,a_name3,a_name4)
|
B_TYPE_NAME_3, B_TYPE_NAME_4, B_NAME_3, B_NAME_4, A_TYPE_NAME_3, A_TYPE_NAME_4, A_NAME_3, A_NAME_4)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -269,7 +273,8 @@ Rgba mix(Rgba color1, Rgba color2, float t) {
|
|||||||
// ================
|
// ================
|
||||||
|
|
||||||
|
|
||||||
#define DEF_GRADIENT(COLOR,COLOR_CONS,CONTROL_POINT,GRADIENT1,GRADIENT2,GRADIENT3,GRADIENT4,GRADIENT5) \
|
#define DEF_GRADIENT( \
|
||||||
|
COLOR, COLOR_CONS, CONTROL_POINT, GRADIENT_1, GRADIENT_2, GRADIENT_3, GRADIENT_4, GRADIENT_5) \
|
||||||
struct CONTROL_POINT { \
|
struct CONTROL_POINT { \
|
||||||
float offset; \
|
float offset; \
|
||||||
COLOR color; \
|
COLOR color; \
|
||||||
@ -279,29 +284,29 @@ CONTROL_POINT gradient_control_point(float offset, COLOR color) {
|
|||||||
return CONTROL_POINT(offset,color); \
|
return CONTROL_POINT(offset,color); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
struct GRADIENT1 { \
|
struct GRADIENT_1 { \
|
||||||
CONTROL_POINT control_point1; \
|
CONTROL_POINT control_point1; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
struct GRADIENT2 { \
|
struct GRADIENT_2 { \
|
||||||
CONTROL_POINT control_point1; \
|
CONTROL_POINT control_point1; \
|
||||||
CONTROL_POINT control_point2; \
|
CONTROL_POINT control_point2; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
struct GRADIENT3 { \
|
struct GRADIENT_3 { \
|
||||||
CONTROL_POINT control_point1; \
|
CONTROL_POINT control_point1; \
|
||||||
CONTROL_POINT control_point2; \
|
CONTROL_POINT control_point2; \
|
||||||
CONTROL_POINT control_point3; \
|
CONTROL_POINT control_point3; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
struct GRADIENT4 { \
|
struct GRADIENT_4 { \
|
||||||
CONTROL_POINT control_point1; \
|
CONTROL_POINT control_point1; \
|
||||||
CONTROL_POINT control_point2; \
|
CONTROL_POINT control_point2; \
|
||||||
CONTROL_POINT control_point3; \
|
CONTROL_POINT control_point3; \
|
||||||
CONTROL_POINT control_point4; \
|
CONTROL_POINT control_point4; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
struct GRADIENT5 { \
|
struct GRADIENT_5 { \
|
||||||
CONTROL_POINT control_point1; \
|
CONTROL_POINT control_point1; \
|
||||||
CONTROL_POINT control_point2; \
|
CONTROL_POINT control_point2; \
|
||||||
CONTROL_POINT control_point3; \
|
CONTROL_POINT control_point3; \
|
||||||
@ -309,93 +314,88 @@ struct GRADIENT5 {
|
|||||||
CONTROL_POINT control_point5; \
|
CONTROL_POINT control_point5; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
GRADIENT2 gradient \
|
GRADIENT_2 gradient \
|
||||||
( CONTROL_POINT control_point1 \
|
( CONTROL_POINT control_point1 \
|
||||||
, CONTROL_POINT control_point2 ) { \
|
, CONTROL_POINT control_point2 ) { \
|
||||||
return GRADIENT2(control_point1,control_point2); \
|
return GRADIENT_2(control_point1, control_point2); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
GRADIENT3 gradient \
|
GRADIENT_3 gradient \
|
||||||
( CONTROL_POINT control_point1 \
|
( CONTROL_POINT control_point1 \
|
||||||
, CONTROL_POINT control_point2 \
|
, CONTROL_POINT control_point2 \
|
||||||
, CONTROL_POINT control_point3 ) { \
|
, CONTROL_POINT control_point3 ) { \
|
||||||
return GRADIENT3(control_point1,control_point2,control_point3); \
|
return GRADIENT_3(control_point1, control_point2, control_point3); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
GRADIENT4 gradient \
|
GRADIENT_4 gradient \
|
||||||
( CONTROL_POINT control_point1 \
|
( CONTROL_POINT control_point1 \
|
||||||
, CONTROL_POINT control_point2 \
|
, CONTROL_POINT control_point2 \
|
||||||
, CONTROL_POINT control_point3 \
|
, CONTROL_POINT control_point3 \
|
||||||
, CONTROL_POINT control_point4 ) { \
|
, CONTROL_POINT control_point4 ) { \
|
||||||
return GRADIENT4(control_point1,control_point2,control_point3,control_point4); \
|
return GRADIENT_4(control_point1, control_point2, control_point3, control_point4); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
GRADIENT5 gradient \
|
GRADIENT_5 gradient \
|
||||||
( CONTROL_POINT control_point1 \
|
( CONTROL_POINT control_point1 \
|
||||||
, CONTROL_POINT control_point2 \
|
, CONTROL_POINT control_point2 \
|
||||||
, CONTROL_POINT control_point3 \
|
, CONTROL_POINT control_point3 \
|
||||||
, CONTROL_POINT control_point4 \
|
, CONTROL_POINT control_point4 \
|
||||||
, CONTROL_POINT control_point5 ) { \
|
, CONTROL_POINT control_point5 ) { \
|
||||||
return GRADIENT5(control_point1,control_point2,control_point3,control_point4,control_point5); \
|
return GRADIENT_5 \
|
||||||
|
(control_point1, control_point2, control_point3, control_point4, control_point5); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
COLOR sample(GRADIENT2 gradient, float offset) { \
|
COLOR sample(GRADIENT_2 gradient, float offset) { \
|
||||||
float span = gradient.control_point2.offset - gradient.control_point1.offset; \
|
float span = gradient.control_point2.offset - gradient.control_point1.offset; \
|
||||||
float t = clamp((offset - gradient.control_point1.offset)/span); \
|
float t = clamp((offset - gradient.control_point1.offset)/span); \
|
||||||
return COLOR_CONS(mix(gradient.control_point1.color.raw,gradient.control_point2.color.raw,t)); \
|
return COLOR_CONS(mix \
|
||||||
|
(gradient.control_point1.color.raw, gradient.control_point2.color.raw, t)); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
COLOR sample(GRADIENT3 gradient, float offset) { \
|
COLOR sample(GRADIENT_3 gradient, float offset) { \
|
||||||
if (offset < gradient.control_point1.offset) { \
|
if (offset < gradient.control_point1.offset) { \
|
||||||
return gradient.control_point1.color; \
|
return gradient.control_point1.color; \
|
||||||
} else if (offset < gradient.control_point2.offset) { \
|
} else if (offset < gradient.control_point2.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point1,gradient.control_point2),offset); \
|
return sample(GRADIENT_2(gradient.control_point1, gradient.control_point2), offset); \
|
||||||
} else if (offset < gradient.control_point3.offset) { \
|
} else if (offset < gradient.control_point3.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point2,gradient.control_point3),offset); \
|
return sample(GRADIENT_2(gradient.control_point2, gradient.control_point3), offset); \
|
||||||
} else { \
|
} else { \
|
||||||
return gradient.control_point3.color; \
|
return gradient.control_point3.color; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
COLOR sample(GRADIENT4 gradient, float offset) { \
|
COLOR sample(GRADIENT_4 gradient, float offset) { \
|
||||||
if (offset < gradient.control_point1.offset) { \
|
if (offset < gradient.control_point1.offset) { \
|
||||||
return gradient.control_point1.color; \
|
return gradient.control_point1.color; \
|
||||||
} else if (offset < gradient.control_point2.offset) { \
|
} else if (offset < gradient.control_point2.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point1,gradient.control_point2),offset); \
|
return sample(GRADIENT_2(gradient.control_point1, gradient.control_point2), offset); \
|
||||||
} else if (offset < gradient.control_point3.offset) { \
|
} else if (offset < gradient.control_point3.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point2,gradient.control_point3),offset); \
|
return sample(GRADIENT_2(gradient.control_point2, gradient.control_point3), offset); \
|
||||||
} else if (offset < gradient.control_point4.offset) { \
|
} else if (offset < gradient.control_point4.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point3,gradient.control_point4),offset); \
|
return sample(GRADIENT_2(gradient.control_point3, gradient.control_point4), offset); \
|
||||||
} else { \
|
} else { \
|
||||||
return gradient.control_point4.color; \
|
return gradient.control_point4.color; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
COLOR sample(GRADIENT5 gradient, float offset) { \
|
COLOR sample(GRADIENT_5 gradient, float offset) { \
|
||||||
if (offset < gradient.control_point1.offset) { \
|
if (offset < gradient.control_point1.offset) { \
|
||||||
return gradient.control_point1.color; \
|
return gradient.control_point1.color; \
|
||||||
} else if (offset < gradient.control_point2.offset) { \
|
} else if (offset < gradient.control_point2.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point1,gradient.control_point2),offset); \
|
return sample(GRADIENT_2(gradient.control_point1, gradient.control_point2), offset); \
|
||||||
} else if (offset < gradient.control_point3.offset) { \
|
} else if (offset < gradient.control_point3.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point2,gradient.control_point3),offset); \
|
return sample(GRADIENT_2(gradient.control_point2, gradient.control_point3), offset); \
|
||||||
} else if (offset < gradient.control_point4.offset) { \
|
} else if (offset < gradient.control_point4.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point3,gradient.control_point4),offset); \
|
return sample(GRADIENT_2(gradient.control_point3, gradient.control_point4), offset); \
|
||||||
} else if (offset < gradient.control_point5.offset) { \
|
} else if (offset < gradient.control_point5.offset) { \
|
||||||
return sample(GRADIENT2(gradient.control_point4,gradient.control_point5),offset); \
|
return sample(GRADIENT_2(gradient.control_point4, gradient.control_point5), offset); \
|
||||||
} else { \
|
} else { \
|
||||||
return gradient.control_point5.color; \
|
return gradient.control_point5.color; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
||||||
DEF_GRADIENT(Rgb,rgb,RgbGradientControlPoint,RgbGradient1,RgbGradient2,RgbGradient3,RgbGradient4,RgbGradient5)
|
DEF_GRADIENT(Rgb, rgb, RgbGradientControlPoint, RgbGradient1, RgbGradient2, RgbGradient3, \
|
||||||
DEF_GRADIENT(Rgba,rgba,RgbaGradientControlPoint,RgbaGradient1,RgbaGradient2,RgbaGradient3,RgbaGradient4,RgbaGradient5)
|
RgbGradient4, RgbGradient5)
|
||||||
|
DEF_GRADIENT(Rgba, rgba, RgbaGradientControlPoint, RgbaGradient1, RgbaGradient2, RgbaGradient3, \
|
||||||
|
RgbaGradient4, RgbaGradient5)
|
||||||
|
|
||||||
|
|
||||||
//Rgba blend(Rgba bottom, Rgba top, float t) {
|
|
||||||
// float weight = t * a(top);
|
|
||||||
// float rgb = mix(bottom.raw.rgb, top.raw.rgb, weight);
|
|
||||||
// float alpha = a(bottom) + a(top);
|
|
||||||
//}
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
100
|
|
@ -1,23 +1,21 @@
|
|||||||
/// This code is the body of the fragment shader main function of a GLSL shape.
|
//! This code is the body of the fragment shader main function of a GLSL shape.
|
||||||
|
|
||||||
// =================
|
|
||||||
// === Constants ===
|
|
||||||
// =================
|
|
||||||
|
|
||||||
const int DISPLAY_MODE_NORMAL = 0;
|
|
||||||
const int DISPLAY_MODE_DEBUG_SDF = 1;
|
|
||||||
const int DISPLAY_MODE_DEBUG_ID = 2;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ============
|
// =======================
|
||||||
// === Init ===
|
// === Shape Rendering ===
|
||||||
// ============
|
// =======================
|
||||||
|
// The shape is first rendered by sampling the SDF equation generated by EnsoGL shape system and
|
||||||
|
// then it is clipped by a rectangle of the canvas size. The clipping is performed because the
|
||||||
|
// sprite size is slightly bigger than the canvas size in order to display anti-aliased border
|
||||||
|
// pixels when the sprite coordinates are not integers or if the scene is zoomed. See the docs
|
||||||
|
// attached to the shape system's geometry material to learn more.
|
||||||
|
|
||||||
Env env = Env(1);
|
|
||||||
vec2 position = input_local.xy ;
|
vec2 position = input_local.xy ;
|
||||||
Shape shape = run(env,position);
|
Shape view_box = debug_shape(rect(position, input_size));
|
||||||
float alpha = shape.color.color.raw.a;
|
Shape shape = run(position);
|
||||||
|
shape = intersection_no_blend(shape, view_box);
|
||||||
|
float alpha = shape.color.repr.raw.a;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -26,21 +24,25 @@ float alpha = shape.color.color.raw.a;
|
|||||||
// ===========================
|
// ===========================
|
||||||
|
|
||||||
float alpha_no_aa = alpha > ID_ALPHA_THRESHOLD ? 1.0 : 0.0;
|
float alpha_no_aa = alpha > ID_ALPHA_THRESHOLD ? 1.0 : 0.0;
|
||||||
|
|
||||||
if (pointer_events_enabled) {
|
if (pointer_events_enabled) {
|
||||||
output_id = encode(input_global_instance_id,alpha_no_aa);
|
output_id = encode(input_global_instance_id,alpha_no_aa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =======================
|
// =====================
|
||||||
// === Color Rendering ===
|
// === Display Modes ===
|
||||||
// =======================
|
// =====================
|
||||||
|
|
||||||
if (input_display_mode == DISPLAY_MODE_NORMAL) {
|
if (input_display_mode == DISPLAY_MODE_NORMAL) {
|
||||||
output_color = srgba(unpremultiply(shape.color)).raw;
|
output_color = srgba(shape.color).raw;
|
||||||
output_color.rgb *= alpha;
|
output_color.rgb *= alpha;
|
||||||
|
|
||||||
|
} else if (input_display_mode == DISPLAY_MODE_DEBUG_SHAPE_AA_SPAN) {
|
||||||
|
output_color = srgba(shape.color).raw;
|
||||||
|
output_color.rgb *= alpha;
|
||||||
|
output_color = outside_of_uv() ? vec4(1.0,0.0,0.0,1.0) : output_color;
|
||||||
|
|
||||||
} else if (input_display_mode == DISPLAY_MODE_DEBUG_SDF) {
|
} else if (input_display_mode == DISPLAY_MODE_DEBUG_SDF) {
|
||||||
float zoom = zoom();
|
float zoom = zoom();
|
||||||
float factor = 200.0/zoom * input_pixel_ratio;
|
float factor = 200.0/zoom * input_pixel_ratio;
|
||||||
@ -49,10 +51,42 @@ if (input_display_mode == DISPLAY_MODE_NORMAL) {
|
|||||||
output_color.a = alpha_no_aa;
|
output_color.a = alpha_no_aa;
|
||||||
output_color.rgb *= alpha_no_aa;
|
output_color.rgb *= alpha_no_aa;
|
||||||
|
|
||||||
} else if (input_display_mode == DISPLAY_MODE_DEBUG_ID) {
|
} else if (input_display_mode == DISPLAY_MODE_DEBUG_INSTANCE_ID) {
|
||||||
float object_hue = float((input_global_instance_id * 7) % 100) / 100.0;
|
float hue = float((input_global_instance_id + input_mouse_click_count % 10) * 7 % 100) / 100.0;
|
||||||
Srgb object_color = srgb(hsv(object_hue, 1.0, 0.5));
|
Srgb color = srgb(hsv(hue, 1.0, 0.5));
|
||||||
output_color.rgb = object_color.raw.rgb;
|
output_color.rgb = color.raw.rgb;
|
||||||
output_color.a = alpha_no_aa;
|
output_color.a = alpha_no_aa;
|
||||||
output_color.rgb *= alpha_no_aa;
|
output_color.rgb *= alpha_no_aa;
|
||||||
|
|
||||||
|
} else if (input_display_mode == DISPLAY_MODE_DEBUG_SPRITE_OVERVIEW) {
|
||||||
|
float hue_seed = float(input_global_instance_id + input_mouse_click_count % 10) * 17.0;
|
||||||
|
float hue = mod(hue_seed, 100.0) / 100.0;
|
||||||
|
output_color = srgba(hsva(hue, 1.0, 1.0, alpha_no_aa)).raw;
|
||||||
|
output_color = outside_of_uv() ? vec4(output_color.rgb, 1.0) : output_color;
|
||||||
|
output_color.a *= clamp(float(input_mouse_position.x)/1000.0, 0.1, 1.0);
|
||||||
|
output_color.rgb *= output_color.a;
|
||||||
|
|
||||||
|
} else if (input_display_mode == DISPLAY_MODE_DEBUG_SPRITE_GRID) {
|
||||||
|
float hue = float((input_global_instance_id + input_mouse_click_count % 10) * 7 % 100) / 100.0;
|
||||||
|
Srgba color = srgba(hsv(hue, 1.0, 0.8), 1.0);
|
||||||
|
Srgba grid_color = srgba(hsv(hue, 1.0, 0.6), 1.0);
|
||||||
|
output_color = vec4(color.raw.rgb, clamp(float(input_mouse_position.x)/100.0, 0.1, 1.0));
|
||||||
|
output_color *= alpha_no_aa;
|
||||||
|
output_color = draw_grid(position, 1, grid_color.raw, output_color);
|
||||||
|
output_color = draw_grid(position, 2, grid_color.raw, output_color);
|
||||||
|
output_color = draw_grid(position, 3, grid_color.raw, output_color);
|
||||||
|
|
||||||
|
} else if (input_display_mode == DISPLAY_MODE_DEBUG_SPRITE_UV) {
|
||||||
|
bool overflow = input_uv.x >= 1.0 || input_uv.y >= 1.0;
|
||||||
|
float blue = overflow? .5 : .0;
|
||||||
|
output_color = vec4(input_uv, blue, 1.0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Unknown code, display a debug checkerboard.
|
||||||
|
float stripe_width = input_size.x / 4.0;
|
||||||
|
float stripe_height = input_size.y / 4.0;
|
||||||
|
bool vertical = mod(position.x, stripe_width * 2.0) < stripe_width;
|
||||||
|
bool horizontal = mod(position.y, stripe_height * 2.0) < stripe_height;
|
||||||
|
bool filled = (vertical || horizontal) && !(vertical && horizontal);
|
||||||
|
output_color = filled ? vec4(1.0,0.0,0.0,1.0) : vec4(0.0,0.0,0.0,1.0);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ vec4 encode(int value, float alpha) {
|
|||||||
rgb *= alpha;
|
rgb *= alpha;
|
||||||
#ifdef ID_ENCODING_OVERFLOW_CHECK
|
#ifdef ID_ENCODING_OVERFLOW_CHECK
|
||||||
bool is_overflow = value > MAX_ENCODE_ID;
|
bool is_overflow = value > MAX_ENCODE_ID;
|
||||||
alpha = is_overflow ? (ID_ENCODING_OVERFLOW_ERROR_CODE/255.0) : alpha;
|
alpha = is_overflow ? (float(ID_ENCODING_OVERFLOW_ERROR)/255.0) : alpha;
|
||||||
#endif
|
#endif
|
||||||
return vec4(as_float_u8(chunks)*alpha,alpha);
|
return vec4(as_float_u8(chunks)*alpha,alpha);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
/// A zoom level. Zoom of 1.0 means that all figures on the screen will be displayed with their
|
||||||
|
/// native size. Zoom of 2.0 means that all figures are scaled down twice.
|
||||||
|
float zoom() {
|
||||||
|
return input_z_zoom_1 / input_local.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// We are adding a side padding to all sprites when drawing shapes on the in order to make
|
||||||
|
/// anti-aliasing working properly. Consider a situation when a box moves 0.5 pixels to the right.
|
||||||
|
/// Then the pixel with the x-coordinate 0 should be half-transparent. The pixel on the left from it
|
||||||
|
/// should be half-transparent as well. However, it will not exist without the padding.
|
||||||
|
///
|
||||||
|
/// Also, the padding depends on the zoom level. When shapes are zoomed out 2 times, the screen
|
||||||
|
/// pixel will display 2 pixels of the sprite canvas.
|
||||||
|
float aa_side_padding() {
|
||||||
|
return max(1.0, ceil(1.0 / zoom()));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool outside_of_uv() {
|
||||||
|
return input_uv.x < 0.0 || input_uv.x > 1.0 || input_uv.y < 0.0 || input_uv.y > 1.0;
|
||||||
|
}
|
@ -1,3 +1,64 @@
|
|||||||
|
//! GLSL shape definition boilerplate.
|
||||||
|
|
||||||
|
|
||||||
|
// =============
|
||||||
|
// === Color ===
|
||||||
|
// =============
|
||||||
|
|
||||||
|
/// The default color used for [`Shape`]s. The LCHA representation was chosen because it gives good
|
||||||
|
/// results for color blending (better than RGB and way better than sRGB).
|
||||||
|
struct Color {
|
||||||
|
Lcha repr;
|
||||||
|
};
|
||||||
|
|
||||||
|
Color color (Lcha color) {
|
||||||
|
return Color(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color color(vec3 lch, float a) {
|
||||||
|
return Color(lcha(lch, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
Srgba srgba(Color color) {
|
||||||
|
return srgba(color.repr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==========================
|
||||||
|
// === PremultipliedColor ===
|
||||||
|
// ==========================
|
||||||
|
|
||||||
|
/// The premultiplied version of [`Color`] (the `xyz` components are multiplied by its alpha).
|
||||||
|
struct PremultipliedColor {
|
||||||
|
Lcha repr;
|
||||||
|
};
|
||||||
|
|
||||||
|
PremultipliedColor premultiply(Color t) {
|
||||||
|
float alpha = a(t.repr);
|
||||||
|
vec3 rgb = t.repr.raw.rgb * alpha;
|
||||||
|
return PremultipliedColor(lcha(rgb, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
Color unpremultiply(PremultipliedColor c) {
|
||||||
|
float alpha = c.repr.raw.a;
|
||||||
|
vec3 rgb = alpha > 0.0 ? c.repr.raw.rgb / alpha : c.repr.raw.rgb;
|
||||||
|
return color(rgb, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Implements glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA)
|
||||||
|
/// in the [`Color`]'s color space. See docs of [`Color`] to learn more.
|
||||||
|
PremultipliedColor blend(PremultipliedColor bg, PremultipliedColor fg) {
|
||||||
|
vec4 raw = fg.repr.raw + (1.0 - fg.repr.raw.a) * bg.repr.raw;
|
||||||
|
return PremultipliedColor(lcha(raw));
|
||||||
|
}
|
||||||
|
|
||||||
|
Srgba srgba(PremultipliedColor color) {
|
||||||
|
return srgba(unpremultiply(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ===================
|
// ===================
|
||||||
// === BoundingBox ===
|
// === BoundingBox ===
|
||||||
// ===================
|
// ===================
|
||||||
@ -24,14 +85,14 @@ BoundingBox bounding_box (vec2 size) {
|
|||||||
return BoundingBox(-w2, w2, -h2, h2);
|
return BoundingBox(-w2, w2, -h2, h2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inverses the bounding box. Please note that the inversed bounding box is infinite and thus
|
BoundingBox infinite () {
|
||||||
/// it does not have a proper representation. We represent infinite bounding boxes as 0-sized ones.
|
|
||||||
BoundingBox inverse (BoundingBox a) {
|
|
||||||
return BoundingBox(0.0, 0.0, 0.0, 0.0);
|
return BoundingBox(0.0, 0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox infinite () {
|
/// Inverses the bounding box. Please note that the inversed bounding box is infinite and thus
|
||||||
return BoundingBox(0.0,0.0,0.0,0.0);
|
/// it does not have a proper representation. We represent infinite bounding boxes as 0-sized ones.
|
||||||
|
BoundingBox inverse (BoundingBox a) {
|
||||||
|
return infinite();
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBox unify (BoundingBox a, BoundingBox b) {
|
BoundingBox unify (BoundingBox a, BoundingBox b) {
|
||||||
@ -65,12 +126,13 @@ BoundingBox grow (BoundingBox a, float value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ===========
|
// ===========
|
||||||
// === Sdf ===
|
// === Sdf ===
|
||||||
// ===========
|
// ===========
|
||||||
|
|
||||||
/// Signed distance field. Describes the distance to the nearest point of a shape.
|
/// Signed distance field. Describes the distance to the nearest point of a shape. Follow the link
|
||||||
/// Follow the link to learn more: https://en.wikipedia.org/wiki/Signed_distance_function .
|
/// to learn more: https://en.wikipedia.org/wiki/Signed_distance_function.
|
||||||
struct Sdf {
|
struct Sdf {
|
||||||
float distance;
|
float distance;
|
||||||
};
|
};
|
||||||
@ -105,13 +167,19 @@ Sdf grow (Sdf a, float size) {
|
|||||||
// === BoundSdf ===
|
// === BoundSdf ===
|
||||||
// ================
|
// ================
|
||||||
|
|
||||||
/// Bound SDF. Signed distance field with associated bounds. See documentation of `sdf` and `bbox`
|
/// Bound SDF. Signed distance field with associated bounds. See documentation of [`sdf`] and
|
||||||
/// to learn more.
|
/// [`bbox`] to learn more.
|
||||||
struct BoundSdf {
|
struct BoundSdf {
|
||||||
float distance;
|
float distance;
|
||||||
BoundingBox bounds;
|
BoundingBox bounds;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
float render(BoundSdf sdf) {
|
||||||
|
float zoom = zoom();
|
||||||
|
float growth = 0.5 / zoom;
|
||||||
|
return clamp((-sdf.distance * input_pixel_ratio + growth) * zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// === Getters ===
|
// === Getters ===
|
||||||
|
|
||||||
@ -119,10 +187,6 @@ float distance (BoundSdf a) {
|
|||||||
return a.distance;
|
return a.distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
//BoundingBox bounds (BoundSdf a) {
|
|
||||||
// return a.bounds;
|
|
||||||
//}
|
|
||||||
|
|
||||||
Sdf sdf (BoundSdf a) {
|
Sdf sdf (BoundSdf a) {
|
||||||
return sdf(a.distance);
|
return sdf(a.distance);
|
||||||
}
|
}
|
||||||
@ -179,6 +243,8 @@ BoundSdf intersection (BoundSdf a, BoundSdf b) {
|
|||||||
// === Id ===
|
// === Id ===
|
||||||
// ==========
|
// ==========
|
||||||
|
|
||||||
|
/// The ID of a shape. It is used to identify shapes after rendering to an non-antialiased ID
|
||||||
|
/// texture.
|
||||||
struct Id {
|
struct Id {
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
@ -192,85 +258,79 @@ Id new_id_layer (BoundSdf sdf, int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Premultiplied
|
|
||||||
struct Color {
|
|
||||||
Srgba color;
|
|
||||||
};
|
|
||||||
|
|
||||||
Color premultiply(Srgba t) {
|
|
||||||
float alpha = a(t);
|
|
||||||
vec3 rgb = t.raw.rgb * alpha;
|
|
||||||
return Color(srgba(rgb,alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
Srgba unpremultiply(Color t) {
|
|
||||||
float alpha = t.color.raw.a;
|
|
||||||
vec3 rgb = t.color.raw.rgb / alpha;
|
|
||||||
return srgba(rgb,alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements glBlendFuncSeparate(GL_ONE,GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
Color blend(Color bg, Color fg) {
|
|
||||||
vec4 raw = fg.color.raw + (1.0 - fg.color.raw.a) * bg.color.raw;
|
|
||||||
return Color(srgba(raw));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// =============
|
// =============
|
||||||
// === Shape ===
|
// === Shape ===
|
||||||
// =============
|
// =============
|
||||||
|
|
||||||
float zoom() {
|
/// A visual shape that can be displayed on the screen or combined with other shapes.
|
||||||
return input_z_zoom_1 / input_local.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
float render(BoundSdf sdf) {
|
|
||||||
return clamp((-sdf.distance * input_pixel_ratio + 0.5) * zoom());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: the color is premultiplied.
|
|
||||||
struct Shape {
|
struct Shape {
|
||||||
|
/// The ID of the shape. It is used to identify shapes after rendering to an non-antialiased ID
|
||||||
|
/// texture.
|
||||||
Id id;
|
Id id;
|
||||||
|
/// The Signed Distance Field, describing the shape boundaries.
|
||||||
BoundSdf sdf;
|
BoundSdf sdf;
|
||||||
Color color;
|
/// The color of the shape. Please note that we are storing the premultiplied version of the
|
||||||
|
/// color, as blending requires premultiplied values. We could store the non-premultiplied,
|
||||||
|
/// however, then we would need to unpremultiply the color after blending, which leads to
|
||||||
|
/// a serious issue. If the alpha is 0, then either unpremultiplication needs to be more costly
|
||||||
|
/// and check for this condition, or it will produce infinite/invalid values for the `xyz`
|
||||||
|
/// components. If we blend such a color with another one, then we will get artifacts, as
|
||||||
|
/// multiplying an infinite/invalid value by 0 is an undefined behavior.
|
||||||
|
PremultipliedColor color;
|
||||||
|
/// The opacity of the shape. It is the result of rendering of the [`sdf`].
|
||||||
float alpha;
|
float alpha;
|
||||||
};
|
};
|
||||||
|
|
||||||
Shape shape (Id id, BoundSdf bound_sdf, Srgba rgba) {
|
Shape shape (Id id, BoundSdf bound_sdf, PremultipliedColor color) {
|
||||||
float alpha = render(bound_sdf);
|
float alpha = render(bound_sdf);
|
||||||
rgba.raw.a *= alpha;
|
color.repr.raw *= alpha;
|
||||||
Color color = premultiply(rgba);
|
|
||||||
return Shape(id, bound_sdf, color, alpha);
|
return Shape(id, bound_sdf, color, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape shape (Id id, BoundSdf bound_sdf, Color color) {
|
Shape shape (Id id, BoundSdf bound_sdf, Color color) {
|
||||||
float alpha = render(bound_sdf);
|
return shape(id, bound_sdf, premultiply(color));
|
||||||
return Shape(id,bound_sdf,color,alpha);
|
}
|
||||||
|
|
||||||
|
Shape shape (Id id, BoundSdf bound_sdf, Srgba rgba) {
|
||||||
|
return shape(id, bound_sdf, Color(lcha(rgba)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape shape (Id id, BoundSdf bound_sdf) {
|
||||||
|
return shape(id, bound_sdf, srgba(1.0, 0.0, 0.0, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
Shape shape (Id id, BoundSdf bound_sdf, Lcha lcha) {
|
||||||
|
return shape(id, bound_sdf, Color(lcha));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A debug [`Shape`] constructor. Should not be used to create shapes that are rendered to the
|
||||||
|
/// screen as it's ID is always 0. It can be used to create temporary shapes. For example, it can
|
||||||
|
/// be used to create a clipping rectangle, that will be intersected with another shape.
|
||||||
|
Shape debug_shape (BoundSdf bound_sdf) {
|
||||||
|
Id id = new_id_layer(bound_sdf, 10);
|
||||||
|
return shape(id, bound_sdf);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape resample (Shape s, float multiplier) {
|
Shape resample (Shape s, float multiplier) {
|
||||||
Id id = s.id;
|
Id id = s.id;
|
||||||
BoundSdf sdf = resample(s.sdf, multiplier);
|
BoundSdf sdf = resample(s.sdf, multiplier);
|
||||||
Srgba color = unpremultiply(s.color);
|
s.color.repr.raw.a /= s.alpha;
|
||||||
color.raw.a /= s.alpha;
|
return shape(id, sdf, s.color);
|
||||||
return shape(id,sdf,color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape pixel_snap (Shape s) {
|
Shape pixel_snap (Shape s) {
|
||||||
Id id = s.id;
|
Id id = s.id;
|
||||||
BoundSdf sdf = pixel_snap(s.sdf);
|
BoundSdf sdf = pixel_snap(s.sdf);
|
||||||
Srgba color = unpremultiply(s.color);
|
s.color.repr.raw.a /= s.alpha;
|
||||||
color.raw.a /= s.alpha;
|
return shape(id, sdf, s.color);
|
||||||
return shape(id,sdf,color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape grow (Shape s, float value) {
|
Shape grow (Shape s, float value) {
|
||||||
Id id = s.id;
|
Id id = s.id;
|
||||||
BoundSdf sdf = grow(s.sdf,value);
|
BoundSdf sdf = grow(s.sdf,value);
|
||||||
Srgba color = unpremultiply(s.color);
|
s.color.repr.raw.a /= s.alpha;
|
||||||
color.raw.a /= s.alpha;
|
return shape(id, sdf, s.color);
|
||||||
return shape(id,sdf,color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape inverse (Shape s1) {
|
Shape inverse (Shape s1) {
|
||||||
@ -289,36 +349,27 @@ Shape intersection (Shape s1, Shape s2) {
|
|||||||
return shape(s1.id, intersection(s1.sdf, s2.sdf), blend(s1.color, s2.color));
|
return shape(s1.id, intersection(s1.sdf, s2.sdf), blend(s1.color, s2.color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Shape intersection_no_blend (Shape s1, Shape s2) {
|
||||||
|
return shape(s1.id, intersection(s1.sdf, s2.sdf), s1.color);
|
||||||
|
}
|
||||||
|
|
||||||
Shape set_color(Shape shape, Srgba t) {
|
Shape set_color(Shape shape, Srgba t) {
|
||||||
t.raw.a *= shape.alpha;
|
t.raw.a *= shape.alpha;
|
||||||
Color color = premultiply(t);
|
shape.color = premultiply(Color(lcha(t)));
|
||||||
shape.color = color;
|
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape withInfiniteBounds (Shape s) {
|
Shape with_infinite_bounds (Shape s) {
|
||||||
Id id = s.id;
|
|
||||||
Color color = s.color;
|
|
||||||
BoundSdf sdf = s.sdf;
|
BoundSdf sdf = s.sdf;
|
||||||
sdf.bounds = infinite();
|
sdf.bounds = infinite();
|
||||||
return shape(id, sdf, color);
|
return shape(s.id, sdf, s.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ===========
|
// =================
|
||||||
// === Env ===
|
// === Transform ===
|
||||||
// ===========
|
// =================
|
||||||
|
|
||||||
struct Env {
|
|
||||||
int test;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
|
||||||
////// Transform //////
|
|
||||||
///////////////////////
|
|
||||||
|
|
||||||
vec2 translate (vec2 position, vec2 t) {
|
vec2 translate (vec2 position, vec2 t) {
|
||||||
return position - t;
|
return position - t;
|
||||||
@ -340,3 +391,23 @@ vec2 cartesian2polar (vec2 position) {
|
|||||||
vec2 repeat (vec2 position, vec2 tile_size) {
|
vec2 repeat (vec2 position, vec2 tile_size) {
|
||||||
return mod(position+tile_size/2.0, tile_size) - tile_size/2.0;
|
return mod(position+tile_size/2.0, tile_size) - tile_size/2.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =============
|
||||||
|
// === Debug ===
|
||||||
|
// =============
|
||||||
|
|
||||||
|
vec4 draw_grid(vec2 position, int level, vec4 color, vec4 output_color) {
|
||||||
|
float sampling = pow(2.0, float(level - 1));
|
||||||
|
float width = min(sampling, zoom()) / input_pixel_ratio + 0.1;
|
||||||
|
float sampling2 = sampling / 2.0;
|
||||||
|
bool v = abs(mod(position.x + sampling2, sampling) - sampling2) <= width/2.0/zoom();
|
||||||
|
bool h = abs(mod(position.y + sampling2, sampling) - sampling2) <= width/2.0/zoom();
|
||||||
|
if ((v || h) && !outside_of_uv()) {
|
||||||
|
float alpha = clamp((zoom() - (4.0 - sampling))/(5.0 - sampling), 0.0, 1.0);
|
||||||
|
color *= alpha;
|
||||||
|
output_color = color + (1.0 - color.a) * output_color;
|
||||||
|
}
|
||||||
|
return output_color;
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::display::shape::primitive::def::primitive;
|
use crate::display::shape::primitive::def::primitive;
|
||||||
|
use crate::display::shape::primitive::glsl::codes;
|
||||||
use crate::display::shape::primitive::shader::overload;
|
use crate::display::shape::primitive::shader::overload;
|
||||||
use crate::display::symbol::shader::builder::CodeTemplate;
|
use crate::display::symbol::shader::builder::CodeTemplate;
|
||||||
|
|
||||||
@ -18,15 +19,13 @@ use super::canvas::Canvas;
|
|||||||
|
|
||||||
// === GLSL Sources ===
|
// === GLSL Sources ===
|
||||||
|
|
||||||
|
/// Common GLSL functions for all sprite types.
|
||||||
|
pub const GLSL_PRELUDE: &str = include_str!("../glsl/prelude.glsl");
|
||||||
const MATH: &str = include_str!("../glsl/math.glsl");
|
const MATH: &str = include_str!("../glsl/math.glsl");
|
||||||
const COLOR: &str = include_str!("../glsl/color.glsl");
|
const COLOR: &str = include_str!("../glsl/color.glsl");
|
||||||
const DEBUG: &str = include_str!("../glsl/debug.glsl");
|
const DEBUG: &str = include_str!("../glsl/debug.glsl");
|
||||||
const SHAPE: &str = include_str!("../glsl/shape.glsl");
|
const SHAPE: &str = include_str!("../glsl/shape.glsl");
|
||||||
const FRAGMENT_RUNNER: &str = include_str!("../glsl/fragment_runner.glsl");
|
const FRAGMENT_RUNNER: &str = include_str!("../glsl/fragment_runner.glsl");
|
||||||
const ERROR_CODES: &[(&str, &str)] = &[(
|
|
||||||
"ID_ENCODING_OVERFLOW_ERROR_CODE",
|
|
||||||
include_str!("../glsl/error_codes/id_encoding_overflow.txt"),
|
|
||||||
)];
|
|
||||||
|
|
||||||
|
|
||||||
// === Definition ===
|
// === Definition ===
|
||||||
@ -47,7 +46,7 @@ impl Builder {
|
|||||||
canvas.add_current_function_code_line(iformat!("return {shape_ref.getter()};"));
|
canvas.add_current_function_code_line(iformat!("return {shape_ref.getter()};"));
|
||||||
canvas.submit_shape_constructor("run");
|
canvas.submit_shape_constructor("run");
|
||||||
let shape_def = overload::allow_overloading(&canvas.to_glsl());
|
let shape_def = overload::allow_overloading(&canvas.to_glsl());
|
||||||
let code = [GLSL_PRELUDE.as_str(), "", &shape_header, &shape_def].join("\n\n");
|
let code = [GLSL_BOILERPLATE.as_str(), "", &shape_header, &shape_def].join("\n\n");
|
||||||
let main = format!(
|
let main = format!(
|
||||||
"bool pointer_events_enabled = {};\n{}",
|
"bool pointer_events_enabled = {};\n{}",
|
||||||
pointer_events_enabled, FRAGMENT_RUNNER
|
pointer_events_enabled, FRAGMENT_RUNNER
|
||||||
@ -68,26 +67,49 @@ fn header(label: &str) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// == GLSL_PRELUDE ==
|
// == GLSL Boilerplate ==
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// A common preamble used to start every shader program.
|
/// A common preamble used to start every shader program.
|
||||||
static ref GLSL_PRELUDE: String = make_glsl_prelude();
|
static ref GLSL_BOILERPLATE: String = gen_glsl_boilerplate();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_error_codes() -> String {
|
fn glsl_codes() -> String {
|
||||||
let codes = ERROR_CODES.iter();
|
let codes = codes::DisplayModes::all();
|
||||||
codes.map(|(name, code)| format!("const float {} = {}.0;", name, code.trim())).join("\n")
|
let header = header("Codes");
|
||||||
|
let display_modes = codes
|
||||||
|
.iter()
|
||||||
|
.map(|code| format!("const int {} = {};", code.name().to_uppercase(), code.value()))
|
||||||
|
.join("\n");
|
||||||
|
let error_codes =
|
||||||
|
format!("const int ID_ENCODING_OVERFLOW_ERROR = {};", codes::ID_ENCODING_OVERFLOW_ERROR);
|
||||||
|
format!("{}\n\n{}\n{}", header, display_modes, error_codes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_glsl_prelude() -> String {
|
/// The GLSL common code and debug codes.
|
||||||
|
pub fn glsl_prelude_and_codes() -> String {
|
||||||
|
let codes = glsl_codes();
|
||||||
|
format!("{}\n\n{}", GLSL_PRELUDE, codes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_glsl_boilerplate() -> String {
|
||||||
let redirections = overload::builtin_redirections();
|
let redirections = overload::builtin_redirections();
|
||||||
let math = overload::allow_overloading(MATH);
|
let math = overload::allow_overloading(MATH);
|
||||||
let color = overload::allow_overloading(COLOR);
|
let color = overload::allow_overloading(COLOR);
|
||||||
let debug = overload::allow_overloading(DEBUG);
|
let debug = overload::allow_overloading(DEBUG);
|
||||||
let shape = overload::allow_overloading(SHAPE);
|
let shape = overload::allow_overloading(SHAPE);
|
||||||
let err_codes = make_error_codes();
|
let codes_and_prelude = glsl_prelude_and_codes();
|
||||||
let defs_header = header("SDF Primitives");
|
let defs_header = header("SDF Primitives");
|
||||||
let sdf_defs = overload::allow_overloading(&primitive::all_shapes_glsl_definitions());
|
let sdf_defs = overload::allow_overloading(&primitive::all_shapes_glsl_definitions());
|
||||||
[redirections, err_codes, math, color, debug, shape, defs_header, sdf_defs].join("\n\n")
|
[
|
||||||
|
redirections.as_str(),
|
||||||
|
codes_and_prelude.as_str(),
|
||||||
|
math.as_str(),
|
||||||
|
color.as_str(),
|
||||||
|
debug.as_str(),
|
||||||
|
shape.as_str(),
|
||||||
|
defs_header.as_str(),
|
||||||
|
sdf_defs.as_str(),
|
||||||
|
]
|
||||||
|
.join("\n\n")
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ impl ShapeData {
|
|||||||
|
|
||||||
/// Getter of the shape as GLSL expression.
|
/// Getter of the shape as GLSL expression.
|
||||||
pub fn getter(&self) -> String {
|
pub fn getter(&self) -> String {
|
||||||
iformat!("{self.name}(env,position)")
|
iformat!("{self.name}(position)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,8 +76,8 @@ impl ShapeData {
|
|||||||
|
|
||||||
/// Canvas for drawing vector graphics.
|
/// Canvas for drawing vector graphics.
|
||||||
///
|
///
|
||||||
/// The API is stateful, similar to the API of HTML5 canvas element.
|
/// The API is stateful, similar to the API of HTML5 canvas element. It uses GLSL and signed
|
||||||
/// It uses GLSL and signed distance fields under the hood.
|
/// distance fields under the hood.
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Canvas {
|
pub struct Canvas {
|
||||||
@ -123,17 +123,13 @@ impl Canvas {
|
|||||||
|
|
||||||
/// Defines a new variable in the GLSL code.
|
/// Defines a new variable in the GLSL code.
|
||||||
pub fn define<E: Str>(&mut self, ty: &str, name: &str, expr: E) {
|
pub fn define<E: Str>(&mut self, ty: &str, name: &str, expr: E) {
|
||||||
let max_type_length = 8;
|
|
||||||
let max_name_length = 6;
|
|
||||||
let ty = format!("{:1$}", ty, max_type_length);
|
|
||||||
let name = format!("{:1$}", name, max_name_length);
|
|
||||||
self.add_current_function_code_line(iformat!("{ty} {name} = {expr.as_ref()};"));
|
self.add_current_function_code_line(iformat!("{ty} {name} = {expr.as_ref()};"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Submits the `current_function_lines` as a new shape construction function in the GLSL code.
|
/// Submits the `current_function_lines` as a new shape construction function in the GLSL code.
|
||||||
pub fn submit_shape_constructor(&mut self, name: &str) {
|
pub fn submit_shape_constructor(&mut self, name: &str) {
|
||||||
let body = self.current_function_lines.join("\n ");
|
let body = self.current_function_lines.join("\n ");
|
||||||
let func = iformat!("Shape {name} (Env env, vec2 position) {{\n {body}\n}}");
|
let func = iformat!("Shape {name} (vec2 position) {{\n {body}\n}}");
|
||||||
self.current_function_lines = default();
|
self.current_function_lines = default();
|
||||||
self.functions.push(func);
|
self.functions.push(func);
|
||||||
}
|
}
|
||||||
@ -155,13 +151,11 @@ impl Canvas {
|
|||||||
/// Defines a new shape with a new id and associated parameters, like color.
|
/// Defines a new shape with a new id and associated parameters, like color.
|
||||||
pub fn define_shape(&mut self, num: usize, sdf: &str) -> Shape {
|
pub fn define_shape(&mut self, num: usize, sdf: &str) -> Shape {
|
||||||
self.if_not_defined(num, |this| {
|
self.if_not_defined(num, |this| {
|
||||||
let color = "srgba(1.0,0.0,0.0)";
|
|
||||||
let mut shape = ShapeData::new(num);
|
let mut shape = ShapeData::new(num);
|
||||||
let id = this.get_new_id();
|
let id = this.get_new_id();
|
||||||
this.define("Srgba", "color", iformat!("{color}"));
|
|
||||||
this.define("BoundSdf", "sdf", iformat!("{sdf}"));
|
this.define("BoundSdf", "sdf", iformat!("{sdf}"));
|
||||||
this.define("Id", "id", iformat!("new_id_layer(sdf,{id})"));
|
this.define("Id", "id", iformat!("new_id_layer(sdf,{id})"));
|
||||||
this.add_current_function_code_line("return shape(id,sdf,color);");
|
this.add_current_function_code_line("return shape(id, sdf);");
|
||||||
this.submit_shape_constructor(&shape.name);
|
this.submit_shape_constructor(&shape.name);
|
||||||
shape.add_id(id);
|
shape.add_id(id);
|
||||||
shape
|
shape
|
||||||
|
@ -349,6 +349,7 @@ pub struct ShapeSystemModel {
|
|||||||
pub sprite_system: SpriteSystem,
|
pub sprite_system: SpriteSystem,
|
||||||
pub shape: Rc<RefCell<def::AnyShape>>,
|
pub shape: Rc<RefCell<def::AnyShape>>,
|
||||||
pub material: Rc<RefCell<Material>>,
|
pub material: Rc<RefCell<Material>>,
|
||||||
|
pub geometry_material: Rc<RefCell<Material>>,
|
||||||
/// Enables or disables pointer events on this shape system. All shapes of a shape system which
|
/// Enables or disables pointer events on this shape system. All shapes of a shape system which
|
||||||
/// have pointer events disabled will be completely transparent for the mouse (they will pass
|
/// have pointer events disabled will be completely transparent for the mouse (they will pass
|
||||||
/// through all mouse events to shapes behind them).
|
/// through all mouse events to shapes behind them).
|
||||||
@ -366,10 +367,18 @@ impl ShapeSystemModel {
|
|||||||
pub fn new(shape: def::AnyShape, pointer_events: bool) -> Self {
|
pub fn new(shape: def::AnyShape, pointer_events: bool) -> Self {
|
||||||
let sprite_system = SpriteSystem::new();
|
let sprite_system = SpriteSystem::new();
|
||||||
let material = Rc::new(RefCell::new(Self::default_material()));
|
let material = Rc::new(RefCell::new(Self::default_material()));
|
||||||
|
let geometry_material = Rc::new(RefCell::new(Self::default_geometry_material()));
|
||||||
let pointer_events = Immutable(pointer_events);
|
let pointer_events = Immutable(pointer_events);
|
||||||
let shape = Rc::new(RefCell::new(shape));
|
let shape = Rc::new(RefCell::new(shape));
|
||||||
let do_not_use_shape_definition = default();
|
let do_not_use_shape_definition = default();
|
||||||
Self { sprite_system, shape, material, pointer_events, do_not_use_shape_definition }
|
Self {
|
||||||
|
sprite_system,
|
||||||
|
shape,
|
||||||
|
material,
|
||||||
|
geometry_material,
|
||||||
|
pointer_events,
|
||||||
|
do_not_use_shape_definition,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&self) {
|
fn init(&self) {
|
||||||
@ -384,11 +393,63 @@ impl ShapeSystemModel {
|
|||||||
material.add_input("pixel_ratio", 1.0);
|
material.add_input("pixel_ratio", 1.0);
|
||||||
material.add_input("z_zoom_1", 1.0);
|
material.add_input("z_zoom_1", 1.0);
|
||||||
material.add_input("time", 0.0);
|
material.add_input("time", 0.0);
|
||||||
|
material.add_input_def::<Vector2<i32>>("mouse_position");
|
||||||
|
material.add_input_def::<i32>("mouse_click_count");
|
||||||
material.add_input("display_mode", 0);
|
material.add_input("display_mode", 0);
|
||||||
material.add_output("id", Vector4::<f32>::zero());
|
material.add_output("id", Vector4::<f32>::zero());
|
||||||
material
|
material
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_geometry_material() -> Material {
|
||||||
|
let mut material = SpriteSystem::default_geometry_material();
|
||||||
|
material.set_before_main(shader::builder::glsl_prelude_and_codes());
|
||||||
|
// The GLSL vertex shader implementing automatic shape padding for anti-aliasing. See the
|
||||||
|
// docs of [`aa_side_padding`] to learn more about the concept of shape padding.
|
||||||
|
//
|
||||||
|
// First, we are computing the vertex position without shape padding. This is required to
|
||||||
|
// make the function [`aa_side_padding`] work, as it uses [`zoom`], which uses the
|
||||||
|
// [`input_local.z`] value. The depth of the vertex can be computed only after the
|
||||||
|
// [`model_view_projection`] matrix is applied.
|
||||||
|
//
|
||||||
|
// Please note that this method is not guaranteed to always provide correct results. If
|
||||||
|
// there is a big angle between the camera and the shape normal axes (e.g. when the shape is
|
||||||
|
// significantly rotated around its Y-axis), the padding might be too small. To correct it,
|
||||||
|
// we might take normal axes into account, but it will require more computations, and we do
|
||||||
|
// not need it currently.
|
||||||
|
//
|
||||||
|
// Also, please note that we are first using the [`input_uv`] variable, and then we are
|
||||||
|
// changing it. It's because the unchanged value is the incoming UV in range 0..1, and then
|
||||||
|
// we are scaling it to a bigger range, so the padded area UV is not contained within 0..1.
|
||||||
|
material.set_main(
|
||||||
|
"
|
||||||
|
mat4 model_view_projection = input_view_projection * input_transform;
|
||||||
|
|
||||||
|
// Computing the vertex position without shape padding.
|
||||||
|
vec3 input_local_no_padding = vec3((input_uv - input_alignment) * input_size, 0.0);
|
||||||
|
vec4 position_no_padding = model_view_projection * vec4(input_local_no_padding, 1.0);
|
||||||
|
input_local.z = position_no_padding.z;
|
||||||
|
|
||||||
|
// We are now able to compute the padding and grow the canvas by its value.
|
||||||
|
vec2 padding = vec2(aa_side_padding());
|
||||||
|
if (input_display_mode == DISPLAY_MODE_DEBUG_SPRITE_OVERVIEW) {
|
||||||
|
padding = vec2(float(input_mouse_position.y) / 10.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 padding2 = 2.0 * padding;
|
||||||
|
vec2 padded_size = input_size + padding2;
|
||||||
|
vec2 uv_scale = padded_size / input_size;
|
||||||
|
vec2 uv_offset = padding / input_size;
|
||||||
|
input_uv = vertex_uv * uv_scale - uv_offset;
|
||||||
|
|
||||||
|
// We need to recompute the vertex position with the padding.
|
||||||
|
input_local = vec3((input_uv - input_alignment) * input_size, 0.0);
|
||||||
|
gl_Position = model_view_projection * vec4(input_local,1.0);
|
||||||
|
input_local.z = gl_Position.z;
|
||||||
|
",
|
||||||
|
);
|
||||||
|
material
|
||||||
|
}
|
||||||
|
|
||||||
/// Replaces the shape definition.
|
/// Replaces the shape definition.
|
||||||
#[profile(Detail)]
|
#[profile(Detail)]
|
||||||
pub fn set_shape(&self, shape: def::AnyShape) {
|
pub fn set_shape(&self, shape: def::AnyShape) {
|
||||||
@ -419,6 +480,7 @@ impl ShapeSystemModel {
|
|||||||
#[profile(Detail)]
|
#[profile(Detail)]
|
||||||
fn reload_material(&self) {
|
fn reload_material(&self) {
|
||||||
self.sprite_system.set_material(&*self.material.borrow());
|
self.sprite_system.set_material(&*self.material.borrow());
|
||||||
|
self.sprite_system.set_geometry_material(&*self.geometry_material.borrow());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,15 +116,23 @@ impl DomSymbol {
|
|||||||
dom.set_style_or_warn("position", "absolute");
|
dom.set_style_or_warn("position", "absolute");
|
||||||
dom.set_style_or_warn("width", "0px");
|
dom.set_style_or_warn("width", "0px");
|
||||||
dom.set_style_or_warn("height", "0px");
|
dom.set_style_or_warn("height", "0px");
|
||||||
|
dom.set_style_or_warn("display", "none");
|
||||||
dom.append_or_warn(content);
|
dom.append_or_warn(content);
|
||||||
let display_object = display::object::Instance::new();
|
let display_object = display::object::Instance::new();
|
||||||
let guard = Rc::new(Guard::new(&display_object, &dom));
|
let weak_display_object = display_object.downgrade();
|
||||||
display_object.set_on_updated(enclose!((dom) move |t| {
|
let network = &display_object.network;
|
||||||
let mut transform = inverse_y_translation(t.matrix());
|
frp::extend! { network
|
||||||
|
eval_ display_object.on_show (dom.set_style_or_warn("display", ""));
|
||||||
|
eval_ display_object.on_hide (dom.set_style_or_warn("display", "none"));
|
||||||
|
eval_ display_object.on_updated ([dom] {
|
||||||
|
if let Some(display_object) = weak_display_object.upgrade() {
|
||||||
|
let mut transform = inverse_y_translation(display_object.transformation_matrix());
|
||||||
transform.iter_mut().for_each(|a| *a = eps(*a));
|
transform.iter_mut().for_each(|a| *a = eps(*a));
|
||||||
set_object_transform(&dom, &transform);
|
set_object_transform(&dom, &transform);
|
||||||
}));
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let guard = Rc::new(Guard::new(&display_object, &dom));
|
||||||
Self { dom, display_object, size, guard }
|
Self { dom, display_object, size, guard }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,9 +591,11 @@ impl SymbolData {
|
|||||||
fn init(self) -> Self {
|
fn init(self) -> Self {
|
||||||
let is_hidden = &self.is_hidden;
|
let is_hidden = &self.is_hidden;
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
self.display_object.set_on_hide(f_!(is_hidden.set(true)));
|
let network = &self.display_object.network;
|
||||||
self.display_object.set_on_show(f__!(is_hidden.set(false)));
|
frp::extend! { network
|
||||||
self.display_object.set_on_scene_layer_changed(move |_, old_layers, new_layers| {
|
eval_ self.display_object.on_hide(is_hidden.set(true));
|
||||||
|
eval_ self.display_object.on_show(is_hidden.set(false));
|
||||||
|
eval self.display_object.on_layer_change([] ((_, old_layers, new_layers)) {
|
||||||
for layer in old_layers.iter().filter_map(|t| t.upgrade()) {
|
for layer in old_layers.iter().filter_map(|t| t.upgrade()) {
|
||||||
layer.remove_symbol(id)
|
layer.remove_symbol(id)
|
||||||
}
|
}
|
||||||
@ -601,6 +603,7 @@ impl SymbolData {
|
|||||||
layer.add_symbol(id)
|
layer.add_symbol(id)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +111,71 @@ impl Size {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===================
|
||||||
|
// === SizedObject ===
|
||||||
|
// ===================
|
||||||
|
|
||||||
|
/// A display object bound with [`Size`].
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SizedObject {
|
||||||
|
size: Size,
|
||||||
|
display_object: display::object::Instance,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SizedObject {
|
||||||
|
fn new(attr: Attribute<Vector2<f32>>, transform: &Attribute<Matrix4<f32>>) -> Self {
|
||||||
|
let size = Size::new(attr);
|
||||||
|
let display_object = display::object::Instance::new();
|
||||||
|
let weak_display_object = display_object.downgrade();
|
||||||
|
let network = &display_object.network;
|
||||||
|
frp::extend! { network
|
||||||
|
eval_ display_object.on_updated ([transform] {
|
||||||
|
if let Some(display_object) = weak_display_object.upgrade() {
|
||||||
|
transform.set(display_object.transformation_matrix())
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Self { size, display_object }.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Init display object bindings. In particular defines the behavior of the show and hide
|
||||||
|
/// callbacks.
|
||||||
|
fn init(self) -> Self {
|
||||||
|
let size = &self.size;
|
||||||
|
let display_object = &self.display_object;
|
||||||
|
let network = &display_object.network;
|
||||||
|
frp::extend! { network
|
||||||
|
eval_ display_object.on_show(size.show());
|
||||||
|
eval_ display_object.on_hide(size.hide());
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clone ref the underlying [`Size`].
|
||||||
|
pub fn clone_ref(&self) -> Size {
|
||||||
|
self.size.clone_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HasItem for SizedObject {
|
||||||
|
type Item = Vector2;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CellGetter for SizedObject {
|
||||||
|
fn get(&self) -> Vector2 {
|
||||||
|
self.size.get()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CellSetter for SizedObject {
|
||||||
|
fn set(&self, v: Vector2) {
|
||||||
|
self.size.set(v);
|
||||||
|
self.display_object.set_bounding_box(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ==============
|
// ==============
|
||||||
// === Sprite ===
|
// === Sprite ===
|
||||||
// ==============
|
// ==============
|
||||||
@ -119,17 +184,44 @@ impl Size {
|
|||||||
/// freely rotated only by their local z-axis. This implementation, however, implements sprites as
|
/// freely rotated only by their local z-axis. This implementation, however, implements sprites as
|
||||||
/// full 3D objects. We may want to fork this implementation in the future to create a specialized
|
/// full 3D objects. We may want to fork this implementation in the future to create a specialized
|
||||||
/// 2d representation as well.
|
/// 2d representation as well.
|
||||||
#[derive(Debug, Clone, CloneRef)]
|
#[derive(Debug, Clone, CloneRef, Deref)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub struct Sprite {
|
pub struct Sprite {
|
||||||
pub symbol: Symbol,
|
model: Rc<SpriteModel>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal representation of [`Sprite`].
|
||||||
|
#[derive(Debug, Deref)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub struct SpriteModel {
|
||||||
|
#[deref]
|
||||||
pub instance: SymbolInstance,
|
pub instance: SymbolInstance,
|
||||||
pub size: Size,
|
pub symbol: Symbol,
|
||||||
display_object: display::object::Instance,
|
pub size: SizedObject,
|
||||||
transform: Attribute<Matrix4<f32>>,
|
transform: Attribute<Matrix4<f32>>,
|
||||||
stats: Rc<SpriteStats>,
|
stats: SpriteStats,
|
||||||
erase_on_drop: Rc<EraseOnDrop<Attribute<Vector2<f32>>>>,
|
erase_on_drop: EraseOnDrop<Attribute<Vector2<f32>>>,
|
||||||
unset_parent_on_drop: Rc<display::object::UnsetParentOnDrop>,
|
unset_parent_on_drop: display::object::UnsetParentOnDrop,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpriteModel {
|
||||||
|
/// Constructor.
|
||||||
|
pub fn new(
|
||||||
|
symbol: &Symbol,
|
||||||
|
instance: SymbolInstance,
|
||||||
|
transform: Attribute<Matrix4<f32>>,
|
||||||
|
size: Attribute<Vector2<f32>>,
|
||||||
|
stats: &Stats,
|
||||||
|
) -> Self {
|
||||||
|
let symbol = symbol.clone_ref();
|
||||||
|
let stats = SpriteStats::new(stats);
|
||||||
|
let erase_on_drop = EraseOnDrop::new(size.clone_ref());
|
||||||
|
let size = SizedObject::new(size, &transform);
|
||||||
|
let unset_parent_on_drop = display::object::UnsetParentOnDrop::new(&size.display_object);
|
||||||
|
let default_size = Vector2(DEFAULT_SPRITE_SIZE.0, DEFAULT_SPRITE_SIZE.1);
|
||||||
|
size.set(default_size);
|
||||||
|
Self { symbol, instance, size, transform, stats, erase_on_drop, unset_parent_on_drop }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sprite {
|
impl Sprite {
|
||||||
@ -141,37 +233,8 @@ impl Sprite {
|
|||||||
size: Attribute<Vector2<f32>>,
|
size: Attribute<Vector2<f32>>,
|
||||||
stats: &Stats,
|
stats: &Stats,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let symbol = symbol.clone_ref();
|
let model = SpriteModel::new(symbol, instance, transform, size, stats);
|
||||||
let display_object = display::object::Instance::new();
|
Self { model: Rc::new(model) }
|
||||||
let stats = Rc::new(SpriteStats::new(stats));
|
|
||||||
let erase_on_drop = Rc::new(EraseOnDrop::new(size.clone_ref()));
|
|
||||||
let size = Size::new(size);
|
|
||||||
let unset_parent_on_drop =
|
|
||||||
Rc::new(display::object::UnsetParentOnDrop::new(&display_object));
|
|
||||||
let default_size = Vector2(DEFAULT_SPRITE_SIZE.0, DEFAULT_SPRITE_SIZE.1);
|
|
||||||
size.set(default_size);
|
|
||||||
Self {
|
|
||||||
symbol,
|
|
||||||
instance,
|
|
||||||
size,
|
|
||||||
display_object,
|
|
||||||
transform,
|
|
||||||
stats,
|
|
||||||
erase_on_drop,
|
|
||||||
unset_parent_on_drop,
|
|
||||||
}
|
|
||||||
.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Init display object bindings. In particular defines the behavior of the show and hide
|
|
||||||
/// callbacks.
|
|
||||||
fn init(self) -> Self {
|
|
||||||
let size = &self.size;
|
|
||||||
let transform = &self.transform;
|
|
||||||
self.display_object.set_on_updated(f!((t) transform.set(t.matrix())));
|
|
||||||
self.display_object.set_on_hide(f_!(size.hide()));
|
|
||||||
self.display_object.set_on_show(f__!(size.show()));
|
|
||||||
self
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the symbol id.
|
/// Get the symbol id.
|
||||||
@ -188,16 +251,15 @@ impl Sprite {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl display::Object for Sprite {
|
impl display::Object for SpriteModel {
|
||||||
fn display_object(&self) -> &display::object::Instance {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.display_object
|
&self.size.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Deref for Sprite {
|
impl display::Object for Sprite {
|
||||||
type Target = SymbolInstance;
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
fn deref(&self) -> &Self::Target {
|
self.model.display_object()
|
||||||
&self.instance
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,13 +372,14 @@ impl SpriteSystem {
|
|||||||
|
|
||||||
fn init_shader(&self) {
|
fn init_shader(&self) {
|
||||||
let shader = self.symbol.shader();
|
let shader = self.symbol.shader();
|
||||||
let surface_material = Self::surface_material();
|
let surface_material = Self::default_surface_material();
|
||||||
let geometry_material = Self::geometry_material();
|
let geometry_material = Self::default_geometry_material();
|
||||||
shader.set_geometry_material(&geometry_material);
|
shader.set_geometry_material(&geometry_material);
|
||||||
shader.set_material(&surface_material);
|
shader.set_material(&surface_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn geometry_material() -> Material {
|
/// The default geometry material for all sprites.
|
||||||
|
pub fn default_geometry_material() -> Material {
|
||||||
let mut material = Material::new();
|
let mut material = Material::new();
|
||||||
material.add_input_def::<Vector2<f32>>("size");
|
material.add_input_def::<Vector2<f32>>("size");
|
||||||
material.add_input_def::<Vector2<f32>>("uv");
|
material.add_input_def::<Vector2<f32>>("uv");
|
||||||
@ -339,7 +402,8 @@ impl SpriteSystem {
|
|||||||
material
|
material
|
||||||
}
|
}
|
||||||
|
|
||||||
fn surface_material() -> Material {
|
/// The default surface material for all sprites.
|
||||||
|
pub fn default_surface_material() -> Material {
|
||||||
let mut material = Material::new();
|
let mut material = Material::new();
|
||||||
// FIXME We need to use this output, as we need to declare the same amount of shader
|
// FIXME We need to use this output, as we need to declare the same amount of shader
|
||||||
// FIXME outputs as the number of attachments to framebuffer. We should manage this more
|
// FIXME outputs as the number of attachments to framebuffer. We should manage this more
|
||||||
|
@ -20,6 +20,7 @@ use crate::display::render;
|
|||||||
use crate::display::render::passes::SymbolsRenderPass;
|
use crate::display::render::passes::SymbolsRenderPass;
|
||||||
use crate::display::scene::DomPath;
|
use crate::display::scene::DomPath;
|
||||||
use crate::display::scene::Scene;
|
use crate::display::scene::Scene;
|
||||||
|
use crate::display::shape::primitive::glsl;
|
||||||
use crate::system::web;
|
use crate::system::web;
|
||||||
|
|
||||||
use enso_types::unit2::Duration;
|
use enso_types::unit2::Duration;
|
||||||
@ -229,6 +230,7 @@ pub struct WorldData {
|
|||||||
pub default_scene: Scene,
|
pub default_scene: Scene,
|
||||||
scene_dirty: dirty::SharedBool,
|
scene_dirty: dirty::SharedBool,
|
||||||
uniforms: Uniforms,
|
uniforms: Uniforms,
|
||||||
|
display_mode: Rc<Cell<glsl::codes::DisplayModes>>,
|
||||||
stats: Stats,
|
stats: Stats,
|
||||||
stats_monitor: debug::monitor::Monitor,
|
stats_monitor: debug::monitor::Monitor,
|
||||||
stats_draw_handle: callback::Handle,
|
stats_draw_handle: callback::Handle,
|
||||||
@ -246,7 +248,8 @@ impl WorldData {
|
|||||||
let on = Callbacks::default();
|
let on = Callbacks::default();
|
||||||
let scene_dirty = dirty::SharedBool::new(());
|
let scene_dirty = dirty::SharedBool::new(());
|
||||||
let on_change = enclose!((scene_dirty) move || scene_dirty.set());
|
let on_change = enclose!((scene_dirty) move || scene_dirty.set());
|
||||||
let default_scene = Scene::new(&stats, on_change);
|
let display_mode = Rc::<Cell<glsl::codes::DisplayModes>>::default();
|
||||||
|
let default_scene = Scene::new(&stats, on_change, &display_mode);
|
||||||
let uniforms = Uniforms::new(&default_scene.variables);
|
let uniforms = Uniforms::new(&default_scene.variables);
|
||||||
let debug_hotkeys_handle = default();
|
let debug_hotkeys_handle = default();
|
||||||
let garbage_collector = default();
|
let garbage_collector = default();
|
||||||
@ -262,6 +265,7 @@ impl WorldData {
|
|||||||
default_scene,
|
default_scene,
|
||||||
scene_dirty,
|
scene_dirty,
|
||||||
uniforms,
|
uniforms,
|
||||||
|
display_mode,
|
||||||
stats,
|
stats,
|
||||||
on,
|
on,
|
||||||
debug_hotkeys_handle,
|
debug_hotkeys_handle,
|
||||||
@ -285,24 +289,29 @@ impl WorldData {
|
|||||||
|
|
||||||
fn init_debug_hotkeys(&self) {
|
fn init_debug_hotkeys(&self) {
|
||||||
let stats_monitor = self.stats_monitor.clone_ref();
|
let stats_monitor = self.stats_monitor.clone_ref();
|
||||||
let display_mode = self.uniforms.display_mode.clone_ref();
|
let display_mode = self.display_mode.clone_ref();
|
||||||
|
let display_mode_uniform = self.uniforms.display_mode.clone_ref();
|
||||||
let closure: Closure<dyn Fn(JsValue)> = Closure::new(move |val: JsValue| {
|
let closure: Closure<dyn Fn(JsValue)> = Closure::new(move |val: JsValue| {
|
||||||
let event = val.unchecked_into::<web::KeyboardEvent>();
|
let event = val.unchecked_into::<web::KeyboardEvent>();
|
||||||
|
let digit_prefix = "Digit";
|
||||||
if event.alt_key() && event.ctrl_key() {
|
if event.alt_key() && event.ctrl_key() {
|
||||||
let key = event.code();
|
let key = event.code();
|
||||||
if key == "Backquote" {
|
if key == "Backquote" {
|
||||||
stats_monitor.toggle()
|
stats_monitor.toggle()
|
||||||
} else if key == "Digit0" {
|
|
||||||
display_mode.set(0)
|
|
||||||
} else if key == "Digit1" {
|
|
||||||
display_mode.set(1)
|
|
||||||
} else if key == "Digit2" {
|
|
||||||
display_mode.set(2)
|
|
||||||
} else if key == "KeyP" {
|
} else if key == "KeyP" {
|
||||||
enso_debug_api::save_profile(&profiler::internal::take_log());
|
enso_debug_api::save_profile(&profiler::internal::take_log());
|
||||||
} else if key == "KeyQ" {
|
} else if key == "KeyQ" {
|
||||||
enso_debug_api::save_profile(&profiler::internal::take_log());
|
enso_debug_api::save_profile(&profiler::internal::take_log());
|
||||||
enso_debug_api::LifecycleController::new().map(|api| api.quit());
|
enso_debug_api::LifecycleController::new().map(|api| api.quit());
|
||||||
|
} else if key.starts_with(digit_prefix) {
|
||||||
|
let code_value = key.trim_start_matches(digit_prefix).parse().unwrap_or(0);
|
||||||
|
if let Some(mode) = glsl::codes::DisplayModes::from_value(code_value) {
|
||||||
|
warn!("Setting display mode to {:?}.", mode.name());
|
||||||
|
display_mode.set(mode);
|
||||||
|
} else {
|
||||||
|
warn!("Invalid display mode code: {code_value}.");
|
||||||
|
}
|
||||||
|
display_mode_uniform.set(code_value as i32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -59,13 +59,18 @@ impl<S: Shape> ShapeView<S> {
|
|||||||
|
|
||||||
fn init_on_scene_layer_changed(&self) {
|
fn init_on_scene_layer_changed(&self) {
|
||||||
let weak_model = Rc::downgrade(&self.model);
|
let weak_model = Rc::downgrade(&self.model);
|
||||||
self.display_object().set_on_scene_layer_changed(move |scene, old_layer, new_layer| {
|
let display_object = self.display_object();
|
||||||
|
let network = &display_object.network;
|
||||||
|
frp::extend! { network
|
||||||
|
eval display_object.on_layer_change([] ((scene, old_layer, new_layer)) {
|
||||||
|
let scene = scene.as_ref().unwrap();
|
||||||
if let Some(model) = weak_model.upgrade() {
|
if let Some(model) = weak_model.upgrade() {
|
||||||
model.on_scene_layer_changed(scene, old_layer, new_layer)
|
model.on_scene_layer_changed(scene, old_layer.as_ref(), new_layer.as_ref());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: Shape> HasContent for ShapeView<S> {
|
impl<S: Shape> HasContent for ShapeView<S> {
|
||||||
type Content = S;
|
type Content = S;
|
||||||
@ -298,7 +303,7 @@ impl<Model: 'static, Frp: 'static> Widget<Model, Frp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Model: 'static, Frp: 'static> display::Object for Widget<Model, Frp> {
|
impl<Model: 'static, Frp: 'static> display::Object for Widget<Model, Frp> {
|
||||||
fn display_object(&self) -> &display::object::Instance<Scene> {
|
fn display_object(&self) -> &display::object::Instance {
|
||||||
&self.data.display_object
|
&self.data.display_object
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,6 +191,11 @@ impl<Value> {
|
|||||||
self.value = value;
|
self.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Modifies the value of this uniform.
|
||||||
|
pub fn modify(&mut self, f: impl FnOnce(&mut Value)) {
|
||||||
|
f(&mut self.value);
|
||||||
|
}
|
||||||
|
|
||||||
// /// Checks whether the uniform was changed and not yet updated.
|
// /// Checks whether the uniform was changed and not yet updated.
|
||||||
// pub fn check_dirty(&self) -> bool {
|
// pub fn check_dirty(&self) -> bool {
|
||||||
// self.dirty
|
// self.dirty
|
||||||
|
@ -121,7 +121,7 @@ pub fn main() {
|
|||||||
.on
|
.on
|
||||||
.before_frame
|
.before_frame
|
||||||
.add(move |_time| {
|
.add(move |_time| {
|
||||||
mask.set_position_x(((frame as f32) / 30.0).sin() * 100.0);
|
mask.set_x(((frame as f32) / 30.0).sin() * 100.0);
|
||||||
let _keep_alive = &navigator;
|
let _keep_alive = &navigator;
|
||||||
let _keep_alive = &style_watch;
|
let _keep_alive = &style_watch;
|
||||||
let _keep_alive = &theme_manager;
|
let _keep_alive = &theme_manager;
|
||||||
|
@ -30,9 +30,49 @@ use ensogl_core::display::symbol::geometry::SpriteSystem;
|
|||||||
use ensogl_core::display::symbol::DomSymbol;
|
use ensogl_core::display::symbol::DomSymbol;
|
||||||
use ensogl_core::system::web;
|
use ensogl_core::system::web;
|
||||||
use nalgebra::Vector2;
|
use nalgebra::Vector2;
|
||||||
use nalgebra::Vector3;
|
|
||||||
|
|
||||||
|
|
||||||
|
// ==============
|
||||||
|
// === Export ===
|
||||||
|
// ==============
|
||||||
|
|
||||||
|
pub use ensogl_core::system::web::dom::Shape;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const ELEM_COUNT: i32 = 10;
|
||||||
|
const HTML_PADDING: f32 = 10.0;
|
||||||
|
const VERTICAL_MARGIN: f32 = 10.0;
|
||||||
|
const HEIGHT_FRACTION: f32 = 0.8;
|
||||||
|
|
||||||
|
fn update_shape(screen: Shape, sprites: &[Sprite], dom_symbols: &[DomSymbol]) {
|
||||||
|
let side_offset = 10.0;
|
||||||
|
let display_objects = sprites
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.display_object())
|
||||||
|
.interleave(dom_symbols.iter().map(|s| s.display_object()));
|
||||||
|
let width = (screen.width - 3.0 * side_offset) / ELEM_COUNT as f32 + 2.0 * side_offset;
|
||||||
|
let height = screen.height;
|
||||||
|
for (i, object) in display_objects.enumerate() {
|
||||||
|
let fi = i as f32;
|
||||||
|
let x = -screen.width / 2.0 + width / 2.0 + (width - 2.0 * side_offset) * fi;
|
||||||
|
object.set_position(Vector3(x, 0.0, 0.0));
|
||||||
|
}
|
||||||
|
for symbol in sprites {
|
||||||
|
let size = Vector2::new(width, height * HEIGHT_FRACTION);
|
||||||
|
symbol.size.set(size);
|
||||||
|
symbol.mod_y(|y| y - screen.height / 2.0 + size.y / 2.0 + VERTICAL_MARGIN);
|
||||||
|
}
|
||||||
|
for symbol in dom_symbols {
|
||||||
|
let size = Vector2::new(width, height * HEIGHT_FRACTION - HTML_PADDING * 2.0);
|
||||||
|
symbol.set_size(size);
|
||||||
|
symbol.mod_x(|y| y - HTML_PADDING);
|
||||||
|
symbol.mod_y(|y| y + HTML_PADDING);
|
||||||
|
symbol.mod_y(|y| {
|
||||||
|
y + screen.height / 2.0 - (size.y + HTML_PADDING * 2.0) / 2.0 - VERTICAL_MARGIN
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[entry_point]
|
#[entry_point]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@ -41,7 +81,6 @@ pub fn main() {
|
|||||||
let world = World::new().displayed_in("root");
|
let world = World::new().displayed_in("root");
|
||||||
let scene = &world.default_scene;
|
let scene = &world.default_scene;
|
||||||
let camera = scene.camera();
|
let camera = scene.camera();
|
||||||
let screen = camera.screen();
|
|
||||||
let navigator = Navigator::new(scene, &camera);
|
let navigator = Navigator::new(scene, &camera);
|
||||||
let sprite_system = SpriteSystem::new();
|
let sprite_system = SpriteSystem::new();
|
||||||
world.add_child(&sprite_system);
|
world.add_child(&sprite_system);
|
||||||
@ -50,44 +89,49 @@ pub fn main() {
|
|||||||
let dom_back_layer = &scene.dom.layers.back;
|
let dom_back_layer = &scene.dom.layers.back;
|
||||||
|
|
||||||
let mut sprites: Vec<Sprite> = default();
|
let mut sprites: Vec<Sprite> = default();
|
||||||
let mut css3d_objects: Vec<DomSymbol> = default();
|
let mut dom_symbols: Vec<DomSymbol> = default();
|
||||||
let count = 10;
|
for i in 0..ELEM_COUNT {
|
||||||
for i in 0..count {
|
let fi = i as f32;
|
||||||
let x = i as f32;
|
|
||||||
let width = screen.width * 1.5 / count as f32;
|
|
||||||
let height = screen.height;
|
|
||||||
let y = height / 2.0;
|
|
||||||
if i % 2 == 0 {
|
if i % 2 == 0 {
|
||||||
let height = height * 0.75;
|
|
||||||
let size = Vector2::new(width, height);
|
|
||||||
let position = Vector3::new(width / 1.5 * x + width / 2.0, y, 0.0);
|
|
||||||
let sprite = sprite_system.new_instance();
|
let sprite = sprite_system.new_instance();
|
||||||
sprite.size.set(size);
|
|
||||||
sprite.mod_position(|t| *t = position);
|
|
||||||
sprites.push(sprite);
|
sprites.push(sprite);
|
||||||
} else {
|
} else {
|
||||||
let div = web::document.create_div_or_panic();
|
let div = web::document.create_div_or_panic();
|
||||||
div.set_style_or_warn("width", "100%");
|
div.set_style_or_warn("width", "100%");
|
||||||
div.set_style_or_warn("height", "100%");
|
div.set_style_or_warn("height", "100%");
|
||||||
div.set_inner_html("top-left");
|
div.set_style_or_warn("padding", format!("{HTML_PADDING}px"));
|
||||||
|
div.set_style_or_warn(
|
||||||
|
"font-family",
|
||||||
|
"SF Pro Display,SF Pro Icons,Helvetica Neue,Helvetica,Arial,sans-serif",
|
||||||
|
);
|
||||||
|
div.set_inner_html(
|
||||||
|
"This is a dom element.<br/>\
|
||||||
|
Black boxes are WebGL sprites.<br/><br/>\
|
||||||
|
Try zooming and moving the scene!",
|
||||||
|
);
|
||||||
|
|
||||||
let size = Vector2::new(width, height);
|
|
||||||
let position = Vector3::new(width / 1.5 * x + width / 2.0, y, 0.0);
|
|
||||||
let object = DomSymbol::new(&div);
|
let object = DomSymbol::new(&div);
|
||||||
dom_front_layer.manage(&object);
|
dom_front_layer.manage(&object);
|
||||||
world.add_child(&object);
|
world.add_child(&object);
|
||||||
let r = ((x + 0.0) * 16.0) as u8;
|
let r = ((fi + 2.0) * 64.0 / (ELEM_COUNT as f32)) as u8;
|
||||||
let g = ((x + 2.0) * 32.0) as u8;
|
let g = ((fi + 4.0) * 128.0 / (ELEM_COUNT as f32)) as u8;
|
||||||
let b = ((x + 4.0) * 64.0) as u8;
|
let b = ((fi + 8.0) * 255.0 / (ELEM_COUNT as f32)) as u8;
|
||||||
let color = iformat!("rgb({r},{g},{b})");
|
let color = iformat!("rgb({r},{g},{b})");
|
||||||
div.set_style_or_warn("background-color", color);
|
div.set_style_or_warn("background-color", color);
|
||||||
|
|
||||||
object.dom().append_or_warn(&div);
|
object.dom().append_or_warn(&div);
|
||||||
object.set_size(size);
|
dom_symbols.push(object);
|
||||||
object.mod_position(|t| *t = position);
|
|
||||||
css3d_objects.push(object);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let network = ensogl_core::frp::Network::new("network");
|
||||||
|
|
||||||
|
let sprites2 = sprites.clone();
|
||||||
|
let dom_symbols2 = dom_symbols.clone();
|
||||||
|
ensogl_core::frp::extend! { network
|
||||||
|
eval scene.frp.shape ([] (screen) update_shape(*screen, &sprites2, &dom_symbols2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let layers = vec![dom_front_layer.clone_ref(), dom_back_layer.clone_ref()];
|
let layers = vec![dom_front_layer.clone_ref(), dom_back_layer.clone_ref()];
|
||||||
|
|
||||||
let mut iter_to_change = 0;
|
let mut iter_to_change = 0;
|
||||||
@ -97,14 +141,14 @@ pub fn main() {
|
|||||||
.on
|
.on
|
||||||
.before_frame
|
.before_frame
|
||||||
.add(move |_| {
|
.add(move |_| {
|
||||||
|
let _keep_alive = &network;
|
||||||
let _keep_alive = &navigator;
|
let _keep_alive = &navigator;
|
||||||
let _keep_alive = &sprites;
|
|
||||||
let _keep_alive = &sprite_system;
|
let _keep_alive = &sprite_system;
|
||||||
|
|
||||||
if iter_to_change == 0 {
|
if iter_to_change == 0 {
|
||||||
iter_to_change = 50;
|
iter_to_change = 50;
|
||||||
i = (i + 1) % 2;
|
i = (i + 1) % 2;
|
||||||
for (j, object) in css3d_objects.iter_mut().enumerate() {
|
for (j, object) in dom_symbols.iter_mut().enumerate() {
|
||||||
layers[(i + j) % 2].manage(object);
|
layers[(i + j) % 2].manage(object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,22 @@ mod rectangle {
|
|||||||
let rect = Rect((&width, &height)).corners_radius(10.0.px());
|
let rect = Rect((&width, &height)).corners_radius(10.0.px());
|
||||||
let inside = rect.shrink(BORDER_SIZE.px());
|
let inside = rect.shrink(BORDER_SIZE.px());
|
||||||
let border = &inside.grow((border_size - 1.0).px()) - &inside;
|
let border = &inside.grow((border_size - 1.0).px()) - &inside;
|
||||||
let shape = inside.fill(color) + border.fill(border_color);
|
let shape = border.fill(border_color) + inside.fill(color::Rgba(0.0,0.0,0.0,0.2));
|
||||||
|
// let line = Line(4.0.px()).fill(color::Rgba(1.0,0.0,0.0,1.0));
|
||||||
|
|
||||||
|
// let shape = inside.fill(color::Rgba(0.0,0.0,0.0,0.2));
|
||||||
|
// let shape = shape + line;
|
||||||
|
shape.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod rectangle2 {
|
||||||
|
use super::*;
|
||||||
|
ensogl_core::shape! {
|
||||||
|
(style: Style) {
|
||||||
|
let rect = Rect((10.px(), 10.px()));
|
||||||
|
let shape = rect.fill(color::Rgba::new(0.0, 1.0, 0.0, 1.0));
|
||||||
shape.into()
|
shape.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,8 +123,13 @@ pub fn main() {
|
|||||||
let container = define_rect(container_size * 2.0, container_size, network);
|
let container = define_rect(container_size * 2.0, container_size, network);
|
||||||
let left_stack = define_stack(network);
|
let left_stack = define_stack(network);
|
||||||
let right_stack = define_stack(network);
|
let right_stack = define_stack(network);
|
||||||
left_stack.mod_position_x(|x| x - (container_size) / 2.0);
|
left_stack.mod_x(|x| x - (container_size) / 2.0);
|
||||||
right_stack.mod_position_x(|x| x + (container_size) / 2.0);
|
right_stack.mod_x(|x| x + (container_size) / 2.0);
|
||||||
|
|
||||||
|
let rect = rectangle2::View::new();
|
||||||
|
rect.size.set(Vector2::new(2.0, 2.0));
|
||||||
|
world.add_child(&rect);
|
||||||
|
mem::forget(rect);
|
||||||
|
|
||||||
world.add_child(&container);
|
world.add_child(&container);
|
||||||
container.add_child(&left_stack);
|
container.add_child(&left_stack);
|
||||||
|
@ -189,10 +189,10 @@ fn init(app: &Application) {
|
|||||||
let mut positions = itertools::iproduct!([-450.0, 50.0], [350.0, -50.0]).map(pair_to_vec2);
|
let mut positions = itertools::iproduct!([-450.0, 50.0], [350.0, -50.0]).map(pair_to_vec2);
|
||||||
|
|
||||||
grids_layer.add(&plain_grid_view);
|
grids_layer.add(&plain_grid_view);
|
||||||
plain_grid_view.set_position_xy(positions.next().unwrap());
|
plain_grid_view.set_xy(positions.next().unwrap());
|
||||||
for (view, position) in grid_views_with_headers.iter().zip(positions) {
|
for (view, position) in grid_views_with_headers.iter().zip(positions) {
|
||||||
grids_layer.add(view);
|
grids_layer.add(view);
|
||||||
view.set_position_xy(position);
|
view.set_xy(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
let view = &grid_views_with_headers[0];
|
let view = &grid_views_with_headers[0];
|
||||||
|
@ -88,7 +88,7 @@ pub async fn main() {
|
|||||||
|
|
||||||
let graph_height: f32 = flame_graph.height();
|
let graph_height: f32 = flame_graph.height();
|
||||||
let sequence_diagram_offset = graph_height + sequence_diagram.height.value();
|
let sequence_diagram_offset = graph_height + sequence_diagram.height.value();
|
||||||
sequence_diagram.set_position_y(-sequence_diagram_offset);
|
sequence_diagram.set_y(-sequence_diagram_offset);
|
||||||
|
|
||||||
scene.add_child(&sequence_diagram);
|
scene.add_child(&sequence_diagram);
|
||||||
scene.layers.main.add(&sequence_diagram);
|
scene.layers.main.add(&sequence_diagram);
|
||||||
|
@ -101,7 +101,7 @@ fn init(app: &Application) {
|
|||||||
theme::builtin::light::enable(app);
|
theme::builtin::light::enable(app);
|
||||||
|
|
||||||
let scene = &app.display.default_scene;
|
let scene = &app.display.default_scene;
|
||||||
scene.camera().set_position_xy(Vector2(100.0, -100.0));
|
scene.camera().set_xy(Vector2(100.0, -100.0));
|
||||||
|
|
||||||
let navigator = Navigator::new(scene, &scene.camera());
|
let navigator = Navigator::new(scene, &scene.camera());
|
||||||
navigator.disable_wheel_panning();
|
navigator.disable_wheel_panning();
|
||||||
@ -125,8 +125,8 @@ fn init(app: &Application) {
|
|||||||
scroll_area.add_child(&background);
|
scroll_area.add_child(&background);
|
||||||
scene.layers.below_main.add(&background);
|
scene.layers.below_main.add(&background);
|
||||||
background.size.set(Vector2::new(200.0, 200.0));
|
background.size.set(Vector2::new(200.0, 200.0));
|
||||||
background.set_position_x(100.0);
|
background.set_x(100.0);
|
||||||
background.set_position_y(-100.0);
|
background.set_y(-100.0);
|
||||||
std::mem::forget(background);
|
std::mem::forget(background);
|
||||||
|
|
||||||
|
|
||||||
@ -135,8 +135,8 @@ fn init(app: &Application) {
|
|||||||
let content = content::View::new();
|
let content = content::View::new();
|
||||||
scroll_area.content().add_child(&content);
|
scroll_area.content().add_child(&content);
|
||||||
content.size.set(Vector2::new(300.0, 1000.0));
|
content.size.set(Vector2::new(300.0, 1000.0));
|
||||||
content.set_position_x(150.0);
|
content.set_x(150.0);
|
||||||
content.set_position_y(-500.0);
|
content.set_y(-500.0);
|
||||||
std::mem::forget(content);
|
std::mem::forget(content);
|
||||||
|
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ fn init(app: &Application) {
|
|||||||
let slider2 = make_slider(app);
|
let slider2 = make_slider(app);
|
||||||
slider2.inner().frp.set_width(400.0);
|
slider2.inner().frp.set_width(400.0);
|
||||||
slider2.inner().frp.set_height(50.0);
|
slider2.inner().frp.set_height(50.0);
|
||||||
slider2.inner().set_position_y(60.0);
|
slider2.inner().set_y(60.0);
|
||||||
slider2.inner().frp.set_slider_track_color(color::Lcha(0.4, 0.7, 0.2, 1.0));
|
slider2.inner().frp.set_slider_track_color(color::Lcha(0.4, 0.7, 0.2, 1.0));
|
||||||
slider2.inner().frp.set_value_text_color(color::Lcha(0.2, 0.7, 0.7, 1.0));
|
slider2.inner().frp.set_value_text_color(color::Lcha(0.2, 0.7, 0.7, 1.0));
|
||||||
slider2.inner().frp.set_slider_disabled(true);
|
slider2.inner().frp.set_slider_disabled(true);
|
||||||
@ -89,7 +89,7 @@ fn init(app: &Application) {
|
|||||||
let slider3 = make_slider(app);
|
let slider3 = make_slider(app);
|
||||||
slider3.inner().frp.set_width(400.0);
|
slider3.inner().frp.set_width(400.0);
|
||||||
slider3.inner().frp.set_height(50.0);
|
slider3.inner().frp.set_height(50.0);
|
||||||
slider3.inner().set_position_y(120.0);
|
slider3.inner().set_y(120.0);
|
||||||
slider3.inner().frp.set_slider_track_color(color::Lcha(0.4, 0.7, 0.7, 1.0));
|
slider3.inner().frp.set_slider_track_color(color::Lcha(0.4, 0.7, 0.7, 1.0));
|
||||||
slider3.inner().frp.set_value_text_color(color::Lcha(0.2, 0.7, 0.2, 1.0));
|
slider3.inner().frp.set_value_text_color(color::Lcha(0.2, 0.7, 0.2, 1.0));
|
||||||
slider3.inner().frp.set_label("Inner label");
|
slider3.inner().frp.set_label("Inner label");
|
||||||
@ -98,7 +98,7 @@ fn init(app: &Application) {
|
|||||||
let slider4 = make_slider(app);
|
let slider4 = make_slider(app);
|
||||||
slider4.inner().frp.set_width(400.0);
|
slider4.inner().frp.set_width(400.0);
|
||||||
slider4.inner().frp.set_height(50.0);
|
slider4.inner().frp.set_height(50.0);
|
||||||
slider4.inner().set_position_y(180.0);
|
slider4.inner().set_y(180.0);
|
||||||
slider4.inner().frp.set_slider_track_color(color::Lcha(0.4, 0.7, 0.2, 1.0));
|
slider4.inner().frp.set_slider_track_color(color::Lcha(0.4, 0.7, 0.2, 1.0));
|
||||||
slider4.inner().frp.set_value_text_color(color::Lcha(0.2, 0.7, 0.7, 1.0));
|
slider4.inner().frp.set_value_text_color(color::Lcha(0.2, 0.7, 0.7, 1.0));
|
||||||
slider4.inner().frp.set_label("Disabled label");
|
slider4.inner().frp.set_label("Disabled label");
|
||||||
|
@ -128,22 +128,22 @@ impl Borders {
|
|||||||
eval area.height ([borders](h) {
|
eval area.height ([borders](h) {
|
||||||
borders.right.size.set(Vector2(BORDER_WIDTH + BORDER_PADDING * 2.0, *h));
|
borders.right.size.set(Vector2(BORDER_WIDTH + BORDER_PADDING * 2.0, *h));
|
||||||
borders.left.size.set(Vector2(BORDER_WIDTH + BORDER_PADDING * 2.0, *h));
|
borders.left.size.set(Vector2(BORDER_WIDTH + BORDER_PADDING * 2.0, *h));
|
||||||
borders.right.set_position_y(-h/2.0);
|
borders.right.set_y(-h/2.0);
|
||||||
borders.left.set_position_y(-h/2.0);
|
borders.left.set_y(-h/2.0);
|
||||||
|
|
||||||
borders.bottom_changed_frame_hold.set(DEBUG_FRAME_HOLD);
|
borders.bottom_changed_frame_hold.set(DEBUG_FRAME_HOLD);
|
||||||
borders.bottom.color_rgba.set(RED);
|
borders.bottom.color_rgba.set(RED);
|
||||||
borders.bottom.set_position_y(-*h);
|
borders.bottom.set_y(-*h);
|
||||||
});
|
});
|
||||||
eval area.width ([borders](w) {
|
eval area.width ([borders](w) {
|
||||||
borders.top.size.set(Vector2(*w, BORDER_WIDTH + BORDER_PADDING * 2.0));
|
borders.top.size.set(Vector2(*w, BORDER_WIDTH + BORDER_PADDING * 2.0));
|
||||||
borders.bottom.size.set(Vector2(*w, BORDER_WIDTH + BORDER_PADDING * 2.0));
|
borders.bottom.size.set(Vector2(*w, BORDER_WIDTH + BORDER_PADDING * 2.0));
|
||||||
borders.top.set_position_x(w/2.0);
|
borders.top.set_x(w/2.0);
|
||||||
borders.bottom.set_position_x(w/2.0);
|
borders.bottom.set_x(w/2.0);
|
||||||
|
|
||||||
borders.right_changed_frame_hold.set(DEBUG_FRAME_HOLD);
|
borders.right_changed_frame_hold.set(DEBUG_FRAME_HOLD);
|
||||||
borders.right.color_rgba.set(RED);
|
borders.right.color_rgba.set(RED);
|
||||||
borders.right.set_position_x(*w);
|
borders.right.set_x(*w);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
mem::forget(frp);
|
mem::forget(frp);
|
||||||
|
@ -12,3 +12,7 @@ nalgebra = { version = "0.26.1" }
|
|||||||
num-traits = { version = "0.2" }
|
num-traits = { version = "0.2" }
|
||||||
paste = "1.0.7"
|
paste = "1.0.7"
|
||||||
serde = { version = "1.0", features = ["derive"], optional = true }
|
serde = { version = "1.0", features = ["derive"], optional = true }
|
||||||
|
enso-prelude = { path = "../prelude" }
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
enso-prelude = { path = "../prelude" }
|
||||||
|
177
lib/rust/types/build.rs
Normal file
177
lib/rust/types/build.rs
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
//! Generation of Dim* macros, macros allowing generation of swizzling getters and setters.
|
||||||
|
|
||||||
|
// === Non-Standard Linter Configuration ===
|
||||||
|
#![allow(clippy::bool_to_int_with_if)]
|
||||||
|
#![allow(clippy::let_and_return)]
|
||||||
|
#![allow(clippy::option_map_unit_fn)]
|
||||||
|
#![allow(clippy::precedence)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![deny(non_ascii_idents)]
|
||||||
|
#![deny(unconditional_recursion)]
|
||||||
|
#![warn(unsafe_code)]
|
||||||
|
#![warn(missing_copy_implementations)]
|
||||||
|
#![warn(missing_debug_implementations)]
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
#![warn(trivial_casts)]
|
||||||
|
#![warn(trivial_numeric_casts)]
|
||||||
|
#![warn(unused_import_braces)]
|
||||||
|
#![warn(unused_qualifications)]
|
||||||
|
|
||||||
|
use enso_prelude::*;
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::Write as IoWrite;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =================
|
||||||
|
// === Constants ===
|
||||||
|
// =================
|
||||||
|
|
||||||
|
const FILE: &str = "src/dim_macros.rs";
|
||||||
|
const AXES: &[&str] = &["x", "y", "z", "w"];
|
||||||
|
const INDENT_SIZE: usize = 4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ========================
|
||||||
|
// === Formatting Utils ===
|
||||||
|
// ========================
|
||||||
|
|
||||||
|
fn indent(level: usize) -> String {
|
||||||
|
" ".repeat(level * INDENT_SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// === Implementation ===
|
||||||
|
// ======================
|
||||||
|
|
||||||
|
/// Generates swizzling data. The [`base_dim`] describes what dimension the data should be generated
|
||||||
|
/// in. For example, if it is set to 3, all of "x", "y", and "z" axes will be combined to generate
|
||||||
|
/// the result. The [`dim`] describes the dimension of the swizzling. For example, if it is set to
|
||||||
|
/// 2, the result will contain 2-dimensional coordinates, like "xy", or "yz". If the [`unique`] flag
|
||||||
|
/// is set, the generated swizzling will not have repeated axes (e.g. `xx` is not allowed).
|
||||||
|
///
|
||||||
|
/// The output is a vector of four elements:
|
||||||
|
/// - The swizzling name, like "xy", "xyz", "xz", etc.
|
||||||
|
/// - The swizzling dimension.
|
||||||
|
/// - The swizzling component indexes. For example [0, 2] for "xz".
|
||||||
|
/// - The enumeration of components. For example [0, 1] for "xz".
|
||||||
|
///
|
||||||
|
/// For example, for the base dimension of 3 and the dimension of 2, the following swizzles will be
|
||||||
|
/// generated:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// xz 2 [0, 2] [0, 1]
|
||||||
|
/// yz 2 [1, 2] [0, 1]
|
||||||
|
/// zx 2 [2, 0] [0, 1]
|
||||||
|
/// zy 2 [2, 1] [0, 1]
|
||||||
|
/// zz 2 [2, 2] [0, 1]
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// See the generated [`FILE`] to see the result of this script.
|
||||||
|
fn gen_swizzling(
|
||||||
|
base_dim: usize,
|
||||||
|
dim: usize,
|
||||||
|
unique: bool,
|
||||||
|
) -> Vec<(Vec<String>, usize, Vec<usize>, Vec<usize>)> {
|
||||||
|
let mut vec: Vec<(Vec<String>, Vec<usize>, Vec<usize>)> = vec![(vec![], vec![], vec![])];
|
||||||
|
for _ in 0..dim {
|
||||||
|
vec = vec
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.cartesian_product(AXES[0..base_dim].iter().enumerate())
|
||||||
|
.filter_map(|((mut prod, mut ixs, mut ord), (ix, axis))| {
|
||||||
|
if unique && ixs.contains(&ix) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
prod.push(axis.to_string());
|
||||||
|
ixs.push(ix);
|
||||||
|
ord.push(ord.len());
|
||||||
|
Some((prod, ixs, ord))
|
||||||
|
})
|
||||||
|
.collect_vec();
|
||||||
|
}
|
||||||
|
vec.into_iter().map(|(prod, ixs, ord)| (prod, dim, ixs, ord)).collect_vec()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Just like [`gen_swizzling`], but the output always contains the dimension component. For
|
||||||
|
/// example, if the dimension was set to 2, the output will contain all swizzling combinations that
|
||||||
|
/// contain the "z" component.
|
||||||
|
fn gen_swizzling_force_dim_component(
|
||||||
|
input_dim: usize,
|
||||||
|
dim: usize,
|
||||||
|
unique: bool,
|
||||||
|
) -> Vec<(Vec<String>, usize, Vec<usize>, Vec<usize>)> {
|
||||||
|
let axe = AXES[input_dim - 1];
|
||||||
|
gen_swizzling(input_dim, dim, unique)
|
||||||
|
.into_iter()
|
||||||
|
.filter(|(axes, _, _, _)| axes.contains(&axe.to_string()))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_swizzling_macro_branch(input_dim: usize, unique: bool) -> String {
|
||||||
|
let mut out = String::new();
|
||||||
|
out.write_str(&format!(
|
||||||
|
"{}({}, $f: ident $(,$($args:tt)*)?) => {{ $f! {{ $([$($args)*])? {}\n",
|
||||||
|
indent(1),
|
||||||
|
input_dim,
|
||||||
|
input_dim,
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for dim in 1..input_dim {
|
||||||
|
for (axes, dim, ixs, ord) in gen_swizzling_force_dim_component(input_dim, dim, unique) {
|
||||||
|
out.write_str(&format!("{}{} {} {:?} {:?}\n", indent(2), axes.join(""), dim, ixs, ord))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (axes, dim, ixs, ord) in gen_swizzling(input_dim, input_dim, unique) {
|
||||||
|
out.write_str(&format!("{}{} {} {:?} {:?}\n", indent(2), axes.join(""), dim, ixs, ord))
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
out.write_str(&format!("{}}}}};\n", indent(1))).unwrap();
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The generated macro accepts two arguments, the dimension of the swizzling and another macro name
|
||||||
|
/// that should be called with the swizzling data. The provided macro will be called with the chosen
|
||||||
|
/// dimension and the data generated by the [`gen_swizzling_macro_branch`] function.
|
||||||
|
///
|
||||||
|
/// See the generated [`FILE`] to see the result of this script.
|
||||||
|
fn gen_swizzling_macro(unique: bool) -> String {
|
||||||
|
let mut out = String::new();
|
||||||
|
let sfx = if unique { "_unique" } else { "" };
|
||||||
|
out.write_str("/// Swizzling data for the given dimension.\n").unwrap();
|
||||||
|
out.write_str("/// See the [`build.rs`] file to learn more.\n").unwrap();
|
||||||
|
out.write_str("#[macro_export]\n").unwrap();
|
||||||
|
out.write_str(&format!("macro_rules! with_swizzling_for_dim{} {{\n", sfx)).unwrap();
|
||||||
|
out.write_str(&gen_swizzling_macro_branch(1, unique)).unwrap();
|
||||||
|
out.write_str(&gen_swizzling_macro_branch(2, unique)).unwrap();
|
||||||
|
out.write_str(&gen_swizzling_macro_branch(3, unique)).unwrap();
|
||||||
|
out.write_str(&gen_swizzling_macro_branch(4, unique)).unwrap();
|
||||||
|
out.write_str("}").unwrap();
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
let mut file = File::create(FILE).unwrap();
|
||||||
|
let warning = "THIS IS AN AUTO-GENERATED FILE. DO NOT EDIT IT DIRECTLY!";
|
||||||
|
let border = "!".repeat(warning.len());
|
||||||
|
|
||||||
|
let mut out = String::new();
|
||||||
|
out.write_str("//! Macros allowing generation of swizzling getters and setters.\n").unwrap();
|
||||||
|
out.write_str("//! See the docs of [`build.rs`] and usage places to learn more.\n").unwrap();
|
||||||
|
out.write_str(&format!("\n// {}\n", border)).unwrap();
|
||||||
|
out.write_str("// THIS IS AN AUTO-GENERATED FILE. DO NOT EDIT IT DIRECTLY!\n").unwrap();
|
||||||
|
out.write_str(&format!("// {}\n\n\n", border)).unwrap();
|
||||||
|
out.write_str(&gen_swizzling_macro(false)).unwrap();
|
||||||
|
out.write_str("\n\n").unwrap();
|
||||||
|
out.write_str(&gen_swizzling_macro(true)).unwrap();
|
||||||
|
out.write_str("\n").unwrap();
|
||||||
|
file.write_all(out.as_bytes()).unwrap();
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
157
lib/rust/types/src/dim.rs
Normal file
157
lib/rust/types/src/dim.rs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
//! Definition of Dim* traits. These traits define common operations on types that represent
|
||||||
|
//! dimensional transformations. For example, they define getters, such as `xy()`, or setters, such
|
||||||
|
//! as `set_xy(...)` on 2-dimensional types. Moreover, this module implements these traits for
|
||||||
|
//! suitable nalgebra's Vector types.
|
||||||
|
|
||||||
|
use enso_prelude::*;
|
||||||
|
|
||||||
|
use nalgebra;
|
||||||
|
use nalgebra::Scalar;
|
||||||
|
use nalgebra::Vector2;
|
||||||
|
use nalgebra::Vector3;
|
||||||
|
use nalgebra::Vector4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ===================
|
||||||
|
// === Dim* Traits ===
|
||||||
|
// ===================
|
||||||
|
|
||||||
|
macro_rules! gen_dim_trait {
|
||||||
|
([$prev_dim:tt] $dim:tt
|
||||||
|
$( $name:ident $swizzling_dim:tt [$($dim_ix:tt)*] [$($dim_ord:tt)*] )*
|
||||||
|
) => { paste! {
|
||||||
|
#[doc = "Component swizzling getters for "]
|
||||||
|
#[doc = stringify!($dim)]
|
||||||
|
#[doc = "`-dimensional types."]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub trait [<Dim $dim>] : [<Dim $prev_dim>] {
|
||||||
|
type [<Dim $dim Type>];
|
||||||
|
$(
|
||||||
|
fn $name(&self) -> Self::[<Dim $swizzling_dim Type>];
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An abstract, 0-dimensional type. It is defined to simplify macro definition.
|
||||||
|
pub trait Dim0 {}
|
||||||
|
impl<T> Dim0 for T {}
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim!(1, gen_dim_trait, 0);
|
||||||
|
crate::with_swizzling_for_dim!(2, gen_dim_trait, 1);
|
||||||
|
crate::with_swizzling_for_dim!(3, gen_dim_trait, 2);
|
||||||
|
crate::with_swizzling_for_dim!(4, gen_dim_trait, 3);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// === DimSetter* Traits ===
|
||||||
|
// =========================
|
||||||
|
|
||||||
|
macro_rules! gen_dim_setter_trait {
|
||||||
|
($dim:tt
|
||||||
|
$( $name:ident $swizzling_dim:tt [$($dim_ix:tt)*] [$($dim_ord:tt)*] )*
|
||||||
|
) => { paste! {
|
||||||
|
#[doc = "Component swizzling setters for "]
|
||||||
|
#[doc = stringify!($dim)]
|
||||||
|
#[doc = "`-dimensional types."]
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
pub trait [<Dim Setter $dim>] : [<Dim $dim>] {
|
||||||
|
$(
|
||||||
|
fn [<set_$name>](&mut self, value: Self::[<Dim $swizzling_dim Type>]);
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim_unique!(1, gen_dim_setter_trait);
|
||||||
|
crate::with_swizzling_for_dim_unique!(2, gen_dim_setter_trait);
|
||||||
|
crate::with_swizzling_for_dim_unique!(3, gen_dim_setter_trait);
|
||||||
|
crate::with_swizzling_for_dim_unique!(4, gen_dim_setter_trait);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================
|
||||||
|
// === Getters for nalgebra::Vector* ===
|
||||||
|
// =====================================
|
||||||
|
|
||||||
|
macro_rules! gen_dim_impl_for_vector {
|
||||||
|
([$vec:tt] $dim:tt $( $name:ident $swizzling_dim:tt [$($dim_ix:tt)*] [$($dim_ord:tt)*] )*) => {
|
||||||
|
paste! {
|
||||||
|
impl<T: Scalar + Copy> [<Dim $dim>] for $vec<T> {
|
||||||
|
type [<Dim $dim Type>] = [<Vector $dim>]<T>;
|
||||||
|
$(
|
||||||
|
fn $name(&self) -> Self::[<Dim $swizzling_dim Type>] {
|
||||||
|
gen_dim_impl_for_vector_body!{self, $swizzling_dim, [$($dim_ix)*]}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! gen_dim_impl_for_vector_body {
|
||||||
|
($this:tt, $swizzling_dim:tt, [$dim_ix:tt]) => {
|
||||||
|
$this[$dim_ix]
|
||||||
|
};
|
||||||
|
($this:tt, $swizzling_dim:tt, [$($dim_ix:tt),*]) => { paste! {
|
||||||
|
Self::[<Dim $swizzling_dim Type>]::new( $( $this[$dim_ix] ),* )
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A one dimensional vector, being just a value. It is used mostly to simplify macro definitions.
|
||||||
|
pub type Vector1<T> = T;
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim!(1, gen_dim_impl_for_vector, Vector2);
|
||||||
|
crate::with_swizzling_for_dim!(2, gen_dim_impl_for_vector, Vector2);
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim!(1, gen_dim_impl_for_vector, Vector3);
|
||||||
|
crate::with_swizzling_for_dim!(2, gen_dim_impl_for_vector, Vector3);
|
||||||
|
crate::with_swizzling_for_dim!(3, gen_dim_impl_for_vector, Vector3);
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim!(1, gen_dim_impl_for_vector, Vector4);
|
||||||
|
crate::with_swizzling_for_dim!(2, gen_dim_impl_for_vector, Vector4);
|
||||||
|
crate::with_swizzling_for_dim!(3, gen_dim_impl_for_vector, Vector4);
|
||||||
|
crate::with_swizzling_for_dim!(4, gen_dim_impl_for_vector, Vector4);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// =====================================
|
||||||
|
// === Setters for nalgebra::Vector* ===
|
||||||
|
// =====================================
|
||||||
|
|
||||||
|
macro_rules! gen_dim_setter_impl_for_vector {
|
||||||
|
([$vec:tt] $dim:tt $( $name:ident $swizzling_dim:tt [$($dim_ix:tt)*] [$($dim_ord:tt)*] )*) => {
|
||||||
|
paste! {
|
||||||
|
impl<T: Scalar + Copy> [<Dim Setter $dim>] for $vec<T> {
|
||||||
|
$(
|
||||||
|
fn [<set_ $name>](&mut self, value: Self::[<Dim $swizzling_dim Type>]) {
|
||||||
|
gen_dim_setter_impl_for_vector_body!{self, value, $swizzling_dim, [$($dim_ix)*], [$($dim_ord)*]}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! gen_dim_setter_impl_for_vector_body {
|
||||||
|
($this:tt, $value:tt, $swizzling_dim:tt, [$dim_ix:tt], [$($dim_ord:tt),*]) => {
|
||||||
|
$this[$dim_ix] = $value;
|
||||||
|
};
|
||||||
|
($this:tt, $value:tt, $swizzling_dim:tt, [$($dim_ix:tt),*], [$($dim_ord:tt),*]) => { paste! {
|
||||||
|
$( $this[$dim_ix] = $value[$dim_ord]; )*
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim_unique!(1, gen_dim_setter_impl_for_vector, Vector2);
|
||||||
|
crate::with_swizzling_for_dim_unique!(2, gen_dim_setter_impl_for_vector, Vector2);
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim_unique!(1, gen_dim_setter_impl_for_vector, Vector3);
|
||||||
|
crate::with_swizzling_for_dim_unique!(2, gen_dim_setter_impl_for_vector, Vector3);
|
||||||
|
crate::with_swizzling_for_dim_unique!(3, gen_dim_setter_impl_for_vector, Vector3);
|
||||||
|
|
||||||
|
crate::with_swizzling_for_dim_unique!(1, gen_dim_setter_impl_for_vector, Vector4);
|
||||||
|
crate::with_swizzling_for_dim_unique!(2, gen_dim_setter_impl_for_vector, Vector4);
|
||||||
|
crate::with_swizzling_for_dim_unique!(3, gen_dim_setter_impl_for_vector, Vector4);
|
||||||
|
crate::with_swizzling_for_dim_unique!(4, gen_dim_setter_impl_for_vector, Vector4);
|
441
lib/rust/types/src/dim_macros.rs
Normal file
441
lib/rust/types/src/dim_macros.rs
Normal file
@ -0,0 +1,441 @@
|
|||||||
|
//! Macros allowing generation of swizzling getters and setters.
|
||||||
|
//! See the docs of [`build.rs`] and usage places to learn more.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
// THIS IS AN AUTO-GENERATED FILE. DO NOT EDIT IT DIRECTLY!
|
||||||
|
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
|
|
||||||
|
|
||||||
|
/// Swizzling data for the given dimension.
|
||||||
|
/// See the [`build.rs`] file to learn more.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! with_swizzling_for_dim {
|
||||||
|
(1, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 1
|
||||||
|
x 1 [0] [0]
|
||||||
|
}};
|
||||||
|
(2, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 2
|
||||||
|
y 1 [1] [0]
|
||||||
|
xx 2 [0, 0] [0, 1]
|
||||||
|
xy 2 [0, 1] [0, 1]
|
||||||
|
yx 2 [1, 0] [0, 1]
|
||||||
|
yy 2 [1, 1] [0, 1]
|
||||||
|
}};
|
||||||
|
(3, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 3
|
||||||
|
z 1 [2] [0]
|
||||||
|
xz 2 [0, 2] [0, 1]
|
||||||
|
yz 2 [1, 2] [0, 1]
|
||||||
|
zx 2 [2, 0] [0, 1]
|
||||||
|
zy 2 [2, 1] [0, 1]
|
||||||
|
zz 2 [2, 2] [0, 1]
|
||||||
|
xxx 3 [0, 0, 0] [0, 1, 2]
|
||||||
|
xxy 3 [0, 0, 1] [0, 1, 2]
|
||||||
|
xxz 3 [0, 0, 2] [0, 1, 2]
|
||||||
|
xyx 3 [0, 1, 0] [0, 1, 2]
|
||||||
|
xyy 3 [0, 1, 1] [0, 1, 2]
|
||||||
|
xyz 3 [0, 1, 2] [0, 1, 2]
|
||||||
|
xzx 3 [0, 2, 0] [0, 1, 2]
|
||||||
|
xzy 3 [0, 2, 1] [0, 1, 2]
|
||||||
|
xzz 3 [0, 2, 2] [0, 1, 2]
|
||||||
|
yxx 3 [1, 0, 0] [0, 1, 2]
|
||||||
|
yxy 3 [1, 0, 1] [0, 1, 2]
|
||||||
|
yxz 3 [1, 0, 2] [0, 1, 2]
|
||||||
|
yyx 3 [1, 1, 0] [0, 1, 2]
|
||||||
|
yyy 3 [1, 1, 1] [0, 1, 2]
|
||||||
|
yyz 3 [1, 1, 2] [0, 1, 2]
|
||||||
|
yzx 3 [1, 2, 0] [0, 1, 2]
|
||||||
|
yzy 3 [1, 2, 1] [0, 1, 2]
|
||||||
|
yzz 3 [1, 2, 2] [0, 1, 2]
|
||||||
|
zxx 3 [2, 0, 0] [0, 1, 2]
|
||||||
|
zxy 3 [2, 0, 1] [0, 1, 2]
|
||||||
|
zxz 3 [2, 0, 2] [0, 1, 2]
|
||||||
|
zyx 3 [2, 1, 0] [0, 1, 2]
|
||||||
|
zyy 3 [2, 1, 1] [0, 1, 2]
|
||||||
|
zyz 3 [2, 1, 2] [0, 1, 2]
|
||||||
|
zzx 3 [2, 2, 0] [0, 1, 2]
|
||||||
|
zzy 3 [2, 2, 1] [0, 1, 2]
|
||||||
|
zzz 3 [2, 2, 2] [0, 1, 2]
|
||||||
|
}};
|
||||||
|
(4, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 4
|
||||||
|
w 1 [3] [0]
|
||||||
|
xw 2 [0, 3] [0, 1]
|
||||||
|
yw 2 [1, 3] [0, 1]
|
||||||
|
zw 2 [2, 3] [0, 1]
|
||||||
|
wx 2 [3, 0] [0, 1]
|
||||||
|
wy 2 [3, 1] [0, 1]
|
||||||
|
wz 2 [3, 2] [0, 1]
|
||||||
|
ww 2 [3, 3] [0, 1]
|
||||||
|
xxw 3 [0, 0, 3] [0, 1, 2]
|
||||||
|
xyw 3 [0, 1, 3] [0, 1, 2]
|
||||||
|
xzw 3 [0, 2, 3] [0, 1, 2]
|
||||||
|
xwx 3 [0, 3, 0] [0, 1, 2]
|
||||||
|
xwy 3 [0, 3, 1] [0, 1, 2]
|
||||||
|
xwz 3 [0, 3, 2] [0, 1, 2]
|
||||||
|
xww 3 [0, 3, 3] [0, 1, 2]
|
||||||
|
yxw 3 [1, 0, 3] [0, 1, 2]
|
||||||
|
yyw 3 [1, 1, 3] [0, 1, 2]
|
||||||
|
yzw 3 [1, 2, 3] [0, 1, 2]
|
||||||
|
ywx 3 [1, 3, 0] [0, 1, 2]
|
||||||
|
ywy 3 [1, 3, 1] [0, 1, 2]
|
||||||
|
ywz 3 [1, 3, 2] [0, 1, 2]
|
||||||
|
yww 3 [1, 3, 3] [0, 1, 2]
|
||||||
|
zxw 3 [2, 0, 3] [0, 1, 2]
|
||||||
|
zyw 3 [2, 1, 3] [0, 1, 2]
|
||||||
|
zzw 3 [2, 2, 3] [0, 1, 2]
|
||||||
|
zwx 3 [2, 3, 0] [0, 1, 2]
|
||||||
|
zwy 3 [2, 3, 1] [0, 1, 2]
|
||||||
|
zwz 3 [2, 3, 2] [0, 1, 2]
|
||||||
|
zww 3 [2, 3, 3] [0, 1, 2]
|
||||||
|
wxx 3 [3, 0, 0] [0, 1, 2]
|
||||||
|
wxy 3 [3, 0, 1] [0, 1, 2]
|
||||||
|
wxz 3 [3, 0, 2] [0, 1, 2]
|
||||||
|
wxw 3 [3, 0, 3] [0, 1, 2]
|
||||||
|
wyx 3 [3, 1, 0] [0, 1, 2]
|
||||||
|
wyy 3 [3, 1, 1] [0, 1, 2]
|
||||||
|
wyz 3 [3, 1, 2] [0, 1, 2]
|
||||||
|
wyw 3 [3, 1, 3] [0, 1, 2]
|
||||||
|
wzx 3 [3, 2, 0] [0, 1, 2]
|
||||||
|
wzy 3 [3, 2, 1] [0, 1, 2]
|
||||||
|
wzz 3 [3, 2, 2] [0, 1, 2]
|
||||||
|
wzw 3 [3, 2, 3] [0, 1, 2]
|
||||||
|
wwx 3 [3, 3, 0] [0, 1, 2]
|
||||||
|
wwy 3 [3, 3, 1] [0, 1, 2]
|
||||||
|
wwz 3 [3, 3, 2] [0, 1, 2]
|
||||||
|
www 3 [3, 3, 3] [0, 1, 2]
|
||||||
|
xxxx 4 [0, 0, 0, 0] [0, 1, 2, 3]
|
||||||
|
xxxy 4 [0, 0, 0, 1] [0, 1, 2, 3]
|
||||||
|
xxxz 4 [0, 0, 0, 2] [0, 1, 2, 3]
|
||||||
|
xxxw 4 [0, 0, 0, 3] [0, 1, 2, 3]
|
||||||
|
xxyx 4 [0, 0, 1, 0] [0, 1, 2, 3]
|
||||||
|
xxyy 4 [0, 0, 1, 1] [0, 1, 2, 3]
|
||||||
|
xxyz 4 [0, 0, 1, 2] [0, 1, 2, 3]
|
||||||
|
xxyw 4 [0, 0, 1, 3] [0, 1, 2, 3]
|
||||||
|
xxzx 4 [0, 0, 2, 0] [0, 1, 2, 3]
|
||||||
|
xxzy 4 [0, 0, 2, 1] [0, 1, 2, 3]
|
||||||
|
xxzz 4 [0, 0, 2, 2] [0, 1, 2, 3]
|
||||||
|
xxzw 4 [0, 0, 2, 3] [0, 1, 2, 3]
|
||||||
|
xxwx 4 [0, 0, 3, 0] [0, 1, 2, 3]
|
||||||
|
xxwy 4 [0, 0, 3, 1] [0, 1, 2, 3]
|
||||||
|
xxwz 4 [0, 0, 3, 2] [0, 1, 2, 3]
|
||||||
|
xxww 4 [0, 0, 3, 3] [0, 1, 2, 3]
|
||||||
|
xyxx 4 [0, 1, 0, 0] [0, 1, 2, 3]
|
||||||
|
xyxy 4 [0, 1, 0, 1] [0, 1, 2, 3]
|
||||||
|
xyxz 4 [0, 1, 0, 2] [0, 1, 2, 3]
|
||||||
|
xyxw 4 [0, 1, 0, 3] [0, 1, 2, 3]
|
||||||
|
xyyx 4 [0, 1, 1, 0] [0, 1, 2, 3]
|
||||||
|
xyyy 4 [0, 1, 1, 1] [0, 1, 2, 3]
|
||||||
|
xyyz 4 [0, 1, 1, 2] [0, 1, 2, 3]
|
||||||
|
xyyw 4 [0, 1, 1, 3] [0, 1, 2, 3]
|
||||||
|
xyzx 4 [0, 1, 2, 0] [0, 1, 2, 3]
|
||||||
|
xyzy 4 [0, 1, 2, 1] [0, 1, 2, 3]
|
||||||
|
xyzz 4 [0, 1, 2, 2] [0, 1, 2, 3]
|
||||||
|
xyzw 4 [0, 1, 2, 3] [0, 1, 2, 3]
|
||||||
|
xywx 4 [0, 1, 3, 0] [0, 1, 2, 3]
|
||||||
|
xywy 4 [0, 1, 3, 1] [0, 1, 2, 3]
|
||||||
|
xywz 4 [0, 1, 3, 2] [0, 1, 2, 3]
|
||||||
|
xyww 4 [0, 1, 3, 3] [0, 1, 2, 3]
|
||||||
|
xzxx 4 [0, 2, 0, 0] [0, 1, 2, 3]
|
||||||
|
xzxy 4 [0, 2, 0, 1] [0, 1, 2, 3]
|
||||||
|
xzxz 4 [0, 2, 0, 2] [0, 1, 2, 3]
|
||||||
|
xzxw 4 [0, 2, 0, 3] [0, 1, 2, 3]
|
||||||
|
xzyx 4 [0, 2, 1, 0] [0, 1, 2, 3]
|
||||||
|
xzyy 4 [0, 2, 1, 1] [0, 1, 2, 3]
|
||||||
|
xzyz 4 [0, 2, 1, 2] [0, 1, 2, 3]
|
||||||
|
xzyw 4 [0, 2, 1, 3] [0, 1, 2, 3]
|
||||||
|
xzzx 4 [0, 2, 2, 0] [0, 1, 2, 3]
|
||||||
|
xzzy 4 [0, 2, 2, 1] [0, 1, 2, 3]
|
||||||
|
xzzz 4 [0, 2, 2, 2] [0, 1, 2, 3]
|
||||||
|
xzzw 4 [0, 2, 2, 3] [0, 1, 2, 3]
|
||||||
|
xzwx 4 [0, 2, 3, 0] [0, 1, 2, 3]
|
||||||
|
xzwy 4 [0, 2, 3, 1] [0, 1, 2, 3]
|
||||||
|
xzwz 4 [0, 2, 3, 2] [0, 1, 2, 3]
|
||||||
|
xzww 4 [0, 2, 3, 3] [0, 1, 2, 3]
|
||||||
|
xwxx 4 [0, 3, 0, 0] [0, 1, 2, 3]
|
||||||
|
xwxy 4 [0, 3, 0, 1] [0, 1, 2, 3]
|
||||||
|
xwxz 4 [0, 3, 0, 2] [0, 1, 2, 3]
|
||||||
|
xwxw 4 [0, 3, 0, 3] [0, 1, 2, 3]
|
||||||
|
xwyx 4 [0, 3, 1, 0] [0, 1, 2, 3]
|
||||||
|
xwyy 4 [0, 3, 1, 1] [0, 1, 2, 3]
|
||||||
|
xwyz 4 [0, 3, 1, 2] [0, 1, 2, 3]
|
||||||
|
xwyw 4 [0, 3, 1, 3] [0, 1, 2, 3]
|
||||||
|
xwzx 4 [0, 3, 2, 0] [0, 1, 2, 3]
|
||||||
|
xwzy 4 [0, 3, 2, 1] [0, 1, 2, 3]
|
||||||
|
xwzz 4 [0, 3, 2, 2] [0, 1, 2, 3]
|
||||||
|
xwzw 4 [0, 3, 2, 3] [0, 1, 2, 3]
|
||||||
|
xwwx 4 [0, 3, 3, 0] [0, 1, 2, 3]
|
||||||
|
xwwy 4 [0, 3, 3, 1] [0, 1, 2, 3]
|
||||||
|
xwwz 4 [0, 3, 3, 2] [0, 1, 2, 3]
|
||||||
|
xwww 4 [0, 3, 3, 3] [0, 1, 2, 3]
|
||||||
|
yxxx 4 [1, 0, 0, 0] [0, 1, 2, 3]
|
||||||
|
yxxy 4 [1, 0, 0, 1] [0, 1, 2, 3]
|
||||||
|
yxxz 4 [1, 0, 0, 2] [0, 1, 2, 3]
|
||||||
|
yxxw 4 [1, 0, 0, 3] [0, 1, 2, 3]
|
||||||
|
yxyx 4 [1, 0, 1, 0] [0, 1, 2, 3]
|
||||||
|
yxyy 4 [1, 0, 1, 1] [0, 1, 2, 3]
|
||||||
|
yxyz 4 [1, 0, 1, 2] [0, 1, 2, 3]
|
||||||
|
yxyw 4 [1, 0, 1, 3] [0, 1, 2, 3]
|
||||||
|
yxzx 4 [1, 0, 2, 0] [0, 1, 2, 3]
|
||||||
|
yxzy 4 [1, 0, 2, 1] [0, 1, 2, 3]
|
||||||
|
yxzz 4 [1, 0, 2, 2] [0, 1, 2, 3]
|
||||||
|
yxzw 4 [1, 0, 2, 3] [0, 1, 2, 3]
|
||||||
|
yxwx 4 [1, 0, 3, 0] [0, 1, 2, 3]
|
||||||
|
yxwy 4 [1, 0, 3, 1] [0, 1, 2, 3]
|
||||||
|
yxwz 4 [1, 0, 3, 2] [0, 1, 2, 3]
|
||||||
|
yxww 4 [1, 0, 3, 3] [0, 1, 2, 3]
|
||||||
|
yyxx 4 [1, 1, 0, 0] [0, 1, 2, 3]
|
||||||
|
yyxy 4 [1, 1, 0, 1] [0, 1, 2, 3]
|
||||||
|
yyxz 4 [1, 1, 0, 2] [0, 1, 2, 3]
|
||||||
|
yyxw 4 [1, 1, 0, 3] [0, 1, 2, 3]
|
||||||
|
yyyx 4 [1, 1, 1, 0] [0, 1, 2, 3]
|
||||||
|
yyyy 4 [1, 1, 1, 1] [0, 1, 2, 3]
|
||||||
|
yyyz 4 [1, 1, 1, 2] [0, 1, 2, 3]
|
||||||
|
yyyw 4 [1, 1, 1, 3] [0, 1, 2, 3]
|
||||||
|
yyzx 4 [1, 1, 2, 0] [0, 1, 2, 3]
|
||||||
|
yyzy 4 [1, 1, 2, 1] [0, 1, 2, 3]
|
||||||
|
yyzz 4 [1, 1, 2, 2] [0, 1, 2, 3]
|
||||||
|
yyzw 4 [1, 1, 2, 3] [0, 1, 2, 3]
|
||||||
|
yywx 4 [1, 1, 3, 0] [0, 1, 2, 3]
|
||||||
|
yywy 4 [1, 1, 3, 1] [0, 1, 2, 3]
|
||||||
|
yywz 4 [1, 1, 3, 2] [0, 1, 2, 3]
|
||||||
|
yyww 4 [1, 1, 3, 3] [0, 1, 2, 3]
|
||||||
|
yzxx 4 [1, 2, 0, 0] [0, 1, 2, 3]
|
||||||
|
yzxy 4 [1, 2, 0, 1] [0, 1, 2, 3]
|
||||||
|
yzxz 4 [1, 2, 0, 2] [0, 1, 2, 3]
|
||||||
|
yzxw 4 [1, 2, 0, 3] [0, 1, 2, 3]
|
||||||
|
yzyx 4 [1, 2, 1, 0] [0, 1, 2, 3]
|
||||||
|
yzyy 4 [1, 2, 1, 1] [0, 1, 2, 3]
|
||||||
|
yzyz 4 [1, 2, 1, 2] [0, 1, 2, 3]
|
||||||
|
yzyw 4 [1, 2, 1, 3] [0, 1, 2, 3]
|
||||||
|
yzzx 4 [1, 2, 2, 0] [0, 1, 2, 3]
|
||||||
|
yzzy 4 [1, 2, 2, 1] [0, 1, 2, 3]
|
||||||
|
yzzz 4 [1, 2, 2, 2] [0, 1, 2, 3]
|
||||||
|
yzzw 4 [1, 2, 2, 3] [0, 1, 2, 3]
|
||||||
|
yzwx 4 [1, 2, 3, 0] [0, 1, 2, 3]
|
||||||
|
yzwy 4 [1, 2, 3, 1] [0, 1, 2, 3]
|
||||||
|
yzwz 4 [1, 2, 3, 2] [0, 1, 2, 3]
|
||||||
|
yzww 4 [1, 2, 3, 3] [0, 1, 2, 3]
|
||||||
|
ywxx 4 [1, 3, 0, 0] [0, 1, 2, 3]
|
||||||
|
ywxy 4 [1, 3, 0, 1] [0, 1, 2, 3]
|
||||||
|
ywxz 4 [1, 3, 0, 2] [0, 1, 2, 3]
|
||||||
|
ywxw 4 [1, 3, 0, 3] [0, 1, 2, 3]
|
||||||
|
ywyx 4 [1, 3, 1, 0] [0, 1, 2, 3]
|
||||||
|
ywyy 4 [1, 3, 1, 1] [0, 1, 2, 3]
|
||||||
|
ywyz 4 [1, 3, 1, 2] [0, 1, 2, 3]
|
||||||
|
ywyw 4 [1, 3, 1, 3] [0, 1, 2, 3]
|
||||||
|
ywzx 4 [1, 3, 2, 0] [0, 1, 2, 3]
|
||||||
|
ywzy 4 [1, 3, 2, 1] [0, 1, 2, 3]
|
||||||
|
ywzz 4 [1, 3, 2, 2] [0, 1, 2, 3]
|
||||||
|
ywzw 4 [1, 3, 2, 3] [0, 1, 2, 3]
|
||||||
|
ywwx 4 [1, 3, 3, 0] [0, 1, 2, 3]
|
||||||
|
ywwy 4 [1, 3, 3, 1] [0, 1, 2, 3]
|
||||||
|
ywwz 4 [1, 3, 3, 2] [0, 1, 2, 3]
|
||||||
|
ywww 4 [1, 3, 3, 3] [0, 1, 2, 3]
|
||||||
|
zxxx 4 [2, 0, 0, 0] [0, 1, 2, 3]
|
||||||
|
zxxy 4 [2, 0, 0, 1] [0, 1, 2, 3]
|
||||||
|
zxxz 4 [2, 0, 0, 2] [0, 1, 2, 3]
|
||||||
|
zxxw 4 [2, 0, 0, 3] [0, 1, 2, 3]
|
||||||
|
zxyx 4 [2, 0, 1, 0] [0, 1, 2, 3]
|
||||||
|
zxyy 4 [2, 0, 1, 1] [0, 1, 2, 3]
|
||||||
|
zxyz 4 [2, 0, 1, 2] [0, 1, 2, 3]
|
||||||
|
zxyw 4 [2, 0, 1, 3] [0, 1, 2, 3]
|
||||||
|
zxzx 4 [2, 0, 2, 0] [0, 1, 2, 3]
|
||||||
|
zxzy 4 [2, 0, 2, 1] [0, 1, 2, 3]
|
||||||
|
zxzz 4 [2, 0, 2, 2] [0, 1, 2, 3]
|
||||||
|
zxzw 4 [2, 0, 2, 3] [0, 1, 2, 3]
|
||||||
|
zxwx 4 [2, 0, 3, 0] [0, 1, 2, 3]
|
||||||
|
zxwy 4 [2, 0, 3, 1] [0, 1, 2, 3]
|
||||||
|
zxwz 4 [2, 0, 3, 2] [0, 1, 2, 3]
|
||||||
|
zxww 4 [2, 0, 3, 3] [0, 1, 2, 3]
|
||||||
|
zyxx 4 [2, 1, 0, 0] [0, 1, 2, 3]
|
||||||
|
zyxy 4 [2, 1, 0, 1] [0, 1, 2, 3]
|
||||||
|
zyxz 4 [2, 1, 0, 2] [0, 1, 2, 3]
|
||||||
|
zyxw 4 [2, 1, 0, 3] [0, 1, 2, 3]
|
||||||
|
zyyx 4 [2, 1, 1, 0] [0, 1, 2, 3]
|
||||||
|
zyyy 4 [2, 1, 1, 1] [0, 1, 2, 3]
|
||||||
|
zyyz 4 [2, 1, 1, 2] [0, 1, 2, 3]
|
||||||
|
zyyw 4 [2, 1, 1, 3] [0, 1, 2, 3]
|
||||||
|
zyzx 4 [2, 1, 2, 0] [0, 1, 2, 3]
|
||||||
|
zyzy 4 [2, 1, 2, 1] [0, 1, 2, 3]
|
||||||
|
zyzz 4 [2, 1, 2, 2] [0, 1, 2, 3]
|
||||||
|
zyzw 4 [2, 1, 2, 3] [0, 1, 2, 3]
|
||||||
|
zywx 4 [2, 1, 3, 0] [0, 1, 2, 3]
|
||||||
|
zywy 4 [2, 1, 3, 1] [0, 1, 2, 3]
|
||||||
|
zywz 4 [2, 1, 3, 2] [0, 1, 2, 3]
|
||||||
|
zyww 4 [2, 1, 3, 3] [0, 1, 2, 3]
|
||||||
|
zzxx 4 [2, 2, 0, 0] [0, 1, 2, 3]
|
||||||
|
zzxy 4 [2, 2, 0, 1] [0, 1, 2, 3]
|
||||||
|
zzxz 4 [2, 2, 0, 2] [0, 1, 2, 3]
|
||||||
|
zzxw 4 [2, 2, 0, 3] [0, 1, 2, 3]
|
||||||
|
zzyx 4 [2, 2, 1, 0] [0, 1, 2, 3]
|
||||||
|
zzyy 4 [2, 2, 1, 1] [0, 1, 2, 3]
|
||||||
|
zzyz 4 [2, 2, 1, 2] [0, 1, 2, 3]
|
||||||
|
zzyw 4 [2, 2, 1, 3] [0, 1, 2, 3]
|
||||||
|
zzzx 4 [2, 2, 2, 0] [0, 1, 2, 3]
|
||||||
|
zzzy 4 [2, 2, 2, 1] [0, 1, 2, 3]
|
||||||
|
zzzz 4 [2, 2, 2, 2] [0, 1, 2, 3]
|
||||||
|
zzzw 4 [2, 2, 2, 3] [0, 1, 2, 3]
|
||||||
|
zzwx 4 [2, 2, 3, 0] [0, 1, 2, 3]
|
||||||
|
zzwy 4 [2, 2, 3, 1] [0, 1, 2, 3]
|
||||||
|
zzwz 4 [2, 2, 3, 2] [0, 1, 2, 3]
|
||||||
|
zzww 4 [2, 2, 3, 3] [0, 1, 2, 3]
|
||||||
|
zwxx 4 [2, 3, 0, 0] [0, 1, 2, 3]
|
||||||
|
zwxy 4 [2, 3, 0, 1] [0, 1, 2, 3]
|
||||||
|
zwxz 4 [2, 3, 0, 2] [0, 1, 2, 3]
|
||||||
|
zwxw 4 [2, 3, 0, 3] [0, 1, 2, 3]
|
||||||
|
zwyx 4 [2, 3, 1, 0] [0, 1, 2, 3]
|
||||||
|
zwyy 4 [2, 3, 1, 1] [0, 1, 2, 3]
|
||||||
|
zwyz 4 [2, 3, 1, 2] [0, 1, 2, 3]
|
||||||
|
zwyw 4 [2, 3, 1, 3] [0, 1, 2, 3]
|
||||||
|
zwzx 4 [2, 3, 2, 0] [0, 1, 2, 3]
|
||||||
|
zwzy 4 [2, 3, 2, 1] [0, 1, 2, 3]
|
||||||
|
zwzz 4 [2, 3, 2, 2] [0, 1, 2, 3]
|
||||||
|
zwzw 4 [2, 3, 2, 3] [0, 1, 2, 3]
|
||||||
|
zwwx 4 [2, 3, 3, 0] [0, 1, 2, 3]
|
||||||
|
zwwy 4 [2, 3, 3, 1] [0, 1, 2, 3]
|
||||||
|
zwwz 4 [2, 3, 3, 2] [0, 1, 2, 3]
|
||||||
|
zwww 4 [2, 3, 3, 3] [0, 1, 2, 3]
|
||||||
|
wxxx 4 [3, 0, 0, 0] [0, 1, 2, 3]
|
||||||
|
wxxy 4 [3, 0, 0, 1] [0, 1, 2, 3]
|
||||||
|
wxxz 4 [3, 0, 0, 2] [0, 1, 2, 3]
|
||||||
|
wxxw 4 [3, 0, 0, 3] [0, 1, 2, 3]
|
||||||
|
wxyx 4 [3, 0, 1, 0] [0, 1, 2, 3]
|
||||||
|
wxyy 4 [3, 0, 1, 1] [0, 1, 2, 3]
|
||||||
|
wxyz 4 [3, 0, 1, 2] [0, 1, 2, 3]
|
||||||
|
wxyw 4 [3, 0, 1, 3] [0, 1, 2, 3]
|
||||||
|
wxzx 4 [3, 0, 2, 0] [0, 1, 2, 3]
|
||||||
|
wxzy 4 [3, 0, 2, 1] [0, 1, 2, 3]
|
||||||
|
wxzz 4 [3, 0, 2, 2] [0, 1, 2, 3]
|
||||||
|
wxzw 4 [3, 0, 2, 3] [0, 1, 2, 3]
|
||||||
|
wxwx 4 [3, 0, 3, 0] [0, 1, 2, 3]
|
||||||
|
wxwy 4 [3, 0, 3, 1] [0, 1, 2, 3]
|
||||||
|
wxwz 4 [3, 0, 3, 2] [0, 1, 2, 3]
|
||||||
|
wxww 4 [3, 0, 3, 3] [0, 1, 2, 3]
|
||||||
|
wyxx 4 [3, 1, 0, 0] [0, 1, 2, 3]
|
||||||
|
wyxy 4 [3, 1, 0, 1] [0, 1, 2, 3]
|
||||||
|
wyxz 4 [3, 1, 0, 2] [0, 1, 2, 3]
|
||||||
|
wyxw 4 [3, 1, 0, 3] [0, 1, 2, 3]
|
||||||
|
wyyx 4 [3, 1, 1, 0] [0, 1, 2, 3]
|
||||||
|
wyyy 4 [3, 1, 1, 1] [0, 1, 2, 3]
|
||||||
|
wyyz 4 [3, 1, 1, 2] [0, 1, 2, 3]
|
||||||
|
wyyw 4 [3, 1, 1, 3] [0, 1, 2, 3]
|
||||||
|
wyzx 4 [3, 1, 2, 0] [0, 1, 2, 3]
|
||||||
|
wyzy 4 [3, 1, 2, 1] [0, 1, 2, 3]
|
||||||
|
wyzz 4 [3, 1, 2, 2] [0, 1, 2, 3]
|
||||||
|
wyzw 4 [3, 1, 2, 3] [0, 1, 2, 3]
|
||||||
|
wywx 4 [3, 1, 3, 0] [0, 1, 2, 3]
|
||||||
|
wywy 4 [3, 1, 3, 1] [0, 1, 2, 3]
|
||||||
|
wywz 4 [3, 1, 3, 2] [0, 1, 2, 3]
|
||||||
|
wyww 4 [3, 1, 3, 3] [0, 1, 2, 3]
|
||||||
|
wzxx 4 [3, 2, 0, 0] [0, 1, 2, 3]
|
||||||
|
wzxy 4 [3, 2, 0, 1] [0, 1, 2, 3]
|
||||||
|
wzxz 4 [3, 2, 0, 2] [0, 1, 2, 3]
|
||||||
|
wzxw 4 [3, 2, 0, 3] [0, 1, 2, 3]
|
||||||
|
wzyx 4 [3, 2, 1, 0] [0, 1, 2, 3]
|
||||||
|
wzyy 4 [3, 2, 1, 1] [0, 1, 2, 3]
|
||||||
|
wzyz 4 [3, 2, 1, 2] [0, 1, 2, 3]
|
||||||
|
wzyw 4 [3, 2, 1, 3] [0, 1, 2, 3]
|
||||||
|
wzzx 4 [3, 2, 2, 0] [0, 1, 2, 3]
|
||||||
|
wzzy 4 [3, 2, 2, 1] [0, 1, 2, 3]
|
||||||
|
wzzz 4 [3, 2, 2, 2] [0, 1, 2, 3]
|
||||||
|
wzzw 4 [3, 2, 2, 3] [0, 1, 2, 3]
|
||||||
|
wzwx 4 [3, 2, 3, 0] [0, 1, 2, 3]
|
||||||
|
wzwy 4 [3, 2, 3, 1] [0, 1, 2, 3]
|
||||||
|
wzwz 4 [3, 2, 3, 2] [0, 1, 2, 3]
|
||||||
|
wzww 4 [3, 2, 3, 3] [0, 1, 2, 3]
|
||||||
|
wwxx 4 [3, 3, 0, 0] [0, 1, 2, 3]
|
||||||
|
wwxy 4 [3, 3, 0, 1] [0, 1, 2, 3]
|
||||||
|
wwxz 4 [3, 3, 0, 2] [0, 1, 2, 3]
|
||||||
|
wwxw 4 [3, 3, 0, 3] [0, 1, 2, 3]
|
||||||
|
wwyx 4 [3, 3, 1, 0] [0, 1, 2, 3]
|
||||||
|
wwyy 4 [3, 3, 1, 1] [0, 1, 2, 3]
|
||||||
|
wwyz 4 [3, 3, 1, 2] [0, 1, 2, 3]
|
||||||
|
wwyw 4 [3, 3, 1, 3] [0, 1, 2, 3]
|
||||||
|
wwzx 4 [3, 3, 2, 0] [0, 1, 2, 3]
|
||||||
|
wwzy 4 [3, 3, 2, 1] [0, 1, 2, 3]
|
||||||
|
wwzz 4 [3, 3, 2, 2] [0, 1, 2, 3]
|
||||||
|
wwzw 4 [3, 3, 2, 3] [0, 1, 2, 3]
|
||||||
|
wwwx 4 [3, 3, 3, 0] [0, 1, 2, 3]
|
||||||
|
wwwy 4 [3, 3, 3, 1] [0, 1, 2, 3]
|
||||||
|
wwwz 4 [3, 3, 3, 2] [0, 1, 2, 3]
|
||||||
|
wwww 4 [3, 3, 3, 3] [0, 1, 2, 3]
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Swizzling data for the given dimension.
|
||||||
|
/// See the [`build.rs`] file to learn more.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! with_swizzling_for_dim_unique {
|
||||||
|
(1, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 1
|
||||||
|
x 1 [0] [0]
|
||||||
|
}};
|
||||||
|
(2, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 2
|
||||||
|
y 1 [1] [0]
|
||||||
|
xy 2 [0, 1] [0, 1]
|
||||||
|
yx 2 [1, 0] [0, 1]
|
||||||
|
}};
|
||||||
|
(3, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 3
|
||||||
|
z 1 [2] [0]
|
||||||
|
xz 2 [0, 2] [0, 1]
|
||||||
|
yz 2 [1, 2] [0, 1]
|
||||||
|
zx 2 [2, 0] [0, 1]
|
||||||
|
zy 2 [2, 1] [0, 1]
|
||||||
|
xyz 3 [0, 1, 2] [0, 1, 2]
|
||||||
|
xzy 3 [0, 2, 1] [0, 1, 2]
|
||||||
|
yxz 3 [1, 0, 2] [0, 1, 2]
|
||||||
|
yzx 3 [1, 2, 0] [0, 1, 2]
|
||||||
|
zxy 3 [2, 0, 1] [0, 1, 2]
|
||||||
|
zyx 3 [2, 1, 0] [0, 1, 2]
|
||||||
|
}};
|
||||||
|
(4, $f: ident $(,$($args:tt)*)?) => { $f! { $([$($args)*])? 4
|
||||||
|
w 1 [3] [0]
|
||||||
|
xw 2 [0, 3] [0, 1]
|
||||||
|
yw 2 [1, 3] [0, 1]
|
||||||
|
zw 2 [2, 3] [0, 1]
|
||||||
|
wx 2 [3, 0] [0, 1]
|
||||||
|
wy 2 [3, 1] [0, 1]
|
||||||
|
wz 2 [3, 2] [0, 1]
|
||||||
|
xyw 3 [0, 1, 3] [0, 1, 2]
|
||||||
|
xzw 3 [0, 2, 3] [0, 1, 2]
|
||||||
|
xwy 3 [0, 3, 1] [0, 1, 2]
|
||||||
|
xwz 3 [0, 3, 2] [0, 1, 2]
|
||||||
|
yxw 3 [1, 0, 3] [0, 1, 2]
|
||||||
|
yzw 3 [1, 2, 3] [0, 1, 2]
|
||||||
|
ywx 3 [1, 3, 0] [0, 1, 2]
|
||||||
|
ywz 3 [1, 3, 2] [0, 1, 2]
|
||||||
|
zxw 3 [2, 0, 3] [0, 1, 2]
|
||||||
|
zyw 3 [2, 1, 3] [0, 1, 2]
|
||||||
|
zwx 3 [2, 3, 0] [0, 1, 2]
|
||||||
|
zwy 3 [2, 3, 1] [0, 1, 2]
|
||||||
|
wxy 3 [3, 0, 1] [0, 1, 2]
|
||||||
|
wxz 3 [3, 0, 2] [0, 1, 2]
|
||||||
|
wyx 3 [3, 1, 0] [0, 1, 2]
|
||||||
|
wyz 3 [3, 1, 2] [0, 1, 2]
|
||||||
|
wzx 3 [3, 2, 0] [0, 1, 2]
|
||||||
|
wzy 3 [3, 2, 1] [0, 1, 2]
|
||||||
|
xyzw 4 [0, 1, 2, 3] [0, 1, 2, 3]
|
||||||
|
xywz 4 [0, 1, 3, 2] [0, 1, 2, 3]
|
||||||
|
xzyw 4 [0, 2, 1, 3] [0, 1, 2, 3]
|
||||||
|
xzwy 4 [0, 2, 3, 1] [0, 1, 2, 3]
|
||||||
|
xwyz 4 [0, 3, 1, 2] [0, 1, 2, 3]
|
||||||
|
xwzy 4 [0, 3, 2, 1] [0, 1, 2, 3]
|
||||||
|
yxzw 4 [1, 0, 2, 3] [0, 1, 2, 3]
|
||||||
|
yxwz 4 [1, 0, 3, 2] [0, 1, 2, 3]
|
||||||
|
yzxw 4 [1, 2, 0, 3] [0, 1, 2, 3]
|
||||||
|
yzwx 4 [1, 2, 3, 0] [0, 1, 2, 3]
|
||||||
|
ywxz 4 [1, 3, 0, 2] [0, 1, 2, 3]
|
||||||
|
ywzx 4 [1, 3, 2, 0] [0, 1, 2, 3]
|
||||||
|
zxyw 4 [2, 0, 1, 3] [0, 1, 2, 3]
|
||||||
|
zxwy 4 [2, 0, 3, 1] [0, 1, 2, 3]
|
||||||
|
zyxw 4 [2, 1, 0, 3] [0, 1, 2, 3]
|
||||||
|
zywx 4 [2, 1, 3, 0] [0, 1, 2, 3]
|
||||||
|
zwxy 4 [2, 3, 0, 1] [0, 1, 2, 3]
|
||||||
|
zwyx 4 [2, 3, 1, 0] [0, 1, 2, 3]
|
||||||
|
wxyz 4 [3, 0, 1, 2] [0, 1, 2, 3]
|
||||||
|
wxzy 4 [3, 0, 2, 1] [0, 1, 2, 3]
|
||||||
|
wyxz 4 [3, 1, 0, 2] [0, 1, 2, 3]
|
||||||
|
wyzx 4 [3, 1, 2, 0] [0, 1, 2, 3]
|
||||||
|
wzxy 4 [3, 2, 0, 1] [0, 1, 2, 3]
|
||||||
|
wzyx 4 [3, 2, 1, 0] [0, 1, 2, 3]
|
||||||
|
}};
|
||||||
|
}
|
@ -29,6 +29,8 @@
|
|||||||
// ==============
|
// ==============
|
||||||
|
|
||||||
pub mod algebra;
|
pub mod algebra;
|
||||||
|
pub mod dim;
|
||||||
|
pub mod dim_macros;
|
||||||
pub mod num;
|
pub mod num;
|
||||||
pub mod topology;
|
pub mod topology;
|
||||||
pub mod unit;
|
pub mod unit;
|
||||||
|
Loading…
Reference in New Issue
Block a user