sync
This commit is contained in:
parent
1641585177
commit
d9b8c8f666
41
Cargo.lock
generated
41
Cargo.lock
generated
@ -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",
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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"
|
||||
|
||||
214
mp/src/app.rs
214
mp/src/app.rs
@ -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 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 render_task = render_tasks.lock().await;
|
||||
render_task.render().await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_background(app: &mut App, event: &Event) {
|
||||
match event {
|
||||
Event::Draw(_) => {
|
||||
// Render Task
|
||||
|
||||
info!("Starting background task......");
|
||||
let tasks = app.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;
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
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);
|
||||
|
||||
@ -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
22
mp/src/errors.rs
Normal 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
76
mp/src/file.rs
Normal 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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
31
mp/src/menu.rs
Normal 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;
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
bridge_id,
|
||||
sender,
|
||||
buffer: Arc::new(Mutex::new(vec![0u8; 256 * 256 * 4])),
|
||||
render_window: bridge_render_window,
|
||||
draw_list,
|
||||
},
|
||||
receiver,
|
||||
)
|
||||
) -> Self {
|
||||
Self {
|
||||
bridge_id,
|
||||
sender,
|
||||
buffer: Arc::new(Mutex::new(vec![0u8; 256 * 256 * 4])),
|
||||
render_window: bridge_render_window,
|
||||
draw_list,
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,54 +113,65 @@ 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);
|
||||
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 {
|
||||
width: window.width as usize,
|
||||
height: window.height as usize,
|
||||
data: None,
|
||||
updated: TextureUpdated::Full,
|
||||
},
|
||||
);
|
||||
let bridge = TextureBridge::new(texture, &GIAPP, window);
|
||||
let mut windows = self.windows.wm();
|
||||
let (_, bridge) = windows.add_window(window_id, bridge);
|
||||
self.bridge = Some(bridge);
|
||||
}
|
||||
|
||||
self.draw.draw_walk(cx, walk);
|
||||
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 get_texture(&self) -> Option<Texture> {
|
||||
self.bridge
|
||||
.as_ref()
|
||||
.map(|bridge| bridge.lock().unwrap().texture().clone())
|
||||
}
|
||||
|
||||
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 window = Window {
|
||||
height: height as u32,
|
||||
width: width as u32,
|
||||
};
|
||||
|
||||
let texture = Texture::new_with_format(
|
||||
cx,
|
||||
TextureFormat::VecRGBAf32 {
|
||||
width: window.width as usize,
|
||||
height: window.height as usize,
|
||||
data: None,
|
||||
updated: TextureUpdated::Full,
|
||||
},
|
||||
);
|
||||
|
||||
let bridge = TextureBridge::new(texture, &GIAPP, window);
|
||||
let (_, bridge) = manager.add_window(window_id, bridge);
|
||||
|
||||
self.set_bridge(bridge);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
pub mod area;
|
||||
pub mod renderer;
|
||||
pub mod selector_modal;
|
||||
|
||||
44
mp/src/widgets/selector_modal.rs
Normal file
44
mp/src/widgets/selector_modal.rs
Normal 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}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
}
|
||||
|
||||
@ -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>,
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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})+) => {
|
||||
@ -14,10 +16,23 @@ macro_rules! elementvec {
|
||||
}
|
||||
}
|
||||
|
||||
$(pub fn $element(&self) -> &Arc< $element_ty> {
|
||||
$(pub fn $element(&self) -> &Arc<$element_ty> {
|
||||
&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;
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use wgpu::util::DeviceExt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ColorMap {
|
||||
uniform: ColorMapUniform,
|
||||
uniform_buffer: wgpu::Buffer,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user