Sfoglia il codice sorgente

app: add a splash screen with cool scrambling text

darkfi 3 giorni fa
parent
commit
ccf070324f
4 ha cambiato i file con 137 aggiunte e 2 eliminazioni
  1. 64 0
      bin/app/src/app/node.rs
  2. 67 2
      bin/app/src/app/schema/mod.rs
  3. 2 0
      bin/app/src/scene.rs
  4. 4 0
      bin/app/src/ui/mod.rs

+ 64 - 0
bin/app/src/app/node.rs

@@ -276,6 +276,70 @@ pub fn create_text(name: &str) -> SceneNode {
     node
 }
 
+pub fn create_text_scramble(name: &str) -> SceneNode {
+    let mut node = SceneNode::new(name, SceneNodeType::TextScramble);
+
+    let mut prop = Property::new("rect", PropertyType::Float32, PropertySubType::Pixel);
+    prop.set_array_len(4);
+    prop.allow_exprs();
+    node.add_property(prop).unwrap();
+
+    let mut prop = Property::new("height", PropertyType::Float32, PropertySubType::Pixel);
+    node.add_property(prop).unwrap();
+
+    let mut prop = Property::new("lineheight", PropertyType::Float32, PropertySubType::Pixel);
+    prop.set_ui_text("Line Height", "Line height/lead (em)");
+    prop.set_defaults_f32(vec![1.2]).unwrap();
+    prop.set_range_f32(0., f32::MAX);
+    node.add_property(prop).unwrap();
+
+    let mut prop = Property::new("text_align", PropertyType::Enum, PropertySubType::Null);
+    prop.set_enum_items(vec!["start", "end", "left", "center", "right", "justify"]).unwrap();
+    prop.set_defaults_str(vec!["start".to_string()]).unwrap();
+    node.add_property(prop).unwrap();
+
+    let prop = Property::new("font_size", PropertyType::Float32, PropertySubType::Pixel);
+    node.add_property(prop).unwrap();
+
+    let prop = Property::new("text", PropertyType::Str, PropertySubType::Null);
+    node.add_property(prop).unwrap();
+
+    let mut prop = Property::new("text_color", PropertyType::Float32, PropertySubType::Color);
+    prop.set_array_len(4);
+    prop.set_range_f32(0., 1.);
+    node.add_property(prop).unwrap();
+
+    let mut prop = Property::new("overflow_wrap", PropertyType::Enum, PropertySubType::Null);
+    prop.set_enum_items(vec!["normal", "anywhere", "break-word"]).unwrap();
+    prop.set_defaults_str(vec!["normal".to_string()]).unwrap();
+    node.add_property(prop).unwrap();
+
+    let prop = Property::new("z_index", PropertyType::Uint32, PropertySubType::Null);
+    node.add_property(prop).unwrap();
+
+    let prop = Property::new("priority", PropertyType::Uint32, PropertySubType::Null);
+    node.add_property(prop).unwrap();
+
+    let prop = Property::new("use_i18n", PropertyType::Bool, PropertySubType::Null);
+    node.add_property(prop).unwrap();
+
+    let prop = Property::new("debug", PropertyType::Bool, PropertySubType::Null);
+    node.add_property(prop).unwrap();
+
+    let mut prop = Property::new("solve_probability", PropertyType::Float32, PropertySubType::Null);
+    prop.set_ui_text("Solve Probability", "Chance per tick that an unsolved character locks in");
+    prop.set_defaults_f32(vec![0.1]).unwrap();
+    prop.set_range_f32(0., 1.);
+    node.add_property(prop).unwrap();
+
+    let mut prop = Property::new("tick_interval", PropertyType::Uint32, PropertySubType::Null);
+    prop.set_ui_text("Tick Interval", "Milliseconds between scramble animation ticks");
+    prop.set_defaults_u32(vec![50]).unwrap();
+    node.add_property(prop).unwrap();
+
+    node
+}
+
 pub fn create_baseedit(name: &str) -> SceneNode {
     let mut node = SceneNode::new(name, SceneNodeType::Edit);
 

+ 67 - 2
bin/app/src/app/schema/mod.rs

@@ -25,7 +25,10 @@ use kvdb_overlay::Database;
 
 use crate::{
     app::{
-        node::{create_button, create_layer, create_text, create_vector_art, create_video},
+        node::{
+            create_button, create_layer, create_text, create_text_scramble, create_vector_art,
+            create_video,
+        },
         App,
     },
     expr::{self, Compiler},
@@ -33,7 +36,8 @@ use crate::{
     prop::{PropertyAtomicGuard, PropertyFloat32, Role},
     scene::{SceneNodePtr, Slot},
     sfx, shape,
-    ui::{emoji_picker, Button, Layer, Text, VectorArt, VectorShape, Video},
+    shape,
+    ui::{emoji_picker, Button, Layer, Text, TextScramble, VectorArt, VectorShape, Video},
     util::i18n::I18nBabelFish,
 };
 
@@ -64,6 +68,9 @@ mod android_ui_consts {
     pub const NETSTAT_OVERLAY_BTN_W: f32 = 200.;
     pub const NETSTAT_OVERLAY_BTN_H: f32 = 90.;
     pub const NETSTAT_OVERLAY_BTN_FONTSIZE: f32 = 40.;
+
+    pub const SPLASH_FONTSIZE: f32 = 52.;
+    pub const SPLASH_MARGIN: f32 = 40.;
 }
 
 #[cfg(target_os = "android")]
@@ -130,6 +137,9 @@ mod ui_consts {
     pub const NETSTAT_OVERLAY_BTN_H: f32 = 45.;
     pub const NETSTAT_OVERLAY_BTN_FONTSIZE: f32 = 20.;
 
+    pub const SPLASH_FONTSIZE: f32 = 26.;
+    pub const SPLASH_MARGIN: f32 = 20.;
+
     pub use super::desktop_paths::*;
 }
 
@@ -238,6 +248,61 @@ pub async fn make(app: &App, window: SceneNodePtr, i18n_fish: &I18nBabelFish, db
         content.setup(|me| Layer::new(me, app.renderer.clone(), app.redraw_trigger.clone())).await;
     window.link(content.clone());
 
+    // Splash layer with the scramble message
+    cc.add_const_f32("SPLASH_FONTSIZE", SPLASH_FONTSIZE);
+    cc.add_const_f32("SPLASH_MARGIN", SPLASH_MARGIN);
+    let splash_layer = create_layer("splash_layer");
+    let prop = splash_layer.get_property("rect").unwrap();
+    prop.set_f32(atom, Role::App, 0, 0.).unwrap();
+    prop.set_f32(atom, Role::App, 1, 0.).unwrap();
+    prop.set_expr(atom, Role::App, 2, expr::load_var("w")).unwrap();
+    prop.set_expr(atom, Role::App, 3, expr::load_var("h")).unwrap();
+    splash_layer.set_property_bool(atom, Role::App, "is_visible", true).unwrap();
+    splash_layer.set_property_u32(atom, Role::App, "z_index", 2).unwrap();
+    let splash_layer = splash_layer
+        .setup(|me| Layer::new(me, app.renderer.clone(), app.redraw_trigger.clone()))
+        .await;
+    content.link(splash_layer.clone());
+
+    let node = create_text_scramble("splash_msg");
+    let prop = node.get_property("rect").unwrap();
+    prop.set_f32(atom, Role::App, 0, SPLASH_MARGIN).unwrap();
+    let code = cc.compile("h * 0.4").unwrap();
+    prop.set_expr(atom, Role::App, 1, code).unwrap();
+    let code = cc.compile("w - 2 * SPLASH_MARGIN").unwrap();
+    prop.set_expr(atom, Role::App, 2, code).unwrap();
+    prop.set_f32(atom, Role::App, 3, SPLASH_FONTSIZE * 1.2).unwrap();
+    node.set_property_u32(atom, Role::App, "z_index", 0).unwrap();
+    node.set_property_f32(atom, Role::App, "font_size", SPLASH_FONTSIZE).unwrap();
+    node.set_property_enum(atom, Role::App, "text_align", "center").unwrap();
+    let prop = node.get_property("text_color").unwrap();
+    prop.set_f32(atom, Role::App, 0, 1.).unwrap();
+    prop.set_f32(atom, Role::App, 1, 1.).unwrap();
+    prop.set_f32(atom, Role::App, 2, 1.).unwrap();
+    prop.set_f32(atom, Role::App, 3, 1.).unwrap();
+    node.set_property_str(atom, Role::App, "text", "welcome back commander").unwrap();
+    let node = node
+        .setup(|me| {
+            TextScramble::new(
+                me,
+                window_scale.clone(),
+                app.renderer.clone(),
+                i18n_fish.clone(),
+                app.redraw_trigger.clone(),
+            )
+        })
+        .await;
+    splash_layer.link(node);
+
+    // Hide the splash layer after 3s
+    let redraw = app.redraw_trigger.clone();
+    let hide_task = app.ex.spawn(async move {
+        msleep(3000).await;
+        let atom = &mut redraw.make_guard(gfxtag!("splash_layer hide"));
+        splash_layer.set_property_bool(atom, Role::App, "is_visible", false).unwrap();
+    });
+    app.tasks.lock().unwrap().push(hide_task);
+
     if COLOR_SCHEME == ColorScheme::DarkMode {
         let node = create_video("king");
         let prop = node.get_property("rect").unwrap();

+ 2 - 0
bin/app/src/scene.rs

@@ -120,6 +120,7 @@ pub enum SceneNodeType {
     Setting = 21,
     Menu = 22,
     TokenTable = 23,
+    TextScramble = 24,
     PluginRoot = 100,
     Plugin = 101,
 }
@@ -599,6 +600,7 @@ pub enum Pimpl {
     Menu(ui::MenuPtr),
     TokenTable(ui::TokenTablePtr),
     Setting(SettingPtr),
+    TextScramble(ui::TextScramblePtr),
     #[cfg(feature = "enable-plugin-darkirc")]
     DarkIrc(plugin::DarkIrcPtr),
     #[cfg(feature = "enable-plugin-fud")]

+ 4 - 0
bin/app/src/ui/mod.rs

@@ -80,6 +80,8 @@ mod menu;
 pub use menu::{Menu, MenuPtr};
 mod text;
 pub use text::{Text, TextPtr};
+mod text_scramble;
+pub use text_scramble::{TextScramble, TextScramblePtr};
 mod win;
 pub use win::{GestureAction, Window, WindowPtr};
 
@@ -317,6 +319,7 @@ pub fn get_ui_object_ptr(node: &SceneNode3) -> Arc<dyn UIObject + Send> {
         Pimpl::ScrollLayer(obj) => obj.clone(),
         Pimpl::VectorArt(obj) => obj.clone(),
         Pimpl::Text(obj) => obj.clone(),
+        Pimpl::TextScramble(obj) => obj.clone(),
         Pimpl::Edit(obj) => obj.clone(),
         Pimpl::ChatView(obj) => obj.clone(),
         Pimpl::Image(obj) => obj.clone(),
@@ -336,6 +339,7 @@ pub fn get_ui_object3<'a>(node: &'a SceneNode3) -> &'a dyn UIObject {
         Pimpl::ScrollLayer(obj) => obj.as_ref(),
         Pimpl::VectorArt(obj) => obj.as_ref(),
         Pimpl::Text(obj) => obj.as_ref(),
+        Pimpl::TextScramble(obj) => obj.as_ref(),
         Pimpl::Edit(obj) => obj.as_ref(),
         Pimpl::ChatView(obj) => obj.as_ref(),
         Pimpl::Image(obj) => obj.as_ref(),