Просмотр исходного кода

app/gfx: create RenderApi trait for Renderer and RendererSync so code can be reused easily

jkds 6 месяцев назад
Родитель
Сommit
7635f80b27

+ 95 - 63
bin/app/src/gfx/api.rs

@@ -16,9 +16,12 @@
  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::sync::{
-    atomic::{AtomicU32, Ordering},
-    Arc,
+use std::{
+    cell::{Cell, UnsafeCell},
+    sync::{
+        atomic::{AtomicU32, Ordering},
+        Arc,
+    },
 };
 
 use super::{
@@ -109,6 +112,29 @@ impl std::fmt::Debug for ManagedSeqAnim {
     }
 }
 
+/// This trait allows `Renderer` and `RendererSync` to be used interchangeably helping with
+/// code reuse.
+pub trait RenderApi {
+    /// Allocate a texture on the gfx card
+    fn new_texture(
+        &self,
+        width: u16,
+        height: u16,
+        data: Vec<u8>,
+        fmt: TextureFormat,
+        tag: DebugTag,
+    ) -> ManagedTexturePtr;
+
+    /// Create a buffer to store vertices
+    fn new_vertex_buffer(&self, verts: Vec<Vertex>, tag: DebugTag) -> ManagedBufferPtr;
+
+    /// Create a buffer to store triangle faces
+    fn new_index_buffer(&self, indices: Vec<u16>, tag: DebugTag) -> ManagedBufferPtr;
+
+    /// Modify render tree.
+    fn replace_draw_calls(&self, batch_id: Option<BatchGuardId>, dcs: Vec<(DcId, DrawCall)>);
+}
+
 #[derive(Clone)]
 pub struct Renderer {
     /// We are abusing async_channel since it's cloneable whereas std::sync::mpsc is shit.
@@ -151,18 +177,6 @@ impl Renderer {
         (gfx_texture_id, epoch)
     }
 
-    pub fn new_texture(
-        &self,
-        width: u16,
-        height: u16,
-        data: Vec<u8>,
-        fmt: TextureFormat,
-        tag: DebugTag,
-    ) -> ManagedTexturePtr {
-        let (id, epoch) = self.new_unmanaged_texture(width, height, data, fmt, tag);
-        Arc::new(ManagedTexture { id, epoch, renderer: self.clone(), tag })
-    }
-
     fn delete_unmanaged_texture(&self, texture: TextureId, epoch: EpochIndex, tag: DebugTag) {
         let method = GraphicsMethod::DeleteTexture((texture, tag));
         self.send_with_epoch(method, epoch);
@@ -194,15 +208,6 @@ impl Renderer {
         (gfx_buffer_id, epoch)
     }
 
-    pub fn new_vertex_buffer(&self, verts: Vec<Vertex>, tag: DebugTag) -> ManagedBufferPtr {
-        let (id, epoch) = self.new_unmanaged_vertex_buffer(verts, tag);
-        Arc::new(ManagedBuffer { id, epoch, renderer: self.clone(), tag, buftype: 0 })
-    }
-    pub fn new_index_buffer(&self, indices: Vec<u16>, tag: DebugTag) -> ManagedBufferPtr {
-        let (id, epoch) = self.new_unmanaged_index_buffer(indices, tag);
-        Arc::new(ManagedBuffer { id, epoch, renderer: self.clone(), tag, buftype: 1 })
-    }
-
     fn delete_unmanaged_buffer(
         &self,
         buffer: BufferId,
@@ -250,17 +255,6 @@ impl Renderer {
         self.send_with_epoch(method, epoch);
     }
 
-    pub fn replace_draw_calls(&self, batch_id: Option<BatchGuardId>, dcs: Vec<(DcId, DrawCall)>) {
-        let method = GraphicsMethod::ReplaceGfxDrawCalls { batch_id, dcs };
-        self.send(method);
-
-        // I'm not sure whether we need this. Anyway its not fully reliable either since
-        // we have no guarantee that when `Stage::update()` whether this method is ready
-        // in the receiver.
-        #[cfg(target_os = "android")]
-        miniquad::window::schedule_update();
-    }
-
     fn start_batch(&self, batch_id: BatchGuardId, tag: DebugTag) {
         let method = GraphicsMethod::StartBatch { batch_id, tag };
         self.send(method);
@@ -284,6 +278,40 @@ impl Renderer {
     }
 }
 
+impl RenderApi for Renderer {
+    fn new_texture(
+        &self,
+        width: u16,
+        height: u16,
+        data: Vec<u8>,
+        fmt: TextureFormat,
+        tag: DebugTag,
+    ) -> ManagedTexturePtr {
+        let (id, epoch) = self.new_unmanaged_texture(width, height, data, fmt, tag);
+        Arc::new(ManagedTexture { id, epoch, renderer: self.clone(), tag })
+    }
+
+    fn new_vertex_buffer(&self, verts: Vec<Vertex>, tag: DebugTag) -> ManagedBufferPtr {
+        let (id, epoch) = self.new_unmanaged_vertex_buffer(verts, tag);
+        Arc::new(ManagedBuffer { id, epoch, renderer: self.clone(), tag, buftype: 0 })
+    }
+    fn new_index_buffer(&self, indices: Vec<u16>, tag: DebugTag) -> ManagedBufferPtr {
+        let (id, epoch) = self.new_unmanaged_index_buffer(indices, tag);
+        Arc::new(ManagedBuffer { id, epoch, renderer: self.clone(), tag, buftype: 1 })
+    }
+
+    fn replace_draw_calls(&self, batch_id: Option<BatchGuardId>, dcs: Vec<(DcId, DrawCall)>) {
+        let method = GraphicsMethod::ReplaceGfxDrawCalls { batch_id, dcs };
+        self.send(method);
+
+        // I'm not sure whether we need this. Anyway its not fully reliable either since
+        // we have no guarantee that when `Stage::update()` whether this method is ready
+        // in the receiver.
+        #[cfg(target_os = "android")]
+        miniquad::window::schedule_update();
+    }
+}
+
 #[derive(Clone)]
 pub enum GraphicsMethod {
     NewTexture((u16, u16, Vec<u8>, TextureFormat, TextureId, DebugTag)),
@@ -329,59 +357,63 @@ impl Default for GraphicsMethod {
 }
 
 pub struct RendererSync<'a> {
-    stage: &'a mut Stage,
-    is_dirty: bool,
+    stage: UnsafeCell<&'a mut Stage>,
 }
 
 impl<'a> RendererSync<'a> {
     pub fn new(stage: &'a mut Stage) -> Self {
-        Self { stage, is_dirty: false }
+        Self { stage: UnsafeCell::new(stage) }
     }
 
-    // Texture methods
-    pub fn new_texture(
-        &mut self,
+    // SAFETY: The '&a mut Stage' reference stored in UnsafeCell is guaranteed to be unique
+    // for the lifetime 'a of this RendererSync. No other references to this Stage can exist
+    // while RendererSync is alive, due to Rust's borrow checker rules on mutable references.
+    // Therefore, it's safe to return &mut Stage through &self.
+    fn stage(&self) -> &mut Stage {
+        unsafe { &mut *self.stage.get() }
+    }
+}
+
+impl RenderApi for RendererSync<'_> {
+    fn new_texture(
+        &self,
         width: u16,
         height: u16,
         data: Vec<u8>,
         fmt: TextureFormat,
         tag: DebugTag,
     ) -> ManagedTexturePtr {
-        let renderer = self.stage.renderer.clone();
+        let stage = self.stage();
+        let renderer = stage.renderer.clone();
         let id = NEXT_TEXTURE_ID.fetch_add(1, Ordering::Relaxed);
-        self.stage.method_new_texture(width, height, &data, fmt, id);
+        stage.method_new_texture(width, height, &data, fmt, id);
         Arc::new(ManagedTexture { id, epoch: 0, renderer, tag })
     }
 
-    // Buffer methods
-    pub fn new_vertex_buffer(&mut self, verts: Vec<Vertex>, tag: DebugTag) -> ManagedBufferPtr {
-        let renderer = self.stage.renderer.clone();
+    fn new_vertex_buffer(&self, verts: Vec<Vertex>, tag: DebugTag) -> ManagedBufferPtr {
+        let stage = self.stage();
+        let renderer = stage.renderer.clone();
         let id = NEXT_BUFFER_ID.fetch_add(1, Ordering::Relaxed);
-        self.stage.method_new_vertex_buffer(&verts, id);
+        stage.method_new_vertex_buffer(&verts, id);
         Arc::new(ManagedBuffer { id, epoch: 0, renderer, tag, buftype: 0 })
     }
 
-    pub fn new_index_buffer(&mut self, indices: Vec<u16>, tag: DebugTag) -> ManagedBufferPtr {
-        let renderer = self.stage.renderer.clone();
+    fn new_index_buffer(&self, indices: Vec<u16>, tag: DebugTag) -> ManagedBufferPtr {
+        let stage = self.stage();
+        let renderer = stage.renderer.clone();
         let id = NEXT_BUFFER_ID.fetch_add(1, Ordering::Relaxed);
-        self.stage.method_new_index_buffer(&indices, id);
+        stage.method_new_index_buffer(&indices, id);
         Arc::new(ManagedBuffer { id, epoch: 0, renderer, tag, buftype: 1 })
     }
 
-    // Draw calls (no batching)
-    pub fn replace_draw_calls(&mut self, dcs: Vec<(DcId, DrawCall)>) {
+    /// Draw calls (no batching). The batch ID is ignored here.
+    fn replace_draw_calls(&self, _: Option<BatchGuardId>, dcs: Vec<(DcId, DrawCall)>) {
+        let stage = self.stage();
         let timest = unixtime();
-        self.stage.apply_draw_calls(timest, dcs);
-        self.is_dirty = true;
-    }
-}
+        stage.apply_draw_calls(timest, dcs);
 
-impl Drop for RendererSync<'_> {
-    fn drop(&mut self) {
-        if self.is_dirty {
-            // Force an update
-            #[cfg(target_os = "android")]
-            miniquad::window::schedule_update();
-        }
+        // Force an update
+        #[cfg(target_os = "android")]
+        miniquad::window::schedule_update();
     }
 }

+ 1 - 1
bin/app/src/gfx/mod.rs

@@ -43,7 +43,7 @@ use anim::{Frame as AnimFrame, GfxSeqAnim};
 mod api;
 pub use api::{
     EpochIndex, GraphicsMethod, ManagedBuffer, ManagedBufferPtr, ManagedSeqAnim, ManagedSeqAnimPtr,
-    ManagedTexture, ManagedTexturePtr, Renderer, RendererSync,
+    ManagedTexture, ManagedTexturePtr, RenderApi, Renderer, RendererSync,
 };
 mod ev;
 pub use ev::{

+ 2 - 1
bin/app/src/mesh.rs

@@ -17,7 +17,8 @@
  */
 
 use crate::gfx::{
-    DebugTag, DrawMesh, ManagedBufferPtr, ManagedTexturePtr, Point, Rectangle, Renderer, Vertex,
+    DebugTag, DrawMesh, ManagedBufferPtr, ManagedTexturePtr, Point, Rectangle, RenderApi, Renderer,
+    Vertex,
 };
 
 pub type Color = [f32; 4];

+ 1 - 1
bin/app/src/text/atlas.rs

@@ -18,7 +18,7 @@
 
 use miniquad::TextureFormat;
 
-use crate::gfx::{DebugTag, ManagedTexturePtr, Rectangle, Renderer};
+use crate::gfx::{DebugTag, ManagedTexturePtr, Rectangle, RenderApi, Renderer};
 
 /// Prevents render artifacts from aliasing.
 /// Even with aliasing turned off, some bleed still appears possibly

+ 1 - 1
bin/app/src/ui/chatview/mod.rs

@@ -42,7 +42,7 @@ pub use page::FileMessageStatus;
 use page::MessageBuffer;
 
 use crate::{
-    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, Renderer},
+    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, RenderApi, Renderer},
     prop::{
         BatchGuardId, BatchGuardPtr, PropertyAtomicGuard, PropertyColor, PropertyFloat32,
         PropertyRect, PropertyUint32, Role,

+ 1 - 1
bin/app/src/ui/chatview/page.rs

@@ -38,7 +38,7 @@ use url::Url;
 
 use super::{MessageId, Timestamp};
 use crate::{
-    gfx::{gfxtag, DrawInstruction, ManagedTexturePtr, Point, Rectangle, Renderer},
+    gfx::{gfxtag, DrawInstruction, ManagedTexturePtr, Point, Rectangle, RenderApi, Renderer},
     mesh::{Color, MeshBuilder, COLOR_CYAN, COLOR_GREEN, COLOR_RED, COLOR_WHITE},
     prop::{PropertyColor, PropertyFloat32, PropertyPtr},
     scene::SceneNodeWeak,

+ 1 - 1
bin/app/src/ui/edit/action.rs

@@ -20,7 +20,7 @@ use parking_lot::Mutex as SyncMutex;
 use rand::{rngs::OsRng, Rng};
 
 use crate::{
-    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, Renderer},
+    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, RenderApi, Renderer},
     mesh::{Color, MeshBuilder},
     prop::BatchGuardId,
     text,

+ 24 - 11
bin/app/src/ui/edit/mod.rs

@@ -38,8 +38,8 @@ use tracing::instrument;
 use crate::android::textinput::AndroidTextInputState;
 use crate::{
     gfx::{
-        gfxtag, DrawCall, DrawInstruction, DrawMesh, Point, Rectangle, Renderer, RendererSync,
-        Vertex,
+        gfxtag, DrawCall, DrawInstruction, DrawMesh, Point, Rectangle, RenderApi, Renderer,
+        RendererSync, Vertex,
     },
     mesh::MeshBuilder,
     prop::{
@@ -776,7 +776,7 @@ impl BaseEdit {
         false
     }
 
-    fn handle_touch_move(&self, mut touch_pos: Point) -> bool {
+    fn handle_touch_move(&self, renderer: &mut RendererSync, mut touch_pos: Point) -> bool {
         if !self.is_active.get() {
             return false
         }
@@ -879,7 +879,7 @@ impl BaseEdit {
         }
         true
     }
-    fn handle_touch_end(&self, mut touch_pos: Point) -> bool {
+    async fn handle_touch_end(&self, mut touch_pos: Point) -> bool {
         //t!("handle_touch_end({touch_pos:?})");
         self.abs_to_local(&mut touch_pos);
 
@@ -899,9 +899,7 @@ impl BaseEdit {
         scroll_sender.try_send(None).unwrap();
 
         let node = self.node();
-        smol::block_on(async {
-            node.trigger("focus_request", vec![]).await.unwrap();
-        });
+        node.trigger("focus_request", vec![]).await.unwrap();
 
         true
     }
@@ -1827,7 +1825,7 @@ impl UIObject for BaseEdit {
 
     fn handle_touch_sync(
         &self,
-        _render_api: &mut RendererSync,
+        renderer: &mut RendererSync,
         phase: TouchPhase,
         id: u64,
         touch_pos: Point,
@@ -1843,9 +1841,24 @@ impl UIObject for BaseEdit {
 
         match phase {
             TouchPhase::Started => self.handle_touch_start(touch_pos),
-            TouchPhase::Moved => self.handle_touch_move(touch_pos),
-            TouchPhase::Ended => self.handle_touch_end(touch_pos),
-            TouchPhase::Cancelled => false,
+            TouchPhase::Moved => self.handle_touch_move(renderer, touch_pos),
+            TouchPhase::Ended | TouchPhase::Cancelled => false,
+        }
+    }
+
+    async fn handle_touch(&self, phase: TouchPhase, id: u64, touch_pos: Point) -> bool {
+        if !self.is_active.get() {
+            return false
+        }
+
+        // Ignore multi-touch
+        if id != 0 {
+            return false
+        }
+
+        match phase {
+            TouchPhase::Started | TouchPhase::Moved | TouchPhase::Cancelled => false,
+            TouchPhase::Ended => self.handle_touch_end(touch_pos).await,
         }
     }
 }

+ 1 - 1
bin/app/src/ui/emoji_picker/mod.rs

@@ -27,7 +27,7 @@ use std::sync::{
 };
 
 use crate::{
-    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, Renderer},
+    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, RenderApi, Renderer},
     prop::{
         BatchGuardPtr, PropertyAtomicGuard, PropertyFloat32, PropertyRect, PropertyUint32, Role,
     },

+ 4 - 1
bin/app/src/ui/image.rs

@@ -25,7 +25,10 @@ use std::{io::Cursor, sync::Arc};
 use tracing::instrument;
 
 use crate::{
-    gfx::{gfxtag, DrawCall, DrawInstruction, DrawMesh, ManagedTexturePtr, Rectangle, Renderer},
+    gfx::{
+        gfxtag, DrawCall, DrawInstruction, DrawMesh, ManagedTexturePtr, Rectangle, RenderApi,
+        Renderer,
+    },
     mesh::{MeshBuilder, MeshInfo, COLOR_WHITE},
     prop::{BatchGuardPtr, PropertyAtomicGuard, PropertyRect, PropertyStr, PropertyUint32, Role},
     scene::{Pimpl, SceneNodeWeak},

+ 1 - 1
bin/app/src/ui/layer.rs

@@ -24,7 +24,7 @@ use std::sync::Arc;
 use tracing::instrument;
 
 use crate::{
-    gfx::{DrawCall, DrawInstruction, Point, Rectangle, Renderer, RendererSync},
+    gfx::{DrawCall, DrawInstruction, Point, Rectangle, RenderApi, Renderer, RendererSync},
     prop::{BatchGuardPtr, PropertyAtomicGuard, PropertyBool, PropertyRect, PropertyUint32, Role},
     scene::{Pimpl, SceneNodePtr, SceneNodeWeak},
     util::i18n::I18nBabelFish,

+ 5 - 24
bin/app/src/ui/menu.rs

@@ -32,7 +32,7 @@ use std::{
 };
 
 use crate::{
-    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, Renderer, RendererSync},
+    gfx::{gfxtag, DrawCall, DrawInstruction, Point, Rectangle, RenderApi, Renderer, RendererSync},
     mesh::MeshBuilder,
     prop::{
         BatchGuardId, BatchGuardPtr, PropertyAtomicGuard, PropertyBool, PropertyColor,
@@ -311,7 +311,7 @@ impl Menu {
         self.renderer.replace_draw_calls(Some(atom.batch_id), draw_update.draw_calls);
     }
 
-    fn redraw_scroll(&self) {
+    fn redraw_scroll<R: RenderApi>(&self, renderer: &R) {
         let rect = self.rect.get();
         let scroll = self.scroll.load(Ordering::Relaxed);
 
@@ -327,26 +327,7 @@ impl Menu {
         };
 
         let draw_calls = vec![(self.root_dc_key, root_dc)];
-        self.renderer.replace_draw_calls(None, draw_calls);
-    }
-
-    fn redraw_scroll_sync(&self, renderer: &mut RendererSync) {
-        let rect = self.rect.get();
-        let scroll = self.scroll.load(Ordering::Relaxed);
-
-        // Only recreate root with updated scroll position
-        let root_instrs =
-            vec![DrawInstruction::ApplyView(rect), DrawInstruction::Move(Point::new(0., -scroll))];
-
-        let root_dc = DrawCall {
-            instrs: root_instrs,
-            dcs: vec![self.content_dc_key],
-            z_index: self.z_index.get(),
-            debug_str: "menu_root",
-        };
-
-        let draw_calls = vec![(self.root_dc_key, root_dc)];
-        renderer.replace_draw_calls(draw_calls);
+        renderer.replace_draw_calls(None, draw_calls);
     }
 
     fn scrollview(&self, scroll: f32) {
@@ -383,7 +364,7 @@ impl Menu {
             while speed.abs() >= EPSILON {
                 let scroll = self.scroll.load(Ordering::Relaxed);
                 self.scrollview(scroll + speed);
-                self.redraw_scroll();
+                self.redraw_scroll(&self.renderer);
                 speed *= resist;
                 self.speed.store(speed, Ordering::Relaxed);
                 darkfi::system::msleep(16).await;
@@ -539,7 +520,7 @@ impl UIObject for Menu {
                 };
 
                 self.scrollview(scroll);
-                self.redraw_scroll_sync(renderer);
+                self.redraw_scroll(renderer);
                 true
             }
 

+ 1 - 1
bin/app/src/ui/mod.rs

@@ -112,7 +112,7 @@ pub trait UIObject: Sync {
 
     fn handle_touch_sync(
         &self,
-        _render_api: &mut RendererSync,
+        _renderer: &mut RendererSync,
         _phase: TouchPhase,
         _id: u64,
         _touch_pos: Point,

+ 1 - 1
bin/app/src/ui/text.rs

@@ -23,7 +23,7 @@ use std::sync::Arc;
 use tracing::instrument;
 
 use crate::{
-    gfx::{gfxtag, DrawCall, DrawInstruction, Rectangle, Renderer},
+    gfx::{gfxtag, DrawCall, DrawInstruction, Rectangle, RenderApi, Renderer},
     mesh::MeshBuilder,
     prop::{
         BatchGuardPtr, PropertyAtomicGuard, PropertyBool, PropertyColor, PropertyFloat32,

+ 1 - 1
bin/app/src/ui/vector_art/mod.rs

@@ -23,7 +23,7 @@ use std::sync::Arc;
 use tracing::instrument;
 
 use crate::{
-    gfx::{gfxtag, DrawCall, DrawInstruction, DrawMesh, Rectangle, Renderer},
+    gfx::{gfxtag, DrawCall, DrawInstruction, DrawMesh, Rectangle, RenderApi, Renderer},
     prop::{BatchGuardPtr, PropertyAtomicGuard, PropertyBool, PropertyRect, PropertyUint32, Role},
     scene::{Pimpl, SceneNodeWeak},
     ExecutorPtr,

+ 1 - 1
bin/app/src/ui/vid/decode/android.rs

@@ -27,7 +27,7 @@ use std::{
 
 use crate::{
     android::vid::{self, DecodedFrame},
-    gfx::{gfxtag, Renderer},
+    gfx::{gfxtag, Renderer, RenderApi},
     ui::vid::{Av1VideoData, YuvTextures},
     util::spawn_thread,
 };

+ 1 - 1
bin/app/src/ui/vid/decode/mod.rs

@@ -21,7 +21,7 @@
 use parking_lot::Mutex as SyncMutex;
 use std::sync::Arc;
 
-use crate::gfx::Renderer;
+use crate::gfx::{RenderApi, Renderer};
 
 use super::Av1VideoData;
 

+ 1 - 1
bin/app/src/ui/vid/decode/rav1d.rs

@@ -25,7 +25,7 @@ use rav1d::{
 use std::{sync::Arc, time::Instant};
 
 use crate::{
-    gfx::{gfxtag, Renderer},
+    gfx::{gfxtag, RenderApi, Renderer},
     ui::vid::{ivf::IvfStreamingDemuxer, Av1VideoData, YuvTextures},
     util::spawn_thread,
 };

+ 1 - 1
bin/app/src/ui/vid/mod.rs

@@ -25,7 +25,7 @@ use tracing::instrument;
 use crate::{
     gfx::{
         anim::Frame, gfxtag, DrawCall, DrawInstruction, DrawMesh, GraphicPipeline,
-        ManagedSeqAnimPtr, ManagedTexturePtr, Rectangle, Renderer,
+        ManagedSeqAnimPtr, ManagedTexturePtr, Rectangle, RenderApi, Renderer,
     },
     mesh::{MeshBuilder, MeshInfo, COLOR_WHITE},
     prop::{BatchGuardPtr, PropertyAtomicGuard, PropertyRect, PropertyStr, PropertyUint32, Role},

+ 1 - 1
bin/app/src/ui/win.rs

@@ -27,7 +27,7 @@ use crate::{
         gfxtag, DrawCall, DrawInstruction, GraphicsEventCharSub, GraphicsEventKeyDownSub,
         GraphicsEventKeyUpSub, GraphicsEventMouseButtonDownSub, GraphicsEventMouseButtonUpSub,
         GraphicsEventMouseMoveSub, GraphicsEventMouseWheelSub, GraphicsEventPublisherPtr,
-        GraphicsEventTouchSub, Point, Rectangle, Renderer, RendererSync,
+        GraphicsEventTouchSub, Point, Rectangle, RenderApi, Renderer, RendererSync,
     },
     prop::{
         BatchGuardPtr, PropertyAtomicGuard, PropertyDimension, PropertyFloat32, PropertyStr, Role,