|
@@ -18,15 +18,19 @@
|
|
|
|
|
|
|
|
use async_trait::async_trait;
|
|
use async_trait::async_trait;
|
|
|
use futures::stream::{FuturesUnordered, StreamExt};
|
|
use futures::stream::{FuturesUnordered, StreamExt};
|
|
|
|
|
+use log::{log_enabled, Level::Trace};
|
|
|
use miniquad::{KeyCode, KeyMods, MouseButton, TouchPhase};
|
|
use miniquad::{KeyCode, KeyMods, MouseButton, TouchPhase};
|
|
|
-use std::sync::{Arc, Weak};
|
|
|
|
|
|
|
+use std::{
|
|
|
|
|
+ fmt::Debug,
|
|
|
|
|
+ sync::{Arc, Weak},
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
use crate::{
|
|
use crate::{
|
|
|
error::{Error, Result},
|
|
error::{Error, Result},
|
|
|
expr::{SExprMachine, SExprVal},
|
|
expr::{SExprMachine, SExprVal},
|
|
|
gfx::{GfxBufferId, GfxDrawCall, GfxDrawMesh, GfxTextureId, Point, Rectangle},
|
|
gfx::{GfxBufferId, GfxDrawCall, GfxDrawMesh, GfxTextureId, Point, Rectangle},
|
|
|
prop::{ModifyAction, PropertyPtr, Role},
|
|
prop::{ModifyAction, PropertyPtr, Role},
|
|
|
- scene::{Pimpl, SceneNode as SceneNode3, SceneNodeId, SceneNodePtr},
|
|
|
|
|
|
|
+ scene::{Pimpl, SceneNode as SceneNode3, SceneNodeId, SceneNodePtr, SceneNodeWeak},
|
|
|
ExecutorPtr,
|
|
ExecutorPtr,
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -56,6 +60,9 @@ pub use text::{Text, TextPtr};
|
|
|
mod win;
|
|
mod win;
|
|
|
pub use win::{Window, WindowPtr};
|
|
pub use win::{Window, WindowPtr};
|
|
|
|
|
|
|
|
|
|
+macro_rules! e { ($($arg:tt)*) => { error!(target: "scene::on_modify", $($arg)*); } }
|
|
|
|
|
+macro_rules! t { ($($arg:tt)*) => { trace!(target: "scene::on_modify", $($arg)*); } }
|
|
|
|
|
+
|
|
|
#[async_trait]
|
|
#[async_trait]
|
|
|
pub trait UIObject: Sync {
|
|
pub trait UIObject: Sync {
|
|
|
fn priority(&self) -> u32;
|
|
fn priority(&self) -> u32;
|
|
@@ -107,45 +114,41 @@ pub struct DrawUpdate {
|
|
|
|
|
|
|
|
pub struct OnModify<T> {
|
|
pub struct OnModify<T> {
|
|
|
ex: ExecutorPtr,
|
|
ex: ExecutorPtr,
|
|
|
- node_name: String,
|
|
|
|
|
- node_id: SceneNodeId,
|
|
|
|
|
|
|
+ node: SceneNodeWeak,
|
|
|
me: Weak<T>,
|
|
me: Weak<T>,
|
|
|
pub tasks: Vec<smol::Task<()>>,
|
|
pub tasks: Vec<smol::Task<()>>,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl<T: Send + Sync + 'static> OnModify<T> {
|
|
impl<T: Send + Sync + 'static> OnModify<T> {
|
|
|
- pub fn new(ex: ExecutorPtr, node_name: String, node_id: SceneNodeId, me: Weak<T>) -> Self {
|
|
|
|
|
- Self { ex, node_name, node_id, me, tasks: vec![] }
|
|
|
|
|
|
|
+ pub fn new(ex: ExecutorPtr, node: SceneNodeWeak, me: Weak<T>) -> Self {
|
|
|
|
|
+ Self { ex, node, me, tasks: vec![] }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
pub fn when_change<F>(&mut self, prop: PropertyPtr, f: impl Fn(Arc<T>) -> F + Send + 'static)
|
|
pub fn when_change<F>(&mut self, prop: PropertyPtr, f: impl Fn(Arc<T>) -> F + Send + 'static)
|
|
|
where
|
|
where
|
|
|
F: std::future::Future<Output = ()> + Send + 'static,
|
|
F: std::future::Future<Output = ()> + Send + 'static,
|
|
|
{
|
|
{
|
|
|
- let node_name = self.node_name.clone();
|
|
|
|
|
- let node_id = self.node_id;
|
|
|
|
|
-
|
|
|
|
|
- let mut on_modify_subs = vec![(None, prop.subscribe_modify())];
|
|
|
|
|
|
|
+ let mut on_modify_subs = vec![(Arc::downgrade(&prop), None, prop.subscribe_modify())];
|
|
|
for dep in prop.get_depends() {
|
|
for dep in prop.get_depends() {
|
|
|
let Some(dep_prop) = dep.prop.upgrade() else { continue };
|
|
let Some(dep_prop) = dep.prop.upgrade() else { continue };
|
|
|
- on_modify_subs.push((Some(dep.i), dep_prop.subscribe_modify()));
|
|
|
|
|
|
|
+ on_modify_subs.push((dep.prop, Some(dep.i), dep_prop.subscribe_modify()));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- let prop_name = prop.name.clone();
|
|
|
|
|
let me = self.me.clone();
|
|
let me = self.me.clone();
|
|
|
|
|
+ let node = self.node.clone();
|
|
|
let task = self.ex.spawn(async move {
|
|
let task = self.ex.spawn(async move {
|
|
|
loop {
|
|
loop {
|
|
|
let mut poll_queues = FuturesUnordered::new();
|
|
let mut poll_queues = FuturesUnordered::new();
|
|
|
- for (i, (prop_i, on_modify_sub)) in on_modify_subs.iter().enumerate() {
|
|
|
|
|
|
|
+ for (i, (prop_weak, prop_i, on_modify_sub)) in on_modify_subs.iter().enumerate() {
|
|
|
let recv = on_modify_sub.receive();
|
|
let recv = on_modify_sub.receive();
|
|
|
poll_queues.push(async move {
|
|
poll_queues.push(async move {
|
|
|
let (role, action) = recv.await.ok()?;
|
|
let (role, action) = recv.await.ok()?;
|
|
|
- Some((i, prop_i, role, action))
|
|
|
|
|
|
|
+ Some((i, prop_weak, prop_i, role, action))
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- let Some(Some((idx, prop_i, role, action))) = poll_queues.next().await else {
|
|
|
|
|
- error!(target: "app", "Property '{}':{}/'{}' on_modify pipe is broken", node_name, node_id, prop_name);
|
|
|
|
|
|
|
+ let Some(Some((idx, prop_weak, prop_i, role, action))) = poll_queues.next().await else {
|
|
|
|
|
+ e!("Property {:?} on_modify pipe is broken", prop);
|
|
|
return
|
|
return
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -161,14 +164,19 @@ impl<T: Send + Sync + 'static> OnModify<T> {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- trace!(target: "app", "Property '{}':{}/'{}' modified", node_name, node_id, prop_name);
|
|
|
|
|
|
|
+ if (idx == 0) {
|
|
|
|
|
+ t!("Property {:?} modified [depend_idx={idx}, role={role:?}]", prop);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ t!(
|
|
|
|
|
+ "Property {:?} modified -> triggering {:?} [depend_idx={idx}, role={role:?}]",
|
|
|
|
|
+ prop_weak.upgrade().unwrap(),
|
|
|
|
|
+ prop
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
let Some(self_) = me.upgrade() else {
|
|
let Some(self_) = me.upgrade() else {
|
|
|
// Should not happen
|
|
// Should not happen
|
|
|
- panic!(
|
|
|
|
|
- "'{}':{}/'{}' self destroyed before modify_task was stopped!",
|
|
|
|
|
- node_name, node_id, prop_name
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ panic!("{:?} self destroyed before modify_task was stopped!", prop);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
//debug!(target: "app", "property modified");
|
|
//debug!(target: "app", "property modified");
|