Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wip/wdanilo/text shape system single scene 183406745 #3776

Merged
merged 297 commits into from
Nov 3, 2022

Conversation

wdanilo
Copy link
Member

@wdanilo wdanilo commented Oct 6, 2022

Pull Request Description

Implementation of fast fonts rendering 🥳🎉

Changes to glyphs and Shape Systems

  1. Glyphs are using shape system now. When a new font is created in a layer used by another font, the fonts definitions are re-used and no shader re-compilation happens.
  2. The shape system definition was re-written from scratch. It's implementation is simpler, faster, and more extensible.
  3. The ensogl::define_shape_system! macro was renamed to ensogl::shape!. Also, unlike the previous version, it requires now the first style: Style argument always.

Changes to scene and layer management.

  1. Scene is a global entity right now. It simplifies many computations. In particular, when a new shape is created, it does not require Shape Proxy objects anymore, as it can get the scene reference at the creation time. This change does NOT mean that multi-scene projects are impossible. Quite the opposite. The world object instantiates the global scene variable and in case of the existence of multiple scenes, it can instantiate the object multiple times per frame, once per every scene. 2.

  2. A display object can be added to only one layer now. This simplification allows us to make the code faster and simpler. We never used the possibility to add the same object to multiple layers, so this functionality was removed. The api layer.ad_exclusive was changed to simply layer.add. 3.

IntelliJ configuration inclusion.

This PR also includes a sharable IntelliJ run configuration and a script to re-generate it based on available crates. The script is located in build/intellij-run-config-gen. This is how int looks in IntelliJ:

Screen.Recording.2022-10-31.at.08.36.57.mov

Checklist

Please include the following checklist in your PR:

  • The documentation has been updated if necessary.
  • All code conforms to the
    Scala,
    Java,
    and
    Rust
    style guides.
  • All code has been tested:
    • Unit tests have been written where possible.
    • If GUI codebase was changed: Enso GUI was tested when built using BOTH
      ./run ide build and ./run ide watch.

where
R: Clone + RangeOverlap + RangeOps,
<R as RangeOps>::Item: Clone + PartialOrd, {
let mut ranges = ranges.to_vec();
<R as RangeOps>::Item: Clone + Ord, {
crate::gen_iter!({
ranges.sort_unstable_by(|a, b| a.start().partial_cmp(b.start()).unwrap());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that the bound is Ord, partial_cmp+unwrap can be replaced by cmp.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, right! thanks!

@wdanilo wdanilo marked this pull request as ready for review October 31, 2022 06:38
let md = fs::metadata(path);
let md = md.unwrap_or_else(|_| panic!("Could get metadata of {}", path.display()));
if md.is_dir() {
let file_name = path.file_name().map(|t| t.to_string_lossy().to_string());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

folder_name might be clearer, as we just checked that it is a folder.

@@ -0,0 +1,382 @@
//! Generate IntelliJ run configurations and place them in the .idea/runConfigurations directory.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are we ensuring this script does not go out of date? Should this be executed on CI to check the output has not changed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do it as part of fat script (I'll chat with Michal)

Comment on lines 103 to 107
/// Callback list used to register new callbacks when this registry is running. During run,
/// the [`callback_list`] is borrowed and thus can't be mutated.
#[derivative(Debug = "ignore")]
callback_list_during_run: RefCell<Vec<(Guard, Box<F>)>>,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some additional information about how these two lists are managed and operated during a run might be good here.
After reading the code, I'd suggest the following change:

Suggested change
/// Callback list used to register new callbacks when this registry is running. During run,
/// the [`callback_list`] is borrowed and thus can't be mutated.
#[derivative(Debug = "ignore")]
callback_list_during_run: RefCell<Vec<(Guard, Box<F>)>>,
}
/// Temporary buffer to store new callbacks that are registered while the registry is running. During a run,
/// the [`callback_list`] is borrowed and thus new callbacks cannot be added because it cannot be mutated.
/// The buffer is processed and emptied after the registry has finished processing the existing callbacks.
#[derivative(Debug = "ignore")]
new_callback_buffer: RefCell<Vec<(Guard, Box<F>)>>,
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the comment, but I did not change the var name. I feel that callback_list_during_run is more descriptive.

/// [`T2`] will be passed as copies.
/// - The [`Ref1`] registry accepts callbacks in a form of [`FnMut(&T1)`].
/// - The [`NoArgs`] registry is a registry for [`FnMut()`] functions.
/// - The [`NoArgs`] registry is a registry for [`FnMut()`] functions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate line.

Suggested change
/// - The [`NoArgs`] registry is a registry for [`FnMut()`] functions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@@ -99,7 +99,7 @@ fn init(app: &Application) {
list_view.focus();
app.display.add_child(&list_view);
// FIXME[WD]: This should not be needed after text gets proper depth-handling.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this FIXME need re-evaluating?

@@ -161,6 +161,7 @@ pub fn main() {
});
}

// TODO: pub fn extend do define_endpoints_2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

@@ -170,21 +171,18 @@ fn init(app: Application) {
let _text = quote.to_string() + snowman + zalgo;
let _text = "test".to_string();
// area.set_content("aஓbc🧑🏾de\nfghij\nklmno\npqrst\n01234\n56789");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented code and what seems to be testing code.

pub use anyhow_macros::*;

#[macro_export]
macro_rules! ite {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this? Seems a bit overkill to replace if cond then { a } else { b } with ite!(cond, a, b).

Copy link
Member Author

@wdanilo wdanilo Nov 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As agreed via phone, lets leave it for now and lets chat about it on discord.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed my mind, removing it :)

pub fn init_wasm() {
init_tracing(WARN);
pub fn init_global() {
init_tracing(DEBUG);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
init_tracing(DEBUG);
init_tracing(WARN);

@@ -815,6 +815,7 @@ pub async fn main_internal(config: enso_build::config::Config) -> Result {
try_join(git_clean, clean_cache).await?;
}
Target::Lint => {
println!("LINTING!!!");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Print left in code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ouch, thanks!

Comment on lines 155 to 156
// DEBUG!("{scene.layers.node_searcher_mask:#?}");
// DEBUG!("{scene.layers.viz:#?}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are left intentionally, there is a comment for it: // These comments are left for easy debugging in the future.. Its not a new code and I think these should be left there.

Comment on lines 103 to 104
// FIXME: scissor box should not be computed from the left screen border. It should be affected
// by the camera position.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME without owner. (Maybe should just be fixed)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment on lines 185 to 226
// let grid_views_with_headers =
// std::iter::repeat_with(|| setup_grid_view_with_headers(app)).take(3).collect_vec();
// let with_hover_mask = [&grid_views_with_headers[2]];
// let with_selection_mask = [&grid_views_with_headers[1], &grid_views_with_headers[2]];
let mut positions = itertools::iproduct!([-450.0, 50.0], [350.0, -50.0]).map(pair_to_vec2);

grids_layer.add_exclusive(&plain_grid_view);
grids_layer.add(&plain_grid_view);
plain_grid_view.set_position_xy(positions.next().unwrap());
for (view, position) in grid_views_with_headers.iter().zip(positions) {
grids_layer.add_exclusive(view);
view.set_position_xy(position);
}

let view = &grid_views_with_headers[0];
for i in (0..1000).step_by(2) {
view.set_column_width((i, 60.0));
}

for view in with_hover_mask {
view.hover_highlight_frp().setup_masked_layer(Some(hover_layer.downgrade()));
let params = grid_view::simple::EntryParams {
bg_color: color::Lcha::from(color::Rgba(0.7, 0.7, 0.9, 1.0)),
bg_margin: 0.0,
text_offset: 8.0,
text_color: color::Lcha::from(color::Rgba(0.9, 0.9, 0.9, 1.0)),
..default()
};
view.hover_highlight_frp().set_entries_params(params);
}

for view in with_selection_mask {
view.selection_highlight_frp().setup_masked_layer(Some(selection_layer.downgrade()));
let params = grid_view::simple::EntryParams {
bg_color: color::Lcha::from(color::Rgba(0.5, 0.5, 0.5, 1.0)),
bg_margin: 0.0,
text_color: color::Lcha::from(color::Rgba(1.0, 1.0, 1.0, 1.0)),
text_offset: 8.0,
..default()
};
view.selection_highlight_frp().set_entries_params(params);
}
// for (view, position) in grid_views_with_headers.iter().zip(positions) {
// grids_layer.add(view);
// view.set_position_xy(position);
// }

// let view = &grid_views_with_headers[0];
// for i in (0..3).step_by(2) {
// view.set_column_width((i, 60.0));
// }

// for view in with_hover_mask {
// view.hover_highlight_frp().setup_masked_layer(Some(hover_layer.downgrade()));
// let params = grid_view::simple::EntryParams {
// bg_color: color::Lcha::from(color::Rgba(0.7, 0.7, 0.9, 1.0)),
// bg_margin: 0.0,
// text_offset: 8.0,
// text_color: color::Lcha::from(color::Rgba(0.9, 0.9, 0.9, 1.0)),
// ..default()
// };
// view.hover_highlight_frp().set_entries_params(params);
// }
//
// for view in with_selection_mask {
// view.selection_highlight_frp().setup_masked_layer(Some(selection_layer.downgrade()));
// let params = grid_view::simple::EntryParams {
// bg_color: color::Lcha::from(color::Rgba(0.5, 0.5, 0.5, 1.0)),
// bg_margin: 0.0,
// text_color: color::Lcha::from(color::Rgba(1.0, 1.0, 1.0, 1.0)),
// text_offset: 8.0,
// ..default()
// };
// view.selection_highlight_frp().set_entries_params(params);
// }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of commented code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is accidental, sorry for that

@@ -231,7 +231,7 @@ fn init(app: &Application) {
navigator.disable_wheel_panning();

std::mem::forget(plain_grid_view);
std::mem::forget(grid_views_with_headers);
// std::mem::forget(grid_views_with_headers);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More commented code.

@@ -177,5 +178,8 @@ mod test {
test_merged!([0..=1, 1..=2, 2..=3], [0..=3]);
test_merged!([0..=2, 3..=5, 1..=4], [0..=5]);
test_merged!([0..=10, 5..=15], [0..=15]);

test_merged!([0..2, 0..1], [0..2]);
test_merged!([0..10, 4..5, 8..11], [0..11]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not really documented and tested, but what happens for non-overlapping ranges or multiple partial but not overall overlapping ranges?
There should be test cases checking the correct output for those. For example,

  • test_merged!([0..10, 20..30, 40..50], [0..10, 20..30, 40..50]);
  • test_merged!([0..10, 5..20, 21..30, 25..40], [0..20, 21..30]);
    And I would also add this edge case:
    test_merged!([0..10, 10..20], [0..20]); (I would assume that to be correct, even if they are only “adjacent” and not overlapping)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are never using it for such cases, but your right, tests should cover it. Adding them there! thanks for catching it!

@wdanilo wdanilo merged commit 48ce68c into develop Nov 3, 2022
@wdanilo wdanilo deleted the wip/wdanilo/text-shape-system-single-scene-183406745 branch November 3, 2022 07:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants