use core_types::transform::Footprint; use dyn_any::{DynAny, StaticType, StaticTypeSized}; use glam::DVec2; use std::fmt::Debug; use std::future::Future; use std::hash::{Hash, Hasher}; use std::pin::Pin; use std::ptr::addr_of; use std::sync::Arc; use std::time::Duration; use text_nodes::FontCache; use vector_types::vector::style::RenderMode; #[cfg(feature = "wgpu")] #[derive(Debug, Clone, Hash, PartialEq, Eq, DynAny)] pub struct ImageTexture(Arc); #[cfg(feature = "wgpu")] impl AsRef for ImageTexture { fn as_ref(&self) -> &wgpu::Texture { &self.0 } } #[cfg(feature = "wgpu")] impl From for ImageTexture { fn from(texture: wgpu::Texture) -> Self { Self(Arc::new(texture)) } } #[cfg(feature = "wgpu")] impl From> for ImageTexture { fn from(texture: Arc) -> Self { Self(texture) } } #[cfg(feature = "wgpu")] impl From for Arc { fn from(image_texture: ImageTexture) -> Self { image_texture.0 } } #[cfg(not(feature = "wgpu"))] #[derive(Debug, Clone, Hash, PartialEq, Eq, DynAny)] pub struct ImageTexture; #[cfg(target_family = "wasm")] pub type ResourceFuture = Pin, ApplicationError>>>>; #[cfg(not(target_family = "wasm"))] pub type ResourceFuture = Pin, ApplicationError>> + Send>>; pub trait ApplicationIo { type Executor; fn gpu_executor(&self) -> Option<&Self::Executor> { None } fn load_resource(&self, url: impl AsRef) -> Result; } impl ApplicationIo for &T { type Executor = T::Executor; fn gpu_executor(&self) -> Option<&T::Executor> { (**self).gpu_executor() } fn load_resource<'a>(&self, url: impl AsRef) -> Result { (**self).load_resource(url) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ApplicationError { NotFound, InvalidUrl, } #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum NodeGraphUpdateMessage {} pub trait NodeGraphUpdateSender { fn send(&self, message: NodeGraphUpdateMessage); } impl NodeGraphUpdateSender for std::sync::Mutex { fn send(&self, message: NodeGraphUpdateMessage) { self.lock().as_mut().unwrap().send(message) } } pub trait GetEditorPreferences { fn max_render_region_area(&self) -> u32; } #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ExportFormat { #[default] Svg, Raster, } #[derive(Debug, Default, Clone, Copy, PartialEq, DynAny)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TimingInformation { pub time: f64, pub animation_time: Duration, } #[derive(Debug, Default, Clone, Copy, PartialEq, DynAny)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RenderConfig { pub viewport: Footprint, pub scale: f64, pub time: TimingInformation, pub pointer: DVec2, #[cfg_attr(feature = "serde", serde(alias = "view_mode"))] pub render_mode: RenderMode, pub export_format: ExportFormat, pub for_export: bool, pub for_eyedropper: bool, } struct Logger; impl NodeGraphUpdateSender for Logger { fn send(&self, message: NodeGraphUpdateMessage) { log::warn!("dispatching message with fallback node graph update sender {message:?}"); } } struct DummyPreferences; impl GetEditorPreferences for DummyPreferences { fn max_render_region_area(&self) -> u32 { 1024 * 1024 } } pub struct EditorApi { /// Font data (for rendering text) made available to the graph through the `PlatformEditorApi`. pub font_cache: FontCache, /// Gives access to APIs like a rendering surface (native window handle or HTML5 canvas) and WGPU (which becomes WebGPU on web). pub application_io: Option>, pub node_graph_message_sender: Box, /// Editor preferences made available to the graph through the `PlatformEditorApi`. pub editor_preferences: Box, } impl Eq for EditorApi {} impl Default for EditorApi { fn default() -> Self { Self { font_cache: FontCache::default(), application_io: None, node_graph_message_sender: Box::new(Logger), editor_preferences: Box::new(DummyPreferences), } } } impl Hash for EditorApi { fn hash(&self, state: &mut H) { self.font_cache.hash(state); self.application_io.as_ref().map_or(0, |io| io.as_ref() as *const _ as usize).hash(state); (self.node_graph_message_sender.as_ref() as *const dyn NodeGraphUpdateSender).hash(state); (self.editor_preferences.as_ref() as *const dyn GetEditorPreferences).hash(state); } } impl core_types::graphene_hash::CacheHash for EditorApi { fn cache_hash(&self, state: &mut H) { core::hash::Hash::hash(self, state); } } impl PartialEq for EditorApi { fn eq(&self, other: &Self) -> bool { self.font_cache == other.font_cache && self.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize) == other.application_io.as_ref().map_or(0, |io| addr_of!(io) as usize) && std::ptr::eq(self.node_graph_message_sender.as_ref() as *const _, other.node_graph_message_sender.as_ref() as *const _) && std::ptr::eq(self.editor_preferences.as_ref() as *const _, other.editor_preferences.as_ref() as *const _) } } impl Debug for EditorApi { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("EditorApi").field("font_cache", &self.font_cache).finish() } } unsafe impl StaticType for EditorApi { type Static = EditorApi; }