This commit is contained in:
Tsuki 2024-11-19 16:12:59 +08:00
parent 1641585177
commit d9b8c8f666
19 changed files with 535 additions and 181 deletions

41
Cargo.lock generated
View File

@ -681,7 +681,7 @@ dependencies = [
"const_panic",
"encase_derive",
"glam",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -1013,7 +1013,7 @@ checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd"
dependencies = [
"log",
"presser",
"thiserror",
"thiserror 1.0.69",
"windows 0.58.0",
]
@ -1721,6 +1721,7 @@ dependencies = [
"mp_elements",
"native-dialog",
"once_cell",
"thiserror 2.0.3",
"tokio",
"tracing",
"tracing-subscriber",
@ -1742,7 +1743,7 @@ dependencies = [
"radarg_plugin_interface",
"rust-embed",
"serde",
"thiserror",
"thiserror 1.0.69",
"tokio",
"toml",
]
@ -1782,7 +1783,7 @@ dependencies = [
"rustc-hash",
"spirv",
"termcolor",
"thiserror",
"thiserror 1.0.69",
"unicode-xid",
]
@ -1860,7 +1861,7 @@ dependencies = [
"objc_id",
"once_cell",
"raw-window-handle 0.5.2",
"thiserror",
"thiserror 1.0.69",
"versions",
"wfd",
"which",
@ -2284,7 +2285,7 @@ dependencies = [
"rand_chacha",
"simd_helpers",
"system-deps",
"thiserror",
"thiserror 1.0.69",
"v_frame",
"wasm-bindgen",
]
@ -2359,7 +2360,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox",
"thiserror",
"thiserror 1.0.69",
]
[[package]]
@ -2775,7 +2776,16 @@ version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
"thiserror-impl 1.0.69",
]
[[package]]
name = "thiserror"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
dependencies = [
"thiserror-impl 2.0.3",
]
[[package]]
@ -2789,6 +2799,17 @@ dependencies = [
"syn 2.0.87",
]
[[package]]
name = "thiserror-impl"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
]
[[package]]
name = "thread_local"
version = "1.1.8"
@ -3263,7 +3284,7 @@ dependencies = [
"raw-window-handle 0.6.2",
"rustc-hash",
"smallvec",
"thiserror",
"thiserror 1.0.69",
"wgpu-hal",
"wgpu-types",
]
@ -3305,7 +3326,7 @@ dependencies = [
"renderdoc-sys",
"rustc-hash",
"smallvec",
"thiserror",
"thiserror 1.0.69",
"wasm-bindgen",
"web-sys",
"wgpu-types",

View File

@ -6,7 +6,7 @@ use mp_elements::{
use std::sync::{Arc, Mutex};
pub use mp_elements::app::Window;
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct TextureBridge {
dirty: bool,
_buffer: Arc<tokio::sync::Mutex<Vec<u8>>>,
@ -41,7 +41,7 @@ impl TextureBridge {
app.draw(&self.window, draw_list).await;
}
pub async fn load_data(buffer: Arc<Mutex<Vec<u8>>>, ctx: &Ctx, render_window: &RenderWindow) {
pub async fn load_data(buffer: &mut Vec<u8>, ctx: &Ctx, render_window: &RenderWindow) {
let output = &render_window.output().output_buffer;
let (sender, receiver) = flume::bounded(1);
@ -54,7 +54,6 @@ impl TextureBridge {
{
let view = slice.get_mapped_range();
let mut buffer = buffer.lock().unwrap();
buffer.copy_from_slice(&view[..]);
}
output.unmap();

View File

@ -19,3 +19,4 @@ tokio = { version = "1.41.1", features = ["full"] }
element_bridge = { path = "../element_bridge", version = "*" }
futures = "0.3.31"
async-trait = "0.1.83"
thiserror = "2.0.3"

View File

@ -1,22 +1,22 @@
use crate::file::*;
use crate::menu::{handle_menu, spawn_background};
use crate::widgets::area::TAreaWidgetRefExt;
use crate::windows_manager::WindowsManager;
use crate::windows_manager::WM;
use crate::{render_task::RenderTasks, PLUGIN_MANAGER, RUNTIME};
use crate::{DATAPOOL, GIAPP};
use ::log::info;
use element_bridge::TextureBridge;
use makepad_widgets::makepad_micro_serde::*;
use makepad_widgets::*;
use mp_core::Data;
use mp_elements::elements::ppi::PPIConfig;
use mp_elements::elements::PPI;
use mp_elements::app::DrawList as DW;
use std::path::PathBuf;
use std::sync::Arc;
use window_menu::WindowMenuWidgetRefExt;
use tokio::sync::Mutex;
live_design! {
import makepad_widgets::base::*;
import makepad_widgets::theme_desktop_dark::*;
import crate::app_ui::MainView;
import crate::widgets::selector_modal::SelectorModal;
HELLO = "Hello, World!";
@ -55,6 +55,40 @@ live_design! {
}
}
notification = <PopupNotification> {
content: {
height: Fit,
width: Fit,
padding: 10,
<RoundedView> {
height: Fit,
width: 240,
padding: 30,
show_bg: true,
draw_bg: {
color: #3c3c3c
radius: 3.0
}
notifacion_title = <Label> {
text: "Notification"
}
notification_message = <Label> {
width: 170
}
close_popup_button = <Button> {
width: Fit,
height: Fit,
margin: {top: -20 },
icon_walk: {width: 10, height: 10}
}
}
}
}
selector = <SelectorModal>{}
<MainView>{}
}
window_menu = {
@ -86,14 +120,55 @@ live_design! {
}
#[derive(Default, Clone, Debug)]
pub enum AppAction {
OpenFile,
OpenFolder,
Quit,
Task(TaskAction),
File(FileAction),
Notification {
message: String,
duration: f64,
},
#[default]
None,
}
impl AppAction {
pub fn register_task(id: usize, bridge: Arc<TextureBridge>, draw_list: DW) -> AppAction {
AppAction::Task(TaskAction::Register(id, bridge, draw_list))
}
}
#[derive(Debug, Clone)]
pub enum TaskAction {
Register(usize, Arc<TextureBridge>, DW),
Unregister(),
}
#[derive(Debug, Clone)]
pub enum FileAction {
OpenFile(PathBuf),
OpenFolder(PathBuf),
}
#[derive(Live, LiveHook)]
pub struct App {
#[live]
ui: WidgetRef,
#[rust]
render_tasks: Arc<Mutex<RenderTasks>>,
pub render_tasks: Arc<Mutex<RenderTasks>>,
#[rust]
windows_manager: WindowsManager,
windows_manager: WM,
#[rust]
tex_reciver: ToUIReceiver<Vec<u8>>,
#[rust]
file_manager: FileManager,
#[rust]
timer: Timer,
}
impl LiveRegister for App {
@ -102,6 +177,7 @@ impl LiveRegister for App {
crate::app_ui::live_design(_cx);
crate::widgets::area::live_design(_cx);
crate::widgets::renderer::live_design(_cx);
crate::widgets::selector_modal::live_design(_cx);
}
}
@ -112,46 +188,27 @@ struct AppStateRon {
impl MatchEvent for App {
// Start UP
fn handle_startup(&mut self, _cx: &mut Cx) {}
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {}
}
impl AppMain for App {
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
self.match_event(cx, event);
self.ui.handle_event(cx, event, &mut Scope::empty());
spawn_background(self, event);
handle_menu(event);
}
}
fn spawn_background(app: &mut App, event: &Event) {
match event {
Event::Draw(_) => {
// Render Task
info!("Starting background task......");
let tasks = app.render_tasks.clone();
fn handle_startup(&mut self, cx: &mut Cx) {
info!("Starting up......");
let ui = self.ui.clone();
let area = ui.tarea(id!(quad));
area.set_windows(self.windows_manager.clone());
// Listening to the render tasks
let render_tasks = self.render_tasks.clone();
RUNTIME.spawn(async move {
let tasks = tasks.lock().await;
tasks.render().await;
});
let tasks = app.render_tasks.clone();
let all_buffers = app.windows_manager.buffer();
RUNTIME.spawn(async move {
let mut tasks = tasks.lock().await;
tasks.listen(all_buffers).await;
let render_task = render_tasks.lock().await;
render_task.render().await;
});
}
_ => {}
}
fn handle_signal(&mut self, cx: &mut Cx) {
self.file_manager.try_deal_file(cx);
}
fn handle_menu(event: &Event) {
match event {
Event::MacosMenuCommand(command) => {
if command == &LiveId::from_str("open_file") {
fn handle_action(&mut self, _cx: &mut Cx, e: &Action) {
let ui = self.ui.clone();
match e.cast() {
AppAction::OpenFile => {
use native_dialog::FileDialog;
info!("Open File Dialog");
let supported_extensions = PLUGIN_MANAGER.supported_extensions();
@ -161,12 +218,75 @@ fn handle_menu(event: &Event) {
.unwrap();
if let Some(file) = file {
info!("File: {:?}", file);
}
}
}
_ => {}
_cx.action(AppAction::File(FileAction::OpenFile(file)));
}
}
AppAction::OpenFolder => {
info!("Open Folder");
}
AppAction::Quit => {
info!("Quit");
}
AppAction::Task(task) => match task {
TaskAction::Register(bridge_id, bridge, draw_list) => {
info!(
"Register Task for {:?}, draw_list: {:?}",
bridge_id, draw_list
);
let bridge = bridge.render_window();
let sender = self.tex_reciver.sender();
RUNTIME.block_on(async {
let mut render_tasks = self.render_tasks.lock().await;
render_tasks.register_task(sender, bridge_id, bridge, draw_list);
});
}
TaskAction::Unregister() => {
info!("Unregister Task");
}
},
AppAction::File(file) => match file {
FileAction::OpenFile(file) => {
info!("Open File: {:?}", file);
self.file_manager.load_data(&file);
}
FileAction::OpenFolder(folder) => {
info!("Open Folder: {:?}", folder);
}
},
AppAction::Notification { message, duration } => {
let notifacion: PopupNotificationRef = ui.popup_notification(id!(notification));
let timer = _cx.start_timeout(duration);
self.timer = timer;
ui.label(id!(notification_message)).set_text(&message);
notifacion.open(_cx);
}
_ => {}
}
}
}
impl AppMain for App {
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
self.match_event(cx, event);
self.ui.handle_event(cx, event, &mut Scope::empty());
spawn_background(self, event);
handle_menu(cx, event);
self.timer.is_event(event).map(|_| {
let notifacion: PopupNotificationRef = self.ui.popup_notification(id!(notification));
notifacion.close(cx);
});
}
}
impl App {}
app_main!(App);

View File

@ -60,29 +60,7 @@ live_design! {
y: 0.5
},
quad = <Area> {
// draw: {
// // this example shader is ported from kishimisu's tutorial
// fn pixel(self) -> vec4 {
// // let uv = self.pos - 0.5;
// // let uv0 = uv;
// // let finalColor = vec3(0.0);
// // let i = 0;
// // for _i in 0..4 { // you cannot refer to _i inside the for loop; use i instead
// // uv = fract(uv * -1.5) - 0.5;
// // let d = length(uv) * exp(-length(uv0));
// // let col = Pal::iq2(length(uv0) + float(i) * .4 + self.time * .4);
// // d = sin(d*8. + self.time) / 8.;
// // d = abs(d);
// // d = pow(0.01 / d, 1.2);
// // finalColor += col * d;
// // i = i+1;
// // }
// // return vec4(finalColor ,1);
// }
// }
id: "Primary"
}
}

22
mp/src/errors.rs Normal file
View File

@ -0,0 +1,22 @@
use mp_core::errors::*;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum PanicErr {}
#[derive(Debug, Error)]
pub enum AppErr {
#[error("App Error: {0}")]
DataErr(#[from] DataError),
#[error("App Error: {0}")]
ConfigErr(#[from] ConfigError),
#[error("App Error: {0}")]
OtherErr(String),
}
impl AppErr {
pub fn other<P: Into<String>>(p: P) -> AppErr {
AppErr::OtherErr(p.into())
}
}

76
mp/src/file.rs Normal file
View File

@ -0,0 +1,76 @@
use crate::{app::AppAction, errors::AppErr, GIAPP, RUNTIME};
use std::path::Path;
use log::info;
use makepad_widgets::{Cx, ToUIReceiver, ToUISender};
use mp_core::{datapool::Value, errors::DataError, Data};
use crate::DATAPOOL;
#[derive(Default)]
pub struct FileManager {
receiver: ToUIReceiver<Vec<Result<Value<Data>, DataError>>>,
}
impl FileManager {
pub fn new() -> Self {
let receiver = ToUIReceiver::default();
Self { receiver }
}
pub fn load_data(&self, path: &Path) {
let sender = self.receiver.sender();
let path = path.to_path_buf();
RUNTIME.spawn(async move {
let data = DATAPOOL.get_or_load_async(&path).await;
sender.send(vec![data]).unwrap();
});
}
pub fn load_folder(&self, path: &Path) {
for entry in path.read_dir().unwrap() {
let entry = entry.unwrap();
let path = entry.path();
if path.is_dir() {
continue;
} else {
self.load_data(&path);
}
}
}
pub fn try_deal_file(&mut self, cx: &mut Cx) {
while let Ok(mut data) = self.receiver.try_recv() {
if data.len() == 1 {
let data = data.pop().unwrap();
if let Ok(data) = data {
info!("Data: {:?}", data);
cx.action(AppAction::Notification {
message: format!("hello,World, {:?}", data),
duration: 3.0,
});
let pipelines = GIAPP.pipelines();
let data = data.get(0).unwrap();
let supported_elements = pipelines.supported_elements(&data);
if supported_elements.is_empty() {
cx.action(AppAction::Notification {
message: "No supported elements".to_string(),
duration: 3.0,
});
} else {
let names = supported_elements
.iter()
.map(|e| e.name().to_string())
.collect::<Vec<_>>();
cx.action(AppAction::Notification {
message: format!("Supported elements: {:?}", names),
duration: 3.0,
});
}
}
} else {
}
}
}
}

View File

@ -6,6 +6,9 @@ pub use makepad_widgets;
pub use makepad_widgets::makepad_draw;
pub use makepad_widgets::makepad_platform;
pub mod app_ui;
pub mod errors;
pub mod file;
pub mod menu;
pub mod render_task;
pub mod widgets;

31
mp/src/menu.rs Normal file
View File

@ -0,0 +1,31 @@
use makepad_widgets::{Cx, Event, LiveId};
use crate::{
app::{App, AppAction},
RUNTIME,
};
pub fn handle_menu(cx: &mut Cx, event: &Event) {
match event {
Event::MacosMenuCommand(command) => {
if command == &LiveId::from_str("open_file") {
cx.action(AppAction::OpenFile);
}
}
_ => {}
}
}
pub fn spawn_background(app: &mut App, event: &Event) {
match event {
Event::Draw(_) => {
// Render Task
let tasks = app.render_tasks.clone();
RUNTIME.spawn(async move {
let tasks = tasks.lock().await;
tasks.render().await;
});
}
_ => {}
}
}

View File

@ -6,7 +6,7 @@ use crate::{
use element_bridge::TextureBridge;
use futures::future::BoxFuture;
use log::info;
use makepad_widgets::{Cx, Texture};
use makepad_widgets::{Cx, Texture, ToUISender};
use mp_elements::{
app::{DrawList, RenderWindow},
App,
@ -15,7 +15,7 @@ use std::sync::{Arc, Mutex};
#[derive(Default)]
pub struct RenderTasks {
pub(crate) tasks: Vec<(tokio::sync::mpsc::Receiver<Vec<u8>>, RenderTask)>,
pub(crate) tasks: Vec<RenderTask>,
}
impl RenderTasks {
@ -23,18 +23,19 @@ impl RenderTasks {
Self { tasks: Vec::new() }
}
fn push_task(&mut self, task: (tokio::sync::mpsc::Receiver<Vec<u8>>, RenderTask)) {
fn push_task(&mut self, task: RenderTask) {
self.tasks.push(task);
}
pub fn register_task(
&mut self,
sender: ToUISender<Vec<u8>>,
bridge_id: usize,
bridge: Arc<RenderWindow>,
draw_list: DrawList,
) {
let (task, receiver) = RenderTask::new(bridge_id, bridge, draw_list);
self.push_task((receiver, task));
let task = RenderTask::new(bridge_id, sender, bridge, draw_list);
self.push_task(task);
}
pub fn clear(&mut self) {
@ -46,39 +47,18 @@ impl RenderTasks {
let futures: Vec<_> = self
.tasks
.iter()
.map(|(_, task)| async {
.map(|task| async {
info!("Drawing task");
task.draw().await;
})
.collect();
info!("all tasks: {:?}", futures.len());
futures::future::join_all(futures).await;
}
pub async fn listen(&mut self, manager: AllBuffers) {
let mut futures = Vec::new();
for (receiver, _) in self.tasks.iter_mut() {
let manager = manager.lock().unwrap();
let buffer = manager.get(&0).unwrap().clone();
let future = async move {
while let Some(data) = receiver.recv().await {
let mut buffer = buffer.lock().await;
info!("Received data");
buffer.copy_from_slice(&data);
}
};
futures.push(Box::pin(future));
}
futures::future::join_all(futures).await;
}
}
pub struct RenderTask {
// bridge: element_bridge::TextureBridge,
bridge_id: usize,
sender: tokio::sync::mpsc::Sender<Vec<u8>>,
sender: ToUISender<Vec<u8>>,
buffer: Arc<Mutex<Vec<u8>>>,
render_window: Arc<RenderWindow>,
draw_list: DrawList,
@ -87,20 +67,17 @@ pub struct RenderTask {
impl RenderTask {
pub fn new(
bridge_id: usize,
sender: ToUISender<Vec<u8>>,
bridge_render_window: Arc<RenderWindow>,
draw_list: DrawList,
) -> (Self, tokio::sync::mpsc::Receiver<Vec<u8>>) {
let (sender, receiver) = tokio::sync::mpsc::channel(1);
(
) -> Self {
Self {
bridge_id,
sender,
buffer: Arc::new(Mutex::new(vec![0u8; 256 * 256 * 4])),
render_window: bridge_render_window,
draw_list,
},
receiver,
)
}
}
pub async fn draw(&self) {
@ -109,15 +86,8 @@ impl RenderTask {
.await;
let ctx = GIAPP.ctx();
TextureBridge::load_data(self.buffer.clone(), ctx, &self.render_window).await;
let bf = {
let buffer = self.buffer.clone();
let buffer = buffer.lock().unwrap();
buffer.clone()
};
self.sender.send(bf).await.unwrap();
let mut bf = Vec::with_capacity(256 * 256 * 4);
TextureBridge::load_data(&mut bf, ctx, &self.render_window).await;
self.sender.send(bf).unwrap();
}
}

View File

@ -3,8 +3,9 @@ use std::sync::Arc;
use std::sync::Mutex;
use crate::windows_manager::WindowId;
use crate::windows_manager::WindowsManager;
use crate::windows_manager::WM;
use crate::GIAPP;
use ::log::info;
use element_bridge::{TextureBridge, Window};
use makepad_widgets::makepad_derive_widget::*;
use makepad_widgets::makepad_draw::*;
@ -26,10 +27,18 @@ pub struct TArea {
#[layout]
layout: Layout,
#[live]
time: f32,
id: String,
#[live]
min_width: i64,
#[live]
min_height: i64,
#[live(1.0)]
width_scale: f64,
#[rust]
bridge: Option<Arc<Mutex<TextureBridge>>>,
#[rust]
windows: WM,
}
#[derive(Debug, Clone)]
@ -104,33 +113,28 @@ impl Widget for TArea {
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {}
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
self.draw.begin(cx, walk, self.layout);
self.draw.end(cx);
DrawStep::done()
}
}
impl TArea {
fn set_bridge(&mut self, bridge: Arc<Mutex<TextureBridge>>) {
self.bridge = Some(bridge);
self.draw
.draw_vars
.set_texture(0, self.bridge.as_ref().unwrap().lock().unwrap().texture());
}
fn init_bridge(&mut self, cx: &mut Cx, manager: &mut WindowsManager) {
let window_id = WindowId::new("Primary");
// let height = self.walk.height.
// let width = self.walk.width.fixed_or_zero();
let height = 256;
let width = 256;
let rect = cx.peek_walk_turtle(walk);
let current_size = rect.size;
let current_texture = self.get_texture();
// If the texture is not created or the size is different, recreate the texture
if current_texture.is_none()
|| current_texture
.unwrap()
.get_format(cx)
.vec_width_height()
.map(|(w, h)| (w as f64, h as f64))
!= Some((current_size.x, current_size.y))
{
let window_id = WindowId::new(&self.id);
let (width, height) = (current_size.x, current_size.y);
let dpi = cx.current_dpi_factor();
let window = Window {
height: height as u32,
width: width as u32,
};
info!("Creating texture for window: {:?}", window_id);
let texture = Texture::new_with_format(
cx,
TextureFormat::VecRGBAf32 {
@ -140,18 +144,34 @@ impl TArea {
updated: TextureUpdated::Full,
},
);
let bridge = TextureBridge::new(texture, &GIAPP, window);
let (_, bridge) = manager.add_window(window_id, bridge);
let mut windows = self.windows.wm();
let (_, bridge) = windows.add_window(window_id, bridge);
self.bridge = Some(bridge);
}
self.set_bridge(bridge);
self.draw.draw_walk(cx, walk);
DrawStep::done()
}
}
impl TArea {
fn get_texture(&self) -> Option<Texture> {
self.bridge
.as_ref()
.map(|bridge| bridge.lock().unwrap().texture().clone())
}
fn set_windows(&mut self, windows: WM) {
info!("Setting windows for area: {}", self.id);
self.windows = windows;
}
}
impl TAreaRef {
pub fn init_bridge(&self, cx: &mut Cx, manager: &mut WindowsManager) {
if let Some(mut bridge) = self.borrow_mut() {
bridge.init_bridge(cx, manager);
pub fn set_windows(&self, windows: WM) {
if let Some(mut area) = self.borrow_mut() {
area.set_windows(windows);
}
}
}

View File

@ -1,2 +1,3 @@
pub mod area;
pub mod renderer;
pub mod selector_modal;

View File

@ -0,0 +1,44 @@
use makepad_widgets::*;
live_design! {
import makepad_widgets::base::*;
import makepad_widgets::theme_desktop_dark::*;
SelectorModal = <Modal> {
content: {
height: 600,
width: 300,
show_bg: true,
draw_bg: {
color: #3c3c3c
}
align: {
x: 0.5,
y: 0.5
}
<RoundedView> {
show_bg: true,
draw_bg: {
color: #3c3c3c
radius: 3.0
}
notifacion_title = <Label> {
text: "Notification"
}
notification_message = <Label> {
width: 170
}
close_popup_button = <Button> {
width: Fit,
height: Fit,
margin: {top: -20 },
icon_walk: {width: 10, height: 10}
}
}
}
}
}

View File

@ -1,13 +1,13 @@
use std::{
collections::HashMap,
sync::{Arc, Mutex},
sync::{Arc, Mutex, MutexGuard},
};
use element_bridge::TextureBridge;
pub type AllBuffers = Arc<Mutex<HashMap<usize, Arc<tokio::sync::Mutex<Vec<u8>>>>>>;
#[derive(Eq, Hash, PartialEq)]
#[derive(Eq, Hash, PartialEq, Debug)]
pub struct WindowId {
id: u64,
name: String,
@ -30,13 +30,27 @@ impl WindowsManager {
}
}
pub fn edit_window<F>(&mut self, id: WindowId, f: F) -> (usize, Arc<Mutex<TextureBridge>>)
where
F: FnOnce(&mut TextureBridge),
{
let bridge = self.inner.get(&id).unwrap();
let mut _bridge = bridge.lock().unwrap();
f(&mut _bridge);
(0, bridge.clone())
}
pub fn add_window(
&mut self,
id: WindowId,
bridge: TextureBridge,
) -> (usize, Arc<Mutex<TextureBridge>>) {
let bridge = Arc::new(Mutex::new(bridge));
self.inner.insert(id, bridge.clone());
// New window
self.inner
.entry(id)
.and_modify(|e| *e = bridge.clone())
.or_insert(bridge.clone());
let new_id = self.all_bridges.len();
self.all_bridges.push((new_id, bridge.clone()));
@ -45,12 +59,11 @@ impl WindowsManager {
let bridge = bridge.lock().unwrap();
bridge.buffer()
};
// self.all_revelant_buffers.push((new_id, buffer));
self.all_revelant_buffers
.lock()
.unwrap()
.insert(new_id, buffer);
(new_id, bridge)
}
@ -71,3 +84,20 @@ impl WindowId {
}
}
}
#[derive(Clone, Default)]
pub struct WM(Arc<std::sync::Mutex<WindowsManager>>);
impl WM {
pub fn new() -> Self {
Self(Arc::new(std::sync::Mutex::new(WindowsManager::new())))
}
pub fn windows_manager(&self) -> Arc<std::sync::Mutex<WindowsManager>> {
self.0.clone()
}
pub fn wm(&self) -> MutexGuard<'_, WindowsManager> {
self.0.lock().unwrap()
}
}

View File

@ -160,11 +160,13 @@ impl App {
}
}
#[derive(Debug)]
pub struct Window {
pub width: u32,
pub height: u32,
}
#[derive(Debug)]
pub struct RenderWindow {
_texture: wgpu::Texture,
_texture_size: wgpu::Extent3d,
@ -256,7 +258,7 @@ impl Ctx {
}
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct DrawList {
pub elements: Vec<(std::sync::Arc<ElementAttach>, Elements)>, // 修复字段访问权限
}
@ -383,6 +385,7 @@ impl BufferKey {
}
}
#[derive(Debug)]
pub struct Output {
pub output_buffer: wgpu::Buffer,
}

View File

@ -11,7 +11,7 @@ use wgpu::util::DeviceExt;
macro_rules! elements {
($(($element_name:ident,$element: ty),)+) => {
#[derive(Clone)]
#[derive(Clone,Debug)]
pub enum Elements {
$($element_name(Arc<$element>),)+
}
@ -66,6 +66,18 @@ macro_rules! elements {
$(Elements::$element_name(element) => element.draw(attach, render_pass),)+
}
}
pub fn name(&self) -> &'static str {
match self {
$(Elements::$element_name(_) => <$element>::NAME,)+
}
}
pub fn desc(&self) -> &'static str {
match self {
$(Elements::$element_name(_) => <$element>::DESC,)+
}
}
}
impl<'a> ElementsRef<'a> {
@ -104,9 +116,11 @@ pub trait Element {
type Vertex;
type Uniform;
type Data;
type Config;
const NAME: &'static str;
const DESC: &'static str;
fn new(ctx: &Ctx) -> Self;
// fn new_attachment<'a>(&self, ctx: &Ctx) -> ElementAttach;
@ -131,6 +145,7 @@ pub trait Element {
) -> ElementAttach;
}
#[derive(Debug)]
pub struct ElementAttach {
pub vertex_buffer: wgpu::Buffer,
pub index_buffer: Option<wgpu::Buffer>,

View File

@ -17,6 +17,7 @@ const EMAXNUM: u64 = 50;
const AMAXNUM: u64 = 360;
const RMAXNUM: u64 = 50;
#[derive(Debug)]
pub struct PPI {
bind_group_layout: wgpu::BindGroupLayout,
pipeline: wgpu::RenderPipeline,
@ -75,6 +76,9 @@ impl Element for PPI {
type Config = PPIConfig;
const NAME: &'static str = "PPI";
const DESC: &'static str = "To Draw PPI";
fn new(ctx: &Ctx) -> Self {
let device = &ctx.device;

View File

@ -1,5 +1,7 @@
use crate::app::Ctx;
use crate::elements::Elements;
use crate::elements::*;
use mp_core::{Data, DataValue};
use std::sync::Arc;
macro_rules! elementvec {
($({$element: ident, $element_ty: ty, $element_mut: ident})+) => {
@ -18,6 +20,19 @@ macro_rules! elementvec {
&self.$element
})+
pub fn supported_elements(&self, data: &Data) -> Vec<Elements>{
let mut results = Vec::new();
$(
if let Ok(data) = data.try_into() {
if self.$element.supports(data) {
let elements = self.$element().clone();
results.push(elements.into());
}
}
)+
return results;
}
}
};

View File

@ -1,5 +1,6 @@
use wgpu::util::DeviceExt;
#[derive(Debug)]
pub struct ColorMap {
uniform: ColorMapUniform,
uniform_buffer: wgpu::Buffer,