Skip to content

Commit

Permalink
Rename model_def to model_from_url. Fixes #68
Browse files Browse the repository at this point in the history
  • Loading branch information
FredrikNoren committed Feb 13, 2023
1 parent cafd188 commit 88ac71c
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 57 deletions.
17 changes: 11 additions & 6 deletions crates/animation/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use std::{
collections::HashMap, sync::Arc, time::{Duration, SystemTime}
collections::HashMap,
sync::Arc,
time::{Duration, SystemTime},
};

use convert_case::{Case, Casing};
use derive_more::Display;
use kiwi_core::{asset_cache, hierarchy::children, time};
use kiwi_ecs::{components, query, Debuggable, EntityId, MakeDefault, Networked, Store, SystemGroup};
use kiwi_model::{animation_binder, model, model_def, ModelDef};
use kiwi_model::{animation_binder, model, model_from_url, ModelFromUrl};
use kiwi_std::{
asset_cache::{AssetCache, AsyncAssetKeyExt}, asset_url::{AnimationAssetType, ModelAssetType, TypedAssetUrl}
asset_cache::{AssetCache, AsyncAssetKeyExt},
asset_url::{AnimationAssetType, ModelAssetType, TypedAssetUrl},
};
use kiwi_ui::Editable;
use serde::{Deserialize, Serialize};
Expand All @@ -28,7 +31,7 @@ components!("animation", {
/// the animations base pose, so we apply the pose from the animations model to make sure they
/// correspond
@[Debuggable, Networked, Store]
animation_apply_base_pose: ModelDef,
animation_apply_base_pose: ModelFromUrl,
@[Debuggable, Networked, Store]
copy_animation_controller_to_children: (),
@[Debuggable, Networked, Store]
Expand Down Expand Up @@ -176,7 +179,9 @@ pub fn animation_systems() -> SystemGroup {
if ctrlr.apply_base_pose {
if let Some(action) = ctrlr.actions.get(0) {
if let AnimationClipRef::FromModelAsset(def) = &action.clip {
world.add_component(id, animation_apply_base_pose(), ModelDef(def.model_crate().unwrap().model())).unwrap();
world
.add_component(id, animation_apply_base_pose(), ModelFromUrl(def.model_crate().unwrap().model()))
.unwrap();
}
}
}
Expand All @@ -203,7 +208,7 @@ pub fn animation_systems() -> SystemGroup {
let mut in_error = Vec::new();
for (id, (controller, binder)) in q.iter(world, qs) {
let retaget = world.get(id, animation_retargeting()).unwrap_or(AnimationRetargeting::None);
let model = world.get_ref(id, model_def()).map(|def| def.0.clone()).ok();
let model = world.get_ref(id, model_from_url()).ok().and_then(|def| Some(TypedAssetUrl::parse(def).ok()?));
// Calc
for action in controller.actions.iter() {
match action.clip.get_clip(assets.clone(), retaget, model.clone()) {
Expand Down
10 changes: 6 additions & 4 deletions crates/animation/src/retargeting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ use anyhow::Context;
use async_trait::async_trait;
use kiwi_core::transform::{rotation, translation};
use kiwi_editor_derive::ElementEditor;
use kiwi_model::{Model, ModelDef};
use kiwi_model::{Model, ModelFromUrl};
use kiwi_std::{
asset_cache::{AssetCache, AssetKeepalive, AsyncAssetKey, AsyncAssetKeyExt, SyncAssetKeyExt}, asset_url::{AnimationAssetType, ModelAssetType, ServerBaseUrlKey, TypedAssetUrl}, download_asset::AssetError
asset_cache::{AssetCache, AssetKeepalive, AsyncAssetKey, AsyncAssetKeyExt, SyncAssetKeyExt},
asset_url::{AnimationAssetType, ModelAssetType, ServerBaseUrlKey, TypedAssetUrl},
download_asset::AssetError,
};
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -50,7 +52,7 @@ impl AsyncAssetKey<Result<Arc<AnimationClip>, AssetError>> for AnimationClipReta
let base_url = ServerBaseUrlKey.get(&assets);
let clip_url: TypedAssetUrl<AnimationAssetType> = self.clip.resolve(&base_url).context("Failed to resolve clip url")?.into();
let anim_model =
ModelDef(clip_url.model_crate().context("Invalid clip url")?.model()).get(&assets).await.context("Failed to load model")?;
ModelFromUrl(clip_url.model_crate().context("Invalid clip url")?.model()).get(&assets).await.context("Failed to load model")?;
let clip = AnimationClipFromUrl::new(clip_url.unwrap_abs(), true).get(&assets).await.context("No such clip")?;
match self.translation_retargeting {
AnimationRetargeting::None => Ok(clip),
Expand All @@ -65,7 +67,7 @@ impl AsyncAssetKey<Result<Arc<AnimationClip>, AssetError>> for AnimationClipReta
.context("No retarget_model specified")?
.resolve(&base_url)
.context("Failed to resolve retarget url")?;
let retarget_model = ModelDef(retarget_model_url.into()).get(&assets).await.context("Failed to load retarget model")?;
let retarget_model = ModelFromUrl(retarget_model_url.into()).get(&assets).await.context("Failed to load retarget model")?;
let mut clip = (*clip).clone();
let anim_root = anim_model.roots()[0];
let _retarget_root = retarget_model.roots()[0];
Expand Down
59 changes: 38 additions & 21 deletions crates/model/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,31 @@ use futures::StreamExt;
use glam::{vec4, Vec3};
use itertools::Itertools;
use kiwi_core::{
asset_cache, async_ecs::{async_run, AsyncRun}, bounding::{local_bounding_aabb, world_bounding_aabb, world_bounding_sphere}, hierarchy::{children, despawn_recursive}, main_scene, runtime, transform::{get_world_position, inv_local_to_world, local_to_world, mesh_to_world}
asset_cache,
async_ecs::{async_run, AsyncRun},
bounding::{local_bounding_aabb, world_bounding_aabb, world_bounding_sphere},
hierarchy::{children, despawn_recursive},
main_scene, runtime,
transform::{get_world_position, inv_local_to_world, local_to_world, mesh_to_world},
};
use kiwi_ecs::{
components, query, ComponentDesc, Debuggable, Description, EntityData, EntityId, Name, Networked, Store, SystemGroup, World
components, query, ComponentDesc, Debuggable, Description, EntityData, EntityId, Name, Networked, Store, SystemGroup, World,
};
use kiwi_gpu::mesh_buffer::GpuMeshFromUrl;
use kiwi_renderer::{
color, gpu_primitives, materials::{
flat_material::{get_flat_shader, FlatMaterialKey}, pbr_material::{get_pbr_shader, PbrMaterialFromUrl}
}, primitives, RenderPrimitive, StandardShaderKey
color, gpu_primitives,
materials::{
flat_material::{get_flat_shader, FlatMaterialKey},
pbr_material::{get_pbr_shader, PbrMaterialFromUrl},
},
primitives, RenderPrimitive, StandardShaderKey,
};
use kiwi_std::{
asset_cache::{AssetCache, AsyncAssetKey, AsyncAssetKeyExt, SyncAssetKey, SyncAssetKeyExt}, asset_url::{AbsAssetUrl, AssetUrl, ModelAssetType, ServerBaseUrlKey, TypedAssetUrl}, download_asset::{AssetError, BytesFromUrl, JsonFromUrl}, log_result, math::Line
asset_cache::{AssetCache, AsyncAssetKey, AsyncAssetKeyExt, SyncAssetKey, SyncAssetKeyExt},
asset_url::{AbsAssetUrl, AssetUrl, ModelAssetType, ServerBaseUrlKey, TypedAssetUrl},
download_asset::{AssetError, BytesFromUrl, JsonFromUrl},
log_result,
math::Line,
};
use serde::{Deserialize, Serialize};
mod model;
Expand All @@ -27,6 +39,7 @@ pub use model::*;
use tokio::sync::Semaphore;

use self::loading_material::{LoadingMaterialKey, LoadingShaderKey};
use anyhow::Context;

pub mod loading_material;

Expand All @@ -37,8 +50,8 @@ components!("model", {
animation_bind_id: String,

model: Arc<Model>,
@[Debuggable, Networked, Store]
model_def: ModelDef,
@[Debuggable, Networked, Store, Name["Model from url"], Description["Load a model from the given url or relative path"]]
model_from_url: String,

@[Networked, Store]
pbr_renderer_primitives_from_url: Vec<PbrRenderPrimitiveFromUrl>,
Expand All @@ -59,7 +72,7 @@ components!("model", {
async fn internal_spawn_models_from_defs(
assets: &AssetCache,
async_run: AsyncRun,
entities_with_models: HashMap<String, (ModelDef, Vec<EntityId>)>,
entities_with_models: HashMap<String, Vec<EntityId>>,
) -> anyhow::Result<()> {
// Meanwhile, spawn a spinning cube onto the entity.
let cube = CubeMeshKey.get(assets);
Expand All @@ -84,7 +97,7 @@ async fn internal_spawn_models_from_defs(
.set_default(local_to_world())
.set_default(inv_local_to_world());

let mut ids = entities_with_models.values().flat_map(|v| &v.1).copied().collect_vec();
let mut ids = entities_with_models.values().flatten().copied().collect_vec();

let cube_fail = Arc::new(cube.clone().set(color(), vec4(1.0, 0.0, 0.0, 1.0)));

Expand All @@ -97,9 +110,13 @@ async fn internal_spawn_models_from_defs(
}
});

let iter = entities_with_models.into_values().map(|(k, ids)| async move {
let iter = entities_with_models.into_iter().map(|(k, ids)| async move {
tracing::debug!("Loading model: {k:#?}");
match k.get(assets).await {
let url = match TypedAssetUrl::parse(k).context("Failed to parse url") {
Ok(url) => url,
Err(e) => return (ids, Err(e)),
};
match ModelFromUrl(url).get(assets).await.context("Failed to load model") {
Ok(v) => (ids, Ok(v)),
Err(e) => (ids, Err(e)),
}
Expand Down Expand Up @@ -149,7 +166,7 @@ pub fn model_systems() -> SystemGroup {
SystemGroup::new(
"model_systems",
vec![
query((children(),)).incl(model_def()).despawned().to_system(|q, world, qs, _| {
query((children(),)).incl(model_from_url()).despawned().to_system(|q, world, qs, _| {
for (_, (children,)) in q.collect_cloned(world, qs) {
for c in children {
if world.has_component(c, is_model_node()) {
Expand All @@ -158,16 +175,16 @@ pub fn model_systems() -> SystemGroup {
}
}
}),
query(()).incl(model_def()).despawned().to_system(|q, world, qs, _| {
query(()).incl(model_from_url()).despawned().to_system(|q, world, qs, _| {
for (id, _) in q.collect_cloned(world, qs) {
remove_model(world, id);
}
}),
query((model_def().changed(),)).to_system(|q, world, qs, _| {
let mut new_models = HashMap::new();
query((model_from_url().changed(),)).to_system(|q, world, qs, _| {
let mut new_models = HashMap::<String, Vec<EntityId>>::new();
for (id, (model_from_url,)) in q.iter(world, qs) {
let entry = new_models.entry(format!("{model_from_url:?}")).or_insert_with(|| (model_from_url.clone(), Vec::new()));
entry.1.push(id);
let entry = new_models.entry(model_from_url.clone()).or_default();
entry.push(id);
}
if new_models.is_empty() {
return;
Expand Down Expand Up @@ -207,14 +224,14 @@ fn remove_model(world: &mut World, entity: EntityId) {
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelDef(pub TypedAssetUrl<ModelAssetType>);
impl ModelDef {
pub struct ModelFromUrl(pub TypedAssetUrl<ModelAssetType>);
impl ModelFromUrl {
pub fn new(url: impl AsRef<str>) -> anyhow::Result<Self> {
Ok(Self(TypedAssetUrl::parse(url)?))
}
}
#[async_trait]
impl AsyncAssetKey<Result<Arc<Model>, AssetError>> for ModelDef {
impl AsyncAssetKey<Result<Arc<Model>, AssetError>> for ModelFromUrl {
async fn load(self, assets: AssetCache) -> Result<Arc<Model>, AssetError> {
let base_url = ServerBaseUrlKey.get(&assets);
let url = self.0.clone().resolve(&base_url).unwrap();
Expand Down
15 changes: 10 additions & 5 deletions crates/model_import/examples/model_loading.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use glam::*;
use kiwi_app::AppBuilder;
use kiwi_core::{
asset_cache, camera::{active_camera, far}, main_scene, transform::*
asset_cache,
camera::{active_camera, far},
main_scene,
transform::*,
};
use kiwi_ecs::{EntityData, World};
use kiwi_element::ElementComponentExt;
use kiwi_model::{model_def, ModelDef};
use kiwi_model::{model_from_url, ModelFromUrl};
use kiwi_model_import::{MaterialFilter, ModelImportPipeline, ModelImportTransform, ModelTransform};
use kiwi_primitives::{Cube, Quad};
use kiwi_renderer::{color, materials::pbr_material::PbrMaterialFromUrl};
use kiwi_std::{
asset_cache::AsyncAssetKeyExt, asset_url::{AbsAssetUrl, AssetUrl, TypedAssetUrl}, math::SphericalCoords
asset_cache::AsyncAssetKeyExt,
asset_url::{AbsAssetUrl, AssetUrl, TypedAssetUrl},
math::SphericalCoords,
};
use reqwest::Url;

Expand Down Expand Up @@ -88,7 +93,7 @@ async fn init(world: &mut World) {
let mut model_defs = Vec::new();
for pipeline in asset_pipelines.iter() {
let model_url = pipeline.produce_local_model_url(&assets).await.unwrap();
model_defs.push(ModelDef(TypedAssetUrl::new(Url::from_file_path(model_url).unwrap())));
model_defs.push(ModelFromUrl(TypedAssetUrl::new(Url::from_file_path(model_url).unwrap())));
}

// "Regular" spawning
Expand All @@ -104,7 +109,7 @@ async fn init(world: &mut World) {
for (i, mod_def) in model_defs.iter().enumerate() {
let xy = vec2(i as f32 * 3., 3.);
Cube.el().set(translation(), xy.extend(-0.9)).set(color(), vec4(0.3, 0.3, 0.3, 1.)).spawn_static(world);
EntityData::new().set(model_def(), mod_def.clone()).set(translation(), xy.extend(0.1)).spawn(world);
EntityData::new().set(model_from_url(), mod_def.0.to_string()).set(translation(), xy.extend(0.1)).spawn(world);
}

kiwi_cameras::spherical::new(vec3(0., 0., 0.), SphericalCoords::new(std::f32::consts::PI / 4., std::f32::consts::PI / 4., 5.))
Expand Down
24 changes: 18 additions & 6 deletions crates/model_import/src/model_crate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,32 @@ use image::{ImageOutputFormat, RgbaImage};
use itertools::Itertools;
use kiwi_animation::{animation_bind_id_from_name, AnimationClip};
use kiwi_core::{
bounding::local_bounding_aabb, hierarchy::children, name, transform::{local_to_parent, local_to_world, mesh_to_local, TransformSystem}
bounding::local_bounding_aabb,
hierarchy::children,
name,
transform::{local_to_parent, local_to_world, mesh_to_local, TransformSystem},
};
use kiwi_ecs::{query, query_mut, Component, ComponentValue, EntityData, EntityId, FrameEvent, System, World};
use kiwi_model::{
animation_bind_id, model_def, model_skin_ix, model_skins, pbr_renderer_primitives_from_url, Model, ModelDef, PbrRenderPrimitiveFromUrl
animation_bind_id, model_from_url, model_skin_ix, model_skins, pbr_renderer_primitives_from_url, Model, ModelFromUrl,
PbrRenderPrimitiveFromUrl,
};
use kiwi_physics::{
collider::{character_controller_height, character_controller_radius, collider, ColliderDef, ColliderFromUrls}, mesh::PhysxGeometryFromUrl, physx::PhysicsKey
collider::{character_controller_height, character_controller_radius, collider, ColliderDef, ColliderFromUrls},
mesh::PhysxGeometryFromUrl,
physx::PhysicsKey,
};
use kiwi_renderer::{
double_sided, lod::{gpu_lod, lod_cutoffs}, materials::pbr_material::PbrMaterialFromUrl
double_sided,
lod::{gpu_lod, lod_cutoffs},
materials::pbr_material::PbrMaterialFromUrl,
};
use kiwi_std::{
asset_cache::{AssetCache, SyncAssetKeyExt}, asset_url::AbsAssetUrl, download_asset::AssetsCacheDir, mesh::Mesh, shapes::AABB
asset_cache::{AssetCache, SyncAssetKeyExt},
asset_url::AbsAssetUrl,
download_asset::AssetsCacheDir,
mesh::Mesh,
shapes::AABB,
};
use ordered_float::Float;
use physxx::{PxConvexFlag, PxConvexMeshDesc, PxDefaultMemoryOutputStream, PxMeshFlag, PxTriangleMeshDesc};
Expand Down Expand Up @@ -432,7 +444,7 @@ impl ModelCrate {
}

pub fn create_object_from_model(&mut self) {
self.create_object(EntityData::new().set(model_def(), ModelDef(dotdot_path(self.models.loc.path(ModelCrate::MAIN)).into())))
self.create_object(EntityData::new().set(model_from_url(), dotdot_path(self.models.loc.path(ModelCrate::MAIN)).into()))
}

pub fn create_object(&mut self, data: EntityData) {
Expand Down
4 changes: 2 additions & 2 deletions crates/naturals/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use kiwi_core::{
transform::{local_to_world, translation},
};
use kiwi_ecs::{components, query, EntityData, EntityId, FnSystem, SystemGroup};
use kiwi_model::{Model, ModelDef, ModelSpawnOpts, ModelSpawnRoot};
use kiwi_model::{Model, ModelFromUrl, ModelSpawnOpts, ModelSpawnRoot};
use kiwi_renderer::color;
use kiwi_std::{
asset_cache::{AssetCache, AsyncAssetKeyExt, SyncAssetKey, SyncAssetKeyExt},
Expand Down Expand Up @@ -162,7 +162,7 @@ async fn update_natural_layer(
.0
.iter()
.filter_map(|url| {
let model = Box::new(ModelDef(url.join("../models/main.json").ok()?.into())) as BoxModelKey;
let model = Box::new(ModelFromUrl(url.join("../models/main.json").ok()?.into())) as BoxModelKey;
Some((element.clone(), model))
})
.collect_vec()
Expand Down
6 changes: 3 additions & 3 deletions crates/object/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use kiwi_decals::decal;
use kiwi_ecs::{
components, query, query_mut, Debuggable, Description, DeserWorldWithWarnings, EntityId, Name, Networked, Store, SystemGroup, World,
};
use kiwi_model::{model_def, ModelDef};
use kiwi_model::{model_from_url, ModelFromUrl};
use kiwi_physics::collider::collider;
use kiwi_std::{
asset_cache::{AssetCache, AsyncAssetKey, AsyncAssetKeyExt, SyncAssetKeyExt},
Expand Down Expand Up @@ -66,8 +66,8 @@ impl AsyncAssetKey<Result<Arc<World>, AssetError>> for ObjectFromUrl {
let DeserWorldWithWarnings { mut world, warnings } = tokio::task::block_in_place(|| serde_json::from_slice(&data))
.with_context(|| format!("Failed to deserialize object2 from url {}", obj_url))?;
warnings.log_warnings();
for (_id, (url,), _) in query_mut((model_def(),), ()).iter(&mut world, None) {
*url = ModelDef(url.0.resolve(&obj_url).context("Failed to resolve model url")?.into());
for (_id, (url,), _) in query_mut((model_from_url(),), ()).iter(&mut world, None) {
*url = AssetUrl::parse(&url).context("Invalid model url")?.resolve(&obj_url).context("Failed to resolve model url")?.into();
}
for (_id, (def,), _) in query_mut((collider(),), ()).iter(&mut world, None) {
def.resolve(&obj_url).context("Failed to resolve collider")?;
Expand Down
Loading

0 comments on commit 88ac71c

Please sign in to comment.