refactor: begin conversion to bevy, do proper frame wait
Signed-off-by: Schmarni <marnistromer@gmail.com>
This commit is contained in:
@@ -6,122 +6,117 @@ use crate::core::registry::Registry;
|
||||
use crate::core::resource::get_resource_file;
|
||||
use crate::nodes::alias::{Alias, AliasList};
|
||||
use crate::nodes::spatial::Spatial;
|
||||
use crate::nodes::Node;
|
||||
use crate::nodes::{Aspect, Node};
|
||||
use crate::DefaultMaterial;
|
||||
use bevy::app::Plugin;
|
||||
use bevy::asset::Handle;
|
||||
use bevy::color::{Alpha, Color, LinearRgba, Srgba};
|
||||
use bevy::prelude::AlphaMode;
|
||||
use bevy::reflect::{GetField, PartialReflect, Reflect};
|
||||
use color_eyre::eyre::eyre;
|
||||
use glam::{Mat4, Vec2, Vec3};
|
||||
use once_cell::sync::{Lazy, OnceCell};
|
||||
use parking_lot::Mutex;
|
||||
use rustc_hash::FxHashMap;
|
||||
use stardust_xr::values::ResourceID;
|
||||
use tracing::warn;
|
||||
|
||||
use std::ffi::OsStr;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::ops::Deref;
|
||||
use std::sync::{Arc, Weak};
|
||||
use stereokit_rust::material::Transparency;
|
||||
use stereokit_rust::maths::Bounds;
|
||||
use stereokit_rust::sk::MainThreadToken;
|
||||
use stereokit_rust::{material::Material, model::Model as SKModel, tex::Tex, util::Color128};
|
||||
|
||||
pub struct MaterialWrapper(pub Material);
|
||||
impl Hash for MaterialWrapper {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.get_shader().0.as_ptr().hash(state);
|
||||
for param in self.0.get_all_param_info() {
|
||||
param.to_string().hash(state)
|
||||
}
|
||||
self.0.get_chain().map(MaterialWrapper).hash(state)
|
||||
}
|
||||
}
|
||||
impl PartialEq for MaterialWrapper {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
if self.0.get_shader().0.as_ptr() != other.0.get_shader().0.as_ptr() {
|
||||
return false;
|
||||
}
|
||||
if self.0.get_all_param_info().count() != other.0.get_all_param_info().count() {
|
||||
return false;
|
||||
}
|
||||
for self_param in self.0.get_all_param_info() {
|
||||
let Some(other_param) = other
|
||||
.0
|
||||
.get_all_param_info()
|
||||
.get_data(self_param.get_name(), self_param.get_type())
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
if self_param.to_string() != other_param.to_string() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
self.0.get_chain().map(MaterialWrapper) == other.0.get_chain().map(MaterialWrapper)
|
||||
}
|
||||
}
|
||||
impl Eq for MaterialWrapper {}
|
||||
unsafe impl Send for MaterialWrapper {}
|
||||
unsafe impl Sync for MaterialWrapper {}
|
||||
|
||||
#[derive(Default)]
|
||||
struct MaterialRegistry(Mutex<FxHashMap<u64, String>>);
|
||||
impl MaterialRegistry {
|
||||
fn add_or_get(&self, material: Arc<MaterialWrapper>) -> Arc<MaterialWrapper> {
|
||||
let mut lock = self.0.lock();
|
||||
let hash = {
|
||||
use std::hash::{Hash, Hasher};
|
||||
let mut hasher = std::collections::hash_map::DefaultHasher::new();
|
||||
material.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
|
||||
if let Some(id) = lock.get(&hash) {
|
||||
if let Ok(existing) = Material::find(id) {
|
||||
return Arc::new(MaterialWrapper(existing));
|
||||
}
|
||||
}
|
||||
|
||||
lock.insert(hash, material.0.get_id().to_string());
|
||||
material
|
||||
}
|
||||
}
|
||||
|
||||
static MATERIAL_REGISTRY: Lazy<MaterialRegistry> = Lazy::new(MaterialRegistry::default);
|
||||
static MODEL_REGISTRY: Registry<Model> = Registry::new();
|
||||
static HOLDOUT_MATERIAL: OnceCell<Arc<MaterialWrapper>> = OnceCell::new();
|
||||
static HOLDOUT_MATERIAL: OnceCell<Arc<DefaultMaterial>> = OnceCell::new();
|
||||
|
||||
impl MaterialParameter {
|
||||
fn apply_to_material(&self, client: &Client, material: &Material, parameter_name: &str) {
|
||||
let mut params = material.get_all_param_info();
|
||||
fn apply_to_material(
|
||||
&self,
|
||||
client: &Client,
|
||||
material: &mut DefaultMaterial,
|
||||
parameter_name: &str,
|
||||
) {
|
||||
match self {
|
||||
MaterialParameter::Bool(val) => {
|
||||
params.set_bool(parameter_name, *val);
|
||||
}
|
||||
MaterialParameter::Int(val) => {
|
||||
params.set_int(parameter_name, &[*val]);
|
||||
}
|
||||
MaterialParameter::UInt(val) => {
|
||||
params.set_uint(parameter_name, &[*val]);
|
||||
}
|
||||
MaterialParameter::Float(val) => {
|
||||
params.set_float(parameter_name, *val);
|
||||
}
|
||||
MaterialParameter::Vec2(val) => {
|
||||
params.set_vec2(parameter_name, Vec2::from(*val));
|
||||
}
|
||||
MaterialParameter::Vec3(val) => {
|
||||
params.set_vec3(parameter_name, Vec3::from(*val));
|
||||
}
|
||||
MaterialParameter::Color(val) => {
|
||||
params.set_color(
|
||||
parameter_name,
|
||||
Color128::new(val.c.r, val.c.g, val.c.b, val.a),
|
||||
);
|
||||
}
|
||||
MaterialParameter::Bool(val) => match parameter_name {
|
||||
name => {
|
||||
if let Some(field) = material.get_field_mut::<bool>(name) {
|
||||
*field = *val;
|
||||
} else {
|
||||
warn!("unknown bool material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
},
|
||||
MaterialParameter::Int(val) => match parameter_name {
|
||||
name => {
|
||||
if let Some(field) = material.get_field_mut::<i32>(name) {
|
||||
*field = *val;
|
||||
} else {
|
||||
warn!("unknown bool material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
},
|
||||
MaterialParameter::UInt(val) => match parameter_name {
|
||||
name => {
|
||||
if let Some(field) = material.get_field_mut::<u32>(name) {
|
||||
*field = *val;
|
||||
} else {
|
||||
warn!("unknown bool material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
},
|
||||
MaterialParameter::Float(val) => match parameter_name {
|
||||
name => {
|
||||
if let Some(field) = material.get_field_mut::<f32>(name) {
|
||||
*field = *val;
|
||||
} else {
|
||||
warn!("unknown bool material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
},
|
||||
MaterialParameter::Vec2(val) => match parameter_name {
|
||||
name => {
|
||||
if let Some(field) = material.get_field_mut::<Vec2>(name) {
|
||||
*field = (*val).into();
|
||||
} else {
|
||||
warn!("unknown bool material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
},
|
||||
MaterialParameter::Vec3(val) => match parameter_name {
|
||||
name => {
|
||||
if let Some(field) = material.get_field_mut::<Vec3>(name) {
|
||||
*field = (*val).into();
|
||||
} else {
|
||||
warn!("unknown bool material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
},
|
||||
MaterialParameter::Color(val) => match parameter_name {
|
||||
"color" => {
|
||||
material.base_color = LinearRgba::new(val.c.r, val.c.g, val.c.b, val.a).into()
|
||||
}
|
||||
name => {
|
||||
if let Some(field) = material.get_field_mut::<Color>(name) {
|
||||
*field = LinearRgba::new(val.c.r, val.c.g, val.c.b, val.a).into();
|
||||
} else {
|
||||
warn!("unknown bool material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
},
|
||||
MaterialParameter::Texture(resource) => {
|
||||
match parameter_name {
|
||||
name => {
|
||||
warn!("unknown texture material parameter name: {name}");
|
||||
}
|
||||
}
|
||||
let Some(texture_path) =
|
||||
get_resource_file(resource, client, &[OsStr::new("png"), OsStr::new("jpg")])
|
||||
else {
|
||||
return;
|
||||
};
|
||||
if let Ok(tex) = Tex::from_file(texture_path, true, None) {
|
||||
params.set_texture(parameter_name, &tex);
|
||||
}
|
||||
// if let Ok(tex) = Tex::from_file(texture_path, true, None) {
|
||||
// params.set_texture(parameter_name, &tex);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,16 +128,26 @@ pub struct ModelPart {
|
||||
space: Arc<Spatial>,
|
||||
model: Weak<Model>,
|
||||
pending_material_parameters: Mutex<FxHashMap<String, MaterialParameter>>,
|
||||
pending_material_replacement: Mutex<Option<Arc<MaterialWrapper>>>,
|
||||
pending_material_replacement: Mutex<Option<Arc<Handle<DefaultMaterial>>>>,
|
||||
aliases: AliasList,
|
||||
}
|
||||
|
||||
pub struct StardustModelPlugin;
|
||||
impl Plugin for StardustModelPlugin {
|
||||
fn build(&self, app: &mut bevy::prelude::App) {}
|
||||
}
|
||||
|
||||
impl ModelPart {
|
||||
fn create_for_model(model: &Arc<Model>, sk_model: &SKModel) {
|
||||
// The value isn't even used?!
|
||||
HOLDOUT_MATERIAL.get_or_init(|| {
|
||||
let mut mat = Material::copy(&Material::unlit());
|
||||
mat.transparency(Transparency::None);
|
||||
mat.color_tint(Color128::BLACK_TRANSPARENT);
|
||||
Arc::new(MaterialWrapper(mat))
|
||||
let mut mat = DefaultMaterial {
|
||||
unlit: true,
|
||||
alpha_mode: AlphaMode::Opaque,
|
||||
base_color: Srgba::BLACK.with_alpha(0.0).into(),
|
||||
..Default::default()
|
||||
};
|
||||
Arc::new(mat)
|
||||
});
|
||||
|
||||
let nodes = sk_model.get_nodes();
|
||||
@@ -307,7 +312,7 @@ impl ModelPartAspect for ModelPart {
|
||||
pub struct Model {
|
||||
space: Arc<Spatial>,
|
||||
_resource_id: ResourceID,
|
||||
sk_model: OnceCell<SKModel>,
|
||||
sk_model: OnceCell<()>,
|
||||
parts: Mutex<Vec<Arc<ModelPart>>>,
|
||||
}
|
||||
impl Model {
|
||||
|
||||
Reference in New Issue
Block a user