mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
another scene graph refactoring, changed fake inheritance to composition
This commit is contained in:
Generated
+16
-14
@@ -7,21 +7,23 @@
|
||||
<list default="true" id="1932b2c4-d6ff-413c-9558-19959667326b" name="Default Changelist" comment="scene graph">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Cargo.lock" beforeDir="false" afterPath="$PROJECT_DIR$/Cargo.lock" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/border.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/border.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/builder.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/button.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/button.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/canvas.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/canvas.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/event.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/event.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/grid.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/grid.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/image.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/image.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/node.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/node.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/scroll_bar.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/scroll_bar.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/scroll_content_presenter.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/scroll_content_presenter.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/scroll_viewer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/scroll_viewer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/text.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/text.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/gui/window.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/gui/window.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/deferred_light_renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/deferred_light_renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/gbuffer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/gbuffer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/particle_system_renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/particle_system_renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/shadow_map_renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/shadow_map_renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/renderer/sprite_renderer.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/renderer/sprite_renderer.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/fbx/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/fbx/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/resource/model.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/resource/model.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/animation.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/animation.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/camera.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/camera.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/graph.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/graph.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/light.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/light.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/mesh.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/mesh.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/mod.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/mod.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/node.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/node.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/particle_system.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/particle_system.rs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/pivot.rs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/scene/sprite.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/scene/sprite.rs" afterDir="false" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
|
||||
Generated
+7
-7
@@ -883,7 +883,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rg3d"
|
||||
version = "0.1.10"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -892,14 +892,14 @@ dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lexical 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rg3d-core 0.1.5",
|
||||
"rg3d-physics 0.1.5",
|
||||
"rg3d-core 0.1.6",
|
||||
"rg3d-physics 0.1.6",
|
||||
"rg3d-sound 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rg3d-core"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@@ -908,10 +908,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rg3d-physics"
|
||||
version = "0.1.5"
|
||||
version = "0.1.6"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rg3d-core 0.1.5",
|
||||
"rg3d-core 0.1.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -919,7 +919,7 @@ name = "rg3d-sound"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rg3d-core 0.1.5",
|
||||
"rg3d-core 0.1.6",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "rg3d"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
authors = ["Dmitry Stepanov <[email protected]>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
@@ -1,8 +1,17 @@
|
||||
use std::ffi::CString;
|
||||
use rg3d_core::{
|
||||
color::Color,
|
||||
math::{vec3::Vec3, mat4::Mat4},
|
||||
};
|
||||
use crate::{
|
||||
renderer::gpu_texture::GpuTexture,
|
||||
scene::{
|
||||
camera::Camera, Scene,
|
||||
node::Node, SceneInterface,
|
||||
camera::Camera,
|
||||
Scene,
|
||||
node::Node,
|
||||
SceneInterface,
|
||||
light::LightKind,
|
||||
base::AsBase
|
||||
},
|
||||
renderer::{
|
||||
surface::SurfaceSharedData,
|
||||
@@ -12,13 +21,6 @@ use crate::{
|
||||
shadow_map_renderer::SpotShadowMapRenderer,
|
||||
},
|
||||
};
|
||||
use rg3d_core::{
|
||||
color::Color,
|
||||
math::{vec3::Vec3, mat4::Mat4},
|
||||
};
|
||||
use crate::scene::light::LightKind;
|
||||
use crate::renderer::gpu_texture::GpuTexture;
|
||||
use crate::scene::node::NodeTrait;
|
||||
|
||||
struct AmbientLightShader {
|
||||
program: GpuProgram,
|
||||
@@ -241,7 +243,7 @@ impl DeferredLightRenderer {
|
||||
let SceneInterface { graph, .. } = scene.interface();
|
||||
|
||||
for light_node in graph.linear_iter() {
|
||||
if !light_node.get_global_visibility() {
|
||||
if !light_node.base().get_global_visibility() {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -255,12 +257,12 @@ impl DeferredLightRenderer {
|
||||
LightKind::Point(point_light) => point_light.get_radius(),
|
||||
};
|
||||
|
||||
let light_position = light_node.get_global_position();
|
||||
let light_radius_scale = light_node.get_local_transform().get_scale().max_value();
|
||||
let light_position = light_node.base().get_global_position();
|
||||
let light_radius_scale = light_node.base().get_local_transform().get_scale().max_value();
|
||||
let light_radius = light_radius_scale * raw_radius;
|
||||
let light_r_inflate = 1.05 * light_radius;
|
||||
let light_radius_vec = Vec3::new(light_r_inflate, light_r_inflate, light_r_inflate);
|
||||
let light_emit_direction = light_node.get_up_vector().normalized().unwrap_or(Vec3::UP);
|
||||
let light_emit_direction = light_node.base().get_up_vector().normalized().unwrap_or(Vec3::UP);
|
||||
|
||||
match light.get_kind() {
|
||||
LightKind::Spot(_) => {
|
||||
@@ -318,7 +320,7 @@ impl DeferredLightRenderer {
|
||||
self.shader.set_light_cone_angle_cos(cone_angle_cos);
|
||||
self.shader.set_wvp_matrix(&frame_matrix);
|
||||
self.shader.set_shadow_map_inv_size(0.0); // TODO
|
||||
self.shader.set_camera_position(&camera.get_global_position());
|
||||
self.shader.set_camera_position(&camera.base().get_global_position());
|
||||
self.shader.set_depth_sampler_id(0);
|
||||
self.shader.set_color_sampler_id(1);
|
||||
self.shader.set_normal_sampler_id(2);
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
node::Node,
|
||||
graph::Graph,
|
||||
camera::Camera,
|
||||
node::NodeTrait
|
||||
base::AsBase
|
||||
},
|
||||
renderer::{
|
||||
gl::types::GLuint, gl,
|
||||
@@ -239,7 +239,7 @@ impl GBuffer {
|
||||
|
||||
for node in graph.linear_iter() {
|
||||
if let Node::Mesh(mesh) = node {
|
||||
if !node.get_global_visibility() {
|
||||
if !node.base().get_global_visibility() {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ impl GBuffer {
|
||||
let world = if is_skinned {
|
||||
Mat4::IDENTITY
|
||||
} else {
|
||||
node.get_global_transform()
|
||||
node.base().get_global_transform()
|
||||
};
|
||||
let mvp = view_projection * world;
|
||||
|
||||
@@ -263,8 +263,8 @@ impl GBuffer {
|
||||
for bone_handle in surface.bones.iter() {
|
||||
let bone_node = graph.get(*bone_handle);
|
||||
self.bone_matrices.push(
|
||||
bone_node.get_global_transform() *
|
||||
bone_node.get_inv_bind_pose_transform());
|
||||
bone_node.base().get_global_transform() *
|
||||
bone_node.base().get_inv_bind_pose_transform());
|
||||
}
|
||||
|
||||
self.shader.set_bone_matrices(&self.bone_matrices);
|
||||
|
||||
@@ -13,13 +13,13 @@ use crate::{
|
||||
gpu_texture::GpuTexture,
|
||||
},
|
||||
scene::{
|
||||
node::Node,
|
||||
particle_system,
|
||||
SceneInterface,
|
||||
SceneContainer,
|
||||
node::NodeTrait,
|
||||
},
|
||||
base::AsBase
|
||||
}
|
||||
};
|
||||
use crate::scene::node::Node;
|
||||
|
||||
struct ParticleSystemShader {
|
||||
program: GpuProgram,
|
||||
@@ -154,7 +154,7 @@ impl ParticleSystemRenderer {
|
||||
|
||||
particle_system.generate_draw_data(&mut self.sorted_particles,
|
||||
&mut self.draw_data,
|
||||
&camera.get_global_position());
|
||||
&camera.base().get_global_position());
|
||||
|
||||
self.geometry_buffer.set_triangles(self.draw_data.get_triangles());
|
||||
self.geometry_buffer.set_vertices(self.draw_data.get_vertices());
|
||||
@@ -172,7 +172,7 @@ impl ParticleSystemRenderer {
|
||||
|
||||
self.shader.set_diffuse_texture(0);
|
||||
self.shader.set_view_projection_matrix(&camera.get_view_projection_matrix());
|
||||
self.shader.set_world_matrix(&node.get_global_transform());
|
||||
self.shader.set_world_matrix(&node.base().get_global_transform());
|
||||
self.shader.set_camera_up_vector(&camera_up);
|
||||
self.shader.set_camera_side_vector(&camera_side);
|
||||
self.shader.set_depth_buffer_texture(1);
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{
|
||||
scene::{
|
||||
node::Node,
|
||||
graph::Graph,
|
||||
node::NodeTrait
|
||||
base::AsBase
|
||||
},
|
||||
renderer::{
|
||||
gpu_texture::GpuTexture,
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
gpu_program::{GpuProgram, UniformLocation},
|
||||
error::RendererError,
|
||||
gl
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
pub struct SpotShadowMapShader {
|
||||
@@ -130,7 +130,7 @@ impl SpotShadowMapRenderer {
|
||||
|
||||
for node in graph.linear_iter() {
|
||||
if let Node::Mesh(mesh) = node {
|
||||
if !node.get_global_visibility() {
|
||||
if !node.base().get_global_visibility() {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ impl SpotShadowMapRenderer {
|
||||
let world = if is_skinned {
|
||||
Mat4::IDENTITY
|
||||
} else {
|
||||
node.get_global_transform()
|
||||
node.base().get_global_transform()
|
||||
};
|
||||
let mvp = *light_view_projection * world;
|
||||
|
||||
@@ -152,8 +152,8 @@ impl SpotShadowMapRenderer {
|
||||
for bone_handle in surface.bones.iter() {
|
||||
let bone_node = graph.get(*bone_handle);
|
||||
self.bone_matrices.push(
|
||||
bone_node.get_global_transform() *
|
||||
bone_node.get_inv_bind_pose_transform());
|
||||
bone_node.base().get_global_transform() *
|
||||
bone_node.base().get_inv_bind_pose_transform());
|
||||
}
|
||||
|
||||
self.shader.set_bone_matrices(&self.bone_matrices);
|
||||
|
||||
@@ -3,18 +3,21 @@ use rg3d_core::{
|
||||
math::mat4::Mat4,
|
||||
math::vec3::Vec3,
|
||||
};
|
||||
use rg3d_core::color::Color;
|
||||
use crate::{
|
||||
scene::SceneContainer,
|
||||
scene::{
|
||||
SceneContainer,
|
||||
node::Node,
|
||||
SceneInterface,
|
||||
base::AsBase
|
||||
},
|
||||
renderer::{
|
||||
surface::SurfaceSharedData,
|
||||
gpu_program::{GpuProgram, UniformLocation},
|
||||
error::RendererError,
|
||||
gl, gpu_texture::GpuTexture,
|
||||
},
|
||||
scene::{SceneInterface},
|
||||
};
|
||||
use rg3d_core::color::Color;
|
||||
use crate::scene::node::{NodeTrait, Node};
|
||||
|
||||
pub struct SpriteShader {
|
||||
program: GpuProgram,
|
||||
@@ -143,7 +146,7 @@ impl SpriteRenderer {
|
||||
|
||||
self.shader.set_diffuse_texture(0);
|
||||
self.shader.set_view_projection_matrix(&camera.get_view_projection_matrix());
|
||||
self.shader.set_world_matrix(&node.get_global_transform());
|
||||
self.shader.set_world_matrix(&node.base().get_global_transform());
|
||||
self.shader.set_camera_up_vector(&camera_up);
|
||||
self.shader.set_camera_side_vector(&camera_side);
|
||||
self.shader.set_size(sprite.get_size());
|
||||
|
||||
+10
-14
@@ -32,31 +32,27 @@ use crate::{
|
||||
texture::FbxTexture,
|
||||
attribute::FbxAttribute,
|
||||
error::FbxError,
|
||||
}
|
||||
},
|
||||
},
|
||||
scene::{
|
||||
animation::{
|
||||
AnimationContainer,
|
||||
Track,
|
||||
KeyFrame,
|
||||
Animation
|
||||
Animation,
|
||||
},
|
||||
graph::Graph,
|
||||
SceneInterfaceMut,
|
||||
Scene,
|
||||
node::{
|
||||
Node,
|
||||
NodeTrait,
|
||||
NodeTraitPrivate
|
||||
},
|
||||
node::Node,
|
||||
mesh::Mesh,
|
||||
light::{
|
||||
Light,
|
||||
LightKind,
|
||||
PointLight,
|
||||
SpotLight
|
||||
SpotLight,
|
||||
},
|
||||
pivot::Pivot,
|
||||
base::{Base, AsBase},
|
||||
},
|
||||
engine::resource_manager::ResourceManager,
|
||||
renderer::{
|
||||
@@ -1164,12 +1160,12 @@ impl Fbx {
|
||||
let fbx_light_component = self.component_pool.borrow(model.light);
|
||||
Node::Light(self.convert_light(fbx_light_component.as_light()?))
|
||||
} else {
|
||||
Node::Pivot(Pivot::default())
|
||||
Node::Base(Base::default())
|
||||
};
|
||||
|
||||
node.set_name(model.name.as_str());
|
||||
node.base_mut().set_name(model.name.as_str());
|
||||
let node_local_rotation = quat_from_euler(model.rotation);
|
||||
let transform = node.get_local_transform_mut();
|
||||
let transform = node.base_mut().get_local_transform_mut();
|
||||
transform.set_rotation(node_local_rotation);
|
||||
transform.set_scale(model.scale);
|
||||
transform.set_position(model.translation);
|
||||
@@ -1179,7 +1175,7 @@ impl Fbx {
|
||||
transform.set_rotation_pivot(model.rotation_pivot);
|
||||
transform.set_scaling_offset(model.scaling_offset);
|
||||
transform.set_scaling_pivot(model.scaling_pivot);
|
||||
node.get_data_mut().inv_bind_pose_transform = model.inv_bind_transform;
|
||||
node.base_mut().inv_bind_pose_transform = model.inv_bind_transform;
|
||||
|
||||
let node_handle = graph.add_node(node);
|
||||
|
||||
@@ -1268,7 +1264,7 @@ impl Fbx {
|
||||
pub fn convert(&self, resource_manager: &mut ResourceManager, scene: &mut Scene) -> Result<Handle<Node>, FbxError> {
|
||||
let SceneInterfaceMut { animations, graph, .. } = scene.interface_mut();
|
||||
let mut instantiated_nodes = Vec::new();
|
||||
let root = graph.add_node(Node::Pivot(Pivot::default()));
|
||||
let root = graph.add_node(Node::Base(Base::default()));
|
||||
let animation_handle = animations.add(Animation::default());
|
||||
let mut fbx_model_to_node_map = HashMap::new();
|
||||
for component_handle in self.components.iter() {
|
||||
|
||||
+13
-8
@@ -1,5 +1,12 @@
|
||||
use crate::{
|
||||
scene::{Scene, node::Node, animation::Animation},
|
||||
scene::{
|
||||
Scene,
|
||||
node::Node,
|
||||
animation::Animation,
|
||||
SceneInterface,
|
||||
SceneInterfaceMut,
|
||||
base::AsBase
|
||||
},
|
||||
resource::{fbx, fbx::error::FbxError},
|
||||
engine::resource_manager::ResourceManager,
|
||||
};
|
||||
@@ -11,8 +18,6 @@ use rg3d_core::{
|
||||
pool::Handle,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
};
|
||||
use crate::scene::node::{NodeTrait, NodeTraitPrivate};
|
||||
use crate::scene::{SceneInterface, SceneInterfaceMut};
|
||||
|
||||
pub struct Model {
|
||||
pub(in crate) path: PathBuf,
|
||||
@@ -62,17 +67,17 @@ impl Model {
|
||||
let SceneInterface { graph: resource_graph, .. } = model.scene.interface();
|
||||
|
||||
let root = resource_graph.copy_node(resource_graph.get_root(), dest_graph);
|
||||
dest_graph.get_mut(root).get_data_mut().is_resource_instance = true;
|
||||
dest_graph.get_mut(root).base_mut().is_resource_instance = true;
|
||||
|
||||
// Notify instantiated nodes about resource they were created from.
|
||||
let mut stack = Vec::new();
|
||||
stack.push(root);
|
||||
while let Some(node_handle) = stack.pop() {
|
||||
let node = dest_graph.get_mut(node_handle);
|
||||
node.get_data_mut().resource = Some(Arc::clone(&model_rc));
|
||||
node.base_mut().resource = Some(Arc::clone(&model_rc));
|
||||
|
||||
// Continue on children.
|
||||
for child_handle in node.get_children() {
|
||||
for child_handle in node.base().get_children() {
|
||||
stack.push(child_handle.clone());
|
||||
}
|
||||
}
|
||||
@@ -138,9 +143,9 @@ impl Model {
|
||||
for (i, ref_track) in ref_anim.get_tracks().iter().enumerate() {
|
||||
let ref_node = resource_graph.get(ref_track.get_node());
|
||||
// Find instantiated node that corresponds to node in resource
|
||||
let instance_node = dest_graph.find_by_name(root, ref_node.get_name());
|
||||
let instance_node = dest_graph.find_by_name(root, ref_node.base().get_name());
|
||||
if instance_node.is_none() {
|
||||
println!("Failed to retarget animation for node {}", ref_node.get_name())
|
||||
println!("Failed to retarget animation for node {}", ref_node.base().get_name())
|
||||
}
|
||||
// One-to-one track mapping so there is [i] indexing.
|
||||
anim_copy.get_tracks_mut()[i].set_node(instance_node);
|
||||
|
||||
@@ -22,8 +22,9 @@ use std::sync::{Mutex, Arc};
|
||||
use crate::{
|
||||
scene::{
|
||||
SceneInterface,
|
||||
node::{Node, NodeTrait},
|
||||
node::{Node},
|
||||
graph::Graph,
|
||||
base::AsBase
|
||||
},
|
||||
resource::model::Model,
|
||||
};
|
||||
@@ -333,7 +334,7 @@ impl Animation {
|
||||
} = resource.get_scene().interface();
|
||||
if let Some(ref_animation) = resource_animations.pool.at(0) {
|
||||
for track in self.get_tracks_mut() {
|
||||
let track_node = graph.get(track.get_node());
|
||||
let track_node = graph.get(track.get_node()).base();
|
||||
// Find corresponding track in resource using names of nodes, not
|
||||
// original handles of instantiated nodes. We can't use original
|
||||
// handles here because animation can be targetted to a node that
|
||||
@@ -346,7 +347,7 @@ impl Animation {
|
||||
// animation targetted to character instance.
|
||||
let mut found = false;
|
||||
for ref_track in ref_animation.get_tracks().iter() {
|
||||
if track_node.get_name() == resource_graph.get(ref_track.get_node()).get_name() {
|
||||
if track_node.get_name() == resource_graph.get(ref_track.get_node()).base().get_name() {
|
||||
track.set_key_frames(ref_track.get_key_frames());
|
||||
found = true;
|
||||
break;
|
||||
@@ -462,8 +463,8 @@ impl AnimationContainer {
|
||||
// Reset local transform of animated nodes first
|
||||
for animation in self.pool.iter() {
|
||||
for track in animation.get_tracks() {
|
||||
let node = graph.get_mut(track.get_node());
|
||||
let transform = node.get_local_transform_mut();
|
||||
let base = graph.get_mut(track.get_node()).base_mut();
|
||||
let transform = base.get_local_transform_mut();
|
||||
transform.set_position(Default::default());
|
||||
transform.set_rotation(Default::default());
|
||||
// TODO: transform.set_scale(Vec3::new(1.0, 1.0, 1.0));
|
||||
@@ -486,8 +487,8 @@ impl AnimationContainer {
|
||||
}
|
||||
|
||||
if let Some(keyframe) = track.get_key_frame(animation.get_time_position()) {
|
||||
let node = graph.get_mut(track.get_node());
|
||||
let transform = node.get_local_transform_mut();
|
||||
let base = graph.get_mut(track.get_node()).base_mut();
|
||||
let transform = base.get_local_transform_mut();
|
||||
transform.set_rotation(transform.get_rotation().nlerp(&keyframe.rotation, weight));
|
||||
transform.set_position(transform.get_position() + keyframe.position.scale(weight));
|
||||
// TODO: transform.set_scale(transform.get_scale().lerp(&keyframe.scale, weight));
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::{
|
||||
resource::model::Model,
|
||||
scene::{
|
||||
node::Node,
|
||||
transform::Transform
|
||||
}
|
||||
};
|
||||
use rg3d_core::{
|
||||
math::{vec3::Vec3, mat4::Mat4},
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
pool::Handle,
|
||||
};
|
||||
|
||||
pub struct Base {
|
||||
pub name: String,
|
||||
pub local_transform: Transform,
|
||||
pub visibility: bool,
|
||||
pub global_visibility: bool,
|
||||
pub parent: Handle<Node>,
|
||||
pub children: Vec<Handle<Node>>,
|
||||
pub global_transform: Mat4,
|
||||
/// Bone-specific matrix. Non-serializable.
|
||||
pub inv_bind_pose_transform: Mat4,
|
||||
/// A resource from which this node was instantiated from, can work in pair
|
||||
/// with `original` handle to get corresponding node from resource.
|
||||
pub resource: Option<Arc<Mutex<Model>>>,
|
||||
/// Handle to node in scene of model resource from which this node
|
||||
/// was instantiated from.
|
||||
pub original: Handle<Node>,
|
||||
/// When `true` it means that this node is instance of `resource`.
|
||||
/// More precisely - this node is root of whole descendant nodes
|
||||
/// hierarchy which was instantiated from resource.
|
||||
pub is_resource_instance: bool,
|
||||
/// Maximum amount of Some(time) that node will "live" or None
|
||||
/// if node has undefined lifetime.
|
||||
pub lifetime: Option<f32>,
|
||||
}
|
||||
|
||||
pub trait AsBase {
|
||||
fn base(&self) -> &Base;
|
||||
fn base_mut(&mut self) -> &mut Base;
|
||||
}
|
||||
|
||||
impl Base {
|
||||
/// Sets name of node. Can be useful to mark a node to be able to find it later on.
|
||||
pub fn set_name(&mut self, name: &str) {
|
||||
self.name = name.to_owned();
|
||||
}
|
||||
|
||||
/// Returns name of node.
|
||||
pub fn get_name(&self) -> &str {
|
||||
self.name.as_str()
|
||||
}
|
||||
|
||||
/// Returns shared reference to local transform of a node, can be used to fetch
|
||||
/// some local spatial properties, such as position, rotation, scale, etc.
|
||||
pub fn get_local_transform(&self) -> &Transform {
|
||||
&self.local_transform
|
||||
}
|
||||
|
||||
/// Returns mutable reference to local transform of a node, can be used to set
|
||||
/// some local spatial properties, such as position, rotation, scale, etc.
|
||||
pub fn get_local_transform_mut(&mut self) -> &mut Transform {
|
||||
&mut self.local_transform
|
||||
}
|
||||
|
||||
/// Sets lifetime of node in seconds, lifetime is useful for temporary objects.
|
||||
/// Example - you firing a gun, it produces two particle systems for each shot:
|
||||
/// one for gunpowder fumes and one when bullet hits some surface. These particle
|
||||
/// systems won't last very long - usually they will disappear in 1-2 seconds
|
||||
/// but nodes will still be in scene consuming precious CPU clocks. This is where
|
||||
/// lifetimes become handy - you just set appropriate lifetime for a particle
|
||||
/// system node and it will be removed from scene when time will end. This is
|
||||
/// efficient algorithm because scene holds every object in pool and allocation
|
||||
/// or deallocation of node takes very little amount of time.
|
||||
pub fn set_lifetime(&mut self, time_seconds: f32) {
|
||||
self.lifetime = Some(time_seconds);
|
||||
}
|
||||
|
||||
/// Returns current lifetime of a node. Will be None if node has undefined lifetime.
|
||||
/// For more info about lifetimes see [`set_lifetime`].
|
||||
pub fn get_lifetime(&self) -> Option<f32> {
|
||||
self.lifetime.clone()
|
||||
}
|
||||
|
||||
/// Returns handle of parent node.
|
||||
pub fn get_parent(&self) -> rg3d_core::pool::Handle<Node> {
|
||||
self.parent
|
||||
}
|
||||
|
||||
/// Returns slice of handles to children nodes. This can be used, for example, to
|
||||
/// traverse tree starting from some node.
|
||||
pub fn get_children(&self) -> &[Handle<Node>] {
|
||||
self.children.as_slice()
|
||||
}
|
||||
|
||||
/// Returns global transform matrix, such matrix contains combined transformation
|
||||
/// of transforms of parent nodes. This is the final matrix that describes real
|
||||
/// location of object in the world.
|
||||
pub fn get_global_transform(&self) -> Mat4 {
|
||||
self.global_transform
|
||||
}
|
||||
|
||||
/// Returns inverse of bind pose matrix. Bind pose matrix - is special matrix
|
||||
/// for bone nodes, it stores initial transform of bone node at the moment
|
||||
/// of "binding" vertices to bones.
|
||||
pub fn get_inv_bind_pose_transform(&self) -> Mat4 {
|
||||
self.inv_bind_pose_transform
|
||||
}
|
||||
|
||||
pub fn is_resource_instance(&self) -> bool {
|
||||
self.is_resource_instance
|
||||
}
|
||||
|
||||
/// Returns resource from which this node was instantiated from.
|
||||
pub fn get_resource(&self) -> Option<Arc<Mutex<Model>>> {
|
||||
self.resource.clone()
|
||||
}
|
||||
|
||||
/// Sets local visibility of a node.
|
||||
pub fn set_visibility(&mut self, visibility: bool) {
|
||||
self.visibility = visibility;
|
||||
}
|
||||
|
||||
/// Returns local visibility of a node.
|
||||
pub fn get_visibility(&self) -> bool {
|
||||
self.visibility
|
||||
}
|
||||
|
||||
/// Returns combined visibility of an node. This is the final visibility of a node.
|
||||
/// Global visibility calculated using visibility of all parent nodes until root one,
|
||||
/// so if some parent node upper on tree is invisible then all its children will be
|
||||
/// invisible. It defines if object will be rendered. It is *not* the same as real
|
||||
/// visibility point of view of some camera. To check if object is visible from some
|
||||
/// camera, use appropriate method (TODO: which one?)
|
||||
pub fn get_global_visibility(&self) -> bool {
|
||||
self.global_visibility
|
||||
}
|
||||
|
||||
/// Handle to node in scene of model resource from which this node
|
||||
/// was instantiated from.
|
||||
pub fn get_original_handle(&self) -> Handle<Node> {
|
||||
self.original
|
||||
}
|
||||
|
||||
/// Returns position of the node in absolute coordinates.
|
||||
pub fn get_global_position(&self) -> Vec3 {
|
||||
self.global_transform.position()
|
||||
}
|
||||
|
||||
/// Returns "look" vector of global transform basis, in most cases return vector
|
||||
/// will be non-normalized.
|
||||
pub fn get_look_vector(&self) -> Vec3 {
|
||||
self.global_transform.look()
|
||||
}
|
||||
|
||||
/// Returns "side" vector of global transform basis, in most cases return vector
|
||||
/// will be non-normalized.
|
||||
pub fn get_side_vector(&self) -> Vec3 {
|
||||
self.global_transform.side()
|
||||
}
|
||||
|
||||
/// Returns "up" vector of global transform basis, in most cases return vector
|
||||
/// will be non-normalized.
|
||||
pub fn get_up_vector(&self) -> Vec3 {
|
||||
self.global_transform.up()
|
||||
}
|
||||
}
|
||||
|
||||
/// Shallow copy of node data.
|
||||
impl Clone for Base {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
name: self.name.clone(),
|
||||
local_transform: self.local_transform.clone(),
|
||||
global_transform: self.global_transform,
|
||||
visibility: self.visibility,
|
||||
global_visibility: self.global_visibility,
|
||||
inv_bind_pose_transform: self.inv_bind_pose_transform,
|
||||
resource: self.resource.clone(),
|
||||
is_resource_instance: self.is_resource_instance,
|
||||
lifetime: self.lifetime,
|
||||
// Rest of data is *not* copied!
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Base {
|
||||
fn default() -> Self {
|
||||
BaseBuilder::new().build()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsBase for Base {
|
||||
fn base(&self) -> &Base {
|
||||
self
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Base {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
visitor.enter_region(name)?;
|
||||
|
||||
self.name.visit("Name", visitor)?;
|
||||
self.local_transform.visit("Transform", visitor)?;
|
||||
self.visibility.visit("Visibility", visitor)?;
|
||||
self.parent.visit("Parent", visitor)?;
|
||||
self.children.visit("Children", visitor)?;
|
||||
self.resource.visit("Resource", visitor)?;
|
||||
self.is_resource_instance.visit("IsResourceInstance", visitor)?;
|
||||
self.lifetime.visit("Lifetime", visitor)?;
|
||||
|
||||
visitor.leave_region()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BaseBuilder {
|
||||
name: Option<String>,
|
||||
visibility: Option<bool>,
|
||||
local_transform: Option<Transform>,
|
||||
children: Option<Vec<Handle<Node>>>,
|
||||
lifetime: Option<f32>,
|
||||
}
|
||||
|
||||
impl Default for BaseBuilder {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl BaseBuilder {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
name: None,
|
||||
visibility: None,
|
||||
local_transform: None,
|
||||
children: None,
|
||||
lifetime: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_name(mut self, name: &str) -> Self {
|
||||
self.name = Some(name.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_visibility(mut self, visibility: bool) -> Self {
|
||||
self.visibility = Some(visibility);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_local_transform(mut self, transform: Transform) -> Self {
|
||||
self.local_transform = Some(transform);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_children(mut self, children: Vec<Handle<Node>>) -> Self {
|
||||
self.children = Some(children);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_lifetime(mut self, time_seconds: f32) -> Self {
|
||||
self.lifetime = Some(time_seconds);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Base {
|
||||
Base {
|
||||
name: self.name.unwrap_or_default(),
|
||||
children: self.children.unwrap_or_default(),
|
||||
local_transform: self.local_transform.unwrap_or_else(Transform::identity),
|
||||
lifetime: self.lifetime,
|
||||
visibility: self.visibility.unwrap_or(true),
|
||||
global_visibility: true,
|
||||
parent: Handle::NONE,
|
||||
global_transform: Mat4::IDENTITY,
|
||||
inv_bind_pose_transform: Mat4::IDENTITY,
|
||||
resource: None,
|
||||
original: Handle::NONE,
|
||||
is_resource_instance: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-11
@@ -6,11 +6,11 @@ use rg3d_core::{
|
||||
vec2::Vec2
|
||||
}
|
||||
};
|
||||
use crate::scene::node::{CommonNodeData, NodeTrait};
|
||||
use crate::scene::base::{Base, AsBase};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Camera {
|
||||
common: CommonNodeData,
|
||||
base: Base,
|
||||
fov: f32,
|
||||
z_near: f32,
|
||||
z_far: f32,
|
||||
@@ -19,6 +19,16 @@ pub struct Camera {
|
||||
projection_matrix: Mat4,
|
||||
}
|
||||
|
||||
impl AsBase for Camera {
|
||||
fn base(&self) -> &Base {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Camera {
|
||||
fn default() -> Camera {
|
||||
let fov: f32 = 75.0;
|
||||
@@ -26,7 +36,7 @@ impl Default for Camera {
|
||||
let z_far: f32 = 2048.0;
|
||||
|
||||
Camera {
|
||||
common: Default::default(),
|
||||
base: Base::default(),
|
||||
fov,
|
||||
z_near,
|
||||
z_far,
|
||||
@@ -49,7 +59,7 @@ impl Visit for Camera {
|
||||
self.z_near.visit("ZNear", visitor)?;
|
||||
self.z_far.visit("ZFar", visitor)?;
|
||||
self.viewport.visit("Viewport", visitor)?;
|
||||
self.common.visit("Common", visitor)?;
|
||||
self.base.visit("Base", visitor)?;
|
||||
visitor.leave_region()
|
||||
}
|
||||
}
|
||||
@@ -57,9 +67,9 @@ impl Visit for Camera {
|
||||
impl Camera {
|
||||
#[inline]
|
||||
pub fn calculate_matrices(&mut self, aspect: f32) {
|
||||
let pos = self.get_global_position();
|
||||
let look = self.get_look_vector();
|
||||
let up = self.get_up_vector();
|
||||
let pos = self.base.get_global_position();
|
||||
let look = self.base.get_look_vector();
|
||||
let up = self.base.get_up_vector();
|
||||
|
||||
if let Some(view_matrix) = Mat4::look_at(pos, pos + look, up) {
|
||||
self.view_matrix = view_matrix;
|
||||
@@ -103,7 +113,4 @@ impl Camera {
|
||||
pub fn get_z_near(&self) -> f32 {
|
||||
self.z_near
|
||||
}
|
||||
}
|
||||
|
||||
impl_node_trait!(Camera);
|
||||
impl_node_trait_private!(Camera);
|
||||
}
|
||||
+35
-35
@@ -5,9 +5,9 @@ use rg3d_core::{
|
||||
pool::{PoolIterator, PoolIteratorMut, PoolPairIterator},
|
||||
};
|
||||
use crate::scene::{
|
||||
node::{Node, NodeTrait},
|
||||
node::Node,
|
||||
SceneInterface,
|
||||
node::NodeTraitPrivate,
|
||||
base::AsBase,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -31,8 +31,8 @@ impl Graph {
|
||||
/// Creates new graph instance with single root node.
|
||||
pub fn new() -> Self {
|
||||
let mut pool: Pool<Node> = Pool::new();
|
||||
let mut root = Node::Pivot(Default::default());
|
||||
root.set_name("__ROOT__");
|
||||
let mut root = Node::Base(Default::default());
|
||||
root.base_mut().set_name("__ROOT__");
|
||||
let root = pool.spawn(root);
|
||||
Self {
|
||||
stack: Vec::new(),
|
||||
@@ -99,8 +99,8 @@ impl Graph {
|
||||
self.stack.clear();
|
||||
self.stack.push(node_handle);
|
||||
while let Some(handle) = self.stack.pop() {
|
||||
let node = self.pool.borrow(handle);
|
||||
for child in node.get_children().iter() {
|
||||
let base = self.pool.borrow(handle).base();
|
||||
for child in base.get_children().iter() {
|
||||
self.stack.push(*child);
|
||||
}
|
||||
self.pool.free(handle);
|
||||
@@ -112,9 +112,9 @@ impl Graph {
|
||||
pub fn link_nodes(&mut self, child_handle: Handle<Node>, parent_handle: Handle<Node>) {
|
||||
self.unlink_nodes(child_handle);
|
||||
let child = self.pool.borrow_mut(child_handle);
|
||||
child.get_data_mut().parent = parent_handle;
|
||||
child.base_mut().parent = parent_handle;
|
||||
let parent = self.pool.borrow_mut(parent_handle);
|
||||
parent.get_data_mut().children.push(child_handle);
|
||||
parent.base_mut().children.push(child_handle);
|
||||
}
|
||||
|
||||
/// Unlinks specified node from its parent, so node will become root.
|
||||
@@ -122,14 +122,14 @@ impl Graph {
|
||||
pub fn unlink_nodes(&mut self, node_handle: Handle<Node>) {
|
||||
// Replace parent handle of child
|
||||
let node = self.pool.borrow_mut(node_handle);
|
||||
let parent_handle = node.get_parent();
|
||||
node.get_data_mut().parent = Handle::NONE;
|
||||
let parent_handle = node.base().parent;
|
||||
node.base_mut().parent = Handle::NONE;
|
||||
|
||||
// Remove child from parent's children list
|
||||
if parent_handle.is_some() {
|
||||
let parent = self.pool.borrow_mut(parent_handle);
|
||||
if let Some(i) = parent.get_children().iter().position(|h| *h == node_handle) {
|
||||
parent.get_data_mut().children.remove(i);
|
||||
if let Some(i) = parent.base().get_children().iter().position(|h| *h == node_handle) {
|
||||
parent.base_mut().children.remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -137,11 +137,11 @@ impl Graph {
|
||||
/// Tries to find a copy of `node_handle` in hierarchy tree starting from `root_handle`.
|
||||
pub fn find_copy_of(&self, root_handle: Handle<Node>, node_handle: Handle<Node>) -> Handle<Node> {
|
||||
let root = self.pool.borrow(root_handle);
|
||||
if root.get_original_handle() == node_handle {
|
||||
if root.base().get_original_handle() == node_handle {
|
||||
return root_handle;
|
||||
}
|
||||
|
||||
for child_handle in root.get_children() {
|
||||
for child_handle in root.base().get_children() {
|
||||
let out = self.find_copy_of(*child_handle, node_handle);
|
||||
if out.is_some() {
|
||||
return out;
|
||||
@@ -154,12 +154,12 @@ impl Graph {
|
||||
/// Searches node with specified name starting from specified node. If nothing was found,
|
||||
/// [`Handle::NONE`] is returned.
|
||||
pub fn find_by_name(&self, root_node: Handle<Node>, name: &str) -> Handle<Node> {
|
||||
let node = self.pool.borrow(root_node);
|
||||
if node.get_name() == name {
|
||||
let base = self.pool.borrow(root_node).base();
|
||||
if base.get_name() == name {
|
||||
root_node
|
||||
} else {
|
||||
let mut result: Handle<Node> = Handle::NONE;
|
||||
for child in node.get_children() {
|
||||
for child in base.get_children() {
|
||||
let child_handle = self.find_by_name(*child, name);
|
||||
if !child_handle.is_none() {
|
||||
result = child_handle;
|
||||
@@ -202,10 +202,10 @@ impl Graph {
|
||||
fn copy_node_raw(&self, root_handle: Handle<Node>, dest_graph: &mut Graph, old_new_mapping: &mut HashMap<Handle<Node>, Handle<Node>>) -> Handle<Node> {
|
||||
let src_node = self.pool.borrow(root_handle);
|
||||
let mut dest_node = src_node.clone();
|
||||
dest_node.get_data_mut().original = root_handle;
|
||||
dest_node.base_mut().original = root_handle;
|
||||
let dest_copy_handle = dest_graph.add_node(dest_node);
|
||||
old_new_mapping.insert(root_handle, dest_copy_handle);
|
||||
for src_child_handle in src_node.get_children() {
|
||||
for src_child_handle in src_node.base().get_children() {
|
||||
let dest_child_handle = self.copy_node_raw(*src_child_handle, dest_graph, old_new_mapping);
|
||||
if !dest_child_handle.is_none() {
|
||||
dest_graph.link_nodes(dest_child_handle, dest_copy_handle);
|
||||
@@ -217,7 +217,7 @@ impl Graph {
|
||||
fn find_model_root(&self, from: Handle<Node>) -> Handle<Node> {
|
||||
let mut model_root_handle = from;
|
||||
while model_root_handle.is_some() {
|
||||
let model_node = self.pool.borrow(model_root_handle);
|
||||
let model_node = self.pool.borrow(model_root_handle).base();
|
||||
|
||||
if model_node.get_parent().is_none() {
|
||||
// We have no parent on node, then it must be root.
|
||||
@@ -244,14 +244,14 @@ impl Graph {
|
||||
// objects, but here we'll assume that modellers will not create models with duplicated
|
||||
// names.
|
||||
for node in self.pool.iter_mut() {
|
||||
if let Some(model) = node.get_resource() {
|
||||
let base = node.base_mut();
|
||||
if let Some(model) = base.get_resource() {
|
||||
let model = model.lock().unwrap();
|
||||
let SceneInterface { graph: resource_graph, .. } = model.get_scene().interface();
|
||||
for (handle, resource_node) in resource_graph.pair_iter() {
|
||||
if resource_node.get_name() == node.get_name() {
|
||||
let data = node.get_data_mut();
|
||||
data.original = handle;
|
||||
data.inv_bind_pose_transform = resource_node.get_inv_bind_pose_transform();
|
||||
if resource_node.base().get_name() == base.get_name() {
|
||||
base.original = handle;
|
||||
base.inv_bind_pose_transform = resource_node.base().get_inv_bind_pose_transform();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -282,8 +282,8 @@ impl Graph {
|
||||
|
||||
if let Some(node) = self.pool.at_mut(i) {
|
||||
if let Node::Mesh(mesh) = node {
|
||||
let node_name = String::from(mesh.get_name());
|
||||
if let Some(model) = mesh.get_resource() {
|
||||
let node_name = String::from(mesh.base().get_name());
|
||||
if let Some(model) = mesh.base().get_resource() {
|
||||
let model = model.lock().unwrap();
|
||||
let resource_node_handle = model.find_node_by_name(node_name.as_str());
|
||||
let SceneInterface { graph: resource_graph, .. } = model.get_scene().interface();
|
||||
@@ -315,22 +315,22 @@ impl Graph {
|
||||
self.stack.push(self.root);
|
||||
while let Some(handle) = self.stack.pop() {
|
||||
// Calculate local transform and get parent handle
|
||||
let parent_handle = self.pool.borrow_mut(handle).get_parent();
|
||||
let parent_handle = self.pool.borrow_mut(handle).base().get_parent();
|
||||
|
||||
let (parent_global_transform, parent_visibility) =
|
||||
if parent_handle.is_some() {
|
||||
let parent = self.pool.borrow(parent_handle);
|
||||
(parent.get_global_transform(), parent.get_global_visibility())
|
||||
(parent.base().get_global_transform(), parent.base().get_global_visibility())
|
||||
} else {
|
||||
(Mat4::IDENTITY, true)
|
||||
};
|
||||
|
||||
let node = self.pool.borrow_mut(handle);
|
||||
node.get_data_mut().global_transform = parent_global_transform * node.get_local_transform().get_matrix();
|
||||
node.get_data_mut().global_visibility = parent_visibility && node.get_visibility();
|
||||
node.base_mut().global_transform = parent_global_transform * node.base().get_local_transform().get_matrix();
|
||||
node.base_mut().global_visibility = parent_visibility && node.base().get_visibility();
|
||||
|
||||
// Queue children and continue traversal on them
|
||||
for child_handle in node.get_children() {
|
||||
for child_handle in node.base().get_children() {
|
||||
self.stack.push(child_handle.clone());
|
||||
}
|
||||
}
|
||||
@@ -344,8 +344,8 @@ impl Graph {
|
||||
self.update_transforms();
|
||||
|
||||
for node in self.pool.iter_mut() {
|
||||
if let Some(lifetime) = node.get_lifetime() {
|
||||
node.set_lifetime(lifetime - dt);
|
||||
if let Some(lifetime) = node.base().get_lifetime() {
|
||||
node.base_mut().set_lifetime(lifetime - dt);
|
||||
}
|
||||
|
||||
match node {
|
||||
@@ -357,7 +357,7 @@ impl Graph {
|
||||
|
||||
for i in 0..self.pool.get_capacity() {
|
||||
let remove = if let Some(node) = self.pool.at(i) {
|
||||
if let Some(lifetime) = node.get_lifetime() {
|
||||
if let Some(lifetime) = node.base().get_lifetime() {
|
||||
lifetime <= 0.0
|
||||
} else {
|
||||
false
|
||||
|
||||
+19
-14
@@ -6,7 +6,7 @@ use rg3d_core::{
|
||||
VisitResult
|
||||
}
|
||||
};
|
||||
use crate::scene::node::{CommonNodeData, CommonNodeBuilderData};
|
||||
use crate::scene::base::{BaseBuilder, Base, AsBase};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SpotLight {
|
||||
@@ -146,15 +146,25 @@ impl Visit for LightKind {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Light {
|
||||
common: CommonNodeData,
|
||||
base: Base,
|
||||
kind: LightKind,
|
||||
color: Color,
|
||||
}
|
||||
|
||||
impl AsBase for Light {
|
||||
fn base(&self) -> &Base {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Light {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
common: Default::default(),
|
||||
base: Default::default(),
|
||||
kind: LightKind::Point(Default::default()),
|
||||
color: Color::WHITE,
|
||||
}
|
||||
@@ -172,7 +182,7 @@ impl Visit for Light {
|
||||
}
|
||||
self.kind.visit("Kind", visitor)?;
|
||||
self.color.visit("Color", visitor)?;
|
||||
self.common.visit("Common", visitor)?;
|
||||
self.base.visit("Base", visitor)?;
|
||||
|
||||
visitor.leave_region()
|
||||
}
|
||||
@@ -181,7 +191,7 @@ impl Visit for Light {
|
||||
impl Light {
|
||||
pub fn new(kind: LightKind) -> Self {
|
||||
Self {
|
||||
common: Default::default(),
|
||||
base: Default::default(),
|
||||
kind,
|
||||
color: Color::WHITE,
|
||||
}
|
||||
@@ -208,26 +218,21 @@ impl Light {
|
||||
}
|
||||
}
|
||||
|
||||
impl_node_trait!(Light);
|
||||
impl_node_trait_private!(Light);
|
||||
|
||||
pub struct LightBuilder {
|
||||
common: CommonNodeBuilderData,
|
||||
base_builder: BaseBuilder,
|
||||
kind: LightKind,
|
||||
color: Option<Color>,
|
||||
}
|
||||
|
||||
impl LightBuilder {
|
||||
pub fn new(kind: LightKind) -> Self {
|
||||
pub fn new(kind: LightKind, base_builder: BaseBuilder) -> Self {
|
||||
Self {
|
||||
common: Default::default(),
|
||||
base_builder,
|
||||
kind,
|
||||
color: None
|
||||
}
|
||||
}
|
||||
|
||||
impl_common_node_builder_methods!();
|
||||
|
||||
pub fn with_color(mut self, color: Color) -> Self {
|
||||
self.color = Some(color);
|
||||
self
|
||||
@@ -235,7 +240,7 @@ impl LightBuilder {
|
||||
|
||||
pub fn build(self) -> Light {
|
||||
Light {
|
||||
common: From::from(self.common),
|
||||
base: self.base_builder.build(),
|
||||
kind: self.kind,
|
||||
color: self.color.unwrap_or(Color::WHITE)
|
||||
}
|
||||
|
||||
+14
-7
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
renderer::surface::Surface,
|
||||
scene::node::CommonNodeData
|
||||
scene::base::{Base, AsBase}
|
||||
};
|
||||
use rg3d_core::visitor::{
|
||||
Visit,
|
||||
@@ -10,24 +10,34 @@ use rg3d_core::visitor::{
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Mesh {
|
||||
common: CommonNodeData,
|
||||
base: Base,
|
||||
surfaces: Vec<Surface>,
|
||||
}
|
||||
|
||||
impl Default for Mesh {
|
||||
fn default() -> Mesh {
|
||||
Mesh {
|
||||
common: Default::default(),
|
||||
base: Default::default(),
|
||||
surfaces: Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsBase for Mesh {
|
||||
fn base(&self) -> &Base {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Mesh {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
visitor.enter_region(name)?;
|
||||
|
||||
self.common.visit("Common", visitor)?;
|
||||
self.base.visit("Common", visitor)?;
|
||||
|
||||
// No need to serialize surfaces, correct ones will be assigned on resolve stage.
|
||||
visitor.leave_region()
|
||||
@@ -50,6 +60,3 @@ impl Mesh {
|
||||
self.surfaces.push(surface);
|
||||
}
|
||||
}
|
||||
|
||||
impl_node_trait!(Mesh);
|
||||
impl_node_trait_private!(Mesh);
|
||||
+4
-3
@@ -8,12 +8,13 @@ pub mod particle_system;
|
||||
pub mod transform;
|
||||
pub mod sprite;
|
||||
pub mod graph;
|
||||
pub mod pivot;
|
||||
pub mod base;
|
||||
|
||||
use crate::scene::{
|
||||
animation::AnimationContainer,
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait},
|
||||
node::Node,
|
||||
base::AsBase,
|
||||
};
|
||||
use rg3d_physics::{Physics, rigid_body::RigidBody};
|
||||
use rg3d_core::{
|
||||
@@ -94,7 +95,7 @@ impl Scene {
|
||||
// Sync node positions with assigned physics bodies
|
||||
for (node, body) in self.node_rigid_body_map.iter() {
|
||||
if self.graph.is_valid_handle(*node) {
|
||||
let node = self.graph.get_mut(*node);
|
||||
let node = self.graph.get_mut(*node).base_mut();
|
||||
if self.physics.is_valid_body_handle(*body) {
|
||||
let body = self.physics.borrow_body(*body);
|
||||
node.get_local_transform_mut().set_position(body.get_position());
|
||||
|
||||
+39
-446
@@ -1,303 +1,14 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::{
|
||||
scene::{
|
||||
camera::Camera,
|
||||
mesh::Mesh,
|
||||
light::Light,
|
||||
particle_system::ParticleSystem,
|
||||
transform::Transform,
|
||||
sprite::Sprite,
|
||||
pivot::Pivot
|
||||
},
|
||||
resource::model::Model,
|
||||
};
|
||||
use rg3d_core::{
|
||||
math::{vec3::Vec3, mat4::Mat4},
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
pool::Handle,
|
||||
};
|
||||
|
||||
pub trait NodeTrait {
|
||||
/// Sets name of node. Can be useful to mark a node to be able to find it later on.
|
||||
fn set_name(&mut self, name: &str);
|
||||
|
||||
/// Returns name of node.
|
||||
fn get_name(&self) -> &str;
|
||||
|
||||
/// Returns shared reference to local transform of a node, can be used to fetch
|
||||
/// some local spatial properties, such as position, rotation, scale, etc.
|
||||
fn get_local_transform(&self) -> &Transform;
|
||||
|
||||
/// Returns mutable reference to local transform of a node, can be used to set
|
||||
/// some local spatial properties, such as position, rotation, scale, etc.
|
||||
fn get_local_transform_mut(&mut self) -> &mut Transform;
|
||||
|
||||
/// Sets lifetime of node in seconds, lifetime is useful for temporary objects.
|
||||
/// Example - you firing a gun, it produces two particle systems for each shot:
|
||||
/// one for gunpowder fumes and one when bullet hits some surface. These particle
|
||||
/// systems won't last very long - usually they will disappear in 1-2 seconds
|
||||
/// but nodes will still be in scene consuming precious CPU clocks. This is where
|
||||
/// lifetimes become handy - you just set appropriate lifetime for a particle
|
||||
/// system node and it will be removed from scene when time will end. This is
|
||||
/// efficient algorithm because scene holds every object in pool and allocation
|
||||
/// or deallocation of node takes very little amount of time.
|
||||
fn set_lifetime(&mut self, time_seconds: f32);
|
||||
|
||||
/// Returns current lifetime of a node. Will be None if node has undefined lifetime.
|
||||
/// For more info about lifetimes see [`set_lifetime`].
|
||||
fn get_lifetime(&self) -> Option<f32>;
|
||||
|
||||
/// Returns handle of parent node.
|
||||
fn get_parent(&self) -> Handle<Node>;
|
||||
|
||||
/// Returns slice of handles to children nodes. This can be used, for example, to
|
||||
/// traverse tree starting from some node.
|
||||
fn get_children(&self) -> &[Handle<Node>];
|
||||
|
||||
/// Returns global transform matrix, such matrix contains combined transformation
|
||||
/// of transforms of parent nodes. This is the final matrix that describes real
|
||||
/// location of object in the world.
|
||||
fn get_global_transform(&self) -> Mat4;
|
||||
|
||||
/// Returns inverse of bind pose matrix. Bind pose matrix - is special matrix
|
||||
/// for bone nodes, it stores initial transform of bone node at the moment
|
||||
/// of "binding" vertices to bones.
|
||||
fn get_inv_bind_pose_transform(&self) -> Mat4;
|
||||
|
||||
/// Returns resource from which this node was instantiated from.
|
||||
fn get_resource(&self) -> Option<Arc<Mutex<Model>>>;
|
||||
|
||||
/// Sets local visibility of a node.
|
||||
fn set_visibility(&mut self, visibility: bool);
|
||||
|
||||
/// Returns local visibility of a node.
|
||||
fn get_visibility(&self) -> bool;
|
||||
|
||||
/// Returns combined visibility of an node. This is the final visibility of a node.
|
||||
/// Global visibility calculated using visibility of all parent nodes until root one,
|
||||
/// so if some parent node upper on tree is invisible then all its children will be
|
||||
/// invisible. It defines if object will be rendered. It is *not* the same as real
|
||||
/// visibility point of view of some camera. To check if object is visible from some
|
||||
/// camera, use appropriate method (TODO: which one?)
|
||||
fn get_global_visibility(&self) -> bool;
|
||||
|
||||
fn is_resource_instance(&self) -> bool;
|
||||
|
||||
/// Handle to node in scene of model resource from which this node
|
||||
/// was instantiated from.
|
||||
fn get_original_handle(&self) -> Handle<Node>;
|
||||
|
||||
/// Returns position of the node in absolute coordinates.
|
||||
fn get_global_position(&self) -> Vec3 {
|
||||
self.get_global_transform().position()
|
||||
}
|
||||
|
||||
/// Returns "look" vector of global transform basis, in most cases return vector
|
||||
/// will be non-normalized.
|
||||
fn get_look_vector(&self) -> Vec3 {
|
||||
self.get_global_transform().look()
|
||||
}
|
||||
|
||||
/// Returns "side" vector of global transform basis, in most cases return vector
|
||||
/// will be non-normalized.
|
||||
fn get_side_vector(&self) -> Vec3 {
|
||||
self.get_global_transform().side()
|
||||
}
|
||||
|
||||
/// Returns "up" vector of global transform basis, in most cases return vector
|
||||
/// will be non-normalized.
|
||||
fn get_up_vector(&self) -> Vec3 {
|
||||
self.get_global_transform().up()
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides default implementation for all methods of NodeTrait.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Target type must contain `common` field of [`CommonNodeData`] type!
|
||||
macro_rules! impl_node_trait {
|
||||
($ty_name:ident) => {
|
||||
impl $crate::scene::node::NodeTrait for $ty_name {
|
||||
fn set_name(&mut self, name: &str) {
|
||||
self.common.name = name.to_owned();
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &str {
|
||||
self.common.name.as_str()
|
||||
}
|
||||
|
||||
fn get_local_transform(&self) -> &$crate::scene::transform::Transform {
|
||||
&self.common.local_transform
|
||||
}
|
||||
|
||||
fn get_local_transform_mut(&mut self) -> &mut $crate::scene::transform::Transform {
|
||||
&mut self.common.local_transform
|
||||
}
|
||||
|
||||
fn set_lifetime(&mut self, time_seconds: f32) {
|
||||
self.common.lifetime = Some(time_seconds);
|
||||
}
|
||||
|
||||
fn get_lifetime(&self) -> Option<f32> {
|
||||
self.common.lifetime.clone()
|
||||
}
|
||||
|
||||
fn get_parent(&self) -> rg3d_core::pool::Handle<crate::scene::node::Node> {
|
||||
self.common.parent
|
||||
}
|
||||
|
||||
fn get_children(&self) -> &[rg3d_core::pool::Handle<$crate::scene::node::Node>] {
|
||||
self.common.children.as_slice()
|
||||
}
|
||||
|
||||
fn get_global_transform(&self) -> rg3d_core::math::mat4::Mat4 {
|
||||
self.common.global_transform
|
||||
}
|
||||
|
||||
fn get_inv_bind_pose_transform(&self) -> rg3d_core::math::mat4::Mat4 {
|
||||
self.common.inv_bind_pose_transform
|
||||
}
|
||||
|
||||
fn is_resource_instance(&self) -> bool {
|
||||
self.common.is_resource_instance
|
||||
}
|
||||
|
||||
fn get_resource(&self) -> Option<std::sync::Arc<std::sync::Mutex<$crate::resource::model::Model>>> {
|
||||
self.common.resource.clone()
|
||||
}
|
||||
|
||||
fn set_visibility(&mut self, visibility: bool) {
|
||||
self.common.visibility = visibility;
|
||||
}
|
||||
|
||||
fn get_visibility(&self) -> bool {
|
||||
self.common.visibility
|
||||
}
|
||||
|
||||
fn get_global_visibility(&self) -> bool {
|
||||
self.common.global_visibility
|
||||
}
|
||||
|
||||
fn get_original_handle(&self) -> rg3d_core::pool::Handle<$crate::scene::node::Node> {
|
||||
self.common.original
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides default implementation of [`NodeTraitPrivate`].
|
||||
macro_rules! impl_node_trait_private {
|
||||
($ty_name:ident) => {
|
||||
impl $crate::scene::node::NodeTraitPrivate for $ty_name {
|
||||
fn get_data(&self) -> &CommonNodeData {
|
||||
&self.common
|
||||
}
|
||||
|
||||
fn get_data_mut(&mut self) -> &mut CommonNodeData {
|
||||
&mut self.common
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Private trait that gives direct access to common node data,
|
||||
/// it helps preserve encapsulation and does not exposes private
|
||||
/// data to outer world.
|
||||
pub(in crate) trait NodeTraitPrivate {
|
||||
fn get_data(&self) -> &CommonNodeData;
|
||||
|
||||
fn get_data_mut(&mut self) -> &mut CommonNodeData;
|
||||
}
|
||||
|
||||
/// Struct with common node fields to be able to create composite nodes
|
||||
/// faster. It will just require to define common field and expose its
|
||||
/// data via NodeTrait.
|
||||
pub(in crate) struct CommonNodeData {
|
||||
pub name: String,
|
||||
pub local_transform: Transform,
|
||||
pub visibility: bool,
|
||||
pub global_visibility: bool,
|
||||
pub parent: Handle<Node>,
|
||||
pub children: Vec<Handle<Node>>,
|
||||
pub global_transform: Mat4,
|
||||
/// Bone-specific matrix. Non-serializable.
|
||||
pub inv_bind_pose_transform: Mat4,
|
||||
/// A resource from which this node was instantiated from, can work in pair
|
||||
/// with `original` handle to get corresponding node from resource.
|
||||
pub resource: Option<Arc<Mutex<Model>>>,
|
||||
/// Handle to node in scene of model resource from which this node
|
||||
/// was instantiated from.
|
||||
pub original: Handle<Node>,
|
||||
/// When `true` it means that this node is instance of `resource`.
|
||||
/// More precisely - this node is root of whole descendant nodes
|
||||
/// hierarchy which was instantiated from resource.
|
||||
pub is_resource_instance: bool,
|
||||
/// Maximum amount of Some(time) that node will "live" or None
|
||||
/// if node has undefined lifetime.
|
||||
pub lifetime: Option<f32>,
|
||||
}
|
||||
|
||||
impl From<CommonNodeBuilderData> for CommonNodeData {
|
||||
fn from(data: CommonNodeBuilderData) -> Self {
|
||||
Self {
|
||||
name: data.name.unwrap_or_default(),
|
||||
children: data.children.unwrap_or_default(),
|
||||
local_transform: data.local_transform.unwrap_or_else(Transform::identity),
|
||||
lifetime: data.lifetime,
|
||||
visibility: data.visibility.unwrap_or(true),
|
||||
global_visibility: true,
|
||||
parent: Handle::NONE,
|
||||
global_transform: Mat4::IDENTITY,
|
||||
inv_bind_pose_transform: Mat4::IDENTITY,
|
||||
resource: None,
|
||||
original: Handle::NONE,
|
||||
is_resource_instance: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shallow copy of node data.
|
||||
impl Clone for CommonNodeData {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
name: self.name.clone(),
|
||||
local_transform: self.local_transform.clone(),
|
||||
global_transform: self.global_transform,
|
||||
visibility: self.visibility,
|
||||
global_visibility: self.global_visibility,
|
||||
inv_bind_pose_transform: self.inv_bind_pose_transform,
|
||||
resource: self.resource.clone(),
|
||||
is_resource_instance: self.is_resource_instance,
|
||||
lifetime: self.lifetime,
|
||||
// Rest of data is *not* copied!
|
||||
.. Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CommonNodeData {
|
||||
fn default() -> Self {
|
||||
Self::from(CommonNodeBuilderData::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for CommonNodeData {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
visitor.enter_region(name)?;
|
||||
|
||||
self.name.visit("Name", visitor)?;
|
||||
self.local_transform.visit("Transform", visitor)?;
|
||||
self.visibility.visit("Visibility", visitor)?;
|
||||
self.parent.visit("Parent", visitor)?;
|
||||
self.children.visit("Children", visitor)?;
|
||||
self.resource.visit("Resource", visitor)?;
|
||||
self.is_resource_instance.visit("IsResourceInstance", visitor)?;
|
||||
self.lifetime.visit("Lifetime", visitor)?;
|
||||
|
||||
visitor.leave_region()
|
||||
}
|
||||
}
|
||||
use crate::scene::{
|
||||
light::Light,
|
||||
camera::Camera,
|
||||
base::{Base, AsBase},
|
||||
mesh::Mesh,
|
||||
sprite::Sprite,
|
||||
particle_system::ParticleSystem,
|
||||
};
|
||||
|
||||
impl Visit for Node {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
@@ -309,7 +20,7 @@ impl Visit for Node {
|
||||
|
||||
// Call appropriate visit method based on actual variant.
|
||||
match self {
|
||||
Node::Pivot(pivot) => pivot.visit(name, visitor),
|
||||
Node::Base(base) => base.visit(name, visitor),
|
||||
Node::Light(light) => light.visit(name, visitor),
|
||||
Node::Camera(camera) => camera.visit(name, visitor),
|
||||
Node::Mesh(mesh) => mesh.visit(name, visitor),
|
||||
@@ -321,7 +32,7 @@ impl Visit for Node {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Node {
|
||||
Pivot(Pivot),
|
||||
Base(Base),
|
||||
Light(Light),
|
||||
Camera(Camera),
|
||||
Mesh(Mesh),
|
||||
@@ -329,9 +40,34 @@ pub enum Node {
|
||||
ParticleSystem(ParticleSystem),
|
||||
}
|
||||
|
||||
/// Helper macros to reduce code bloat - its purpose it to dispatch
|
||||
/// specified call by actual enum variant.
|
||||
macro_rules! dispatch {
|
||||
($self:ident, $func:ident, $($args:expr),*) => {
|
||||
match $self {
|
||||
Node::Base(v) => v.$func($($args),*),
|
||||
Node::Mesh(v) => v.$func($($args),*),
|
||||
Node::Camera(v) => v.$func($($args),*),
|
||||
Node::Light(v) => v.$func($($args),*),
|
||||
Node::ParticleSystem(v) => v.$func($($args),*),
|
||||
Node::Sprite(v) => v.$func($($args),*),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl AsBase for Node {
|
||||
fn base(&self) -> &Base {
|
||||
dispatch!(self, base, )
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base {
|
||||
dispatch!(self, base_mut, )
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Node {
|
||||
fn default() -> Self {
|
||||
Node::Pivot(Default::default())
|
||||
Node::Base(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +101,7 @@ impl Node {
|
||||
/// Creates new Node based on variant id.
|
||||
pub fn from_id(id: u8) -> Result<Self, String> {
|
||||
match id {
|
||||
0 => Ok(Node::Pivot(Default::default())),
|
||||
0 => Ok(Node::Base(Default::default())),
|
||||
1 => Ok(Node::Light(Default::default())),
|
||||
2 => Ok(Node::Camera(Default::default())),
|
||||
3 => Ok(Node::Mesh(Default::default())),
|
||||
@@ -378,7 +114,7 @@ impl Node {
|
||||
/// Returns actual variant id.
|
||||
pub fn id(&self) -> u8 {
|
||||
match self {
|
||||
Node::Pivot(_) => 0,
|
||||
Node::Base(_) => 0,
|
||||
Node::Light(_) => 1,
|
||||
Node::Camera(_) => 2,
|
||||
Node::Mesh(_) => 3,
|
||||
@@ -392,147 +128,4 @@ impl Node {
|
||||
define_is_as!(is_light, as_light, as_light_mut, Light, Light);
|
||||
define_is_as!(is_particle_system, as_particle_system, as_particle_system_mut, ParticleSystem, ParticleSystem);
|
||||
define_is_as!(is_sprite, as_sprite, as_sprite_mut, Sprite, Sprite);
|
||||
}
|
||||
|
||||
/// Helper macros to reduce code bloat - its purpose it to dispatch
|
||||
/// specified call by actual enum variant.
|
||||
macro_rules! dispatch {
|
||||
($self:ident, $func:ident, $($args:expr),*) => {
|
||||
match $self {
|
||||
Node::Pivot(v) => v.$func($($args),*),
|
||||
Node::Mesh(v) => v.$func($($args),*),
|
||||
Node::Camera(v) => v.$func($($args),*),
|
||||
Node::Light(v) => v.$func($($args),*),
|
||||
Node::ParticleSystem(v) => v.$func($($args),*),
|
||||
Node::Sprite(v) => v.$func($($args),*),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Implement dispatcher for Node variants. This allows Node behave like base
|
||||
/// class of any other specialized nodes.
|
||||
impl NodeTrait for Node {
|
||||
fn set_name(&mut self, name: &str) {
|
||||
dispatch!(self, set_name, name)
|
||||
}
|
||||
|
||||
fn get_name(&self) -> &str {
|
||||
dispatch!(self, get_name,)
|
||||
}
|
||||
|
||||
fn get_local_transform(&self) -> &Transform {
|
||||
dispatch!(self, get_local_transform,)
|
||||
}
|
||||
|
||||
fn get_local_transform_mut(&mut self) -> &mut Transform {
|
||||
dispatch!(self, get_local_transform_mut,)
|
||||
}
|
||||
|
||||
fn set_lifetime(&mut self, time_seconds: f32) {
|
||||
dispatch!(self, set_lifetime, time_seconds)
|
||||
}
|
||||
|
||||
fn get_lifetime(&self) -> Option<f32> {
|
||||
dispatch!(self, get_lifetime,)
|
||||
}
|
||||
|
||||
fn get_parent(&self) -> Handle<Node> {
|
||||
dispatch!(self, get_parent,)
|
||||
}
|
||||
|
||||
fn get_children(&self) -> &[Handle<Node>] {
|
||||
dispatch!(self, get_children,)
|
||||
}
|
||||
|
||||
fn get_global_transform(&self) -> Mat4 {
|
||||
dispatch!(self, get_global_transform,)
|
||||
}
|
||||
|
||||
fn get_inv_bind_pose_transform(&self) -> Mat4 {
|
||||
dispatch!(self, get_inv_bind_pose_transform,)
|
||||
}
|
||||
|
||||
fn get_resource(&self) -> Option<Arc<Mutex<Model>>> {
|
||||
dispatch!(self, get_resource,)
|
||||
}
|
||||
|
||||
fn set_visibility(&mut self, visibility: bool) {
|
||||
dispatch!(self, set_visibility, visibility)
|
||||
}
|
||||
|
||||
fn get_visibility(&self) -> bool {
|
||||
dispatch!(self, get_visibility,)
|
||||
}
|
||||
|
||||
fn get_global_visibility(&self) -> bool {
|
||||
dispatch!(self, get_global_visibility,)
|
||||
}
|
||||
|
||||
fn is_resource_instance(&self) -> bool {
|
||||
dispatch!(self, is_resource_instance,)
|
||||
}
|
||||
|
||||
fn get_original_handle(&self) -> Handle<Node> {
|
||||
dispatch!(self, get_original_handle,)
|
||||
}
|
||||
}
|
||||
|
||||
impl NodeTraitPrivate for Node {
|
||||
fn get_data(&self) -> &CommonNodeData {
|
||||
dispatch!(self, get_data,)
|
||||
}
|
||||
|
||||
fn get_data_mut(&mut self) -> &mut CommonNodeData {
|
||||
dispatch!(self, get_data_mut,)
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate) struct CommonNodeBuilderData {
|
||||
pub name: Option<String>,
|
||||
pub visibility: Option<bool>,
|
||||
pub local_transform: Option<Transform>,
|
||||
pub children: Option<Vec<Handle<Node>>>,
|
||||
pub lifetime: Option<f32>,
|
||||
}
|
||||
|
||||
impl Default for CommonNodeBuilderData {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
name: None,
|
||||
visibility: None,
|
||||
local_transform: None,
|
||||
children: None,
|
||||
lifetime: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_common_node_builder_methods {
|
||||
() => {
|
||||
pub fn with_name(mut self, name: &str) -> Self {
|
||||
self.common.name = Some(name.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_visibility(mut self, visibility: bool) -> Self {
|
||||
self.common.visibility = Some(visibility);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_local_transform(mut self, transform: $crate::scene::transform::Transform) -> Self {
|
||||
self.common.local_transform = Some(transform);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_children(mut self, children: Vec<rg3d_core::pool::Handle<$crate::scene::node::Node>>) -> Self {
|
||||
self.common.children = Some(children);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_lifetime(mut self, time_seconds: f32) -> Self {
|
||||
self.common.lifetime = Some(time_seconds);
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,11 +27,7 @@ use rg3d_core::{
|
||||
use crate::{
|
||||
resource::texture::Texture,
|
||||
renderer::TriangleDefinition,
|
||||
scene::node::{
|
||||
CommonNodeData,
|
||||
CommonNodeBuilderData,
|
||||
NodeTrait,
|
||||
},
|
||||
scene::base::{BaseBuilder, Base, AsBase}
|
||||
};
|
||||
|
||||
/// OpenGL expects this structure packed as in C.
|
||||
@@ -642,7 +638,7 @@ impl Default for Emitter {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ParticleSystem {
|
||||
common: CommonNodeData,
|
||||
base: Base,
|
||||
particles: Vec<Particle>,
|
||||
free_particles: Vec<u32>,
|
||||
emitters: Vec<Emitter>,
|
||||
@@ -651,6 +647,16 @@ pub struct ParticleSystem {
|
||||
color_over_lifetime: Option<ColorGradient>,
|
||||
}
|
||||
|
||||
impl AsBase for ParticleSystem {
|
||||
fn base(&self) -> &Base {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl ParticleSystem {
|
||||
pub fn add_emitter(&mut self, emitter: Emitter) {
|
||||
self.emitters.push(emitter)
|
||||
@@ -715,7 +721,7 @@ impl ParticleSystem {
|
||||
sorted_particles.clear();
|
||||
for (i, particle) in self.particles.iter().enumerate() {
|
||||
if particle.alive {
|
||||
let actual_position = particle.position + self.get_global_position();
|
||||
let actual_position = particle.position + self.base.get_global_position();
|
||||
particle.sqr_distance_to_camera.set(camera_pos.sqr_distance(&actual_position));
|
||||
sorted_particles.push(i as u32);
|
||||
}
|
||||
@@ -801,8 +807,6 @@ impl ParticleSystem {
|
||||
}
|
||||
}
|
||||
|
||||
impl_node_trait!(ParticleSystem);
|
||||
impl_node_trait_private!(ParticleSystem);
|
||||
|
||||
impl Visit for ParticleSystem {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
@@ -814,7 +818,7 @@ impl Visit for ParticleSystem {
|
||||
self.emitters.visit("Emitters", visitor)?;
|
||||
self.acceleration.visit("Acceleration", visitor)?;
|
||||
self.color_over_lifetime.visit("ColorGradient", visitor)?;
|
||||
self.common.visit("Common", visitor)?;
|
||||
self.base.visit("Base", visitor)?;
|
||||
|
||||
visitor.leave_region()
|
||||
}
|
||||
@@ -822,28 +826,22 @@ impl Visit for ParticleSystem {
|
||||
|
||||
impl Default for ParticleSystem {
|
||||
fn default() -> Self {
|
||||
ParticleSystemBuilder::new().build()
|
||||
ParticleSystemBuilder::new(BaseBuilder::new()).build()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ParticleSystemBuilder {
|
||||
common: CommonNodeBuilderData,
|
||||
base_builder: BaseBuilder,
|
||||
emitters: Option<Vec<Emitter>>,
|
||||
texture: Option<Arc<Mutex<Texture>>>,
|
||||
acceleration: Option<Vec3>,
|
||||
color_over_lifetime: Option<ColorGradient>,
|
||||
}
|
||||
|
||||
impl Default for ParticleSystemBuilder {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ParticleSystemBuilder {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(base_builder: BaseBuilder) -> Self {
|
||||
Self {
|
||||
common: Default::default(),
|
||||
base_builder,
|
||||
emitters: None,
|
||||
texture: None,
|
||||
acceleration: None,
|
||||
@@ -851,8 +849,6 @@ impl ParticleSystemBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
impl_common_node_builder_methods!();
|
||||
|
||||
pub fn with_emitters(mut self, emitters: Vec<Emitter>) -> Self {
|
||||
self.emitters = Some(emitters);
|
||||
self
|
||||
@@ -880,7 +876,7 @@ impl ParticleSystemBuilder {
|
||||
|
||||
pub fn build(self) -> ParticleSystem {
|
||||
ParticleSystem {
|
||||
common: From::from(self.common),
|
||||
base: self.base_builder.build(),
|
||||
particles: Vec::new(),
|
||||
free_particles: Vec::new(),
|
||||
emitters: self.emitters.unwrap_or_default(),
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
use crate::scene::node::{CommonNodeData};
|
||||
use rg3d_core::visitor::{Visit, Visitor, VisitResult};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Pivot {
|
||||
common: CommonNodeData
|
||||
}
|
||||
|
||||
impl Default for Pivot {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
common: Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Pivot {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
visitor.enter_region(name)?;
|
||||
|
||||
self.common.visit("Common", visitor)?;
|
||||
|
||||
visitor.leave_region()
|
||||
}
|
||||
}
|
||||
|
||||
impl_node_trait!(Pivot);
|
||||
impl_node_trait_private!(Pivot);
|
||||
+18
-19
@@ -1,25 +1,35 @@
|
||||
use std::sync::{Arc, Mutex};
|
||||
use crate::{
|
||||
resource::texture::Texture,
|
||||
scene::node::{CommonNodeData, CommonNodeBuilderData}
|
||||
};
|
||||
use rg3d_core::{
|
||||
color::Color,
|
||||
visitor::{Visit, VisitResult, Visitor}
|
||||
};
|
||||
use crate::scene::base::{BaseBuilder, Base, AsBase};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Sprite {
|
||||
common: CommonNodeData,
|
||||
base: Base,
|
||||
texture: Option<Arc<Mutex<Texture>>>,
|
||||
color: Color,
|
||||
size: f32,
|
||||
rotation: f32,
|
||||
}
|
||||
|
||||
impl AsBase for Sprite {
|
||||
fn base(&self) -> &Base {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut Base {
|
||||
&mut self.base
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Sprite {
|
||||
fn default() -> Self {
|
||||
SpriteBuilder::new().build()
|
||||
SpriteBuilder::new(BaseBuilder::new()).build()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,9 +68,6 @@ impl Sprite {
|
||||
}
|
||||
}
|
||||
|
||||
impl_node_trait!(Sprite);
|
||||
impl_node_trait_private!(Sprite);
|
||||
|
||||
impl Visit for Sprite {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
visitor.enter_region(name)?;
|
||||
@@ -69,30 +76,24 @@ impl Visit for Sprite {
|
||||
self.color.visit("Color", visitor)?;
|
||||
self.size.visit("Size", visitor)?;
|
||||
self.rotation.visit("Rotation", visitor)?;
|
||||
self.common.visit("Common", visitor)?;
|
||||
self.base.visit("Base", visitor)?;
|
||||
|
||||
visitor.leave_region()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SpriteBuilder {
|
||||
common: CommonNodeBuilderData,
|
||||
base_builder: BaseBuilder,
|
||||
texture: Option<Arc<Mutex<Texture>>>,
|
||||
color: Option<Color>,
|
||||
size: Option<f32>,
|
||||
rotation: Option<f32>,
|
||||
}
|
||||
|
||||
impl Default for SpriteBuilder {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SpriteBuilder {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(base_builder: BaseBuilder) -> Self {
|
||||
Self {
|
||||
common: Default::default(),
|
||||
base_builder,
|
||||
texture: None,
|
||||
color: None,
|
||||
size: None,
|
||||
@@ -100,8 +101,6 @@ impl SpriteBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
impl_common_node_builder_methods!();
|
||||
|
||||
pub fn with_texture(mut self, texture: Arc<Mutex<Texture>>) -> Self {
|
||||
self.texture = Some(texture);
|
||||
self
|
||||
@@ -129,7 +128,7 @@ impl SpriteBuilder {
|
||||
|
||||
pub fn build(self) -> Sprite {
|
||||
Sprite {
|
||||
common: From::from(self.common),
|
||||
base: self.base_builder.build(),
|
||||
texture: self.texture,
|
||||
color: self.color.unwrap_or(Color::WHITE),
|
||||
size: self.size.unwrap_or(0.2),
|
||||
|
||||
Reference in New Issue
Block a user