mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
[BREAKING] drop backward compatibility for assets
- use this tool from 1.0.0-rc.1 https://fyrox.rs/blog/post/fyrox-game-engine-1-0-0-rc-1/#migration to migrate the assets
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#![allow(clippy::doc_lazy_continuation)]
|
||||
#![allow(mismatched_lifetime_syntaxes)]
|
||||
|
||||
use crate::track::TrackBinding;
|
||||
use crate::{
|
||||
core::{
|
||||
algebra::{UnitQuaternion, Vector3},
|
||||
@@ -39,7 +40,11 @@ use crate::{
|
||||
track::Track,
|
||||
};
|
||||
use fxhash::FxHashMap;
|
||||
pub use fyrox_core as core;
|
||||
use fyrox_resource::untyped::ResourceKind;
|
||||
use fyrox_resource::{Resource, ResourceData};
|
||||
pub use pose::{AnimationPose, NodePose};
|
||||
pub use signal::{AnimationEvent, AnimationSignal};
|
||||
use std::{
|
||||
collections::VecDeque,
|
||||
error::Error,
|
||||
@@ -50,13 +55,6 @@ use std::{
|
||||
};
|
||||
use value::{nlerp, TrackValue, ValueBinding};
|
||||
|
||||
use crate::container::TrackDataContainer;
|
||||
use crate::track::TrackBinding;
|
||||
pub use fyrox_core as core;
|
||||
use fyrox_resource::untyped::ResourceKind;
|
||||
pub use pose::{AnimationPose, NodePose};
|
||||
pub use signal::{AnimationEvent, AnimationSignal};
|
||||
|
||||
pub mod container;
|
||||
pub mod machine;
|
||||
pub mod pose;
|
||||
@@ -268,7 +266,7 @@ pub type AnimationTracksDataResource = Resource<AnimationTracksData>;
|
||||
/// The code above creates a simple animation that moves a node along X axis in various ways. The usage of the animation
|
||||
/// is only for the sake of completeness of the example. In the real games you need to add the animation to an animation
|
||||
/// player scene node and it will do the job for you.
|
||||
#[derive(Debug, Reflect, PartialEq)]
|
||||
#[derive(Debug, Reflect, Visit, PartialEq)]
|
||||
pub struct Animation<T: EntityId> {
|
||||
name: ImmutableString,
|
||||
tracks_data: AnimationTracksDataResource,
|
||||
@@ -283,79 +281,16 @@ pub struct Animation<T: EntityId> {
|
||||
max_event_capacity: usize,
|
||||
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
root_motion: Option<RootMotion>,
|
||||
// Non-serialized
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
pose: AnimationPose<T>,
|
||||
// Non-serialized
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
events: VecDeque<AnimationEvent>,
|
||||
}
|
||||
|
||||
#[derive(Visit, Default)]
|
||||
struct OldTrack<T: EntityId> {
|
||||
binding: ValueBinding,
|
||||
frames: TrackDataContainer,
|
||||
enabled: bool,
|
||||
node: T,
|
||||
id: Uuid,
|
||||
}
|
||||
|
||||
impl<T: EntityId> Visit for Animation<T> {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
// Backward compatibility.
|
||||
let mut old_tracks = Vec::<OldTrack<T>>::new();
|
||||
if region.is_reading() {
|
||||
if old_tracks.visit("Tracks", &mut region).is_ok() {
|
||||
let mut tracks_data = AnimationTracksData::default();
|
||||
for old_track in old_tracks {
|
||||
self.track_bindings.insert(
|
||||
old_track.id,
|
||||
TrackBinding {
|
||||
enabled: old_track.enabled,
|
||||
target: old_track.node,
|
||||
},
|
||||
);
|
||||
tracks_data.tracks.push(Track {
|
||||
binding: old_track.binding,
|
||||
frames: old_track.frames,
|
||||
id: old_track.id,
|
||||
});
|
||||
}
|
||||
self.tracks_data = AnimationTracksDataResource::new_ok(
|
||||
Uuid::new_v4(),
|
||||
ResourceKind::Embedded,
|
||||
tracks_data,
|
||||
);
|
||||
} else {
|
||||
self.tracks_data.visit("TracksData", &mut region)?;
|
||||
self.track_bindings.visit("TrackBindings", &mut region)?;
|
||||
}
|
||||
} else {
|
||||
self.tracks_data.visit("TracksData", &mut region)?;
|
||||
self.track_bindings.visit("TrackBindings", &mut region)?;
|
||||
}
|
||||
|
||||
let _ = self.name.visit("Name", &mut region);
|
||||
self.time_position.visit("TimePosition", &mut region)?;
|
||||
let _ = self.time_slice.visit("TimeSlice", &mut region);
|
||||
self.speed.visit("Speed", &mut region)?;
|
||||
self.looped.visit("Looped", &mut region)?;
|
||||
self.enabled.visit("Enabled", &mut region)?;
|
||||
self.signals.visit("Signals", &mut region)?;
|
||||
let _ = self
|
||||
.max_event_capacity
|
||||
.visit("MaxEventCapacity", &mut region);
|
||||
let _ = self
|
||||
.root_motion_settings
|
||||
.visit("RootMotionSettings", &mut region);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: EntityId> TypeUuidProvider for Animation<T> {
|
||||
fn type_uuid() -> Uuid {
|
||||
uuid!("aade8e9d-e2cf-401d-a4d1-59c6943645f3")
|
||||
|
||||
@@ -88,25 +88,13 @@ impl<T: EntityId> TrackBinding<T> {
|
||||
/// Track is responsible in animating a property of a single scene node. The track consists up to 4 parametric curves
|
||||
/// that contains the actual property data. Parametric curves allows the engine to perform various interpolations between
|
||||
/// key values.
|
||||
#[derive(Debug, Reflect, Clone, PartialEq)]
|
||||
#[derive(Debug, Reflect, Clone, PartialEq, Visit)]
|
||||
pub struct Track {
|
||||
pub(super) binding: ValueBinding,
|
||||
pub(super) frames: TrackDataContainer,
|
||||
pub(super) id: Uuid,
|
||||
}
|
||||
|
||||
impl Visit for Track {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
let _ = self.binding.visit("Binding", &mut region); // Backward compatibility
|
||||
let _ = self.id.visit("Id", &mut region); // Backward compatibility
|
||||
let _ = self.frames.visit("Frames", &mut region); // Backward compatibility
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Track {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -168,9 +168,7 @@ impl_reflect!(
|
||||
|
||||
impl_visit!(
|
||||
pub struct Curve {
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub id: Uuid,
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub name: String,
|
||||
pub keys: Vec<CurveKey>,
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
use crate::visitor::VisitorVersion;
|
||||
use crate::{
|
||||
replace_slashes,
|
||||
visitor::{
|
||||
@@ -158,20 +157,9 @@ where
|
||||
if region.reading {
|
||||
self.clear();
|
||||
for index in 0..len as usize {
|
||||
// Backward compatibility with the previous version (verbose, non-flat).
|
||||
if region.version == VisitorVersion::Legacy as u32 {
|
||||
if let Ok(mut item_region) = region.enter_region(&make_name(index)) {
|
||||
let mut object = T::default();
|
||||
object.visit("ItemData", &mut item_region)?;
|
||||
self.push(object);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Try to read the new (flattened) version.
|
||||
let mut object = T::default();
|
||||
object.visit(&make_name(index), &mut region)?;
|
||||
self.push(object);
|
||||
}
|
||||
let mut object = T::default();
|
||||
object.visit(&make_name(index), &mut region)?;
|
||||
self.push(object);
|
||||
}
|
||||
} else {
|
||||
for (index, item) in self.iter_mut().enumerate() {
|
||||
|
||||
@@ -83,12 +83,8 @@ use std::{
|
||||
/// Version of the visitor.
|
||||
#[repr(u32)]
|
||||
pub enum VisitorVersion {
|
||||
/// Version of the old format.
|
||||
Legacy = 0,
|
||||
/// Flattened vector structure.
|
||||
VectorFlattening,
|
||||
/// Removal of `[N:` and `{N:` counters in ascii format.
|
||||
AsciiNoCounters,
|
||||
/// The first stable release of Fyrox 1.0.
|
||||
FirstStableRelease,
|
||||
|
||||
/// ^^ Add a new version above this line ^^.
|
||||
///
|
||||
@@ -475,9 +471,6 @@ pub enum Format {
|
||||
}
|
||||
|
||||
impl Visitor {
|
||||
/// Old header marker for binary version.
|
||||
pub const MAGIC_BINARY_OLD: &'static str = "RG3D";
|
||||
|
||||
/// Sequence of bytes that is automatically written at the start when a visitor is encoded into
|
||||
/// bytes. It is written by [Visitor::save_binary_to_file], [Visitor::save_binary_to_memory],
|
||||
/// and [Visitor::save_binary_to_vec].
|
||||
@@ -487,9 +480,6 @@ impl Visitor {
|
||||
/// these bytes are not at the beginning of the given slice.
|
||||
pub const MAGIC_BINARY_CURRENT: &'static str = "FBAF";
|
||||
|
||||
/// Old header marker for ASCII version.
|
||||
pub const MAGIC_ASCII_OLD: &'static str = "FTAF";
|
||||
|
||||
/// Sequence of bytes that is automatically written at the start when a visitor is encoded into
|
||||
/// ascii form. It is written by [Visitor::save_ascii_to_file], [Visitor::save_ascii_to_memory],
|
||||
/// and [Visitor::save_ascii_to_string].
|
||||
@@ -509,13 +499,9 @@ impl Visitor {
|
||||
pub fn detect_format(src: &mut dyn Read) -> Format {
|
||||
let mut magic: [u8; 4] = Default::default();
|
||||
if src.read_exact(&mut magic).is_ok() {
|
||||
if magic.eq(Visitor::MAGIC_BINARY_OLD.as_bytes())
|
||||
|| magic.eq(Visitor::MAGIC_BINARY_CURRENT.as_bytes())
|
||||
{
|
||||
if magic.eq(Visitor::MAGIC_BINARY_CURRENT.as_bytes()) {
|
||||
return Format::Binary;
|
||||
} else if magic.eq(Visitor::MAGIC_ASCII_OLD.as_bytes())
|
||||
|| magic.eq(Visitor::MAGIC_ASCII_CURRENT.as_bytes())
|
||||
{
|
||||
} else if magic.eq(Visitor::MAGIC_ASCII_CURRENT.as_bytes()) {
|
||||
return Format::Ascii;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
use crate::visitor::VisitorVersion;
|
||||
use crate::{
|
||||
pool::{Handle, Pool},
|
||||
visitor::{
|
||||
@@ -332,47 +331,29 @@ impl Reader for AsciiReader<'_> {
|
||||
..VisitorNode::default()
|
||||
};
|
||||
|
||||
if visitor.version < VisitorVersion::AsciiNoCounters as u32 {
|
||||
let field_count: usize = self.src.read_num_until(b':')?;
|
||||
for _ in 0..field_count {
|
||||
node.fields.push(self.read_field()?);
|
||||
}
|
||||
self.src.skip_until(|ch| ch != b']')?;
|
||||
self.src.skip_n(1)?;
|
||||
} else {
|
||||
loop {
|
||||
self.src.skip_ws()?;
|
||||
let next = self.src.peek()?;
|
||||
if next == b']' {
|
||||
self.src.skip_n(1)?;
|
||||
break;
|
||||
}
|
||||
node.fields.push(self.read_field()?);
|
||||
loop {
|
||||
self.src.skip_ws()?;
|
||||
let next = self.src.peek()?;
|
||||
if next == b']' {
|
||||
self.src.skip_n(1)?;
|
||||
break;
|
||||
}
|
||||
node.fields.push(self.read_field()?);
|
||||
}
|
||||
|
||||
self.src.skip_until(|ch| ch != b'{')?;
|
||||
self.src.skip_n(1)?;
|
||||
|
||||
let mut children = Vec::new();
|
||||
if visitor.version < VisitorVersion::AsciiNoCounters as u32 {
|
||||
let child_count: usize = self.src.read_num_until(b':')?;
|
||||
children.reserve(child_count);
|
||||
for _ in 0..child_count {
|
||||
children.push(self.read_node(visitor)?);
|
||||
}
|
||||
self.src.skip_until(|ch| ch != b'}')?;
|
||||
self.src.skip_n(1)?;
|
||||
} else {
|
||||
loop {
|
||||
self.src.skip_ws()?;
|
||||
let next = self.src.peek()?;
|
||||
if next == b'}' {
|
||||
self.src.skip_n(1)?;
|
||||
break;
|
||||
}
|
||||
children.push(self.read_node(visitor)?);
|
||||
|
||||
loop {
|
||||
self.src.skip_ws()?;
|
||||
let next = self.src.peek()?;
|
||||
if next == b'}' {
|
||||
self.src.skip_n(1)?;
|
||||
break;
|
||||
}
|
||||
children.push(self.read_node(visitor)?);
|
||||
}
|
||||
|
||||
node.children.clone_from(&children);
|
||||
@@ -391,9 +372,7 @@ impl Reader for AsciiReader<'_> {
|
||||
|
||||
let magic: [u8; 4] = [src.next()?, src.next()?, src.next()?, src.next()?];
|
||||
|
||||
let version = if magic.eq(Visitor::MAGIC_ASCII_OLD.as_bytes()) {
|
||||
VisitorVersion::Legacy as u32
|
||||
} else if magic.eq(Visitor::MAGIC_ASCII_CURRENT.as_bytes()) {
|
||||
let version = if magic.eq(Visitor::MAGIC_ASCII_CURRENT.as_bytes()) {
|
||||
src.skip_until(|ch| ch != b':')?;
|
||||
src.skip_n(1)?;
|
||||
src.read_num_until::<u32, _>(b';')?
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
use crate::visitor::VisitorVersion;
|
||||
use crate::{
|
||||
pool::{Handle, Pool},
|
||||
visitor::{
|
||||
@@ -246,9 +245,7 @@ impl Reader for BinaryReader<'_> {
|
||||
let mut magic: [u8; 4] = Default::default();
|
||||
src.read_exact(&mut magic)?;
|
||||
|
||||
let version = if magic.eq(Visitor::MAGIC_BINARY_OLD.as_bytes()) {
|
||||
VisitorVersion::Legacy as u32
|
||||
} else if magic.eq(Visitor::MAGIC_BINARY_CURRENT.as_bytes()) {
|
||||
let version = if magic.eq(Visitor::MAGIC_BINARY_CURRENT.as_bytes()) {
|
||||
src.read_u32::<LittleEndian>()?
|
||||
} else {
|
||||
return Err(VisitError::NotSupportedFormat);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
//! Curve resource holds a [`Curve`]
|
||||
|
||||
use crate::{
|
||||
asset::{io::ResourceIo, Resource, ResourceData, CURVE_RESOURCE_UUID},
|
||||
asset::{io::ResourceIo, Resource, ResourceData},
|
||||
core::{
|
||||
io::FileError, math::curve::Curve, reflect::prelude::*, uuid::Uuid, visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
@@ -32,6 +32,7 @@ use std::{
|
||||
fmt::{Display, Formatter},
|
||||
path::Path,
|
||||
};
|
||||
use uuid::uuid;
|
||||
|
||||
pub mod loader;
|
||||
|
||||
@@ -101,7 +102,7 @@ impl ResourceData for CurveResourceState {
|
||||
|
||||
impl TypeUuidProvider for CurveResourceState {
|
||||
fn type_uuid() -> Uuid {
|
||||
CURVE_RESOURCE_UUID
|
||||
uuid!("f28b949f-28a2-4b68-9089-59c234f58b6b")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
use crate::{
|
||||
asset::{
|
||||
io::ResourceIo, manager::ResourceManager, options::ImportOptions, untyped::ResourceKind,
|
||||
Resource, ResourceData, MODEL_RESOURCE_UUID,
|
||||
Resource, ResourceData,
|
||||
},
|
||||
core::{
|
||||
algebra::{UnitQuaternion, Vector3},
|
||||
@@ -76,6 +76,7 @@ use std::{
|
||||
sync::Arc,
|
||||
};
|
||||
use strum_macros::{AsRefStr, EnumString, VariantNames};
|
||||
use uuid::uuid;
|
||||
|
||||
pub mod loader;
|
||||
|
||||
@@ -104,7 +105,7 @@ impl PrefabData for Model {
|
||||
|
||||
impl TypeUuidProvider for Model {
|
||||
fn type_uuid() -> Uuid {
|
||||
MODEL_RESOURCE_UUID
|
||||
uuid!("44cd768f-b4ca-4804-a98c-0adf85577ada")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1188,14 +1188,7 @@ impl Visit for Base {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
if self.name.visit("Name", &mut region).is_err() {
|
||||
// Name was wrapped into `InheritableVariable` previously, so we must maintain
|
||||
// backward compatibility here.
|
||||
let mut region = region.enter_region("Name")?;
|
||||
let mut value = String::default();
|
||||
value.visit("Value", &mut region)?;
|
||||
self.name = ImmutableString::new(value);
|
||||
}
|
||||
self.name.visit("Name", &mut region)?;
|
||||
self.local_transform.visit("Transform", &mut region)?;
|
||||
self.visibility.visit("Visibility", &mut region)?;
|
||||
self.parent.visit("Parent", &mut region)?;
|
||||
@@ -1209,12 +1202,12 @@ impl Visit for Base {
|
||||
self.original_handle_in_resource
|
||||
.visit("Original", &mut region)?;
|
||||
self.tag.visit("Tag", &mut region)?;
|
||||
let _ = self.properties.visit("Properties", &mut region);
|
||||
let _ = self.frustum_culling.visit("FrustumCulling", &mut region);
|
||||
let _ = self.cast_shadows.visit("CastShadows", &mut region);
|
||||
let _ = self.instance_id.visit("InstanceId", &mut region);
|
||||
let _ = self.enabled.visit("Enabled", &mut region);
|
||||
let _ = self.render_mask.visit("RenderMask", &mut region);
|
||||
self.properties.visit("Properties", &mut region)?;
|
||||
self.frustum_culling.visit("FrustumCulling", &mut region)?;
|
||||
self.cast_shadows.visit("CastShadows", &mut region)?;
|
||||
self.instance_id.visit("InstanceId", &mut region)?;
|
||||
self.enabled.visit("Enabled", &mut region)?;
|
||||
self.render_mask.visit("RenderMask", &mut region)?;
|
||||
|
||||
// Script visiting may fail for various reasons:
|
||||
//
|
||||
@@ -1225,15 +1218,6 @@ impl Visit for Base {
|
||||
// None of the reasons are fatal and we should still give an ability to load such node
|
||||
// to edit or remove it.
|
||||
|
||||
// This block is needed for backward compatibility
|
||||
let mut old_script = None;
|
||||
if region.is_reading() && visit_opt_script("Script", &mut old_script, &mut region).is_ok() {
|
||||
if let Some(old_script) = old_script {
|
||||
self.scripts.push(ScriptRecord::new(old_script));
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let _ = self.scripts.visit("Scripts", &mut region);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -58,11 +58,9 @@ use strum_macros::{AsRefStr, EnumString, VariantNames};
|
||||
#[derive(Clone, Debug, Visit, PartialEq, Reflect)]
|
||||
pub struct BallJoint {
|
||||
/// Whether angular limits are enabled or not. Default is `false`
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub limits_enabled: bool,
|
||||
|
||||
/// Allowed angles range for the joint (in radians).
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub limits_angles: Range<f32>,
|
||||
}
|
||||
|
||||
@@ -85,11 +83,9 @@ pub struct FixedJoint;
|
||||
#[derive(Clone, Debug, Visit, PartialEq, Reflect)]
|
||||
pub struct PrismaticJoint {
|
||||
/// Whether linear limits along local X axis of the joint are enabled or not. Default is `false`
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub limits_enabled: bool,
|
||||
|
||||
/// Allowed linear distance range along local X axis of the joint.
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub limits: Range<f32>,
|
||||
}
|
||||
|
||||
@@ -177,7 +173,6 @@ pub struct Joint {
|
||||
pub(crate) params: InheritableVariable<JointParams>,
|
||||
|
||||
#[reflect(setter = "set_motor_params")]
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub(crate) motor_params: InheritableVariable<JointMotorParams>,
|
||||
|
||||
#[reflect(setter = "set_body1")]
|
||||
@@ -186,7 +181,6 @@ pub struct Joint {
|
||||
#[reflect(setter = "set_body2")]
|
||||
pub(crate) body2: InheritableVariable<Handle<RigidBody>>,
|
||||
|
||||
#[visit(optional)] // Backward compatibility
|
||||
#[reflect(setter = "set_contacts_enabled")]
|
||||
pub(crate) contacts_enabled: InheritableVariable<bool>,
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ use crate::{
|
||||
visitor::prelude::*,
|
||||
},
|
||||
graph::{constructor::ConstructorProvider, BaseSceneGraph},
|
||||
material::{self, Material, MaterialResource},
|
||||
material::{Material, MaterialResource},
|
||||
renderer::{self, bundle::RenderContext},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
@@ -170,7 +170,7 @@ impl Hash for RectangleVertex {
|
||||
/// image, but just changing portion for rendering. Keep in mind that the coordinates are normalized
|
||||
/// which means `[0; 0]` corresponds to top-left corner of the texture and `[1; 1]` corresponds to
|
||||
/// right-bottom corner.
|
||||
#[derive(Reflect, Debug, Clone, ComponentProvider)]
|
||||
#[derive(Reflect, Debug, Clone, Visit, ComponentProvider)]
|
||||
#[reflect(derived_type = "Node")]
|
||||
pub struct Rectangle {
|
||||
base: Base,
|
||||
@@ -190,34 +190,6 @@ pub struct Rectangle {
|
||||
flip_y: InheritableVariable<bool>,
|
||||
}
|
||||
|
||||
impl Visit for Rectangle {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
if region.is_reading() {
|
||||
if let Some(material) =
|
||||
material::visit_old_texture_as_material(&mut region, Material::standard_2d)
|
||||
{
|
||||
self.material = material.into();
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
|
||||
self.base.visit("Base", &mut region)?;
|
||||
self.color.visit("Color", &mut region)?;
|
||||
|
||||
// Backward compatibility.
|
||||
let _ = self.flip_x.visit("FlipX", &mut region);
|
||||
let _ = self.flip_y.visit("FlipY", &mut region);
|
||||
let _ = self.uv_rect.visit("UvRect", &mut region);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Rectangle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -1742,7 +1742,7 @@ impl Visit for Graph {
|
||||
self.sound_context.visit("SoundContext", &mut region)?;
|
||||
self.physics.visit("PhysicsWorld", &mut region)?;
|
||||
self.physics2d.visit("PhysicsWorld2D", &mut region)?;
|
||||
let _ = self.lightmap.visit("Lightmap", &mut region);
|
||||
self.lightmap.visit("Lightmap", &mut region)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1975,7 +1975,6 @@ mod test {
|
||||
script::ScriptTrait,
|
||||
};
|
||||
use fyrox_core::algebra::Vector2;
|
||||
use fyrox_core::append_extension;
|
||||
use fyrox_resource::untyped::ResourceKind;
|
||||
use std::{fs, path::Path, sync::Arc};
|
||||
|
||||
@@ -2184,10 +2183,7 @@ mod test {
|
||||
fn save_scene(scene: &mut Scene, path: &Path) {
|
||||
let mut visitor = Visitor::new();
|
||||
scene.save("Scene", &mut visitor).unwrap();
|
||||
visitor.save_binary_to_file(path).unwrap();
|
||||
visitor
|
||||
.save_ascii_to_file(append_extension(path, "txt"))
|
||||
.unwrap();
|
||||
visitor.save_ascii_to_file(path).unwrap();
|
||||
}
|
||||
|
||||
fn make_resource_manager(root: &Path) -> ResourceManager {
|
||||
|
||||
@@ -60,27 +60,21 @@ use strum_macros::{AsRefStr, EnumString, VariantNames};
|
||||
#[derive(Clone, Debug, Visit, PartialEq, Reflect)]
|
||||
pub struct BallJoint {
|
||||
/// Whether X angular limits are enabled or not. Default is `false`
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub x_limits_enabled: bool,
|
||||
|
||||
/// Allowed angle range around local X axis of the joint (in radians).
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub x_limits_angles: Range<f32>,
|
||||
|
||||
/// Whether Y angular limits are enabled or not. Default is `false`
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub y_limits_enabled: bool,
|
||||
|
||||
/// Allowed angle range around local Y axis of the joint (in radians).
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub y_limits_angles: Range<f32>,
|
||||
|
||||
/// Whether Z angular limits are enabled or not. Default is `false`
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub z_limits_enabled: bool,
|
||||
|
||||
/// Allowed angle range around local Z axis of the joint (in radians).
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub z_limits_angles: Range<f32>,
|
||||
}
|
||||
|
||||
@@ -107,11 +101,9 @@ pub struct FixedJoint;
|
||||
#[derive(Clone, Debug, Visit, PartialEq, Reflect)]
|
||||
pub struct PrismaticJoint {
|
||||
/// Whether linear limits along local joint X axis are enabled or not. Default is `false`
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub limits_enabled: bool,
|
||||
|
||||
/// The min an max relative position of the attached bodies along local X axis of the joint.
|
||||
#[visit(optional)] // Backward compatibility
|
||||
/// The min and max relative position of the attached bodies along local X axis of the joint.
|
||||
pub limits: Range<f32>,
|
||||
}
|
||||
|
||||
@@ -130,11 +122,9 @@ impl Default for PrismaticJoint {
|
||||
#[derive(Clone, Debug, Visit, PartialEq, Reflect)]
|
||||
pub struct RevoluteJoint {
|
||||
/// Whether angular limits around local X axis of the joint are enabled or not. Default is `false`
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub limits_enabled: bool,
|
||||
|
||||
/// Allowed angle range around local X axis of the joint (in radians).
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub limits: Range<f32>,
|
||||
}
|
||||
|
||||
@@ -224,7 +214,6 @@ pub struct Joint {
|
||||
pub(crate) params: InheritableVariable<JointParams>,
|
||||
|
||||
#[reflect(setter = "set_motor_params")]
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub(crate) motor_params: InheritableVariable<JointMotorParams>,
|
||||
|
||||
#[reflect(setter = "set_body1")]
|
||||
@@ -234,11 +223,9 @@ pub struct Joint {
|
||||
pub(crate) body2: InheritableVariable<Handle<RigidBody>>,
|
||||
|
||||
#[reflect(setter = "set_contacts_enabled")]
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub(crate) contacts_enabled: InheritableVariable<bool>,
|
||||
|
||||
#[reflect(setter = "set_auto_rebinding")]
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub(crate) auto_rebind: InheritableVariable<bool>,
|
||||
|
||||
#[visit(optional)]
|
||||
|
||||
@@ -43,7 +43,7 @@ use crate::{
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
Uuid,
|
||||
},
|
||||
material::{self, Material, MaterialResource, MaterialResourceExtension},
|
||||
material::{Material, MaterialResource, MaterialResourceExtension},
|
||||
resource::texture::{TextureKind, TexturePixelKind, TextureResource, TextureResourceExtension},
|
||||
scene::{
|
||||
mesh::{
|
||||
@@ -1250,7 +1250,7 @@ impl SurfaceResourceExtension for SurfaceResource {
|
||||
///
|
||||
/// This code snippet creates a cone surface instance, check the docs for [`SurfaceData`] for more info about built-in
|
||||
/// methods.
|
||||
#[derive(Debug, Reflect, PartialEq)]
|
||||
#[derive(Debug, Reflect, Visit, PartialEq)]
|
||||
pub struct Surface {
|
||||
pub(crate) data: InheritableVariable<SurfaceResource>,
|
||||
|
||||
@@ -1271,6 +1271,7 @@ pub struct Surface {
|
||||
// like so: iterate over all vertices and weight data and calculate index of node handle that
|
||||
// associated with vertex in `bones` array and store it as bone index in vertex.
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
pub(crate) vertex_weights: Vec<VertexWeightSet>,
|
||||
}
|
||||
|
||||
@@ -1294,29 +1295,6 @@ impl Clone for Surface {
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Surface {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
// Backward compatibility.
|
||||
if region.is_reading() {
|
||||
if let Some(material) = material::visit_old_material(&mut region) {
|
||||
self.material = material.into();
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
|
||||
self.data.visit("Data", &mut region)?;
|
||||
self.bones.visit("Bones", &mut region)?;
|
||||
let _ = self.unique_material.visit("UniqueMaterial", &mut region); // Backward compatibility.
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Surface {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -21,10 +21,7 @@
|
||||
//! Contains most common vertex formats and their layouts.
|
||||
|
||||
use crate::{
|
||||
core::{
|
||||
algebra::{Vector2, Vector3, Vector4},
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
},
|
||||
core::algebra::{Vector2, Vector3, Vector4},
|
||||
scene::mesh::buffer::{
|
||||
VertexAttributeDataType, VertexAttributeDescriptor, VertexAttributeUsage, VertexTrait,
|
||||
},
|
||||
@@ -290,114 +287,3 @@ impl Hash for SimpleVertex {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fat vertex used before customizable VertexBuffer was made.
|
||||
/// It is used only to be able to load scenes in old formats to
|
||||
/// keep backward compatibility.
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[repr(C)] // OpenGL expects this structure packed as in C
|
||||
pub struct OldVertex {
|
||||
/// Position of vertex in local coordinates.
|
||||
pub position: Vector3<f32>,
|
||||
/// Texture coordinates.
|
||||
pub tex_coord: Vector2<f32>,
|
||||
/// Normal in local coordinates.
|
||||
pub normal: Vector3<f32>,
|
||||
/// Tangent vector in local coordinates.
|
||||
pub tangent: Vector4<f32>,
|
||||
/// Array of bone weights. Unused bones will have 0.0 weight so they won't
|
||||
/// impact the shape of mesh.
|
||||
pub bone_weights: [f32; 4],
|
||||
/// Array of bone indices. It has indices of bones in array of bones of a
|
||||
/// surface.
|
||||
pub bone_indices: [u8; 4],
|
||||
/// Second texture coordinates.
|
||||
pub second_tex_coord: Vector2<f32>,
|
||||
}
|
||||
|
||||
impl Visit for OldVertex {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
self.position.visit("Position", &mut region)?;
|
||||
self.tex_coord.visit("TexCoord", &mut region)?;
|
||||
self.second_tex_coord.visit("SecondTexCoord", &mut region)?;
|
||||
self.normal.visit("Normal", &mut region)?;
|
||||
self.tangent.visit("Tangent", &mut region)?;
|
||||
|
||||
self.bone_weights[0].visit("Weight0", &mut region)?;
|
||||
self.bone_weights[1].visit("Weight1", &mut region)?;
|
||||
self.bone_weights[2].visit("Weight2", &mut region)?;
|
||||
self.bone_weights[3].visit("Weight3", &mut region)?;
|
||||
|
||||
self.bone_indices[0].visit("BoneIndex0", &mut region)?;
|
||||
self.bone_indices[1].visit("BoneIndex1", &mut region)?;
|
||||
self.bone_indices[2].visit("BoneIndex2", &mut region)?;
|
||||
self.bone_indices[3].visit("BoneIndex3", &mut region)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl VertexTrait for OldVertex {
|
||||
fn layout() -> &'static [VertexAttributeDescriptor] {
|
||||
&[
|
||||
VertexAttributeDescriptor {
|
||||
usage: VertexAttributeUsage::Position,
|
||||
data_type: VertexAttributeDataType::F32,
|
||||
size: 3,
|
||||
divisor: 0,
|
||||
shader_location: 0,
|
||||
normalized: false,
|
||||
},
|
||||
VertexAttributeDescriptor {
|
||||
usage: VertexAttributeUsage::TexCoord0,
|
||||
data_type: VertexAttributeDataType::F32,
|
||||
size: 2,
|
||||
divisor: 0,
|
||||
shader_location: 1,
|
||||
normalized: false,
|
||||
},
|
||||
VertexAttributeDescriptor {
|
||||
usage: VertexAttributeUsage::Normal,
|
||||
data_type: VertexAttributeDataType::F32,
|
||||
size: 3,
|
||||
divisor: 0,
|
||||
shader_location: 2,
|
||||
normalized: false,
|
||||
},
|
||||
VertexAttributeDescriptor {
|
||||
usage: VertexAttributeUsage::Tangent,
|
||||
data_type: VertexAttributeDataType::F32,
|
||||
size: 4,
|
||||
divisor: 0,
|
||||
shader_location: 3,
|
||||
normalized: false,
|
||||
},
|
||||
VertexAttributeDescriptor {
|
||||
usage: VertexAttributeUsage::BoneWeight,
|
||||
data_type: VertexAttributeDataType::F32,
|
||||
size: 4,
|
||||
divisor: 0,
|
||||
shader_location: 4,
|
||||
normalized: false,
|
||||
},
|
||||
VertexAttributeDescriptor {
|
||||
usage: VertexAttributeUsage::BoneIndices,
|
||||
data_type: VertexAttributeDataType::U8,
|
||||
size: 4,
|
||||
divisor: 0,
|
||||
shader_location: 5,
|
||||
normalized: false,
|
||||
},
|
||||
VertexAttributeDescriptor {
|
||||
usage: VertexAttributeUsage::TexCoord1,
|
||||
data_type: VertexAttributeDataType::F32,
|
||||
size: 2,
|
||||
divisor: 0,
|
||||
shader_location: 6,
|
||||
normalized: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,10 +69,8 @@ use crate::{
|
||||
graphics::PolygonFillMode,
|
||||
resource::texture::TextureResource,
|
||||
scene::{
|
||||
base::BaseBuilder,
|
||||
debug::SceneDrawingContext,
|
||||
graph::{Graph, GraphPerformanceStatistics, GraphUpdateSwitches},
|
||||
navmesh::NavigationalMeshBuilder,
|
||||
node::Node,
|
||||
skybox::{SkyBox, SkyBoxKind},
|
||||
sound::SoundEngine,
|
||||
@@ -569,24 +567,9 @@ impl Scene {
|
||||
|
||||
self.graph.visit("Graph", &mut region)?;
|
||||
self.enabled.visit("Enabled", &mut region)?;
|
||||
let _ = self
|
||||
.rendering_options
|
||||
.visit("RenderingOptions", &mut region);
|
||||
let _ = self.sky_box.visit("SkyBox", &mut region);
|
||||
|
||||
// Backward compatibility.
|
||||
if region.is_reading() {
|
||||
let mut navmeshes = NavMeshContainer::default();
|
||||
if navmeshes.visit("NavMeshes", &mut region).is_ok() {
|
||||
for (i, navmesh) in navmeshes.iter().enumerate() {
|
||||
NavigationalMeshBuilder::new(
|
||||
BaseBuilder::new().with_name(format!("Navmesh{i}")),
|
||||
)
|
||||
.with_navmesh(navmesh.clone())
|
||||
.build(&mut self.graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.rendering_options
|
||||
.visit("RenderingOptions", &mut region)?;
|
||||
self.sky_box.visit("SkyBox", &mut region)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -751,7 +751,7 @@ mod test {
|
||||
fn save_scene(scene: &mut Scene, path: &Path) {
|
||||
let mut visitor = Visitor::new();
|
||||
scene.save("Scene", &mut visitor).unwrap();
|
||||
visitor.save_binary_to_file(path).unwrap();
|
||||
visitor.save_ascii_to_file(path).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -39,7 +39,6 @@ pub struct BaseEmitter {
|
||||
#[visit(rename = "SpawnRate")]
|
||||
particle_spawn_rate: u32,
|
||||
/// Maximum amount of particles emitter can emit. Unlimited if < 0
|
||||
#[visit(optional)] // Backward compatibility
|
||||
max_particles: Option<u32>,
|
||||
/// Range of initial lifetime of a particle
|
||||
#[visit(rename = "LifeTime")]
|
||||
|
||||
@@ -36,7 +36,7 @@ use crate::{
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
},
|
||||
material::{self, Material, MaterialResource},
|
||||
material::{Material, MaterialResource},
|
||||
rand::{prelude::StdRng, RngCore, SeedableRng},
|
||||
renderer::{self, bundle::RenderContext},
|
||||
scene::{
|
||||
@@ -309,37 +309,13 @@ impl Visit for ParticleSystem {
|
||||
self.is_playing.visit("Enabled", &mut region)?;
|
||||
self.particles.visit("Particles", &mut region)?;
|
||||
self.free_particles.visit("FreeParticles", &mut region)?;
|
||||
let _ = self.rng.visit("Rng", &mut region);
|
||||
let _ = self.visible_distance.visit("VisibleDistance", &mut region);
|
||||
let _ = self
|
||||
.coordinate_system
|
||||
.visit("CoordinateSystem", &mut region);
|
||||
let _ = self.fadeout_margin.visit("FadeoutMargin", &mut region);
|
||||
|
||||
// Backward compatibility.
|
||||
if region.is_reading() {
|
||||
if let Some(material) = material::visit_old_texture_as_material(
|
||||
&mut region,
|
||||
Material::standard_particle_system,
|
||||
) {
|
||||
self.material = material.into();
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
|
||||
let mut soft_boundary_sharpness_factor = 100.0;
|
||||
if soft_boundary_sharpness_factor
|
||||
.visit("SoftBoundarySharpnessFactor", &mut region)
|
||||
.is_ok()
|
||||
{
|
||||
self.material.data_ref().set_property(
|
||||
"softBoundarySharpnessFactor",
|
||||
soft_boundary_sharpness_factor,
|
||||
);
|
||||
}
|
||||
self.rng.visit("Rng", &mut region)?;
|
||||
self.visible_distance
|
||||
.visit("VisibleDistance", &mut region)?;
|
||||
self.coordinate_system
|
||||
.visit("CoordinateSystem", &mut region)?;
|
||||
self.fadeout_margin.visit("FadeoutMargin", &mut region)?;
|
||||
self.material.visit("Material", &mut region)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ use crate::{
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
},
|
||||
graph::{constructor::ConstructorProvider, BaseSceneGraph},
|
||||
material::{self, Material, MaterialResource},
|
||||
material::{Material, MaterialResource},
|
||||
renderer::{self, bundle::RenderContext},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
@@ -152,7 +152,7 @@ impl VertexTrait for SpriteVertex {
|
||||
/// **does not** reuse it. Ideally, you should reuse the shared material across multiple instances
|
||||
/// to get the best possible performance. Otherwise, each your sprite will be put in a separate batch
|
||||
/// which will force your GPU to render a single sprite in dedicated draw call which is quite slow.
|
||||
#[derive(Debug, Reflect, Clone, ComponentProvider)]
|
||||
#[derive(Debug, Reflect, Clone, ComponentProvider, Visit)]
|
||||
#[reflect(derived_type = "Node")]
|
||||
pub struct Sprite {
|
||||
base: Base,
|
||||
@@ -179,36 +179,6 @@ pub struct Sprite {
|
||||
flip_y: InheritableVariable<bool>,
|
||||
}
|
||||
|
||||
impl Visit for Sprite {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
if region.is_reading() {
|
||||
if let Some(material) =
|
||||
material::visit_old_texture_as_material(&mut region, Material::standard_sprite)
|
||||
{
|
||||
self.material = material.into();
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
} else {
|
||||
self.material.visit("Material", &mut region)?;
|
||||
}
|
||||
|
||||
self.base.visit("Base", &mut region)?;
|
||||
self.color.visit("Color", &mut region)?;
|
||||
self.size.visit("Size", &mut region)?;
|
||||
self.rotation.visit("Rotation", &mut region)?;
|
||||
|
||||
// Backward compatibility.
|
||||
let _ = self.flip_x.visit("FlipX", &mut region);
|
||||
let _ = self.flip_y.visit("FlipY", &mut region);
|
||||
let _ = self.uv_rect.visit("UvRect", &mut region);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Sprite {
|
||||
type Target = Base;
|
||||
|
||||
|
||||
@@ -79,13 +79,12 @@ mod quadtree;
|
||||
|
||||
use crate::scene::node::constructor::NodeConstructor;
|
||||
pub use brushstroke::*;
|
||||
use fyrox_core::visitor::pod::PodVecView;
|
||||
use fyrox_graph::constructor::ConstructorProvider;
|
||||
|
||||
use super::collider::BitMask;
|
||||
|
||||
/// Current implementation version marker.
|
||||
pub const VERSION: u8 = 2;
|
||||
pub const VERSION: u8 = 0;
|
||||
|
||||
lazy_static! {
|
||||
/// Solid white texture
|
||||
@@ -418,58 +417,22 @@ impl Visit for Chunk {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
let mut version = VERSION;
|
||||
let _ = version.visit("Version", &mut region);
|
||||
version.visit("Version", &mut region)?;
|
||||
|
||||
match version {
|
||||
0 => {
|
||||
let mut height_map = Vec::<f32>::new();
|
||||
let mut view = PodVecView::from_pod_vec(&mut height_map);
|
||||
view.visit("Heightmap", &mut region)?;
|
||||
|
||||
self.position.visit("Position", &mut region)?;
|
||||
|
||||
let mut width = 0.0f32;
|
||||
width.visit("Width", &mut region)?;
|
||||
let mut length = 0.0f32;
|
||||
length.visit("Length", &mut region)?;
|
||||
self.physical_size = Vector2::new(width, length);
|
||||
|
||||
let mut width_point_count = 0u32;
|
||||
width_point_count.visit("WidthPointCount", &mut region)?;
|
||||
let mut length_point_count = 0u32;
|
||||
length_point_count.visit("LengthPointCount", &mut region)?;
|
||||
self.height_map_size = Vector2::new(width_point_count, length_point_count);
|
||||
|
||||
self.grid_position = Vector2::new(
|
||||
(self.position.x / width) as i32,
|
||||
(self.position.y / length) as i32,
|
||||
);
|
||||
|
||||
self.heightmap = Some(make_height_map_texture(
|
||||
height_map,
|
||||
Vector2::new(width_point_count, length_point_count),
|
||||
));
|
||||
if let VERSION = version {
|
||||
self.heightmap.visit("Heightmap", &mut region)?;
|
||||
self.hole_mask.visit("HoleMask", &mut region)?;
|
||||
// We do not need to visit position, since its value is implied by grid_position.
|
||||
//self.position.visit("Position", &mut region)?;
|
||||
self.physical_size.visit("PhysicalSize", &mut region)?;
|
||||
self.height_map_size.visit("HeightMapSize", &mut region)?;
|
||||
self.layer_masks.visit("LayerMasks", &mut region)?;
|
||||
self.grid_position.visit("GridPosition", &mut region)?;
|
||||
// Set position to have the value implied by grid_position
|
||||
if region.is_reading() {
|
||||
self.position = self.position()
|
||||
}
|
||||
1 | VERSION => {
|
||||
self.heightmap.visit("Heightmap", &mut region)?;
|
||||
let _ = self.hole_mask.visit("HoleMask", &mut region);
|
||||
// We do not need to visit position, since its value is implied by grid_position.
|
||||
//self.position.visit("Position", &mut region)?;
|
||||
self.physical_size.visit("PhysicalSize", &mut region)?;
|
||||
self.height_map_size.visit("HeightMapSize", &mut region)?;
|
||||
self.layer_masks.visit("LayerMasks", &mut region)?;
|
||||
self.grid_position.visit("GridPosition", &mut region)?;
|
||||
// Set position to have the value implied by grid_position
|
||||
if region.is_reading() {
|
||||
self.position = self.position()
|
||||
}
|
||||
let _ = self.block_size.visit("BlockSize", &mut region);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
if region.is_reading() && version < 2 {
|
||||
self.create_margin();
|
||||
self.block_size.visit("BlockSize", &mut region)?;
|
||||
}
|
||||
|
||||
self.quad_tree = Mutex::new(make_quad_tree(
|
||||
@@ -1151,151 +1114,29 @@ impl Default for Terrain {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Visit)]
|
||||
struct OldLayer {
|
||||
pub material: MaterialResource,
|
||||
pub mask_property_name: String,
|
||||
pub chunk_masks: Vec<TextureResource>,
|
||||
}
|
||||
|
||||
impl Default for OldLayer {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
material: MaterialResource::new_ok(
|
||||
Uuid::new_v4(),
|
||||
Default::default(),
|
||||
Material::standard_terrain(),
|
||||
),
|
||||
mask_property_name: "maskTexture".to_string(),
|
||||
chunk_masks: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Terrain {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
let mut version = VERSION;
|
||||
let _ = version.visit("Version", &mut region);
|
||||
version.visit("Version", &mut region)?;
|
||||
|
||||
match version {
|
||||
0 => {
|
||||
// Old version.
|
||||
self.base.visit("Base", &mut region)?;
|
||||
|
||||
let mut layers =
|
||||
InheritableVariable::<Vec<OldLayer>>::new_modified(Default::default());
|
||||
layers.visit("Layers", &mut region)?;
|
||||
|
||||
let mut width = 0.0f32;
|
||||
width.visit("Width", &mut region)?;
|
||||
let mut length = 0.0f32;
|
||||
length.visit("Length", &mut region)?;
|
||||
|
||||
let mut mask_resolution = 0.0f32;
|
||||
mask_resolution.visit("MaskResolution", &mut region)?;
|
||||
|
||||
let mut height_map_resolution = 0.0f32;
|
||||
height_map_resolution.visit("HeightMapResolution", &mut region)?;
|
||||
|
||||
let mut chunks = Vec::<Chunk>::new();
|
||||
chunks.visit("Chunks", &mut region)?;
|
||||
|
||||
let mut width_chunks = 0u32;
|
||||
width_chunks.visit("WidthChunks", &mut region)?;
|
||||
self.width_chunks = (0..(width_chunks as i32)).into();
|
||||
|
||||
let mut length_chunks = 0u32;
|
||||
length_chunks.visit("LengthChunks", &mut region)?;
|
||||
self.length_chunks = (0..(length_chunks as i32)).into();
|
||||
|
||||
self.chunk_size =
|
||||
Vector2::new(width / width_chunks as f32, length / length_chunks as f32).into();
|
||||
|
||||
self.mask_size = Vector2::new(
|
||||
(self.chunk_size.x * mask_resolution) as u32,
|
||||
(self.chunk_size.y * mask_resolution) as u32,
|
||||
)
|
||||
.into();
|
||||
self.height_map_size = Vector2::new(
|
||||
(self.chunk_size.x * height_map_resolution) as u32,
|
||||
(self.chunk_size.y * height_map_resolution) as u32,
|
||||
)
|
||||
.into();
|
||||
|
||||
// Convert to new format.
|
||||
for mut layer in layers.take() {
|
||||
for chunk in chunks.iter_mut().rev() {
|
||||
chunk.layer_masks.push(layer.chunk_masks.pop().unwrap());
|
||||
}
|
||||
|
||||
// TODO: Due to the bug in resource system, material properties are not kept in sync
|
||||
// so here we must re-create the material and put every property from the old material
|
||||
// to the new.
|
||||
let new_material = Material::standard_terrain();
|
||||
|
||||
// TODO
|
||||
/*
|
||||
let mut material_state = layer.material.state();
|
||||
if let Some(material) = material_state.data() {
|
||||
for (name, value) in material.properties() {
|
||||
Log::verify(new_material.set_property(name.clone(), value.clone()));
|
||||
}
|
||||
}*/
|
||||
|
||||
self.layers.push(Layer {
|
||||
material: MaterialResource::new_ok(
|
||||
Uuid::new_v4(),
|
||||
Default::default(),
|
||||
new_material,
|
||||
),
|
||||
mask_property_name: layer.mask_property_name,
|
||||
..Default::default()
|
||||
});
|
||||
}
|
||||
|
||||
self.chunks = chunks.into();
|
||||
}
|
||||
1 | VERSION => {
|
||||
// Current version
|
||||
self.base.visit("Base", &mut region)?;
|
||||
let _ = self.holes_enabled.visit("HolesEnabled", &mut region);
|
||||
self.layers.visit("Layers", &mut region)?;
|
||||
self.chunk_size.visit("ChunkSize", &mut region)?;
|
||||
self.width_chunks.visit("WidthChunks", &mut region)?;
|
||||
self.length_chunks.visit("LengthChunks", &mut region)?;
|
||||
self.height_map_size.visit("HeightMapSize", &mut region)?;
|
||||
let _ = self.block_size.visit("BlockSize", &mut region);
|
||||
self.mask_size.visit("MaskSize", &mut region)?;
|
||||
self.chunks.visit("Chunks", &mut region)?;
|
||||
}
|
||||
_ => (),
|
||||
if let VERSION = version {
|
||||
// Current version
|
||||
self.base.visit("Base", &mut region)?;
|
||||
self.holes_enabled.visit("HolesEnabled", &mut region)?;
|
||||
self.layers.visit("Layers", &mut region)?;
|
||||
self.chunk_size.visit("ChunkSize", &mut region)?;
|
||||
self.width_chunks.visit("WidthChunks", &mut region)?;
|
||||
self.length_chunks.visit("LengthChunks", &mut region)?;
|
||||
self.height_map_size.visit("HeightMapSize", &mut region)?;
|
||||
self.block_size.visit("BlockSize", &mut region)?;
|
||||
self.mask_size.visit("MaskSize", &mut region)?;
|
||||
self.chunks.visit("Chunks", &mut region)?;
|
||||
}
|
||||
|
||||
if region.is_reading() {
|
||||
self.geometry = TerrainGeometry::new(*self.block_size);
|
||||
if version < 2 {
|
||||
Log::info(format!("Updating terrain to version: {VERSION}"));
|
||||
*self.height_map_size = self.height_map_size.map(|x| x + 2);
|
||||
for c in self.chunks.iter() {
|
||||
if c.height_map_size() != self.height_map_size() {
|
||||
Log::err(format!(
|
||||
"Terrain version update failure, height map size mismatch: {} != {}",
|
||||
c.height_map_size(),
|
||||
self.height_map_size()
|
||||
));
|
||||
}
|
||||
}
|
||||
for pos in self
|
||||
.chunks
|
||||
.iter()
|
||||
.map(|c| c.grid_position)
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
self.align_chunk_margins(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -92,7 +92,7 @@ use std::{
|
||||
};
|
||||
|
||||
/// Current implementation version marker.
|
||||
pub const VERSION: u8 = 1;
|
||||
pub const VERSION: u8 = 0;
|
||||
|
||||
lazy_static! {
|
||||
/// The default material for tiles that have no material set.
|
||||
@@ -979,27 +979,12 @@ impl Visit for TileMap {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
let mut version = if region.is_reading() { 0 } else { VERSION };
|
||||
let _ = version.visit("Version", &mut region);
|
||||
version.visit("Version", &mut region)?;
|
||||
self.base.visit("Base", &mut region)?;
|
||||
self.tile_set.visit("TileSet", &mut region)?;
|
||||
self.tile_scale.visit("TileScale", &mut region)?;
|
||||
self.active_brush.visit("ActiveBrush", &mut region)?;
|
||||
match version {
|
||||
0 => {
|
||||
let mut tiles = InheritableVariable::new_non_modified(Tiles::default());
|
||||
let result = tiles.visit("Tiles", &mut region);
|
||||
result?;
|
||||
let mut data = TileMapData::default();
|
||||
for (p, h) in tiles.iter() {
|
||||
data.set(*p, *h);
|
||||
}
|
||||
self.tiles = Some(Resource::new_ok(
|
||||
Uuid::new_v4(),
|
||||
ResourceKind::Embedded,
|
||||
data,
|
||||
))
|
||||
.into();
|
||||
}
|
||||
VERSION => {
|
||||
self.tiles.visit("Tiles", &mut region)?;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ use crate::{
|
||||
Mesh,
|
||||
},
|
||||
utils::{
|
||||
astar::{Graph, GraphVertex, PathError, PathKind, VertexData, VertexDataProvider},
|
||||
astar::{Graph, PathError, PathKind, VertexData, VertexDataProvider},
|
||||
raw_mesh::{RawMeshBuilder, RawVertex},
|
||||
},
|
||||
};
|
||||
@@ -94,22 +94,7 @@ impl Visit for Navmesh {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
// Backward compatibility.
|
||||
if region.is_reading() {
|
||||
let mut pathfinder = Graph::<GraphVertex>::new();
|
||||
if pathfinder.visit("PathFinder", &mut region).is_ok() {
|
||||
self.vertices = pathfinder
|
||||
.vertices
|
||||
.iter()
|
||||
.map(|v| v.position)
|
||||
.collect::<Vec<_>>();
|
||||
} else {
|
||||
self.vertices.visit("Vertices", &mut region)?;
|
||||
}
|
||||
} else {
|
||||
self.vertices.visit("Vertices", &mut region)?;
|
||||
}
|
||||
|
||||
self.vertices.visit("Vertices", &mut region)?;
|
||||
self.triangles.visit("Triangles", &mut region)?;
|
||||
|
||||
drop(region);
|
||||
|
||||
+4
-126
@@ -10,14 +10,12 @@ use fyrox_core::{
|
||||
algebra::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4},
|
||||
color::Color,
|
||||
io::FileError,
|
||||
parking_lot::Mutex,
|
||||
reflect::prelude::*,
|
||||
sstorage::ImmutableString,
|
||||
uuid::{uuid, Uuid},
|
||||
visitor::{prelude::*, RegionGuard},
|
||||
SafeLock, TypeUuidProvider,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
};
|
||||
use fyrox_graphics::gpu_program::SamplerFallback;
|
||||
use fyrox_resource::{
|
||||
io::ResourceIo,
|
||||
manager::{BuiltInResource, ResourceManager},
|
||||
@@ -609,40 +607,6 @@ pub struct Material {
|
||||
resource_bindings: FxHashMap<ImmutableString, MaterialResourceBinding>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Visit, Clone, Reflect)]
|
||||
enum OldMaterialProperty {
|
||||
Float(f32),
|
||||
FloatArray(Vec<f32>),
|
||||
Int(i32),
|
||||
IntArray(Vec<i32>),
|
||||
UInt(u32),
|
||||
UIntArray(Vec<u32>),
|
||||
Vector2(Vector2<f32>),
|
||||
Vector2Array(Vec<Vector2<f32>>),
|
||||
Vector3(Vector3<f32>),
|
||||
Vector3Array(Vec<Vector3<f32>>),
|
||||
Vector4(Vector4<f32>),
|
||||
Vector4Array(Vec<Vector4<f32>>),
|
||||
Matrix2(Matrix2<f32>),
|
||||
Matrix2Array(Vec<Matrix2<f32>>),
|
||||
Matrix3(Matrix3<f32>),
|
||||
Matrix3Array(Vec<Matrix3<f32>>),
|
||||
Matrix4(Matrix4<f32>),
|
||||
Matrix4Array(Vec<Matrix4<f32>>),
|
||||
Bool(bool),
|
||||
Color(Color),
|
||||
Sampler {
|
||||
value: Option<TextureResource>,
|
||||
fallback: SamplerFallback,
|
||||
},
|
||||
}
|
||||
|
||||
impl Default for OldMaterialProperty {
|
||||
fn default() -> Self {
|
||||
Self::Float(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Material {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
@@ -659,56 +623,8 @@ impl Visit for Material {
|
||||
shader.visit("Shader", &mut region)?;
|
||||
self.shader = shader;
|
||||
|
||||
if region.is_reading() {
|
||||
// Backward compatibility.
|
||||
let mut old_properties = FxHashMap::<ImmutableString, OldMaterialProperty>::default();
|
||||
if old_properties.visit("Properties", &mut region).is_ok() {
|
||||
for (name, old_property) in &old_properties {
|
||||
if let OldMaterialProperty::Sampler { value, .. } = old_property {
|
||||
self.bind(
|
||||
name.clone(),
|
||||
MaterialResourceBinding::Texture(MaterialTextureBinding {
|
||||
value: value.clone(),
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
let properties = self.try_get_or_insert_property_group("properties");
|
||||
|
||||
for (name, old_property) in old_properties {
|
||||
match old_property {
|
||||
OldMaterialProperty::Float(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::FloatArray(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Int(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::IntArray(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::UInt(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::UIntArray(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Vector2(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Vector2Array(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Vector3(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Vector3Array(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Vector4(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Vector4Array(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Matrix2(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Matrix2Array(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Matrix3(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Matrix3Array(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Matrix4(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Matrix4Array(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Bool(v) => properties.set_property(name, v),
|
||||
OldMaterialProperty::Color(v) => properties.set_property(name, v),
|
||||
_ => (),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
self.resource_bindings
|
||||
.visit("ResourceBindings", &mut region)?;
|
||||
}
|
||||
} else {
|
||||
self.resource_bindings
|
||||
.visit("ResourceBindings", &mut region)?;
|
||||
}
|
||||
self.resource_bindings
|
||||
.visit("ResourceBindings", &mut region)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1168,44 +1084,6 @@ impl MaterialResourceExtension for MaterialResource {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn visit_old_material(region: &mut RegionGuard) -> Option<MaterialResource> {
|
||||
let mut old_material = Arc::new(Mutex::new(Material::default()));
|
||||
if let Ok(mut inner) = region.enter_region("Material") {
|
||||
if old_material.visit("Value", &mut inner).is_ok() {
|
||||
return Some(MaterialResource::new_ok(
|
||||
Uuid::new_v4(),
|
||||
Default::default(),
|
||||
old_material.safe_lock().clone(),
|
||||
));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn visit_old_texture_as_material<F>(
|
||||
region: &mut RegionGuard,
|
||||
make_default_material: F,
|
||||
) -> Option<MaterialResource>
|
||||
where
|
||||
F: FnOnce() -> Material,
|
||||
{
|
||||
let mut old_texture: Option<TextureResource> = None;
|
||||
if let Ok(mut inner) = region.enter_region("Texture") {
|
||||
if old_texture.visit("Value", &mut inner).is_ok() {
|
||||
let mut material = make_default_material();
|
||||
material.bind("diffuseTexture", old_texture);
|
||||
return Some(MaterialResource::new_ok(
|
||||
Uuid::new_v4(),
|
||||
Default::default(),
|
||||
material,
|
||||
));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Standard PBR material. Keep in mind that this material is global, any modification
|
||||
/// of it will reflect on every other usage of it.
|
||||
|
||||
@@ -467,7 +467,7 @@ pub use fyrox_graphics::gpu_program::{
|
||||
use fyrox_graphics::{gpu_program::ShaderProperty, DrawParameters};
|
||||
use fyrox_resource::{
|
||||
embedded_data_source, io::ResourceIo, manager::BuiltInResource, untyped::ResourceKind,
|
||||
Resource, ResourceData, SHADER_RESOURCE_UUID,
|
||||
Resource, ResourceData,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use ron::ser::PrettyConfig;
|
||||
@@ -528,7 +528,7 @@ pub struct Shader {
|
||||
|
||||
impl TypeUuidProvider for Shader {
|
||||
fn type_uuid() -> Uuid {
|
||||
SHADER_RESOURCE_UUID
|
||||
uuid!("f1346417-b726-492a-b80f-c02096c6c019")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,21 +69,6 @@ pub mod registry;
|
||||
pub mod state;
|
||||
pub mod untyped;
|
||||
|
||||
/// Type UUID of texture resource. It is defined here to load old versions of resources.
|
||||
pub const TEXTURE_RESOURCE_UUID: Uuid = uuid!("02c23a44-55fa-411a-bc39-eb7a5eadf15c");
|
||||
/// Type UUID of model resource. It is defined here to load old versions of resources.
|
||||
pub const MODEL_RESOURCE_UUID: Uuid = uuid!("44cd768f-b4ca-4804-a98c-0adf85577ada");
|
||||
/// Type UUID of sound buffer resource. It is defined here to load old versions of resources.
|
||||
pub const SOUND_BUFFER_RESOURCE_UUID: Uuid = uuid!("f6a077b7-c8ff-4473-a95b-0289441ea9d8");
|
||||
/// Type UUID of shader resource. It is defined here to load old versions of resources.
|
||||
pub const SHADER_RESOURCE_UUID: Uuid = uuid!("f1346417-b726-492a-b80f-c02096c6c019");
|
||||
/// Type UUID of curve resource. It is defined here to load old versions of resources.
|
||||
pub const CURVE_RESOURCE_UUID: Uuid = uuid!("f28b949f-28a2-4b68-9089-59c234f58b6b");
|
||||
/// Type UUID of HRIR sphere resource. It is defined here to load old versions of resources.
|
||||
pub const HRIR_SPHERE_RESOURCE_UUID: Uuid = uuid!("c92a0fa3-0ed3-49a9-be44-8f06271c6be2");
|
||||
/// Type UUID of font resource. It is defined here to load old versions of resources.
|
||||
pub const FONT_RESOURCE_UUID: Uuid = uuid!("692fec79-103a-483c-bb0b-9fc3a349cb48");
|
||||
|
||||
/// A trait for resource data.
|
||||
pub trait ResourceData: Debug + Visit + Send + Reflect {
|
||||
/// Returns unique data type id.
|
||||
|
||||
@@ -21,19 +21,17 @@
|
||||
//! A module for untyped resources. See [`UntypedResource`] docs for more info.
|
||||
|
||||
use crate::state::ResourceDataWrapper;
|
||||
use crate::ResourceHeaderGuard;
|
||||
use crate::{
|
||||
core::{
|
||||
math::curve::Curve, parking_lot::Mutex, reflect::prelude::*, uuid, uuid::Uuid,
|
||||
visitor::prelude::*, TypeUuidProvider,
|
||||
parking_lot::Mutex, reflect::prelude::*, uuid, uuid::Uuid, visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
manager::ResourceManager,
|
||||
state::{LoadError, ResourceState},
|
||||
Resource, ResourceData, ResourceLoadError, TypedResourceData, CURVE_RESOURCE_UUID,
|
||||
MODEL_RESOURCE_UUID, SHADER_RESOURCE_UUID, SOUND_BUFFER_RESOURCE_UUID, TEXTURE_RESOURCE_UUID,
|
||||
Resource, ResourceData, ResourceLoadError, TypedResourceData,
|
||||
};
|
||||
use crate::{ResourceHeaderGuard, FONT_RESOURCE_UUID, HRIR_SPHERE_RESOURCE_UUID};
|
||||
use fxhash::FxHasher64;
|
||||
use fyrox_core::io::FileError;
|
||||
use fyrox_core::log::Log;
|
||||
use fyrox_core::parking_lot::MutexGuard;
|
||||
use fyrox_core::SafeLock;
|
||||
@@ -41,7 +39,6 @@ use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Write;
|
||||
use std::{
|
||||
error::Error,
|
||||
ffi::OsStr,
|
||||
fmt::{Debug, Display, Formatter},
|
||||
future::Future,
|
||||
hash::{Hash, Hasher},
|
||||
@@ -55,201 +52,6 @@ use std::{
|
||||
const MISSING_RESOURCE_MANAGER: &str =
|
||||
"Resource data constructor container must be provided when serializing resources!";
|
||||
|
||||
/// The UUIDs for resources that cannot be visited as embedded data because none of their
|
||||
/// fields are visited. This is used by `LegacyHeader` to avoid mistakenly interpretting
|
||||
/// a visitor node as an embedded resource.
|
||||
/// Being on this list does *not* prevent future versions of these resources from being
|
||||
/// embedded. It is purely a heuristic to assist with reading legacy resources.
|
||||
const INVALID_EMBEDDED_RESOURCES: &[Uuid] = &[
|
||||
SOUND_BUFFER_RESOURCE_UUID,
|
||||
MODEL_RESOURCE_UUID,
|
||||
HRIR_SPHERE_RESOURCE_UUID,
|
||||
FONT_RESOURCE_UUID,
|
||||
];
|
||||
|
||||
#[derive(Default, Debug, Visit, Clone, PartialEq, Eq, Hash)]
|
||||
enum OldResourceKind {
|
||||
#[default]
|
||||
Embedded,
|
||||
External(PathBuf),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum LegacyHeader {
|
||||
Path(PathBuf),
|
||||
Uuid(Uuid),
|
||||
Data(Box<dyn ResourceData>),
|
||||
}
|
||||
|
||||
impl LegacyHeader {
|
||||
fn visit_path(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut path = PathBuf::default();
|
||||
path.visit(name, visitor)?;
|
||||
if path.as_os_str().is_empty() {
|
||||
return Err(VisitError::FileLoadError(FileError::Custom(
|
||||
"Empty path".to_string(),
|
||||
)));
|
||||
}
|
||||
*self = Self::Path(path);
|
||||
Ok(())
|
||||
}
|
||||
fn visit_details(&mut self, type_uuid: Uuid, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region("Details")?;
|
||||
if type_uuid == SOUND_BUFFER_RESOURCE_UUID {
|
||||
let mut sound_region = region.enter_region("0")?;
|
||||
self.visit_path("Path", &mut sound_region)
|
||||
} else {
|
||||
self.visit_path("Path", &mut region)
|
||||
}
|
||||
}
|
||||
fn take_data(&mut self, uuid: Uuid) -> Option<Box<dyn ResourceData>> {
|
||||
if let Self::Data(data) = std::mem::replace(self, Self::Uuid(uuid)) {
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn is_valid_embedded_type_uuid(uuid: Uuid) -> bool {
|
||||
INVALID_EMBEDDED_RESOURCES.contains(&uuid)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LegacyHeader {
|
||||
fn default() -> Self {
|
||||
Self::Path(PathBuf::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for LegacyHeader {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
assert!(visitor.is_reading());
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
let mut type_uuid = Uuid::default();
|
||||
if type_uuid.visit("TypeUuid", &mut region).is_err() {
|
||||
// We might be reading the old version, try to guess an actual type uuid by
|
||||
// the inner content of the resource data.
|
||||
type_uuid = guess_uuid(&mut region);
|
||||
};
|
||||
let resource_manager = region
|
||||
.blackboard
|
||||
.get::<ResourceManager>()
|
||||
.expect(MISSING_RESOURCE_MANAGER);
|
||||
let resource_manager_state = resource_manager.state();
|
||||
let Some(mut instance) = resource_manager_state
|
||||
.constructors_container
|
||||
.try_create(&type_uuid)
|
||||
else {
|
||||
return Err(VisitError::User(format!(
|
||||
"There's no constructor registered for type {type_uuid}!"
|
||||
)));
|
||||
};
|
||||
drop(resource_manager_state);
|
||||
|
||||
let mut id: u32 = 0;
|
||||
|
||||
if id.visit("Id", &mut region).is_ok() {
|
||||
// We're interested only in embedded resources.
|
||||
if id == 2 {
|
||||
let result = self.visit_details(type_uuid, &mut region);
|
||||
if let Err(err0) = result {
|
||||
if Self::is_valid_embedded_type_uuid(type_uuid) {
|
||||
let result = instance.visit("Details", &mut region);
|
||||
if let Err(err1) = result {
|
||||
let result = instance.visit("State", &mut region);
|
||||
if let Err(err2) = result {
|
||||
return Err(err0.multiple(err1).multiple(err2));
|
||||
}
|
||||
}
|
||||
*self = Self::Data(instance);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err0)
|
||||
}
|
||||
} else {
|
||||
result
|
||||
}
|
||||
} else {
|
||||
Err(VisitError::User("Old resource".into()))
|
||||
}
|
||||
} else {
|
||||
let mut uuid = Uuid::default();
|
||||
if uuid.visit("ResourceUuid", &mut region).is_ok() && !uuid.is_nil() {
|
||||
*self = Self::Uuid(uuid);
|
||||
return Ok(());
|
||||
}
|
||||
let mut old_kind = OldResourceKind::Embedded;
|
||||
old_kind.visit("Kind", &mut region)?;
|
||||
match old_kind {
|
||||
OldResourceKind::External(path) => {
|
||||
if path.as_os_str().is_empty() {
|
||||
return Err(VisitError::FileLoadError(FileError::Custom(
|
||||
"Empty path".to_string(),
|
||||
)));
|
||||
}
|
||||
*self = Self::Path(path);
|
||||
}
|
||||
OldResourceKind::Embedded => {
|
||||
instance.visit("State", &mut region)?;
|
||||
*self = Self::Data(instance);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Heuristic function to guess resource uuid based on inner content of a resource.
|
||||
fn guess_uuid(region: &mut Visitor) -> Uuid {
|
||||
assert!(region.is_reading());
|
||||
|
||||
let guard = region.enter_region("Details");
|
||||
let mut region = match guard {
|
||||
Ok(region) => region,
|
||||
Err(ref err) => {
|
||||
Log::err(err.to_string());
|
||||
drop(guard);
|
||||
Log::info(region.debug());
|
||||
return TEXTURE_RESOURCE_UUID;
|
||||
}
|
||||
};
|
||||
|
||||
let mut mip_count = 0u32;
|
||||
if mip_count.visit("MipCount", &mut region).is_ok() {
|
||||
return TEXTURE_RESOURCE_UUID;
|
||||
}
|
||||
|
||||
let mut curve = Curve::default();
|
||||
if curve.visit("Curve", &mut region).is_ok() {
|
||||
return CURVE_RESOURCE_UUID;
|
||||
}
|
||||
|
||||
let mut id = 0u32;
|
||||
if id.visit("Id", &mut region).is_ok() {
|
||||
return SOUND_BUFFER_RESOURCE_UUID;
|
||||
}
|
||||
|
||||
let mut path = PathBuf::new();
|
||||
if path.visit("Path", &mut region).is_ok() {
|
||||
let ext = path.extension().unwrap_or_default().to_ascii_lowercase();
|
||||
if ext == OsStr::new("rgs")
|
||||
|| ext == OsStr::new("fbx")
|
||||
|| ext == OsStr::new("gltf")
|
||||
|| ext == OsStr::new("glb")
|
||||
{
|
||||
return MODEL_RESOURCE_UUID;
|
||||
} else if ext == OsStr::new("shader")
|
||||
|| path == OsStr::new("Standard")
|
||||
|| path == OsStr::new("StandardTwoSides")
|
||||
|| path == OsStr::new("StandardTerrain")
|
||||
{
|
||||
return SHADER_RESOURCE_UUID;
|
||||
}
|
||||
}
|
||||
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Kind of a resource. It defines how the resource manager will treat a resource content on serialization.
|
||||
#[derive(Default, Reflect, Debug, Visit, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ResourceKind {
|
||||
@@ -537,16 +339,9 @@ impl UntypedResource {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
if region.is_reading() {
|
||||
let mut uuid = Uuid::default();
|
||||
match uuid.visit("Uuid", &mut region) {
|
||||
Ok(()) => {
|
||||
self.read_visit(uuid, type_uuid, &mut region)?;
|
||||
drop(region);
|
||||
}
|
||||
Err(_) => {
|
||||
drop(region);
|
||||
self.legacy_visit(name, visitor)?;
|
||||
}
|
||||
}
|
||||
uuid.visit("Uuid", &mut region)?;
|
||||
self.read_visit(uuid, type_uuid, &mut region)?;
|
||||
drop(region);
|
||||
let resource_manager = visitor
|
||||
.blackboard
|
||||
.get::<ResourceManager>()
|
||||
@@ -569,55 +364,6 @@ impl UntypedResource {
|
||||
}
|
||||
}
|
||||
}
|
||||
fn legacy_visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut header: Arc<Mutex<LegacyHeader>> = Default::default();
|
||||
let result = header.visit(name, visitor);
|
||||
if let Err(err1) = result {
|
||||
header = Arc::default();
|
||||
if let Ok(mut region) = visitor.enter_region(name) {
|
||||
let mut region = if region.has_region("Value") {
|
||||
region.enter_region("Value").unwrap()
|
||||
} else {
|
||||
region
|
||||
};
|
||||
let result = header.visit("State", &mut region);
|
||||
if let Err(err2) = result {
|
||||
if let Ok(mut region) = region.enter_region("State") {
|
||||
let result = header.visit("Data", &mut region);
|
||||
if let Err(err3) = result {
|
||||
return Err(err1.multiple(err2).multiple(err3));
|
||||
}
|
||||
} else {
|
||||
return Err(err1.multiple(err2));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Err(err1);
|
||||
}
|
||||
}
|
||||
let resource_manager = visitor
|
||||
.blackboard
|
||||
.get::<ResourceManager>()
|
||||
.expect("Resource manager must be available when deserializing resources!")
|
||||
.clone();
|
||||
let mut state = resource_manager.state();
|
||||
let mut header = header.try_lock().expect("header locked");
|
||||
match *header {
|
||||
LegacyHeader::Path(ref path) => {
|
||||
Log::info(format!("Requesting {path:?}"));
|
||||
*self = state.request(path);
|
||||
}
|
||||
LegacyHeader::Uuid(uuid) => {
|
||||
*self = uuid.into();
|
||||
}
|
||||
LegacyHeader::Data(_) => {
|
||||
let uuid = Uuid::new_v4();
|
||||
let data = header.take_data(uuid).unwrap();
|
||||
*self = UntypedResource::new_ok_untyped(uuid, ResourceKind::Embedded, data);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn read_visit(
|
||||
&mut self,
|
||||
resource_uuid: Uuid,
|
||||
|
||||
@@ -33,12 +33,12 @@ use crate::{
|
||||
error::SoundError,
|
||||
};
|
||||
use fyrox_core::{
|
||||
io::FileError, reflect::prelude::*, uuid::Uuid, visitor::prelude::*, TypeUuidProvider,
|
||||
io::FileError, reflect::prelude::*, uuid, uuid::Uuid, visitor::prelude::*, TypeUuidProvider,
|
||||
};
|
||||
use fyrox_resource::untyped::ResourceKind;
|
||||
use fyrox_resource::{
|
||||
io::{FileReader, ResourceIo},
|
||||
Resource, ResourceData, SOUND_BUFFER_RESOURCE_UUID,
|
||||
Resource, ResourceData,
|
||||
};
|
||||
use std::{
|
||||
error::Error,
|
||||
@@ -298,7 +298,7 @@ impl SoundBufferResourceExtension for SoundBufferResource {
|
||||
|
||||
impl TypeUuidProvider for SoundBuffer {
|
||||
fn type_uuid() -> Uuid {
|
||||
SOUND_BUFFER_RESOURCE_UUID
|
||||
uuid!("f6a077b7-c8ff-4473-a95b-0289441ea9d8")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ impl DerefMut for SoundBuffer {
|
||||
|
||||
impl ResourceData for SoundBuffer {
|
||||
fn type_uuid(&self) -> Uuid {
|
||||
SOUND_BUFFER_RESOURCE_UUID
|
||||
uuid!("f6a077b7-c8ff-4473-a95b-0289441ea9d8")
|
||||
}
|
||||
|
||||
fn save(&mut self, _path: &Path) -> Result<(), Box<dyn Error>> {
|
||||
|
||||
@@ -61,7 +61,7 @@ use fyrox_core::{
|
||||
};
|
||||
use fyrox_resource::{
|
||||
embedded_data_source, io::ResourceIo, manager::BuiltInResource, options::ImportOptions,
|
||||
untyped::ResourceKind, Resource, ResourceData, TEXTURE_RESOURCE_UUID,
|
||||
untyped::ResourceKind, Resource, ResourceData,
|
||||
};
|
||||
use image::{ColorType, DynamicImage, ImageError, ImageFormat, Pixel};
|
||||
use lazy_static::lazy_static;
|
||||
@@ -287,7 +287,7 @@ pub struct Texture {
|
||||
|
||||
impl TypeUuidProvider for Texture {
|
||||
fn type_uuid() -> Uuid {
|
||||
TEXTURE_RESOURCE_UUID
|
||||
uuid!("02c23a44-55fa-411a-bc39-eb7a5eadf15c")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,17 +363,16 @@ impl Visit for Texture {
|
||||
self.anisotropy.visit("Anisotropy", &mut region)?;
|
||||
self.s_wrap_mode.visit("SWrapMode", &mut region)?;
|
||||
self.t_wrap_mode.visit("TWrapMode", &mut region)?;
|
||||
let _ = self.t_wrap_mode.visit("RWrapMode", &mut region);
|
||||
self.t_wrap_mode.visit("RWrapMode", &mut region)?;
|
||||
self.mip_count.visit("MipCount", &mut region)?;
|
||||
self.kind.visit("Kind", &mut region)?;
|
||||
let mut bytes_view = PodVecView::from_pod_vec(&mut self.bytes);
|
||||
let _ = bytes_view.visit("Data", &mut region);
|
||||
|
||||
let _ = self.base_level.visit("BaseLevel", &mut region);
|
||||
let _ = self.max_level.visit("MaxLevel", &mut region);
|
||||
let _ = self.min_lod.visit("MinLod", &mut region);
|
||||
let _ = self.max_lod.visit("MaxLod", &mut region);
|
||||
let _ = self.lod_bias.visit("LodBias", &mut region);
|
||||
bytes_view.visit("Data", &mut region)?;
|
||||
self.base_level.visit("BaseLevel", &mut region)?;
|
||||
self.max_level.visit("MaxLevel", &mut region)?;
|
||||
self.min_lod.visit("MinLod", &mut region)?;
|
||||
self.max_lod.visit("MaxLod", &mut region)?;
|
||||
self.lod_bias.visit("LodBias", &mut region)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+5
-7
@@ -816,13 +816,11 @@ impl Visit for UserInterface {
|
||||
self.cursor_icon.visit("CursorIcon", &mut region)?;
|
||||
self.double_click_time_slice
|
||||
.visit("DoubleClickTimeSlice", &mut region)?;
|
||||
let _ = self
|
||||
.tooltip_appear_delay
|
||||
.visit("TooltipAppearDelay", &mut region);
|
||||
let _ = self
|
||||
.standard_material
|
||||
.visit("StandardMaterial", &mut region);
|
||||
let _ = self.render_mode.visit("RenderMode", &mut region);
|
||||
self.tooltip_appear_delay
|
||||
.visit("TooltipAppearDelay", &mut region)?;
|
||||
self.standard_material
|
||||
.visit("StandardMaterial", &mut region)?;
|
||||
self.render_mode.visit("RenderMode", &mut region)?;
|
||||
|
||||
if region.is_reading() {
|
||||
for node in self.nodes.iter() {
|
||||
|
||||
@@ -276,10 +276,8 @@ pub struct Window {
|
||||
pub prev_bounds: Option<Rect<f32>>,
|
||||
/// If `true`, then the window can be closed using `Esc` key. Default is `true`. Works only if
|
||||
/// `can_close` is also `true`.
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub close_by_esc: bool,
|
||||
/// If `true`, then the window will be deleted after closing.
|
||||
#[visit(optional)] // Backward compatibility
|
||||
pub remove_on_close: bool,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user