mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
engine build fix + resource system improvements
This commit is contained in:
@@ -38,15 +38,15 @@ use fyrox::{
|
||||
inspectable::InspectablePropertyEditorDefinition, PropertyEditorDefinitionContainer,
|
||||
},
|
||||
material::{
|
||||
shader::{Shader, ShaderError, ShaderState},
|
||||
shader::{Shader, ShaderError, ShaderResource},
|
||||
SharedMaterial,
|
||||
},
|
||||
resource::{
|
||||
curve::{CurveResource, CurveResourceError, CurveResourceState},
|
||||
model::{MaterialSearchOptions, Model, ModelData, ModelLoadError},
|
||||
model::{MaterialSearchOptions, Model, ModelLoadError, ModelResource},
|
||||
texture::{
|
||||
CompressionOptions, Texture, TextureMagnificationFilter, TextureMinificationFilter,
|
||||
TextureWrapMode,
|
||||
CompressionOptions, TextureMagnificationFilter, TextureMinificationFilter,
|
||||
TextureResource, TextureWrapMode,
|
||||
},
|
||||
},
|
||||
scene::{
|
||||
@@ -89,8 +89,8 @@ use fyrox::{
|
||||
HighShelfFilterEffect, LowPassFilterEffect, LowShelfFilterEffect,
|
||||
},
|
||||
reverb::Reverb,
|
||||
Attenuate, AudioBus, Biquad, DistanceModel, Effect, EffectWrapper, SoundBufferResource,
|
||||
SoundBufferResourceLoadError, SoundBufferState, Status,
|
||||
Attenuate, AudioBus, Biquad, DistanceModel, Effect, EffectWrapper, SoundBuffer,
|
||||
SoundBufferResource, SoundBufferResourceLoadError, Status,
|
||||
},
|
||||
terrain::Layer,
|
||||
transform::Transform,
|
||||
@@ -132,7 +132,7 @@ pub fn make_property_editors_container(
|
||||
let container = PropertyEditorDefinitionContainer::new();
|
||||
|
||||
container.insert(TexturePropertyEditorDefinition);
|
||||
container.insert(InheritablePropertyEditorDefinition::<Option<Texture>>::new());
|
||||
container.insert(InheritablePropertyEditorDefinition::<Option<TextureResource>>::new());
|
||||
container.insert(InheritablePropertyEditorDefinition::<Handle<Node>>::new());
|
||||
|
||||
container.insert(MaterialPropertyEditorDefinition {
|
||||
@@ -174,17 +174,17 @@ pub fn make_property_editors_container(
|
||||
.register_inheritable_vec_collection::<fyrox::animation::spritesheet::signal::Signal>();
|
||||
|
||||
container.insert(ResourceFieldPropertyEditorDefinition::<
|
||||
ModelResource,
|
||||
Model,
|
||||
ModelData,
|
||||
ModelLoadError,
|
||||
>::new(Rc::new(|resource_manager, path| {
|
||||
block_on(resource_manager.request_model(path))
|
||||
})));
|
||||
container.insert(InheritablePropertyEditorDefinition::<Option<Model>>::new());
|
||||
container.insert(InheritablePropertyEditorDefinition::<Option<ModelResource>>::new());
|
||||
|
||||
container.insert(ResourceFieldPropertyEditorDefinition::<
|
||||
SoundBufferResource,
|
||||
SoundBufferState,
|
||||
SoundBuffer,
|
||||
SoundBufferResourceLoadError,
|
||||
>::new(Rc::new(|resource_manager, path| {
|
||||
block_on(resource_manager.request_sound_buffer(path))
|
||||
@@ -203,13 +203,13 @@ pub fn make_property_editors_container(
|
||||
container.insert(InheritablePropertyEditorDefinition::<Option<CurveResource>>::new());
|
||||
|
||||
container.insert(ResourceFieldPropertyEditorDefinition::<
|
||||
ShaderResource,
|
||||
Shader,
|
||||
ShaderState,
|
||||
ShaderError,
|
||||
>::new(Rc::new(|resource_manager, path| {
|
||||
block_on(resource_manager.request_shader(path))
|
||||
})));
|
||||
container.insert(InheritablePropertyEditorDefinition::<Option<Shader>>::new());
|
||||
container.insert(InheritablePropertyEditorDefinition::<Option<ShaderResource>>::new());
|
||||
|
||||
container.register_inheritable_inspectable::<ColorGradingLut>();
|
||||
container.register_inheritable_inspectable::<InteractionGroups>();
|
||||
|
||||
@@ -16,7 +16,7 @@ use fyrox::{
|
||||
widget::{Widget, WidgetBuilder, WidgetMessage},
|
||||
BuildContext, Control, Thickness, UiNode, UserInterface,
|
||||
},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
utils::into_gui_texture,
|
||||
};
|
||||
use std::{
|
||||
@@ -30,7 +30,7 @@ pub struct TextureEditor {
|
||||
widget: Widget,
|
||||
image: Handle<UiNode>,
|
||||
resource_manager: ResourceManager,
|
||||
texture: Option<Texture>,
|
||||
texture: Option<TextureResource>,
|
||||
}
|
||||
|
||||
impl Debug for TextureEditor {
|
||||
@@ -55,11 +55,11 @@ impl DerefMut for TextureEditor {
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Eq)]
|
||||
pub enum TextureEditorMessage {
|
||||
Texture(Option<Texture>),
|
||||
Texture(Option<TextureResource>),
|
||||
}
|
||||
|
||||
impl TextureEditorMessage {
|
||||
define_constructor!(TextureEditorMessage:Texture => fn texture(Option<Texture>), layout: false);
|
||||
define_constructor!(TextureEditorMessage:Texture => fn texture(Option<TextureResource>), layout: false);
|
||||
}
|
||||
|
||||
impl Control for TextureEditor {
|
||||
@@ -106,7 +106,7 @@ impl Control for TextureEditor {
|
||||
|
||||
pub struct TextureEditorBuilder {
|
||||
widget_builder: WidgetBuilder,
|
||||
texture: Option<Texture>,
|
||||
texture: Option<TextureResource>,
|
||||
}
|
||||
|
||||
impl TextureEditorBuilder {
|
||||
@@ -117,7 +117,7 @@ impl TextureEditorBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_texture(mut self, texture: Option<Texture>) -> Self {
|
||||
pub fn with_texture(mut self, texture: Option<TextureResource>) -> Self {
|
||||
self.texture = texture;
|
||||
self
|
||||
}
|
||||
@@ -158,14 +158,14 @@ pub struct TexturePropertyEditorDefinition;
|
||||
|
||||
impl PropertyEditorDefinition for TexturePropertyEditorDefinition {
|
||||
fn value_type_id(&self) -> TypeId {
|
||||
TypeId::of::<Option<Texture>>()
|
||||
TypeId::of::<Option<TextureResource>>()
|
||||
}
|
||||
|
||||
fn create_instance(
|
||||
&self,
|
||||
ctx: PropertyEditorBuildContext,
|
||||
) -> Result<PropertyEditorInstance, InspectorError> {
|
||||
let value = ctx.property_info.cast_value::<Option<Texture>>()?;
|
||||
let value = ctx.property_info.cast_value::<Option<TextureResource>>()?;
|
||||
|
||||
Ok(PropertyEditorInstance::Simple {
|
||||
editor: TextureEditorBuilder::new(
|
||||
@@ -189,7 +189,7 @@ impl PropertyEditorDefinition for TexturePropertyEditorDefinition {
|
||||
&self,
|
||||
ctx: PropertyEditorMessageContext,
|
||||
) -> Result<Option<UiMessage>, InspectorError> {
|
||||
let value = ctx.property_info.cast_value::<Option<Texture>>()?;
|
||||
let value = ctx.property_info.cast_value::<Option<TextureResource>>()?;
|
||||
|
||||
Ok(Some(TextureEditorMessage::texture(
|
||||
ctx.instance,
|
||||
|
||||
+8
-8
@@ -109,9 +109,9 @@ use fyrox::{
|
||||
window::{WindowBuilder, WindowMessage, WindowTitle},
|
||||
BuildContext, UiNode, UserInterface, VerticalAlignment,
|
||||
},
|
||||
material::{shader::Shader, Material, PropertyValue, SharedMaterial},
|
||||
material::{shader::ShaderResource, Material, PropertyValue, SharedMaterial},
|
||||
plugin::PluginConstructor,
|
||||
resource::texture::{CompressionOptions, Texture, TextureKind},
|
||||
resource::texture::{CompressionOptions, TextureKind, TextureResource},
|
||||
scene::{
|
||||
camera::{Camera, Projection},
|
||||
mesh::Mesh,
|
||||
@@ -152,13 +152,13 @@ type GameEngine = fyrox::engine::Engine;
|
||||
|
||||
pub fn load_image(data: &[u8]) -> Option<draw::SharedTexture> {
|
||||
Some(into_gui_texture(
|
||||
Texture::load_from_memory(data, CompressionOptions::NoCompression, false).ok()?,
|
||||
TextureResource::load_from_memory(data, CompressionOptions::NoCompression, false).ok()?,
|
||||
))
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref GIZMO_SHADER: Shader = {
|
||||
Shader::from_str(
|
||||
static ref GIZMO_SHADER: ShaderResource = {
|
||||
ShaderResource::from_str(
|
||||
include_str!("../resources/embed/shaders/gizmo.shader",),
|
||||
PathBuf::default(),
|
||||
)
|
||||
@@ -536,7 +536,7 @@ impl Editor {
|
||||
|
||||
let graphics_context = engine.graphics_context.as_initialized_mut();
|
||||
|
||||
if let Ok(icon_img) = Texture::load_from_memory(
|
||||
if let Ok(icon_img) = TextureResource::load_from_memory(
|
||||
include_bytes!("../resources/embed/icon.png"),
|
||||
CompressionOptions::NoCompression,
|
||||
false,
|
||||
@@ -891,7 +891,7 @@ impl Editor {
|
||||
}
|
||||
|
||||
// Setup new one.
|
||||
scene.render_target = Some(Texture::new_render_target(0, 0));
|
||||
scene.render_target = Some(TextureResource::new_render_target(0, 0));
|
||||
self.scene_viewer
|
||||
.set_render_target(&self.engine.user_interface, scene.render_target.clone());
|
||||
|
||||
@@ -1408,7 +1408,7 @@ impl Editor {
|
||||
{
|
||||
let frame_size = self.scene_viewer.frame_bounds(&engine.user_interface).size;
|
||||
if width != frame_size.x as u32 || height != frame_size.y as u32 {
|
||||
scene.render_target = Some(Texture::new_render_target(
|
||||
scene.render_target = Some(TextureResource::new_render_target(
|
||||
frame_size.x as u32,
|
||||
frame_size.y as u32,
|
||||
));
|
||||
|
||||
@@ -39,7 +39,7 @@ use fyrox::{
|
||||
window::{WindowBuilder, WindowTitle},
|
||||
BuildContext, RcUiNodeHandle, Thickness, UiNode, UserInterface, VerticalAlignment,
|
||||
},
|
||||
material::{shader::Shader, Material, PropertyValue, SharedMaterial},
|
||||
material::{shader::ShaderResource, Material, PropertyValue, SharedMaterial},
|
||||
resource::texture::TextureState,
|
||||
scene::{
|
||||
base::BaseBuilder,
|
||||
@@ -89,7 +89,7 @@ pub struct MaterialEditor {
|
||||
preview: PreviewPanel,
|
||||
material: Option<SharedMaterial>,
|
||||
available_shaders: Handle<UiNode>,
|
||||
shaders_list: Vec<Shader>,
|
||||
shaders_list: Vec<ShaderResource>,
|
||||
texture_context_menu: TextureContextMenu,
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ impl MaterialEditor {
|
||||
self.shaders_list.clear();
|
||||
|
||||
self.shaders_list
|
||||
.extend_from_slice(&Shader::standard_shaders());
|
||||
.extend_from_slice(&ShaderResource::standard_shaders());
|
||||
|
||||
for dir in fyrox::walkdir::WalkDir::new(".").into_iter().flatten() {
|
||||
let path = dir.path();
|
||||
|
||||
@@ -11,7 +11,7 @@ use fyrox::{
|
||||
},
|
||||
RenderPassStatistics, SceneRenderPass, SceneRenderPassContext,
|
||||
},
|
||||
resource::texture::{CompressionOptions, Texture},
|
||||
resource::texture::{CompressionOptions, TextureResource},
|
||||
scene::mesh::surface::SurfaceData,
|
||||
};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
@@ -51,8 +51,8 @@ impl OverlayShader {
|
||||
pub struct OverlayRenderPass {
|
||||
quad: GeometryBuffer,
|
||||
shader: OverlayShader,
|
||||
sound_icon: Texture,
|
||||
light_icon: Texture,
|
||||
sound_icon: TextureResource,
|
||||
light_icon: TextureResource,
|
||||
pub pictogram_size: f32,
|
||||
}
|
||||
|
||||
@@ -65,13 +65,13 @@ impl OverlayRenderPass {
|
||||
state,
|
||||
),
|
||||
shader: OverlayShader::new(state).unwrap(),
|
||||
sound_icon: Texture::load_from_memory(
|
||||
sound_icon: TextureResource::load_from_memory(
|
||||
include_bytes!("../resources/embed/sound_source.png"),
|
||||
CompressionOptions::NoCompression,
|
||||
false,
|
||||
)
|
||||
.unwrap(),
|
||||
light_icon: Texture::load_from_memory(
|
||||
light_icon: TextureResource::load_from_memory(
|
||||
include_bytes!("../resources/embed/light_source.png"),
|
||||
CompressionOptions::NoCompression,
|
||||
false,
|
||||
|
||||
@@ -16,7 +16,7 @@ use fyrox::{
|
||||
widget::{WidgetBuilder, WidgetMessage},
|
||||
HorizontalAlignment, Orientation, Thickness, UiNode, VerticalAlignment,
|
||||
},
|
||||
resource::texture::{Texture, TextureKind},
|
||||
resource::texture::{TextureKind, TextureResource},
|
||||
scene::{
|
||||
base::BaseBuilder,
|
||||
camera::{CameraBuilder, Projection},
|
||||
@@ -157,7 +157,7 @@ impl PreviewPanel {
|
||||
|
||||
scene.ambient_lighting_color = Color::opaque(80, 80, 80);
|
||||
|
||||
let render_target = Texture::new_render_target(width, height);
|
||||
let render_target = TextureResource::new_render_target(width, height);
|
||||
scene.render_target = Some(render_target.clone());
|
||||
|
||||
let scene = engine.scenes.add(scene);
|
||||
@@ -371,7 +371,8 @@ impl PreviewPanel {
|
||||
if let Some(frame) = engine.user_interface.node(self.frame).cast::<Image>() {
|
||||
let frame_size = frame.actual_local_size();
|
||||
if rt_width != frame_size.x as u32 || rt_height != frame_size.y as u32 {
|
||||
let rt = Texture::new_render_target(frame_size.x as u32, frame_size.y as u32);
|
||||
let rt =
|
||||
TextureResource::new_render_target(frame_size.x as u32, frame_size.y as u32);
|
||||
scene.render_target = Some(rt.clone());
|
||||
engine.user_interface.send_message(ImageMessage::texture(
|
||||
self.frame,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use crate::{command::Command, scene::commands::SceneContext};
|
||||
use fyrox::{
|
||||
core::sstorage::ImmutableString,
|
||||
material::{shader::Shader, Material, PropertyValue, SharedMaterial},
|
||||
material::{shader::ShaderResource, Material, PropertyValue, SharedMaterial},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -48,7 +48,7 @@ impl Command for SetMaterialPropertyValueCommand {
|
||||
#[derive(Debug)]
|
||||
enum SetMaterialShaderCommandState {
|
||||
Undefined,
|
||||
NonExecuted { new_shader: Shader },
|
||||
NonExecuted { new_shader: ShaderResource },
|
||||
Executed { old_material: Material },
|
||||
Reverted { new_material: Material },
|
||||
}
|
||||
@@ -60,7 +60,7 @@ pub struct SetMaterialShaderCommand {
|
||||
}
|
||||
|
||||
impl SetMaterialShaderCommand {
|
||||
pub fn new(material: SharedMaterial, shader: Shader) -> Self {
|
||||
pub fn new(material: SharedMaterial, shader: ShaderResource) -> Self {
|
||||
Self {
|
||||
material,
|
||||
state: SetMaterialShaderCommandState::NonExecuted { new_shader: shader },
|
||||
|
||||
@@ -2,14 +2,14 @@ use crate::{command::Command, scene::commands::SceneContext};
|
||||
use fyrox::{
|
||||
core::{pool::Handle, sstorage::ImmutableString},
|
||||
material::{shader::SamplerFallback, PropertyValue},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
scene::{mesh::Mesh, node::Node},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TextureSet {
|
||||
Single(Texture),
|
||||
Multiple(Vec<Option<Texture>>),
|
||||
Single(TextureResource),
|
||||
Multiple(Vec<Option<TextureResource>>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -19,7 +19,7 @@ pub struct SetMeshTextureCommand {
|
||||
}
|
||||
|
||||
impl SetMeshTextureCommand {
|
||||
pub fn new(node: Handle<Node>, texture: Texture) -> Self {
|
||||
pub fn new(node: Handle<Node>, texture: TextureResource) -> Self {
|
||||
Self {
|
||||
node,
|
||||
set: TextureSet::Single(texture),
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::{command::Command, create_terrain_layer_material, scene::commands::Sc
|
||||
use fyrox::resource::texture::{TextureKind, TexturePixelKind};
|
||||
use fyrox::{
|
||||
core::pool::Handle,
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
scene::{node::Node, terrain::Layer},
|
||||
utils,
|
||||
};
|
||||
@@ -11,7 +11,7 @@ use fyrox::{
|
||||
pub struct AddTerrainLayerCommand {
|
||||
terrain: Handle<Node>,
|
||||
layer: Option<Layer>,
|
||||
masks: Vec<Texture>,
|
||||
masks: Vec<TextureResource>,
|
||||
}
|
||||
|
||||
impl AddTerrainLayerCommand {
|
||||
@@ -50,7 +50,7 @@ pub struct DeleteTerrainLayerCommand {
|
||||
terrain: Handle<Node>,
|
||||
layer: Option<Layer>,
|
||||
index: usize,
|
||||
masks: Vec<Texture>,
|
||||
masks: Vec<TextureResource>,
|
||||
}
|
||||
|
||||
impl DeleteTerrainLayerCommand {
|
||||
@@ -121,7 +121,7 @@ impl ModifyTerrainHeightCommand {
|
||||
) {
|
||||
chunk
|
||||
.set_heightmap(
|
||||
Texture::from_bytes(
|
||||
TextureResource::from_bytes(
|
||||
TextureKind::Rectangle {
|
||||
width: heigth_map_size.x,
|
||||
height: heigth_map_size.y,
|
||||
|
||||
@@ -37,7 +37,7 @@ use fyrox::{
|
||||
VerticalAlignment, BRUSH_BRIGHT_BLUE, BRUSH_DARKER, BRUSH_DARKEST, BRUSH_LIGHT,
|
||||
BRUSH_LIGHTER, BRUSH_LIGHTEST,
|
||||
},
|
||||
resource::texture::{Texture, TextureState},
|
||||
resource::texture::{TextureResource, TextureState},
|
||||
scene::{
|
||||
camera::{Camera, Projection},
|
||||
node::Node,
|
||||
@@ -764,7 +764,7 @@ impl SceneViewer {
|
||||
));
|
||||
}
|
||||
|
||||
pub fn set_render_target(&self, ui: &UserInterface, render_target: Option<Texture>) {
|
||||
pub fn set_render_target(&self, ui: &UserInterface, render_target: Option<TextureResource>) {
|
||||
ui.send_message(ImageMessage::texture(
|
||||
self.frame,
|
||||
MessageDirection::ToWidget,
|
||||
|
||||
@@ -7,7 +7,7 @@ use fyrox::{
|
||||
window::{Window, WindowBuilder},
|
||||
BuildContext, UiNode, UserInterface,
|
||||
},
|
||||
resource::texture::{CompressionOptions, Texture},
|
||||
resource::texture::{CompressionOptions, TextureResource},
|
||||
scene::camera::{SkyBox, SkyBoxBuilder},
|
||||
};
|
||||
|
||||
@@ -86,8 +86,8 @@ pub fn fetch_node_screen_center_ui(handle: Handle<UiNode>, ui: &UserInterface) -
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn load_texture(data: &[u8]) -> Texture {
|
||||
Texture::load_from_memory(data, CompressionOptions::NoCompression, false)
|
||||
fn load_texture(data: &[u8]) -> TextureResource {
|
||||
TextureResource::load_from_memory(data, CompressionOptions::NoCompression, false)
|
||||
.ok()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ use fyrox::{
|
||||
VerticalAlignment,
|
||||
},
|
||||
material::PropertyValue,
|
||||
resource::{model::Model, texture::Texture},
|
||||
resource::{model::ModelResource, texture::TextureResource},
|
||||
scene::{
|
||||
camera::Camera, decal::Decal, dim2::rectangle::Rectangle, light::spot::SpotLight,
|
||||
mesh::Mesh, particle_system::ParticleSystem, sprite::Sprite, terrain::Terrain, Scene,
|
||||
@@ -60,8 +60,8 @@ pub struct PathFixer {
|
||||
|
||||
#[derive(Clone)]
|
||||
enum SceneResource {
|
||||
Model(Model),
|
||||
Texture(Texture),
|
||||
Model(ModelResource),
|
||||
Texture(TextureResource),
|
||||
// TODO: Add sound buffers.
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ use fyrox::{
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
material::{shader::SamplerFallback, Material, PropertyValue, SharedMaterial},
|
||||
resource::{
|
||||
model::{Model, ModelImportOptions},
|
||||
texture::{Texture, TextureImportOptions},
|
||||
model::{ModelImportOptions, ModelResource},
|
||||
texture::{TextureImportOptions, TextureResource},
|
||||
},
|
||||
scene::{
|
||||
base::BaseBuilder,
|
||||
@@ -55,12 +55,12 @@ use std::sync::Arc;
|
||||
|
||||
struct CustomModelLoader(Arc<ModelLoader>);
|
||||
|
||||
impl ResourceLoader<Model, ModelImportOptions> for CustomModelLoader {
|
||||
impl ResourceLoader<ModelResource, ModelImportOptions> for CustomModelLoader {
|
||||
fn load(
|
||||
&self,
|
||||
resource: Model,
|
||||
resource: ModelResource,
|
||||
default_import_options: ModelImportOptions,
|
||||
event_broadcaster: ResourceEventBroadcaster<Model>,
|
||||
event_broadcaster: ResourceEventBroadcaster<ModelResource>,
|
||||
reload: bool,
|
||||
) -> BoxedLoaderFuture {
|
||||
// Arc is required as BoxedLoaderFuture has a static lifetime and hence self cannot be
|
||||
@@ -79,12 +79,12 @@ impl ResourceLoader<Model, ModelImportOptions> for CustomModelLoader {
|
||||
/// For simplicity we just simply wrap the default loader and log the invocation to the console.
|
||||
struct CustomTextureLoader(Arc<TextureLoader>);
|
||||
|
||||
impl ResourceLoader<Texture, TextureImportOptions> for CustomTextureLoader {
|
||||
impl ResourceLoader<TextureResource, TextureImportOptions> for CustomTextureLoader {
|
||||
fn load(
|
||||
&self,
|
||||
resource: Texture,
|
||||
resource: TextureResource,
|
||||
default_import_options: TextureImportOptions,
|
||||
event_broadcaster: ResourceEventBroadcaster<Texture>,
|
||||
event_broadcaster: ResourceEventBroadcaster<TextureResource>,
|
||||
reload: bool,
|
||||
) -> BoxedLoaderFuture {
|
||||
// Arc is required as BoxedLoaderFuture has a static lifetime and hence self cannot be
|
||||
|
||||
@@ -11,14 +11,14 @@ use fyrox::{
|
||||
UiNode, VerticalAlignment,
|
||||
},
|
||||
plugin::{Plugin, PluginConstructor, PluginContext},
|
||||
resource::texture::{Texture, TextureKind},
|
||||
resource::texture::{TextureKind, TextureResource},
|
||||
scene::{Scene, SceneLoader},
|
||||
utils,
|
||||
window::WindowAttributes,
|
||||
};
|
||||
|
||||
struct Game {
|
||||
render_target: Texture,
|
||||
render_target: TextureResource,
|
||||
scene_handle: Handle<Scene>,
|
||||
scene_image: Handle<UiNode>,
|
||||
exit: Handle<UiNode>,
|
||||
@@ -38,7 +38,7 @@ impl Plugin for Game {
|
||||
// Re-create render target with new size.
|
||||
drop(render_target);
|
||||
self.render_target =
|
||||
Texture::new_render_target(image_size.x as u32, image_size.y as u32);
|
||||
TextureResource::new_render_target(image_size.x as u32, image_size.y as u32);
|
||||
context.scenes[self.scene_handle].render_target = Some(self.render_target.clone());
|
||||
context.user_interface.send_message(ImageMessage::texture(
|
||||
self.scene_image,
|
||||
@@ -100,7 +100,7 @@ impl PluginConstructor for GameConstructor {
|
||||
|
||||
// Create render target and force the scene to render into it.
|
||||
let rt_size = Vector2::new(100.0, 100.0);
|
||||
let render_target = Texture::new_render_target(rt_size.x as u32, rt_size.y as u32);
|
||||
let render_target = TextureResource::new_render_target(rt_size.x as u32, rt_size.y as u32);
|
||||
scene.render_target = Some(render_target.clone());
|
||||
|
||||
// Add the loaded scene to the engine.
|
||||
|
||||
@@ -53,6 +53,7 @@ pub use notify;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub use js_sys;
|
||||
use std::iter::FromIterator;
|
||||
use uuid::Uuid;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub use wasm_bindgen;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@@ -348,3 +349,9 @@ pub fn make_relative_path<P: AsRef<Path>>(path: P) -> Result<PathBuf, std::io::E
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for an entity that has unique type identifier.
|
||||
pub trait TypeUuidProvider: Sized {
|
||||
/// Return type UUID.
|
||||
fn type_uuid() -> Uuid;
|
||||
}
|
||||
|
||||
@@ -6,15 +6,15 @@ use crate::{
|
||||
entry::{TimedEntry, DEFAULT_RESOURCE_LIFETIME},
|
||||
event::{ResourceEvent, ResourceEventBroadcaster},
|
||||
},
|
||||
core::{variable::InheritableVariable, VecExtensions},
|
||||
core::VecExtensions,
|
||||
loader::ResourceLoader,
|
||||
state::ResourceState,
|
||||
task::TaskPool,
|
||||
UntypedResource,
|
||||
};
|
||||
use fxhash::FxHashMap;
|
||||
use std::ffi::OsString;
|
||||
use std::{path::Path, sync::Arc};
|
||||
use fyrox_core::uuid::Uuid;
|
||||
use std::{ffi::OsString, path::Path, sync::Arc};
|
||||
|
||||
pub mod entry;
|
||||
pub mod event;
|
||||
@@ -168,11 +168,14 @@ impl ResourceContainer {
|
||||
}
|
||||
|
||||
/// Tries to load a resources at a given path.
|
||||
pub fn request<P: AsRef<Path>>(&mut self, path: P) -> UntypedResource {
|
||||
pub fn request<P>(&mut self, path: P, type_uuid: Uuid) -> UntypedResource
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
match self.find(path.as_ref()) {
|
||||
Some(existing) => existing.clone(),
|
||||
None => {
|
||||
let resource = UntypedResource::new_pending(path.as_ref().to_owned());
|
||||
let resource = UntypedResource::new_pending(path.as_ref().to_owned(), type_uuid);
|
||||
|
||||
self.push(resource.clone());
|
||||
|
||||
@@ -192,7 +195,7 @@ impl ResourceContainer {
|
||||
|
||||
/// Reloads a single resource.
|
||||
pub fn reload_resource(&mut self, resource: UntypedResource) {
|
||||
let state = resource.0.lock();
|
||||
let mut state = resource.0.lock();
|
||||
|
||||
if !state.is_loading() {
|
||||
let path = state.path().to_path_buf();
|
||||
@@ -218,39 +221,6 @@ impl ResourceContainer {
|
||||
|
||||
resources
|
||||
}
|
||||
|
||||
/// Tries to restore resource by making an attempt to request resource with path from existing
|
||||
/// resource instance. This method is used to restore "shallow" resources after scene
|
||||
/// deserialization.
|
||||
pub fn try_restore_resource(&mut self, resource: &mut UntypedResource) {
|
||||
let path = resource.0.lock().path().to_path_buf();
|
||||
let new_resource = self.request(path);
|
||||
*resource = new_resource;
|
||||
}
|
||||
|
||||
/// Tries to restore resource by making an attempt to request resource with path from existing
|
||||
/// resource instance. This method is used to restore "shallow" resources after scene
|
||||
/// deserialization.
|
||||
pub fn try_restore_optional_resource(&mut self, resource: &mut Option<UntypedResource>) {
|
||||
if let Some(shallow_resource) = resource.as_mut() {
|
||||
let path = shallow_resource.0.lock().path().to_path_buf();
|
||||
let new_resource = self.request(path);
|
||||
*shallow_resource = new_resource;
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to restore resource by making an attempt to request resource with path from existing
|
||||
/// resource instance. This method is used to restore "shallow" resources after scene
|
||||
/// deserialization.
|
||||
pub fn try_restore_inheritable_resource(
|
||||
&mut self,
|
||||
inheritable_resource: &mut InheritableVariable<Option<UntypedResource>>,
|
||||
) {
|
||||
if let Some(shallow_resource) = inheritable_resource.get_value_mut_silent().as_mut() {
|
||||
let new_resource = self.request(shallow_resource.0.lock().path());
|
||||
*shallow_resource = new_resource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Container for ResourceContainer {
|
||||
|
||||
+127
-79
@@ -1,23 +1,23 @@
|
||||
//! Resource management
|
||||
|
||||
#![warn(missing_docs)]
|
||||
// #![warn(missing_docs)] TODO
|
||||
|
||||
use crate::{
|
||||
core::{
|
||||
parking_lot::MutexGuard,
|
||||
reflect::prelude::*,
|
||||
reflect::FieldValue,
|
||||
uuid::{uuid, Uuid},
|
||||
visitor::prelude::*,
|
||||
},
|
||||
state::ResourceState,
|
||||
};
|
||||
use std::fmt::Display;
|
||||
use std::{
|
||||
any::Any,
|
||||
borrow::Cow,
|
||||
fmt::{Debug, Formatter},
|
||||
future::Future,
|
||||
hash::Hash,
|
||||
hash::{Hash, Hasher},
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
path::{Path, PathBuf},
|
||||
@@ -26,8 +26,10 @@ use std::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use crate::manager::ResourceManager;
|
||||
use crate::untyped::UntypedResource;
|
||||
pub use fyrox_core as core;
|
||||
use fyrox_core::TypeUuidProvider;
|
||||
|
||||
pub mod constructor;
|
||||
pub mod container;
|
||||
@@ -39,6 +41,7 @@ pub mod task;
|
||||
pub mod untyped;
|
||||
|
||||
pub const TEXTURE_RESOURCE_UUID: Uuid = uuid!("02c23a44-55fa-411a-bc39-eb7a5eadf15c");
|
||||
pub const MODEL_RESOURCE_UUID: Uuid = uuid!("44cd768f-b4ca-4804-a98c-0adf85577ada");
|
||||
pub const SOUND_BUFFER_RESOURCE_UUID: Uuid = uuid!("f6a077b7-c8ff-4473-a95b-0289441ea9d8");
|
||||
pub const SHADER_RESOURCE_UUID: Uuid = uuid!("f1346417-b726-492a-b80f-c02096c6c019");
|
||||
pub const CURVE_RESOURCE_UUID: Uuid = uuid!("f28b949f-28a2-4b68-9089-59c234f58b6b");
|
||||
@@ -59,13 +62,13 @@ pub trait ResourceData: 'static + Debug + Visit + Send {
|
||||
}
|
||||
|
||||
/// A trait for resource load error.
|
||||
pub trait ResourceLoadError: 'static + Debug + Display + Send + Sync {}
|
||||
pub trait ResourceLoadError: 'static + Debug + Send + Sync {}
|
||||
|
||||
impl<T> ResourceLoadError for T where T: 'static + Display + Debug + Send + Sync {}
|
||||
impl<T> ResourceLoadError for T where T: 'static + Debug + Send + Sync {}
|
||||
|
||||
pub struct ResourceStateGuard<'a, T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
guard: MutexGuard<'a, ResourceState>,
|
||||
phantom: PhantomData<T>,
|
||||
@@ -73,12 +76,25 @@ where
|
||||
|
||||
impl<'a, T> ResourceStateGuard<'a, T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
pub fn get(&mut self) -> ResourceStateRef<'_, T> {
|
||||
match &*self.guard {
|
||||
ResourceState::Pending { path, .. } => ResourceStateRef::Pending { path },
|
||||
ResourceState::LoadError { path, error } => ResourceStateRef::LoadError { path, error },
|
||||
ResourceState::Pending {
|
||||
path, type_uuid, ..
|
||||
} => ResourceStateRef::Pending {
|
||||
path,
|
||||
type_uuid: *type_uuid,
|
||||
},
|
||||
ResourceState::LoadError {
|
||||
path,
|
||||
error,
|
||||
type_uuid,
|
||||
} => ResourceStateRef::LoadError {
|
||||
path,
|
||||
error,
|
||||
type_uuid: *type_uuid,
|
||||
},
|
||||
ResourceState::Ok(data) => {
|
||||
ResourceStateRef::Ok(data.as_any().downcast_ref().expect("Type mismatch!"))
|
||||
}
|
||||
@@ -87,10 +103,21 @@ where
|
||||
|
||||
pub fn get_mut(&mut self) -> ResourceStateRefMut<'_, T> {
|
||||
match &mut *self.guard {
|
||||
ResourceState::Pending { path, .. } => ResourceStateRefMut::Pending { path },
|
||||
ResourceState::LoadError { path, error } => {
|
||||
ResourceStateRefMut::LoadError { path, error }
|
||||
}
|
||||
ResourceState::Pending {
|
||||
path, type_uuid, ..
|
||||
} => ResourceStateRefMut::Pending {
|
||||
path,
|
||||
type_uuid: *type_uuid,
|
||||
},
|
||||
ResourceState::LoadError {
|
||||
path,
|
||||
error,
|
||||
type_uuid,
|
||||
} => ResourceStateRefMut::LoadError {
|
||||
path,
|
||||
error,
|
||||
type_uuid: *type_uuid,
|
||||
},
|
||||
ResourceState::Ok(data) => {
|
||||
ResourceStateRefMut::Ok(data.as_any_mut().downcast_mut().expect("Type mismatch!"))
|
||||
}
|
||||
@@ -107,6 +134,7 @@ where
|
||||
Pending {
|
||||
/// A path to load resource from.
|
||||
path: &'a PathBuf,
|
||||
type_uuid: Uuid,
|
||||
},
|
||||
/// An error has occurred during the load.
|
||||
LoadError {
|
||||
@@ -114,6 +142,7 @@ where
|
||||
path: &'a PathBuf,
|
||||
/// An error.
|
||||
error: &'a Option<Arc<dyn ResourceLoadError>>,
|
||||
type_uuid: Uuid,
|
||||
},
|
||||
/// Actual resource data when it is fully loaded.
|
||||
Ok(&'a T),
|
||||
@@ -125,6 +154,7 @@ pub enum ResourceStateRefMut<'a, T> {
|
||||
Pending {
|
||||
/// A path to load resource from.
|
||||
path: &'a mut PathBuf,
|
||||
type_uuid: Uuid,
|
||||
},
|
||||
/// An error has occurred during the load.
|
||||
LoadError {
|
||||
@@ -132,6 +162,7 @@ pub enum ResourceStateRefMut<'a, T> {
|
||||
path: &'a mut PathBuf,
|
||||
/// An error.
|
||||
error: &'a mut Option<Arc<dyn ResourceLoadError>>,
|
||||
type_uuid: Uuid,
|
||||
},
|
||||
/// Actual resource data when it is fully loaded.
|
||||
Ok(&'a mut T),
|
||||
@@ -142,27 +173,86 @@ impl Default for ResourceState {
|
||||
Self::LoadError {
|
||||
error: None,
|
||||
path: Default::default(),
|
||||
type_uuid: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Visit, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(Debug, Reflect)]
|
||||
#[reflect(hide_all)]
|
||||
pub struct Resource<T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
state: Option<UntypedResource>,
|
||||
#[visit(skip)]
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> Visit for Resource<T>
|
||||
where
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
self.state.visit("State", &mut region)?;
|
||||
|
||||
if region.is_reading() {
|
||||
// Try to restore the shallow handle.
|
||||
let resource_manager = region
|
||||
.blackboard
|
||||
.get::<ResourceManager>()
|
||||
.expect("Resource manager must be available when deserializing resources!");
|
||||
|
||||
let path = self.state.as_ref().unwrap().path();
|
||||
|
||||
// Procedural resources usually have path empty or use it as an id, in this case we need to
|
||||
// check if the file actually exists to not mess up procedural resources.
|
||||
if path.exists() {
|
||||
self.state = Some(
|
||||
resource_manager.request_untyped(path, <T as TypeUuidProvider>::type_uuid()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PartialEq for Resource<T>
|
||||
where
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (&self.state, &other.state) {
|
||||
(Some(a), Some(b)) => a == b,
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Eq for Resource<T> where T: ResourceData + TypeUuidProvider {}
|
||||
|
||||
impl<T> Hash for Resource<T>
|
||||
where
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.state.hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Resource<T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
pub fn new_pending(path: PathBuf) -> Self {
|
||||
Self {
|
||||
state: Some(UntypedResource::new_pending(path)),
|
||||
state: Some(UntypedResource::new_pending(
|
||||
path,
|
||||
<T as TypeUuidProvider>::type_uuid(),
|
||||
)),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@@ -176,7 +266,11 @@ where
|
||||
|
||||
pub fn new_load_error(path: PathBuf, error: Option<Arc<dyn ResourceLoadError>>) -> Self {
|
||||
Self {
|
||||
state: Some(UntypedResource::new_load_error(path, error)),
|
||||
state: Some(UntypedResource::new_load_error(
|
||||
path,
|
||||
error,
|
||||
<T as TypeUuidProvider>::type_uuid(),
|
||||
)),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
@@ -230,6 +324,10 @@ where
|
||||
self.state.as_ref().unwrap().key()
|
||||
}
|
||||
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.state.as_ref().unwrap().0.lock().path().to_path_buf()
|
||||
}
|
||||
|
||||
/// Allows you to obtain reference to the resource data.
|
||||
///
|
||||
/// # Panic
|
||||
@@ -250,7 +348,7 @@ where
|
||||
|
||||
impl<T> Default for Resource<T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
@@ -263,7 +361,7 @@ where
|
||||
|
||||
impl<T> Clone for Resource<T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
@@ -276,7 +374,7 @@ where
|
||||
|
||||
impl<T> From<UntypedResource> for Resource<T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
#[inline]
|
||||
fn from(state: UntypedResource) -> Self {
|
||||
@@ -290,7 +388,7 @@ where
|
||||
#[allow(clippy::from_over_into)]
|
||||
impl<T> Into<UntypedResource> for Resource<T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
#[inline]
|
||||
fn into(self) -> UntypedResource {
|
||||
@@ -300,12 +398,12 @@ where
|
||||
|
||||
impl<T> Future for Resource<T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
type Output = Result<Self, Option<Arc<dyn ResourceLoadError>>>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let inner = self.state.as_ref().unwrap().clone();
|
||||
let mut inner = self.state.as_ref().unwrap().clone();
|
||||
std::pin::Pin::new(&mut inner)
|
||||
.poll(cx)
|
||||
.map(|r| r.map(|_| self.clone()))
|
||||
@@ -315,7 +413,7 @@ where
|
||||
#[doc(hidden)]
|
||||
pub struct ResourceDataRef<'a, T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
guard: MutexGuard<'a, ResourceState>,
|
||||
phantom: PhantomData<T>,
|
||||
@@ -323,7 +421,7 @@ where
|
||||
|
||||
impl<'a, T> Debug for ResourceDataRef<'a, T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match *self.guard {
|
||||
@@ -348,7 +446,7 @@ where
|
||||
|
||||
impl<'a, T> Deref for ResourceDataRef<'a, T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
type Target = T;
|
||||
|
||||
@@ -373,7 +471,7 @@ where
|
||||
|
||||
impl<'a, T> DerefMut for ResourceDataRef<'a, T>
|
||||
where
|
||||
T: ResourceData,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match *self.guard {
|
||||
@@ -395,53 +493,3 @@ where
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines a new resource type via new-type wrapper.
|
||||
#[macro_export]
|
||||
macro_rules! define_new_resource {
|
||||
($(#[$meta:meta])* $name:ident<$state:ty>) => {
|
||||
$(#[$meta])*
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct $name(pub Resource<$state>);
|
||||
|
||||
impl Visit for $name {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
self.0.visit(name, visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Resource<$state>> for $name {
|
||||
fn from(resource: Resource<$state>) -> Self {
|
||||
$name(resource)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for $name {
|
||||
type Target = Resource<$state>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::DerefMut for $name {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::future::Future for $name {
|
||||
type Output = Result<Self, Option<std::sync::Arc<dyn $crate::ResourceLoadError>>>;
|
||||
|
||||
fn poll(
|
||||
mut self: std::pin::Pin<&mut Self>,
|
||||
cx: &mut std::task::Context<'_>,
|
||||
) -> std::task::Poll<Self::Output> {
|
||||
std::pin::Pin::new(&mut self.0)
|
||||
.poll(cx)
|
||||
.map(|r| r.map(|_| self.clone()))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,17 +4,19 @@ use crate::{
|
||||
container::{Container, ResourceContainer},
|
||||
state::ResourceState,
|
||||
task::TaskPool,
|
||||
Resource, ResourceData, ResourceLoadError, UntypedResource,
|
||||
Resource, ResourceData, UntypedResource,
|
||||
};
|
||||
use fyrox_core::uuid::Uuid;
|
||||
use fyrox_core::{
|
||||
futures::future::join_all,
|
||||
make_relative_path, notify,
|
||||
parking_lot::{Mutex, MutexGuard},
|
||||
watcher::FileSystemWatcher,
|
||||
TypeUuidProvider,
|
||||
};
|
||||
use std::{
|
||||
fmt::{Debug, Display, Formatter},
|
||||
ops::Deref,
|
||||
marker::PhantomData,
|
||||
path::Path,
|
||||
sync::Arc,
|
||||
};
|
||||
@@ -69,34 +71,30 @@ pub struct ResourceManager {
|
||||
/// An error that may occur during texture registration.
|
||||
#[derive(Debug)]
|
||||
pub enum ResourceRegistrationError {
|
||||
/// Texture saving has failed.
|
||||
Texture(Arc<dyn ResourceLoadError>),
|
||||
/// Texture was in invalid state (Pending, LoadErr)
|
||||
/// Resource saving has failed.
|
||||
UnableToRegister,
|
||||
/// Resource was in invalid state (Pending, LoadErr)
|
||||
InvalidState,
|
||||
/// Texture is already registered.
|
||||
/// Resource is already registered.
|
||||
AlreadyRegistered,
|
||||
}
|
||||
|
||||
impl Display for ResourceRegistrationError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ResourceRegistrationError::Texture(v) => Display::fmt(v, f),
|
||||
ResourceRegistrationError::UnableToRegister => {
|
||||
write!(f, "Unable to register the resource!")
|
||||
}
|
||||
ResourceRegistrationError::InvalidState => {
|
||||
write!(f, "A texture was in invalid state!")
|
||||
write!(f, "A resource was in invalid state!")
|
||||
}
|
||||
ResourceRegistrationError::AlreadyRegistered => {
|
||||
write!(f, "A texture is already registered!")
|
||||
write!(f, "A resource is already registered!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Arc<dyn ResourceLoadError>> for ResourceRegistrationError {
|
||||
fn from(e: Arc<dyn ResourceLoadError>) -> Self {
|
||||
Self::Texture(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceManager {
|
||||
/// Creates a resource manager with default settings and loaders.
|
||||
pub fn new() -> Self {
|
||||
@@ -118,20 +116,46 @@ impl ResourceManager {
|
||||
self.state.lock()
|
||||
}
|
||||
|
||||
pub fn request<P: AsRef<Path>, T: Deref<Target = Resource<D>>, D: ResourceData>(
|
||||
&self,
|
||||
path: P,
|
||||
) -> T {
|
||||
self.state().containers_mut().resources.request(path)
|
||||
pub fn request<T, P>(&self, path: P) -> Resource<T>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
let untyped = self
|
||||
.state()
|
||||
.containers_mut()
|
||||
.resources
|
||||
.request(path, <T as TypeUuidProvider>::type_uuid());
|
||||
let actual_type_uuid = untyped.type_uuid();
|
||||
assert_eq!(actual_type_uuid, <T as TypeUuidProvider>::type_uuid());
|
||||
Resource {
|
||||
state: Some(untyped),
|
||||
phantom: PhantomData::<T>,
|
||||
}
|
||||
}
|
||||
|
||||
/// Saves given texture in the specified path and registers it in resource manager, so
|
||||
pub fn request_untyped<P>(&self, path: P, type_uuid: Uuid) -> UntypedResource
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
self.state()
|
||||
.containers_mut()
|
||||
.resources
|
||||
.request(path, type_uuid)
|
||||
}
|
||||
|
||||
/// Saves given resources in the specified path and registers it in resource manager, so
|
||||
/// it will be accessible through it later.
|
||||
pub fn register<P: AsRef<Path>>(
|
||||
pub fn register<P, F>(
|
||||
&self,
|
||||
resource: UntypedResource,
|
||||
path: P,
|
||||
) -> Result<(), ResourceRegistrationError> {
|
||||
mut on_register: F,
|
||||
) -> Result<(), ResourceRegistrationError>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
F: FnMut(&dyn ResourceData, &Path) -> bool,
|
||||
{
|
||||
let mut state = self.state();
|
||||
if state.containers().resources.find(path.as_ref()).is_some() {
|
||||
Err(ResourceRegistrationError::AlreadyRegistered)
|
||||
@@ -140,8 +164,8 @@ impl ResourceManager {
|
||||
match &mut *texture_state {
|
||||
ResourceState::Ok(data) => {
|
||||
data.set_path(path.as_ref().to_path_buf());
|
||||
if let Err(e) = data.save() {
|
||||
Err(ResourceRegistrationError::Texture(e))
|
||||
if !on_register(&**data, path.as_ref()) {
|
||||
Err(ResourceRegistrationError::UnableToRegister)
|
||||
} else {
|
||||
std::mem::drop(texture_state);
|
||||
state.containers_mut().resources.push(resource);
|
||||
|
||||
@@ -57,6 +57,7 @@ pub enum ResourceState {
|
||||
path: PathBuf,
|
||||
/// List of wakers to wake future when resource is fully loaded.
|
||||
wakers: Vec<Waker>,
|
||||
type_uuid: Uuid,
|
||||
},
|
||||
/// An error has occurred during the load.
|
||||
LoadError {
|
||||
@@ -64,6 +65,7 @@ pub enum ResourceState {
|
||||
path: PathBuf,
|
||||
/// An error. This wrapped in Option only to be Default_ed.
|
||||
error: Option<Arc<dyn ResourceLoadError>>,
|
||||
type_uuid: Uuid,
|
||||
},
|
||||
/// Actual resource data when it is fully loaded.
|
||||
Ok(Box<dyn ResourceData>),
|
||||
@@ -82,13 +84,21 @@ impl Visit for ResourceState {
|
||||
let mut path = PathBuf::new();
|
||||
path.visit("Path", &mut region)?;
|
||||
|
||||
let mut type_uuid = Uuid::default();
|
||||
let _ = type_uuid.visit("TypeUuid", &mut region);
|
||||
|
||||
*self = Self::Pending {
|
||||
path,
|
||||
wakers: Default::default(),
|
||||
type_uuid,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
} else if let Self::Pending { path, .. } = self {
|
||||
} else if let Self::Pending {
|
||||
path, type_uuid, ..
|
||||
} = self
|
||||
{
|
||||
let _ = type_uuid.visit("TypeUuid", &mut region);
|
||||
path.visit("Path", &mut region)
|
||||
} else {
|
||||
Err(VisitError::User("Enum variant mismatch!".to_string()))
|
||||
@@ -99,10 +109,21 @@ impl Visit for ResourceState {
|
||||
let mut path = PathBuf::new();
|
||||
path.visit("Path", &mut region)?;
|
||||
|
||||
*self = Self::LoadError { path, error: None };
|
||||
let mut type_uuid = Uuid::default();
|
||||
let _ = type_uuid.visit("TypeUuid", &mut region);
|
||||
|
||||
*self = Self::LoadError {
|
||||
path,
|
||||
error: None,
|
||||
type_uuid,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
} else if let Self::LoadError { path, .. } = self {
|
||||
} else if let Self::LoadError {
|
||||
path, type_uuid, ..
|
||||
} = self
|
||||
{
|
||||
let _ = type_uuid.visit("TypeUuid", &mut region);
|
||||
path.visit("Path", &mut region)
|
||||
} else {
|
||||
Err(VisitError::User("Enum variant mismatch!".to_string()))
|
||||
@@ -151,16 +172,25 @@ impl Visit for ResourceState {
|
||||
impl ResourceState {
|
||||
/// Creates new resource in pending state.
|
||||
#[inline]
|
||||
pub fn new_pending(path: PathBuf) -> Self {
|
||||
pub fn new_pending(path: PathBuf, type_uuid: Uuid) -> Self {
|
||||
Self::Pending {
|
||||
path,
|
||||
wakers: Default::default(),
|
||||
type_uuid,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn new_load_error(path: PathBuf, error: Option<Arc<dyn ResourceLoadError>>) -> Self {
|
||||
Self::LoadError { path, error }
|
||||
pub fn new_load_error(
|
||||
path: PathBuf,
|
||||
error: Option<Arc<dyn ResourceLoadError>>,
|
||||
type_uuid: Uuid,
|
||||
) -> Self {
|
||||
Self::LoadError {
|
||||
path,
|
||||
error,
|
||||
type_uuid,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@@ -175,22 +205,34 @@ impl ResourceState {
|
||||
/// Switches the internal state of the resource to [`ResourceState::Pending`].
|
||||
pub fn switch_to_pending_state(&mut self) {
|
||||
match self {
|
||||
ResourceState::LoadError { path, .. } => {
|
||||
ResourceState::LoadError {
|
||||
path, type_uuid, ..
|
||||
} => {
|
||||
*self = ResourceState::Pending {
|
||||
path: std::mem::take(path),
|
||||
wakers: Default::default(),
|
||||
type_uuid: *type_uuid,
|
||||
}
|
||||
}
|
||||
ResourceState::Ok(data) => {
|
||||
*self = ResourceState::Pending {
|
||||
path: data.path().to_path_buf(),
|
||||
wakers: Default::default(),
|
||||
type_uuid: data.type_uuid(),
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn type_uuid(&self) -> Uuid {
|
||||
match self {
|
||||
ResourceState::Pending { type_uuid, .. } => *type_uuid,
|
||||
ResourceState::LoadError { type_uuid, .. } => *type_uuid,
|
||||
ResourceState::Ok(data) => data.type_uuid(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn id(&self) -> u32 {
|
||||
match self {
|
||||
@@ -234,9 +276,11 @@ impl ResourceState {
|
||||
|
||||
/// Changes internal state to [`ResourceState::LoadError`].
|
||||
pub fn commit_error<E: ResourceLoadError>(&mut self, path: PathBuf, error: E) {
|
||||
let type_uuid = self.type_uuid();
|
||||
self.commit(ResourceState::LoadError {
|
||||
path,
|
||||
error: Some(Arc::new(error)),
|
||||
type_uuid,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
use crate::{state::ResourceState, ResourceData, ResourceLoadError};
|
||||
use fyrox_core::{parking_lot::Mutex, visitor::prelude::*};
|
||||
use crate::{state::ResourceState, Resource, ResourceData, ResourceLoadError};
|
||||
use fyrox_core::{parking_lot::Mutex, uuid::Uuid, visitor::prelude::*, TypeUuidProvider};
|
||||
use std::{
|
||||
fmt::{Debug, Formatter},
|
||||
future::Future,
|
||||
hash::{Hash, Hasher},
|
||||
marker::PhantomData,
|
||||
path::PathBuf,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
@@ -24,6 +25,7 @@ impl Default for UntypedResource {
|
||||
fn default() -> Self {
|
||||
Self(Arc::new(Mutex::new(ResourceState::new_pending(
|
||||
Default::default(),
|
||||
Default::default(),
|
||||
))))
|
||||
}
|
||||
}
|
||||
@@ -49,20 +51,30 @@ impl Hash for UntypedResource {
|
||||
}
|
||||
|
||||
impl UntypedResource {
|
||||
pub fn new_pending(path: PathBuf) -> Self {
|
||||
Self(Arc::new(Mutex::new(ResourceState::new_pending(path))))
|
||||
pub fn new_pending(path: PathBuf, type_uuid: Uuid) -> Self {
|
||||
Self(Arc::new(Mutex::new(ResourceState::new_pending(
|
||||
path, type_uuid,
|
||||
))))
|
||||
}
|
||||
|
||||
pub fn new_ok<T: ResourceData>(data: T) -> Self {
|
||||
Self(Arc::new(Mutex::new(ResourceState::new_ok(data))))
|
||||
}
|
||||
|
||||
pub fn new_load_error(path: PathBuf, error: Option<Arc<dyn ResourceLoadError>>) -> Self {
|
||||
pub fn new_load_error(
|
||||
path: PathBuf,
|
||||
error: Option<Arc<dyn ResourceLoadError>>,
|
||||
type_uuid: Uuid,
|
||||
) -> Self {
|
||||
Self(Arc::new(Mutex::new(ResourceState::new_load_error(
|
||||
path, error,
|
||||
path, error, type_uuid,
|
||||
))))
|
||||
}
|
||||
|
||||
pub fn type_uuid(&self) -> Uuid {
|
||||
self.0.lock().type_uuid()
|
||||
}
|
||||
|
||||
/// Returns true if the resource is still loading.
|
||||
pub fn is_loading(&self) -> bool {
|
||||
matches!(*self.0.lock(), ResourceState::Pending { .. })
|
||||
@@ -79,6 +91,28 @@ impl UntypedResource {
|
||||
pub fn key(&self) -> usize {
|
||||
(&*self.0 as *const _) as usize
|
||||
}
|
||||
|
||||
pub fn path(&self) -> PathBuf {
|
||||
match &*self.0.lock() {
|
||||
ResourceState::Pending { path, .. } => path.clone(),
|
||||
ResourceState::LoadError { path, .. } => path.clone(),
|
||||
ResourceState::Ok(data) => data.path().to_path_buf(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_cast<T>(&self) -> Option<Resource<T>>
|
||||
where
|
||||
T: ResourceData + TypeUuidProvider,
|
||||
{
|
||||
if self.type_uuid() == <T as TypeUuidProvider>::type_uuid() {
|
||||
Some(Resource {
|
||||
state: Some(self.clone()),
|
||||
phantom: PhantomData::<T>,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Future for UntypedResource {
|
||||
@@ -86,7 +120,8 @@ impl Future for UntypedResource {
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let state = self.0.clone();
|
||||
match *state.lock() {
|
||||
let mut guard = state.lock();
|
||||
match *guard {
|
||||
ResourceState::Pending { ref mut wakers, .. } => {
|
||||
// Collect wakers, so we'll be able to wake task when worker thread finish loading.
|
||||
let cx_waker = cx.waker();
|
||||
|
||||
@@ -12,8 +12,8 @@ use crate::{
|
||||
buffer::{generic::GenericBuffer, streaming::StreamingBuffer},
|
||||
error::SoundError,
|
||||
};
|
||||
use fyrox_core::{io::FileLoadError, reflect::prelude::*, uuid::Uuid, visitor::prelude::*};
|
||||
use fyrox_resource::{define_new_resource, Resource, ResourceData, SOUND_BUFFER_RESOURCE_UUID};
|
||||
use fyrox_core::{io::FileLoadError, uuid::Uuid, visitor::prelude::*, TypeUuidProvider};
|
||||
use fyrox_resource::{Resource, ResourceData, SOUND_BUFFER_RESOURCE_UUID};
|
||||
use std::{
|
||||
any::Any,
|
||||
borrow::Cow,
|
||||
@@ -162,34 +162,9 @@ pub enum SoundBufferResourceLoadError {
|
||||
Io(FileLoadError),
|
||||
}
|
||||
|
||||
define_new_resource!(
|
||||
/// A shared sound buffer resource.
|
||||
#[derive(Reflect)]
|
||||
#[reflect(hide_all)]
|
||||
SoundBufferResource<SoundBufferState>
|
||||
);
|
||||
|
||||
impl SoundBufferResource {
|
||||
/// Tries to create new streaming sound buffer from a given data source. Returns sound source
|
||||
/// wrapped into Arc<Mutex<>> that can be directly used with sound sources.
|
||||
pub fn new_streaming(data_source: DataSource) -> Result<Self, DataSource> {
|
||||
Ok(Self(Resource::new_ok(SoundBufferState::Streaming(
|
||||
StreamingBuffer::new(data_source)?,
|
||||
))))
|
||||
}
|
||||
|
||||
/// Tries to create new generic sound buffer from a given data source. Returns sound source
|
||||
/// wrapped into Arc<Mutex<>> that can be directly used with sound sources.
|
||||
pub fn new_generic(data_source: DataSource) -> Result<Self, DataSource> {
|
||||
Ok(Self(Resource::new_ok(SoundBufferState::Generic(
|
||||
GenericBuffer::new(data_source)?,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sound buffer is a data source for sound sources. See module documentation for more info.
|
||||
#[derive(Debug, Visit)]
|
||||
pub enum SoundBufferState {
|
||||
pub enum SoundBuffer {
|
||||
/// General-purpose buffer, usually contains all the data and allows random
|
||||
/// access to samples. It is also used to make streaming buffer via composition.
|
||||
Generic(GenericBuffer),
|
||||
@@ -201,7 +176,15 @@ pub enum SoundBufferState {
|
||||
Streaming(StreamingBuffer),
|
||||
}
|
||||
|
||||
impl SoundBufferState {
|
||||
pub type SoundBufferResource = Resource<SoundBuffer>;
|
||||
|
||||
impl TypeUuidProvider for SoundBuffer {
|
||||
fn type_uuid() -> Uuid {
|
||||
SOUND_BUFFER_RESOURCE_UUID
|
||||
}
|
||||
}
|
||||
|
||||
impl SoundBuffer {
|
||||
/// Tries to create new streaming sound buffer from a given data source. It returns raw sound
|
||||
/// buffer that has to be wrapped into Arc<Mutex<>> for use with sound sources.
|
||||
pub fn raw_streaming(data_source: DataSource) -> Result<Self, DataSource> {
|
||||
@@ -213,39 +196,59 @@ impl SoundBufferState {
|
||||
pub fn raw_generic(data_source: DataSource) -> Result<Self, DataSource> {
|
||||
Ok(Self::Generic(GenericBuffer::new(data_source)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SoundBufferState {
|
||||
fn default() -> Self {
|
||||
SoundBufferState::Generic(Default::default())
|
||||
/// Tries to create new streaming sound buffer from a given data source. Returns sound source
|
||||
/// wrapped into Arc<Mutex<>> that can be directly used with sound sources.
|
||||
pub fn new_streaming_resource(
|
||||
data_source: DataSource,
|
||||
) -> Result<Resource<SoundBuffer>, DataSource> {
|
||||
Ok(Resource::new_ok(SoundBuffer::Streaming(
|
||||
StreamingBuffer::new(data_source)?,
|
||||
)))
|
||||
}
|
||||
|
||||
/// Tries to create new generic sound buffer from a given data source. Returns sound source
|
||||
/// wrapped into Arc<Mutex<>> that can be directly used with sound sources.
|
||||
pub fn new_generic_resource(
|
||||
data_source: DataSource,
|
||||
) -> Result<Resource<SoundBuffer>, DataSource> {
|
||||
Ok(Resource::new_ok(SoundBuffer::Generic(GenericBuffer::new(
|
||||
data_source,
|
||||
)?)))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SoundBufferState {
|
||||
impl Default for SoundBuffer {
|
||||
fn default() -> Self {
|
||||
SoundBuffer::Generic(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SoundBuffer {
|
||||
type Target = GenericBuffer;
|
||||
|
||||
/// Returns shared reference to generic buffer for any enum variant. It is possible because
|
||||
/// streaming sound buffers are built on top of generic buffers.
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
SoundBufferState::Generic(v) => v,
|
||||
SoundBufferState::Streaming(v) => v,
|
||||
SoundBuffer::Generic(v) => v,
|
||||
SoundBuffer::Streaming(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for SoundBufferState {
|
||||
impl DerefMut for SoundBuffer {
|
||||
/// Returns mutable reference to generic buffer for any enum variant. It is possible because
|
||||
/// streaming sound buffers are built on top of generic buffers.
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self {
|
||||
SoundBufferState::Generic(v) => v,
|
||||
SoundBufferState::Streaming(v) => v,
|
||||
SoundBuffer::Generic(v) => v,
|
||||
SoundBuffer::Streaming(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceData for SoundBufferState {
|
||||
impl ResourceData for SoundBuffer {
|
||||
fn path(&self) -> Cow<Path> {
|
||||
Cow::from(&self.external_source_path)
|
||||
}
|
||||
|
||||
+12
-16
@@ -29,7 +29,7 @@
|
||||
#![allow(clippy::float_cmp)]
|
||||
|
||||
use crate::{
|
||||
buffer::{streaming::StreamingBuffer, SoundBufferResource, SoundBufferState},
|
||||
buffer::{streaming::StreamingBuffer, SoundBuffer, SoundBufferResource},
|
||||
bus::AudioBusGraph,
|
||||
context::DistanceModel,
|
||||
error::SoundError,
|
||||
@@ -210,7 +210,7 @@ impl SoundSource {
|
||||
// If we already have streaming buffer assigned make sure to decrease use count
|
||||
// so it can be reused later on if needed.
|
||||
if let Some(buffer) = self.buffer.clone() {
|
||||
if let SoundBufferState::Streaming(ref mut streaming) = *buffer.data_ref() {
|
||||
if let SoundBuffer::Streaming(ref mut streaming) = *buffer.data_ref() {
|
||||
streaming.use_count = streaming.use_count.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,7 @@ impl SoundSource {
|
||||
}
|
||||
ResourceStateRefMut::Ok(locked_buffer) => {
|
||||
// Check new buffer if streaming - it must not be used by anyone else.
|
||||
if let SoundBufferState::Streaming(ref mut streaming) = *locked_buffer {
|
||||
if let SoundBuffer::Streaming(ref mut streaming) = *locked_buffer {
|
||||
if streaming.use_count != 0 {
|
||||
return Err(SoundError::StreamingBufferAlreadyInUse);
|
||||
}
|
||||
@@ -340,7 +340,7 @@ impl SoundSource {
|
||||
|
||||
if let Some(buffer) = self.buffer.as_ref() {
|
||||
let mut buffer = buffer.data_ref();
|
||||
if let SoundBufferState::Streaming(ref mut streaming) = *buffer {
|
||||
if let SoundBuffer::Streaming(ref mut streaming) = *buffer {
|
||||
streaming.rewind()?;
|
||||
}
|
||||
}
|
||||
@@ -464,7 +464,7 @@ impl SoundSource {
|
||||
pub fn set_playback_time(&mut self, time: Duration) {
|
||||
if let Some(buffer) = self.buffer.as_ref() {
|
||||
let mut buffer = buffer.data_ref();
|
||||
if let SoundBufferState::Streaming(ref mut streaming) = *buffer {
|
||||
if let SoundBuffer::Streaming(ref mut streaming) = *buffer {
|
||||
// Make sure decoder is at right position.
|
||||
streaming.time_seek(time);
|
||||
}
|
||||
@@ -472,14 +472,14 @@ impl SoundSource {
|
||||
self.playback_pos = time.as_secs_f64() * buffer.sample_rate as f64;
|
||||
// Then adjust buffer read position.
|
||||
self.buf_read_pos = match *buffer {
|
||||
SoundBufferState::Streaming(ref mut streaming) => {
|
||||
SoundBuffer::Streaming(ref mut streaming) => {
|
||||
// Make sure to load correct data into buffer from decoder.
|
||||
streaming.read_next_block();
|
||||
// Streaming sources has different buffer read position because
|
||||
// buffer contains only small portion of data.
|
||||
self.playback_pos % (StreamingBuffer::STREAM_SAMPLE_COUNT as f64)
|
||||
}
|
||||
SoundBufferState::Generic(_) => self.playback_pos,
|
||||
SoundBuffer::Generic(_) => self.playback_pos,
|
||||
};
|
||||
assert!(
|
||||
self.buf_read_pos * (buffer.channel_count() as f64) < buffer.samples().len() as f64
|
||||
@@ -506,7 +506,7 @@ impl SoundSource {
|
||||
self.frame_samples.resize(amount, (0.0, 0.0));
|
||||
}
|
||||
|
||||
fn render_playing(&mut self, buffer: &mut SoundBufferState, amount: usize) {
|
||||
fn render_playing(&mut self, buffer: &mut SoundBuffer, amount: usize) {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
count += self.render_until_block_end(buffer, amount - count);
|
||||
@@ -517,7 +517,7 @@ impl SoundSource {
|
||||
let channel_count = buffer.channel_count();
|
||||
let len = buffer.samples().len();
|
||||
let mut end_reached = true;
|
||||
if let SoundBufferState::Streaming(streaming) = buffer {
|
||||
if let SoundBuffer::Streaming(streaming) = buffer {
|
||||
// Means that this is the last available block.
|
||||
if len != channel_count * StreamingBuffer::STREAM_SAMPLE_COUNT {
|
||||
let _ = streaming.rewind();
|
||||
@@ -542,11 +542,7 @@ impl SoundSource {
|
||||
|
||||
// Renders until the end of the block or until amount samples is written and returns
|
||||
// the number of written samples.
|
||||
fn render_until_block_end(
|
||||
&mut self,
|
||||
buffer: &mut SoundBufferState,
|
||||
mut amount: usize,
|
||||
) -> usize {
|
||||
fn render_until_block_end(&mut self, buffer: &mut SoundBuffer, mut amount: usize) -> usize {
|
||||
let step = self.pitch * self.resampling_multiplier;
|
||||
if step == 1.0 {
|
||||
if self.buf_read_pos < 0.0 {
|
||||
@@ -581,7 +577,7 @@ impl SoundSource {
|
||||
// Does linear resampling while rendering until the end of the block.
|
||||
fn render_until_block_end_resample(
|
||||
&mut self,
|
||||
buffer: &mut SoundBufferState,
|
||||
buffer: &mut SoundBuffer,
|
||||
amount: usize,
|
||||
step: f64,
|
||||
) -> usize {
|
||||
@@ -675,7 +671,7 @@ impl Drop for SoundSource {
|
||||
fn drop(&mut self) {
|
||||
if let Some(buffer) = self.buffer.as_ref() {
|
||||
let mut buffer = buffer.data_ref();
|
||||
if let SoundBufferState::Streaming(ref mut streaming) = *buffer {
|
||||
if let SoundBuffer::Streaming(ref mut streaming) = *buffer {
|
||||
streaming.use_count = streaming.use_count.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use crate::{
|
||||
animation::spritesheet::signal::Signal,
|
||||
core::{algebra::Vector2, math::Rect, reflect::prelude::*, visitor::prelude::*},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
};
|
||||
use std::collections::vec_deque::VecDeque;
|
||||
use strum_macros::{AsRefStr, EnumString, EnumVariantNames};
|
||||
@@ -55,7 +55,7 @@ pub struct SpriteSheetFramesContainer {
|
||||
size: Vector2<u32>,
|
||||
frames: Vec<Vector2<u32>>,
|
||||
#[visit(optional)]
|
||||
texture: Option<Texture>,
|
||||
texture: Option<TextureResource>,
|
||||
}
|
||||
|
||||
impl SpriteSheetFramesContainer {
|
||||
@@ -112,7 +112,7 @@ impl SpriteSheetFramesContainer {
|
||||
}
|
||||
|
||||
/// Returns current texture of the container. To set a texture use sprite sheet animation methods.
|
||||
pub fn texture(&self) -> Option<Texture> {
|
||||
pub fn texture(&self) -> Option<TextureResource> {
|
||||
self.texture.clone()
|
||||
}
|
||||
}
|
||||
@@ -140,7 +140,7 @@ pub struct SpriteSheetAnimation {
|
||||
signals: Vec<Signal>,
|
||||
#[visit(optional)]
|
||||
#[reflect(setter = "set_texture")]
|
||||
texture: Option<Texture>,
|
||||
texture: Option<TextureResource>,
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
events: VecDeque<Event>,
|
||||
@@ -305,13 +305,13 @@ impl SpriteSheetAnimation {
|
||||
}
|
||||
|
||||
/// Sets new texture for the animation.
|
||||
pub fn set_texture(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_texture(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
self.frames_container.texture = texture.clone();
|
||||
std::mem::replace(&mut self.texture, texture)
|
||||
}
|
||||
|
||||
/// Returns current texture of the animation.
|
||||
pub fn texture(&self) -> Option<Texture> {
|
||||
pub fn texture(&self) -> Option<TextureResource> {
|
||||
self.texture.clone()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
//! Executor is a small wrapper that manages plugins and scripts for your game.
|
||||
|
||||
use crate::{
|
||||
asset::manager::ResourceManager,
|
||||
core::instant::Instant,
|
||||
engine::{
|
||||
resource_manager::ResourceManager, Engine, EngineInitParams, GraphicsContext,
|
||||
GraphicsContextParams, SerializationContext,
|
||||
Engine, EngineInitParams, GraphicsContext, GraphicsContextParams, SerializationContext,
|
||||
},
|
||||
event::{Event, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoop},
|
||||
@@ -71,7 +71,7 @@ impl Executor {
|
||||
let serialization_context = Arc::new(SerializationContext::new());
|
||||
let engine = Engine::new(EngineInitParams {
|
||||
graphics_context_params,
|
||||
resource_manager: ResourceManager::new(serialization_context.clone()),
|
||||
resource_manager: ResourceManager::new(),
|
||||
serialization_context,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
+39
-34
@@ -7,18 +7,19 @@ pub mod error;
|
||||
pub mod executor;
|
||||
pub mod resource_loaders;
|
||||
|
||||
use crate::resource::model::Model;
|
||||
use crate::{
|
||||
core::{algebra::Vector2, futures::executor::block_on, instant, pool::Handle},
|
||||
engine::{
|
||||
error::EngineError,
|
||||
resource_manager::{container::event::ResourceEvent, ResourceManager, ResourceWaitContext},
|
||||
asset::{
|
||||
container::event::ResourceEvent, manager::ResourceManager, manager::ResourceWaitContext,
|
||||
},
|
||||
core::{algebra::Vector2, futures::executor::block_on, instant, pool::Handle},
|
||||
engine::error::EngineError,
|
||||
event::Event,
|
||||
event_loop::ControlFlow,
|
||||
gui::UserInterface,
|
||||
plugin::{Plugin, PluginConstructor, PluginContext, PluginRegistrationContext},
|
||||
renderer::{framework::error::FrameworkError, Renderer},
|
||||
resource::{model::Model, texture::TextureKind},
|
||||
resource::{model::ModelResource, texture::TextureKind},
|
||||
scene::{
|
||||
base::NodeScriptMessage,
|
||||
graph::GraphUpdateSwitches,
|
||||
@@ -198,7 +199,7 @@ pub struct Engine {
|
||||
|
||||
performance_statistics: PerformanceStatistics,
|
||||
|
||||
model_events_receiver: Receiver<ResourceEvent<Model>>,
|
||||
model_events_receiver: Receiver<ResourceEvent>,
|
||||
|
||||
#[allow(dead_code)] // Keep engine instance alive.
|
||||
sound_engine: SoundEngine,
|
||||
@@ -605,26 +606,28 @@ impl ScriptProcessor {
|
||||
}
|
||||
|
||||
struct ResourceGraphVertex {
|
||||
resource: Model,
|
||||
resource: ModelResource,
|
||||
children: Vec<ResourceGraphVertex>,
|
||||
}
|
||||
|
||||
impl ResourceGraphVertex {
|
||||
pub fn new(model: Model, resource_manager: ResourceManager) -> Self {
|
||||
pub fn new(model: ModelResource, resource_manager: ResourceManager) -> Self {
|
||||
let mut children = Vec::new();
|
||||
|
||||
// Look for dependent resources.
|
||||
let mut dependent_resources = HashSet::new();
|
||||
for other_model in resource_manager.state().containers().models.iter() {
|
||||
let state = other_model.state();
|
||||
if let ResourceStateRef::Ok(model_data) = state.get() {
|
||||
if model_data
|
||||
.get_scene()
|
||||
.graph
|
||||
.linear_iter()
|
||||
.any(|n| n.resource.as_ref().map_or(false, |r| r == &model))
|
||||
{
|
||||
dependent_resources.insert(other_model.clone());
|
||||
for resource in resource_manager.state().containers().resources.iter() {
|
||||
if let Some(other_model) = resource.try_cast::<Model>() {
|
||||
let mut state = other_model.state();
|
||||
if let ResourceStateRef::Ok(model_data) = state.get() {
|
||||
if model_data
|
||||
.get_scene()
|
||||
.graph
|
||||
.linear_iter()
|
||||
.any(|n| n.resource.as_ref().map_or(false, |r| r == &model))
|
||||
{
|
||||
dependent_resources.insert(other_model.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -644,7 +647,7 @@ impl ResourceGraphVertex {
|
||||
pub fn resolve(&self) {
|
||||
Log::info(format!(
|
||||
"Resolving {} resource from dependency graph...",
|
||||
self.resource.state().path().display()
|
||||
self.resource.path().display()
|
||||
));
|
||||
|
||||
// Wait until resource is fully loaded, then resolve.
|
||||
@@ -663,7 +666,7 @@ struct ResourceDependencyGraph {
|
||||
}
|
||||
|
||||
impl ResourceDependencyGraph {
|
||||
pub fn new(model: Model, resource_manager: ResourceManager) -> Self {
|
||||
pub fn new(model: ModelResource, resource_manager: ResourceManager) -> Self {
|
||||
Self {
|
||||
root: ResourceGraphVertex::new(model, resource_manager),
|
||||
}
|
||||
@@ -828,7 +831,7 @@ impl Engine {
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.models
|
||||
.resources
|
||||
.event_broadcaster
|
||||
.add(rx);
|
||||
|
||||
@@ -1362,22 +1365,24 @@ impl Engine {
|
||||
/// You should only call this manually if you don't use that method.
|
||||
pub fn handle_model_events(&mut self) {
|
||||
while let Ok(event) = self.model_events_receiver.try_recv() {
|
||||
if let ResourceEvent::Reloaded(model) = event {
|
||||
Log::info(format!(
|
||||
"A model resource {} was reloaded, propagating changes...",
|
||||
model.state().path().display()
|
||||
));
|
||||
if let ResourceEvent::Reloaded(resource) = event {
|
||||
if let Some(model) = resource.try_cast::<Model>() {
|
||||
Log::info(format!(
|
||||
"A model resource {} was reloaded, propagating changes...",
|
||||
model.path().display()
|
||||
));
|
||||
|
||||
// Build resource dependency graph and resolve it first.
|
||||
ResourceDependencyGraph::new(model, self.resource_manager.clone()).resolve();
|
||||
// Build resource dependency graph and resolve it first.
|
||||
ResourceDependencyGraph::new(model, self.resource_manager.clone()).resolve();
|
||||
|
||||
Log::info("Propagating changes to active scenes...");
|
||||
Log::info("Propagating changes to active scenes...");
|
||||
|
||||
// Resolve all scenes.
|
||||
// TODO: This might be inefficient if there is bunch of scenes loaded,
|
||||
// however this seems to be very rare case so it should be ok.
|
||||
for scene in self.scenes.iter_mut() {
|
||||
scene.resolve();
|
||||
// Resolve all scenes.
|
||||
// TODO: This might be inefficient if there is bunch of scenes loaded,
|
||||
// however this seems to be very rare case so it should be ok.
|
||||
for scene in self.scenes.iter_mut() {
|
||||
scene.resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,29 +5,29 @@ use crate::{
|
||||
container::event::ResourceEventBroadcaster,
|
||||
loader::{BoxedLoaderFuture, ResourceLoader},
|
||||
},
|
||||
resource::curve::{CurveImportOptions, CurveResource, CurveResourceState},
|
||||
resource::curve::CurveResourceState,
|
||||
utils::log::Log,
|
||||
};
|
||||
use fyrox_resource::untyped::UntypedResource;
|
||||
|
||||
/// Default implementation for curve loading.
|
||||
pub struct CurveLoader;
|
||||
|
||||
impl ResourceLoader<CurveResource, CurveImportOptions> for CurveLoader {
|
||||
impl ResourceLoader for CurveLoader {
|
||||
fn load(
|
||||
&self,
|
||||
curve: CurveResource,
|
||||
_default_import_options: CurveImportOptions,
|
||||
event_broadcaster: ResourceEventBroadcaster<CurveResource>,
|
||||
curve: UntypedResource,
|
||||
event_broadcaster: ResourceEventBroadcaster,
|
||||
reload: bool,
|
||||
) -> BoxedLoaderFuture {
|
||||
Box::pin(async move {
|
||||
let path = curve.state().path().to_path_buf();
|
||||
let path = curve.0.lock().path().to_path_buf();
|
||||
|
||||
match CurveResourceState::from_file(&path).await {
|
||||
Ok(curve_state) => {
|
||||
Log::info(format!("Curve {:?} is loaded!", path));
|
||||
|
||||
curve.state().commit_ok(curve_state);
|
||||
curve.0.lock().commit_ok(curve_state);
|
||||
|
||||
event_broadcaster.broadcast_loaded_or_reloaded(curve, reload);
|
||||
}
|
||||
@@ -37,7 +37,7 @@ impl ResourceLoader<CurveResource, CurveImportOptions> for CurveLoader {
|
||||
path, error
|
||||
));
|
||||
|
||||
curve.state().commit_error(path, error);
|
||||
curve.0.lock().commit_error(path, error);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -8,9 +8,10 @@ use crate::{
|
||||
options::try_get_import_settings,
|
||||
},
|
||||
engine::SerializationContext,
|
||||
resource::model::{Model, ModelData, ModelImportOptions},
|
||||
resource::model::{Model, ModelImportOptions},
|
||||
utils::log::Log,
|
||||
};
|
||||
use fyrox_resource::untyped::UntypedResource;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Default implementation for model loading.
|
||||
@@ -20,32 +21,32 @@ pub struct ModelLoader {
|
||||
/// Node constructors contains a set of constructors that allows to build a node using its
|
||||
/// type UUID.
|
||||
pub serialization_context: Arc<SerializationContext>,
|
||||
pub default_import_options: ModelImportOptions,
|
||||
}
|
||||
|
||||
impl ResourceLoader<Model, ModelImportOptions> for ModelLoader {
|
||||
impl ResourceLoader for ModelLoader {
|
||||
fn load(
|
||||
&self,
|
||||
model: Model,
|
||||
default_import_options: ModelImportOptions,
|
||||
event_broadcaster: ResourceEventBroadcaster<Model>,
|
||||
model: UntypedResource,
|
||||
event_broadcaster: ResourceEventBroadcaster,
|
||||
reload: bool,
|
||||
) -> BoxedLoaderFuture {
|
||||
let resource_manager = self.resource_manager.clone();
|
||||
let node_constructors = self.serialization_context.clone();
|
||||
let default_import_options = self.default_import_options.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
let path = model.state().path().to_path_buf();
|
||||
let path = model.path().to_path_buf();
|
||||
|
||||
let import_options = try_get_import_settings(&path)
|
||||
.await
|
||||
.unwrap_or(default_import_options);
|
||||
|
||||
match ModelData::load(&path, node_constructors, resource_manager, import_options).await
|
||||
{
|
||||
match Model::load(&path, node_constructors, resource_manager, import_options).await {
|
||||
Ok(raw_model) => {
|
||||
Log::info(format!("Model {:?} is loaded!", path));
|
||||
|
||||
model.state().commit_ok(raw_model);
|
||||
model.0.lock().commit_ok(raw_model);
|
||||
|
||||
event_broadcaster.broadcast_loaded_or_reloaded(model, reload);
|
||||
}
|
||||
@@ -55,7 +56,7 @@ impl ResourceLoader<Model, ModelImportOptions> for ModelLoader {
|
||||
path, error
|
||||
));
|
||||
|
||||
model.state().commit_error(path, error);
|
||||
model.0.lock().commit_error(path, error);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -5,29 +5,29 @@ use crate::{
|
||||
container::event::ResourceEventBroadcaster,
|
||||
loader::{BoxedLoaderFuture, ResourceLoader},
|
||||
},
|
||||
material::shader::{Shader, ShaderImportOptions, ShaderState},
|
||||
material::shader::Shader,
|
||||
utils::log::Log,
|
||||
};
|
||||
use fyrox_resource::untyped::UntypedResource;
|
||||
|
||||
/// Default implementation for shader loading.
|
||||
pub struct ShaderLoader;
|
||||
|
||||
impl ResourceLoader<Shader, ShaderImportOptions> for ShaderLoader {
|
||||
impl ResourceLoader for ShaderLoader {
|
||||
fn load(
|
||||
&self,
|
||||
shader: Shader,
|
||||
_default_import_options: ShaderImportOptions,
|
||||
event_broadcaster: ResourceEventBroadcaster<Shader>,
|
||||
shader: UntypedResource,
|
||||
event_broadcaster: ResourceEventBroadcaster,
|
||||
reload: bool,
|
||||
) -> BoxedLoaderFuture {
|
||||
Box::pin(async move {
|
||||
let path = shader.state().path().to_path_buf();
|
||||
let path = shader.path().to_path_buf();
|
||||
|
||||
match ShaderState::from_file(&path).await {
|
||||
match Shader::from_file(&path).await {
|
||||
Ok(shader_state) => {
|
||||
Log::info(format!("Shader {:?} is loaded!", path));
|
||||
|
||||
shader.state().commit_ok(shader_state);
|
||||
shader.0.lock().commit_ok(shader_state);
|
||||
|
||||
event_broadcaster.broadcast_loaded_or_reloaded(shader, reload);
|
||||
}
|
||||
@@ -37,7 +37,7 @@ impl ResourceLoader<Shader, ShaderImportOptions> for ShaderLoader {
|
||||
path, error
|
||||
));
|
||||
|
||||
shader.state().commit_error(path, error);
|
||||
shader.0.lock().commit_error(path, error);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -9,9 +9,8 @@ use crate::{
|
||||
core::reflect::prelude::*,
|
||||
utils::log::Log,
|
||||
};
|
||||
use fyrox_sound::buffer::{
|
||||
DataSource, SoundBufferResource, SoundBufferResourceLoadError, SoundBufferState,
|
||||
};
|
||||
use fyrox_resource::untyped::UntypedResource;
|
||||
use fyrox_sound::buffer::{DataSource, SoundBuffer, SoundBufferResourceLoadError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Defines sound buffer resource import options.
|
||||
@@ -24,18 +23,21 @@ pub struct SoundBufferImportOptions {
|
||||
impl ImportOptions for SoundBufferImportOptions {}
|
||||
|
||||
/// Default implementation for sound buffer loading.
|
||||
pub struct SoundBufferLoader;
|
||||
pub struct SoundBufferLoader {
|
||||
pub default_import_options: SoundBufferImportOptions,
|
||||
}
|
||||
|
||||
impl ResourceLoader<SoundBufferResource, SoundBufferImportOptions> for SoundBufferLoader {
|
||||
impl ResourceLoader for SoundBufferLoader {
|
||||
fn load(
|
||||
&self,
|
||||
resource: SoundBufferResource,
|
||||
default_import_options: SoundBufferImportOptions,
|
||||
event_broadcaster: ResourceEventBroadcaster<SoundBufferResource>,
|
||||
resource: UntypedResource,
|
||||
event_broadcaster: ResourceEventBroadcaster,
|
||||
reload: bool,
|
||||
) -> BoxedLoaderFuture {
|
||||
let default_import_options = self.default_import_options.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
let path = resource.state().path().to_path_buf();
|
||||
let path = resource.path().to_path_buf();
|
||||
|
||||
let import_options = try_get_import_settings(&path)
|
||||
.await
|
||||
@@ -44,20 +46,20 @@ impl ResourceLoader<SoundBufferResource, SoundBufferImportOptions> for SoundBuff
|
||||
match DataSource::from_file(&path).await {
|
||||
Ok(source) => {
|
||||
let buffer = if import_options.stream {
|
||||
SoundBufferState::raw_streaming(source)
|
||||
SoundBuffer::raw_streaming(source)
|
||||
} else {
|
||||
SoundBufferState::raw_generic(source)
|
||||
SoundBuffer::raw_generic(source)
|
||||
};
|
||||
match buffer {
|
||||
Ok(sound_buffer) => {
|
||||
resource.state().commit_ok(sound_buffer);
|
||||
resource.0.lock().commit_ok(sound_buffer);
|
||||
|
||||
event_broadcaster.broadcast_loaded_or_reloaded(resource, reload);
|
||||
|
||||
Log::info(format!("Sound buffer {:?} is loaded!", path));
|
||||
}
|
||||
Err(_) => {
|
||||
resource.state().commit_error(
|
||||
resource.0.lock().commit_error(
|
||||
path.clone(),
|
||||
SoundBufferResourceLoadError::UnsupportedFormat,
|
||||
);
|
||||
@@ -70,7 +72,8 @@ impl ResourceLoader<SoundBufferResource, SoundBufferImportOptions> for SoundBuff
|
||||
Log::err(format!("Invalid data source for sound buffer: {:?}", e));
|
||||
|
||||
resource
|
||||
.state()
|
||||
.0
|
||||
.lock()
|
||||
.commit_error(path.clone(), SoundBufferResourceLoadError::Io(e));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,23 +7,27 @@ use crate::{
|
||||
options::try_get_import_settings,
|
||||
},
|
||||
core::instant,
|
||||
resource::texture::{Texture, TextureData, TextureImportOptions},
|
||||
resource::texture::{Texture, TextureImportOptions},
|
||||
utils::log::Log,
|
||||
};
|
||||
use fyrox_resource::untyped::UntypedResource;
|
||||
|
||||
/// Default implementation for texture loading.
|
||||
pub struct TextureLoader;
|
||||
pub struct TextureLoader {
|
||||
pub default_import_options: TextureImportOptions,
|
||||
}
|
||||
|
||||
impl ResourceLoader<Texture, TextureImportOptions> for TextureLoader {
|
||||
impl ResourceLoader for TextureLoader {
|
||||
fn load(
|
||||
&self,
|
||||
texture: Texture,
|
||||
default_import_options: TextureImportOptions,
|
||||
event_broadcaster: ResourceEventBroadcaster<Texture>,
|
||||
texture: UntypedResource,
|
||||
event_broadcaster: ResourceEventBroadcaster,
|
||||
reload: bool,
|
||||
) -> BoxedLoaderFuture {
|
||||
let default_import_options = self.default_import_options.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
let path = texture.state().path().to_path_buf();
|
||||
let path = texture.path().to_path_buf();
|
||||
|
||||
let import_options = try_get_import_settings(&path)
|
||||
.await
|
||||
@@ -32,8 +36,7 @@ impl ResourceLoader<Texture, TextureImportOptions> for TextureLoader {
|
||||
let gen_mip_maps = import_options.minification_filter.is_using_mip_mapping();
|
||||
|
||||
let time = instant::Instant::now();
|
||||
match TextureData::load_from_file(&path, import_options.compression, gen_mip_maps).await
|
||||
{
|
||||
match Texture::load_from_file(&path, import_options.compression, gen_mip_maps).await {
|
||||
Ok(mut raw_texture) => {
|
||||
Log::info(format!(
|
||||
"Texture {:?} is loaded in {:?}!",
|
||||
@@ -47,7 +50,7 @@ impl ResourceLoader<Texture, TextureImportOptions> for TextureLoader {
|
||||
raw_texture.set_s_wrap_mode(import_options.s_wrap_mode);
|
||||
raw_texture.set_t_wrap_mode(import_options.t_wrap_mode);
|
||||
|
||||
texture.state().commit_ok(raw_texture);
|
||||
texture.0.lock().commit_ok(raw_texture);
|
||||
|
||||
event_broadcaster.broadcast_loaded_or_reloaded(texture, reload);
|
||||
}
|
||||
@@ -57,7 +60,7 @@ impl ResourceLoader<Texture, TextureImportOptions> for TextureLoader {
|
||||
&path, &error
|
||||
));
|
||||
|
||||
texture.state().commit_error(path, error);
|
||||
texture.0.lock().commit_error(path, error);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
+17
-13
@@ -4,7 +4,10 @@
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use crate::material::shader::ShaderResourceExtension;
|
||||
use crate::resource::texture::Texture;
|
||||
use crate::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
algebra::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4},
|
||||
color::Color,
|
||||
@@ -13,9 +16,8 @@ use crate::{
|
||||
sstorage::ImmutableString,
|
||||
visitor::prelude::*,
|
||||
},
|
||||
engine::resource_manager::ResourceManager,
|
||||
material::shader::{PropertyKind, SamplerFallback, Shader},
|
||||
resource::texture::Texture,
|
||||
material::shader::{PropertyKind, SamplerFallback, ShaderResource},
|
||||
resource::texture::TextureResource,
|
||||
};
|
||||
use fxhash::FxHashMap;
|
||||
use std::{
|
||||
@@ -118,7 +120,7 @@ pub enum PropertyValue {
|
||||
/// missing by very specific value in the fallback texture.
|
||||
Sampler {
|
||||
/// Actual value of the sampler. Could be [`None`], in this case `fallback` will be used.
|
||||
value: Option<Texture>,
|
||||
value: Option<TextureResource>,
|
||||
|
||||
/// Sampler fallback value.
|
||||
fallback: SamplerFallback,
|
||||
@@ -234,7 +236,7 @@ impl PropertyValue {
|
||||
);
|
||||
|
||||
/// Tries to unwrap property value as texture.
|
||||
pub fn as_sampler(&self) -> Option<Texture> {
|
||||
pub fn as_sampler(&self) -> Option<TextureResource> {
|
||||
if let PropertyValue::Sampler { value, .. } = self {
|
||||
value.clone()
|
||||
} else {
|
||||
@@ -286,7 +288,7 @@ impl Default for PropertyValue {
|
||||
///
|
||||
/// ```no_run
|
||||
/// use fyrox::{
|
||||
/// material::shader::{Shader, SamplerFallback},
|
||||
/// material::shader::{ShaderResource, SamplerFallback},
|
||||
/// engine::resource_manager::ResourceManager,
|
||||
/// material::{Material, PropertyValue},
|
||||
/// core::sstorage::ImmutableString,
|
||||
@@ -345,7 +347,7 @@ impl Default for PropertyValue {
|
||||
/// material instance. Then we populate properties as usual.
|
||||
#[derive(Default, Debug, Visit, Clone, Reflect)]
|
||||
pub struct Material {
|
||||
shader: Shader,
|
||||
shader: ShaderResource,
|
||||
properties: FxHashMap<ImmutableString, PropertyValue>,
|
||||
}
|
||||
|
||||
@@ -398,7 +400,7 @@ impl Material {
|
||||
///
|
||||
/// ```no_run
|
||||
/// use fyrox::{
|
||||
/// material::shader::{Shader, SamplerFallback},
|
||||
/// material::shader::{ShaderResource, SamplerFallback},
|
||||
/// engine::resource_manager::ResourceManager,
|
||||
/// material::{Material, PropertyValue},
|
||||
/// core::sstorage::ImmutableString
|
||||
@@ -419,12 +421,12 @@ impl Material {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn standard() -> Self {
|
||||
Self::from_shader(Shader::standard(), None)
|
||||
Self::from_shader(ShaderResource::standard(), None)
|
||||
}
|
||||
|
||||
/// Creates new instance of standard terrain material.
|
||||
pub fn standard_terrain() -> Self {
|
||||
Self::from_shader(Shader::standard_terrain(), None)
|
||||
Self::from_shader(ShaderResource::standard_terrain(), None)
|
||||
}
|
||||
|
||||
/// Creates a new material instance with given shader. Each property will have default values
|
||||
@@ -459,7 +461,7 @@ impl Material {
|
||||
/// material
|
||||
/// }
|
||||
/// ```
|
||||
pub fn from_shader(shader: Shader, resource_manager: Option<ResourceManager>) -> Self {
|
||||
pub fn from_shader(shader: ShaderResource, resource_manager: Option<ResourceManager>) -> Self {
|
||||
let data = shader.data_ref();
|
||||
|
||||
let mut property_values = FxHashMap::default();
|
||||
@@ -483,7 +485,9 @@ impl Material {
|
||||
fallback: usage,
|
||||
} => PropertyValue::Sampler {
|
||||
value: default.as_ref().and_then(|path| {
|
||||
resource_manager.clone().map(|rm| rm.request_texture(path))
|
||||
resource_manager
|
||||
.clone()
|
||||
.map(|rm| rm.request::<Texture, _>(path))
|
||||
}),
|
||||
fallback: *usage,
|
||||
},
|
||||
@@ -644,7 +648,7 @@ impl Material {
|
||||
}
|
||||
|
||||
/// Returns a reference to current shader.
|
||||
pub fn shader(&self) -> &Shader {
|
||||
pub fn shader(&self) -> &ShaderResource {
|
||||
&self.shader
|
||||
}
|
||||
|
||||
|
||||
+291
-259
@@ -1,9 +1,232 @@
|
||||
//! Shader is a script for graphics card. This module contains everything related to shaders.
|
||||
//!
|
||||
//! For more info see [`Shader`] struct docs.
|
||||
//! Shader is a script for graphics adapter, it defines how to draw an object.
|
||||
//!
|
||||
//! # Structure
|
||||
//!
|
||||
//! Shader has rigid structure that could be described in this code snipped:
|
||||
//!
|
||||
//! ```ron
|
||||
//! (
|
||||
//! // A set of properties, there could be any amount of properties.
|
||||
//! properties: [
|
||||
//! (
|
||||
//! // Each property must have a name. This name must match with respective
|
||||
//! // uniforms! That's is the whole point of having properties.
|
||||
//! name: "diffuseTexture",
|
||||
//!
|
||||
//! // Value has limited set of possible variants.
|
||||
//! value: Sampler(default: None, fallback: White)
|
||||
//! )
|
||||
//! ],
|
||||
//!
|
||||
//! // A set of render passes (see a section `Render pass` for more info)
|
||||
//! passes: [
|
||||
//! (
|
||||
//! // Name must match with the name of either standard render pass (see below) or
|
||||
//! // one of your passes.
|
||||
//! name: "Forward",
|
||||
//!
|
||||
//! // A set of parameters that regulate renderer pipeline state.
|
||||
//! // This is mandatory field of each render pass.
|
||||
//! draw_parameters: DrawParameters(
|
||||
//! // A face to cull. Either Front or Back.
|
||||
//! cull_face: Some(Back),
|
||||
//!
|
||||
//! // Color mask. Defines which colors should be written to render target.
|
||||
//! color_write: ColorMask(
|
||||
//! red: true,
|
||||
//! green: true,
|
||||
//! blue: true,
|
||||
//! alpha: true,
|
||||
//! ),
|
||||
//!
|
||||
//! // Whether to modify depth buffer or not.
|
||||
//! depth_write: true,
|
||||
//!
|
||||
//! // Whether to use stencil test or not.
|
||||
//! stencil_test: None,
|
||||
//!
|
||||
//! // Whether to perform depth test when drawing.
|
||||
//! depth_test: true,
|
||||
//!
|
||||
//! // Blending options.
|
||||
//! blend: Some(BlendParameters(
|
||||
//! func: BlendFunc(
|
||||
//! sfactor: SrcAlpha,
|
||||
//! dfactor: OneMinusSrcAlpha,
|
||||
//! alpha_sfactor: SrcAlpha,
|
||||
//! alpha_dfactor: OneMinusSrcAlpha,
|
||||
//! ),
|
||||
//! equation: BlendEquation(
|
||||
//! rgb: Add,
|
||||
//! alpha: Add
|
||||
//! )
|
||||
//! )),
|
||||
//!
|
||||
//! // Stencil options.
|
||||
//! stencil_op: StencilOp(
|
||||
//! fail: Keep,
|
||||
//! zfail: Keep,
|
||||
//! zpass: Keep,
|
||||
//! write_mask: 0xFFFF_FFFF,
|
||||
//! ),
|
||||
//! ),
|
||||
//!
|
||||
//! // Vertex shader code.
|
||||
//! vertex_shader:
|
||||
//! r#"
|
||||
//! #version 330 core
|
||||
//!
|
||||
//! layout(location = 0) in vec3 vertexPosition;
|
||||
//! layout(location = 1) in vec2 vertexTexCoord;
|
||||
//!
|
||||
//! uniform mat4 fyrox_worldViewProjection;
|
||||
//!
|
||||
//! out vec2 texCoord;
|
||||
//!
|
||||
//! void main()
|
||||
//! {
|
||||
//! texCoord = vertexTexCoord;
|
||||
//! gl_Position = fyrox_worldViewProjection * vertexPosition;
|
||||
//! }
|
||||
//! "#;
|
||||
//!
|
||||
//! // Pixel shader code.
|
||||
//! pixel_shader:
|
||||
//! r#"
|
||||
//! #version 330 core
|
||||
//!
|
||||
//! // Note that the name of this uniform match the name of the property up above.
|
||||
//! uniform sampler2D diffuseTexture;
|
||||
//!
|
||||
//! out vec4 FragColor;
|
||||
//!
|
||||
//! in vec2 texCoord;
|
||||
//!
|
||||
//! void main()
|
||||
//! {
|
||||
//! FragColor = diffuseColor * texture(diffuseTexture, texCoord);
|
||||
//! }
|
||||
//! "#;
|
||||
//! )
|
||||
//! ],
|
||||
//! )
|
||||
//! ```
|
||||
//!
|
||||
//! Shader should contain at least one render pass to actually do some job. A shader could not
|
||||
//! have properties at all. Currently only vertex and fragment programs are supported. Each
|
||||
//! program mush be written in GLSL. Comprehensive GLSL documentation can be found
|
||||
//! [here](https://www.khronos.org/opengl/wiki/Core_Language_(GLSL))
|
||||
//!
|
||||
//! # Render pass
|
||||
//!
|
||||
//! Modern rendering is a very complex thing that requires drawing an object multiple times
|
||||
//! with different "scripts". For example to draw an object with shadows you need to draw an
|
||||
//! object twice: one directly in a render target, and one in a shadow map. Such stages called
|
||||
//! render passes.
|
||||
//!
|
||||
//! Binding of shaders to render passes is done via names, each render pass has unique name.
|
||||
//!
|
||||
//! ## Predefined passes
|
||||
//!
|
||||
//! There are number of predefined render passes:
|
||||
//!
|
||||
//! - GBuffer - A pass that fills a set of render target sized textures with various data
|
||||
//! about each rendered object. These textures then are used for physically-based lighting.
|
||||
//! Use this pass when you want the standard lighting to work with your objects.
|
||||
//!
|
||||
//! - Forward - A pass that draws an object directly in render target. This pass is very
|
||||
//! limiting, it does not support lighting, shadows, etc. It should be only used to render
|
||||
//! translucent objects.
|
||||
//!
|
||||
//! - SpotShadow - A pass that emits depth values for an object, later this depth map will be
|
||||
//! used to render shadows.
|
||||
//!
|
||||
//! - PointShadow - A pass that emits distance from a fragment to a point light, later this depth
|
||||
//! map will be used to render shadows.
|
||||
//!
|
||||
//! # Built-in variables
|
||||
//!
|
||||
//! There are number of build-in variables that Fyrox pass to each shader automatically:
|
||||
//!
|
||||
//! | Name | Type | Description
|
||||
//! |---------------------------|-----------------|--------------------------------------------
|
||||
//! | fyrox_worldMatrix | `Matrix4` | Local-to-world transformation.
|
||||
//! | fyrox_worldViewProjection | `Matrix4` | Local-to-clip-space transform.
|
||||
//! | fyrox_boneMatrices | `[Matrix4; 60]` | Array of bone matrices.
|
||||
//! | fyrox_useSkeletalAnimation | `Vector3` | Whether skinned meshes is rendering or not.
|
||||
//! | fyrox_cameraPosition | `Vector3` | Position of the camera.
|
||||
//! | fyrox_usePOM | `bool` | Whether to use parallax mapping or not.
|
||||
//! | fyrox_lightPosition | `Vector3` | Light position.
|
||||
//!
|
||||
//! To use any of the variables, just define a uniform with appropriate name:
|
||||
//!
|
||||
//! ```glsl
|
||||
//! uniform mat4 fyrox_worldMatrix;
|
||||
//! uniform vec3 fyrox_cameraPosition;
|
||||
//! ```
|
||||
//!
|
||||
//! This list will be extended in future releases.
|
||||
//!
|
||||
//! # Drawing parameters
|
||||
//!
|
||||
//! Drawing parameters defines which GPU functions to use and at which state. For example, to render
|
||||
//! transparent objects you need to enable blending with specific blending rules. Or you need to disable
|
||||
//! culling to draw objects from both sides. This is when draw parameters comes in handy.
|
||||
//!
|
||||
//! There are relatively large list of drawing parameters and it could confuse a person who didn't get
|
||||
//! used to work with graphics. The following list should help you to use drawing parameters correctly.
|
||||
//!
|
||||
//! - cull_face
|
||||
//! - Defines which side of polygon should be culled.
|
||||
//! - **Possible values:** `None`, [Some(CullFace::XXX)](crate::renderer::framework::state::CullFace)
|
||||
//!
|
||||
//! - color_write:
|
||||
//! - Defines which components of color should be written to a render target
|
||||
//! - **Possible values:** [ColorMask](crate::renderer::framework::state::ColorMask)(...)
|
||||
//!
|
||||
//! - depth_write:
|
||||
//! - Whether to modify depth buffer or not.
|
||||
//! - **Possible values:** `true/false`
|
||||
//!
|
||||
//! - stencil_test:
|
||||
//! - Whether to use stencil test or not.
|
||||
//! - **Possible values:**
|
||||
//! - `None`
|
||||
//! - Some([StencilFunc](crate::renderer::framework::state::StencilFunc))
|
||||
//!
|
||||
//! - depth_test:
|
||||
//! - Whether to perform depth test when drawing.
|
||||
//! - **Possible values:** `true/false`
|
||||
//!
|
||||
//! - blend:
|
||||
//! - Blending options.
|
||||
//! - **Possible values:**
|
||||
//! - `None`
|
||||
//! - Some([BlendFunc](crate::renderer::framework::state::BlendFunc))
|
||||
//!
|
||||
//! - stencil_op:
|
||||
//! - Stencil options.
|
||||
//! - **Possible values:** [StencilOp](crate::renderer::framework::state::StencilOp)
|
||||
//!
|
||||
//! # Standard shader
|
||||
//!
|
||||
//! By default Fyrox uses standard material for rendering, it covers 95% of uses cases and it is very
|
||||
//! flexible. To get standard shader instance, use [`ShaderResource::standard`]
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # use fyrox::material::shader::ShaderResource;
|
||||
//!
|
||||
//! let standard_shader = ShaderResource::standard();
|
||||
//! ```
|
||||
//!
|
||||
//! Usually you don't need to get this shader manually, using of [Material::standard](super::Material::standard)
|
||||
//! is enough.
|
||||
|
||||
use crate::{
|
||||
asset::{define_new_resource, Resource, ResourceData},
|
||||
asset::options::ImportOptions,
|
||||
asset::{Resource, ResourceData},
|
||||
core::{
|
||||
algebra::{Matrix2, Matrix3, Matrix4, Vector2, Vector3, Vector4},
|
||||
io::{self, FileLoadError},
|
||||
@@ -11,11 +234,14 @@ use crate::{
|
||||
sparse::AtomicIndex,
|
||||
visitor::prelude::*,
|
||||
},
|
||||
engine::resource_manager::options::ImportOptions,
|
||||
lazy_static::lazy_static,
|
||||
renderer::framework::framebuffer::DrawParameters,
|
||||
};
|
||||
use fyrox_core::uuid::Uuid;
|
||||
use fyrox_core::TypeUuidProvider;
|
||||
use fyrox_resource::SHADER_RESOURCE_UUID;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
@@ -55,7 +281,7 @@ pub const STANDARD_SHADER_NAMES: [&str; 3] = [
|
||||
/// Usually you don't need to access internals of the shader, but there sometimes could be a need to
|
||||
/// read shader definition, to get supported passes and properties.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ShaderState {
|
||||
pub struct Shader {
|
||||
path: PathBuf,
|
||||
|
||||
/// Shader definition contains description of properties and render passes.
|
||||
@@ -64,7 +290,13 @@ pub struct ShaderState {
|
||||
pub(crate) cache_index: AtomicIndex,
|
||||
}
|
||||
|
||||
impl Visit for ShaderState {
|
||||
impl TypeUuidProvider for Shader {
|
||||
fn type_uuid() -> Uuid {
|
||||
SHADER_RESOURCE_UUID
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for Shader {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
@@ -224,7 +456,7 @@ pub struct PropertyDefinition {
|
||||
pub kind: PropertyKind,
|
||||
}
|
||||
|
||||
/// A render pass definition. See [`Shader`] docs for more info about render passes.
|
||||
/// A render pass definition. See [`ShaderResource`] docs for more info about render passes.
|
||||
#[derive(Default, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub struct RenderPassDefinition {
|
||||
/// A name of render pass.
|
||||
@@ -258,7 +490,7 @@ impl ShaderDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShaderState {
|
||||
impl Shader {
|
||||
pub(crate) async fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, ShaderError> {
|
||||
let content = io::load_file(path.as_ref()).await?;
|
||||
Ok(Self {
|
||||
@@ -277,7 +509,7 @@ impl ShaderState {
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceData for ShaderState {
|
||||
impl ResourceData for Shader {
|
||||
fn path(&self) -> Cow<Path> {
|
||||
Cow::from(&self.path)
|
||||
}
|
||||
@@ -285,6 +517,18 @@ impl ResourceData for ShaderState {
|
||||
fn set_path(&mut self, path: PathBuf) {
|
||||
self.path = path;
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn type_uuid(&self) -> Uuid {
|
||||
<Self as TypeUuidProvider>::type_uuid()
|
||||
}
|
||||
}
|
||||
|
||||
/// A set of possible error variants that can occur during shader loading.
|
||||
@@ -322,262 +566,50 @@ impl From<FileLoadError> for ShaderError {
|
||||
}
|
||||
}
|
||||
|
||||
define_new_resource!(
|
||||
/// Shader is a script for graphics adapter, it defines how to draw an object.
|
||||
///
|
||||
/// # Structure
|
||||
///
|
||||
/// Shader has rigid structure that could be described in this code snipped:
|
||||
///
|
||||
/// ```ron
|
||||
/// (
|
||||
/// // A set of properties, there could be any amount of properties.
|
||||
/// properties: [
|
||||
/// (
|
||||
/// // Each property must have a name. This name must match with respective
|
||||
/// // uniforms! That's is the whole point of having properties.
|
||||
/// name: "diffuseTexture",
|
||||
///
|
||||
/// // Value has limited set of possible variants.
|
||||
/// value: Sampler(default: None, fallback: White)
|
||||
/// )
|
||||
/// ],
|
||||
///
|
||||
/// // A set of render passes (see a section `Render pass` for more info)
|
||||
/// passes: [
|
||||
/// (
|
||||
/// // Name must match with the name of either standard render pass (see below) or
|
||||
/// // one of your passes.
|
||||
/// name: "Forward",
|
||||
///
|
||||
/// // A set of parameters that regulate renderer pipeline state.
|
||||
/// // This is mandatory field of each render pass.
|
||||
/// draw_parameters: DrawParameters(
|
||||
/// // A face to cull. Either Front or Back.
|
||||
/// cull_face: Some(Back),
|
||||
///
|
||||
/// // Color mask. Defines which colors should be written to render target.
|
||||
/// color_write: ColorMask(
|
||||
/// red: true,
|
||||
/// green: true,
|
||||
/// blue: true,
|
||||
/// alpha: true,
|
||||
/// ),
|
||||
///
|
||||
/// // Whether to modify depth buffer or not.
|
||||
/// depth_write: true,
|
||||
///
|
||||
/// // Whether to use stencil test or not.
|
||||
/// stencil_test: None,
|
||||
///
|
||||
/// // Whether to perform depth test when drawing.
|
||||
/// depth_test: true,
|
||||
///
|
||||
/// // Blending options.
|
||||
/// blend: Some(BlendParameters(
|
||||
/// func: BlendFunc(
|
||||
/// sfactor: SrcAlpha,
|
||||
/// dfactor: OneMinusSrcAlpha,
|
||||
/// alpha_sfactor: SrcAlpha,
|
||||
/// alpha_dfactor: OneMinusSrcAlpha,
|
||||
/// ),
|
||||
/// equation: BlendEquation(
|
||||
/// rgb: Add,
|
||||
/// alpha: Add
|
||||
/// )
|
||||
/// )),
|
||||
///
|
||||
/// // Stencil options.
|
||||
/// stencil_op: StencilOp(
|
||||
/// fail: Keep,
|
||||
/// zfail: Keep,
|
||||
/// zpass: Keep,
|
||||
/// write_mask: 0xFFFF_FFFF,
|
||||
/// ),
|
||||
/// ),
|
||||
///
|
||||
/// // Vertex shader code.
|
||||
/// vertex_shader:
|
||||
/// r#"
|
||||
/// #version 330 core
|
||||
///
|
||||
/// layout(location = 0) in vec3 vertexPosition;
|
||||
/// layout(location = 1) in vec2 vertexTexCoord;
|
||||
///
|
||||
/// uniform mat4 fyrox_worldViewProjection;
|
||||
///
|
||||
/// out vec2 texCoord;
|
||||
///
|
||||
/// void main()
|
||||
/// {
|
||||
/// texCoord = vertexTexCoord;
|
||||
/// gl_Position = fyrox_worldViewProjection * vertexPosition;
|
||||
/// }
|
||||
/// "#;
|
||||
///
|
||||
/// // Pixel shader code.
|
||||
/// pixel_shader:
|
||||
/// r#"
|
||||
/// #version 330 core
|
||||
///
|
||||
/// // Note that the name of this uniform match the name of the property up above.
|
||||
/// uniform sampler2D diffuseTexture;
|
||||
///
|
||||
/// out vec4 FragColor;
|
||||
///
|
||||
/// in vec2 texCoord;
|
||||
///
|
||||
/// void main()
|
||||
/// {
|
||||
/// FragColor = diffuseColor * texture(diffuseTexture, texCoord);
|
||||
/// }
|
||||
/// "#;
|
||||
/// )
|
||||
/// ],
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// Shader should contain at least one render pass to actually do some job. A shader could not
|
||||
/// have properties at all. Currently only vertex and fragment programs are supported. Each
|
||||
/// program mush be written in GLSL. Comprehensive GLSL documentation can be found
|
||||
/// [here](https://www.khronos.org/opengl/wiki/Core_Language_(GLSL))
|
||||
///
|
||||
/// # Render pass
|
||||
///
|
||||
/// Modern rendering is a very complex thing that requires drawing an object multiple times
|
||||
/// with different "scripts". For example to draw an object with shadows you need to draw an
|
||||
/// object twice: one directly in a render target, and one in a shadow map. Such stages called
|
||||
/// render passes.
|
||||
///
|
||||
/// Binding of shaders to render passes is done via names, each render pass has unique name.
|
||||
///
|
||||
/// ## Predefined passes
|
||||
///
|
||||
/// There are number of predefined render passes:
|
||||
///
|
||||
/// - GBuffer - A pass that fills a set of render target sized textures with various data
|
||||
/// about each rendered object. These textures then are used for physically-based lighting.
|
||||
/// Use this pass when you want the standard lighting to work with your objects.
|
||||
///
|
||||
/// - Forward - A pass that draws an object directly in render target. This pass is very
|
||||
/// limiting, it does not support lighting, shadows, etc. It should be only used to render
|
||||
/// translucent objects.
|
||||
///
|
||||
/// - SpotShadow - A pass that emits depth values for an object, later this depth map will be
|
||||
/// used to render shadows.
|
||||
///
|
||||
/// - PointShadow - A pass that emits distance from a fragment to a point light, later this depth
|
||||
/// map will be used to render shadows.
|
||||
///
|
||||
/// # Built-in variables
|
||||
///
|
||||
/// There are number of build-in variables that Fyrox pass to each shader automatically:
|
||||
///
|
||||
/// | Name | Type | Description
|
||||
/// |---------------------------|-----------------|--------------------------------------------
|
||||
/// | fyrox_worldMatrix | `Matrix4` | Local-to-world transformation.
|
||||
/// | fyrox_worldViewProjection | `Matrix4` | Local-to-clip-space transform.
|
||||
/// | fyrox_boneMatrices | `[Matrix4; 60]` | Array of bone matrices.
|
||||
/// | fyrox_useSkeletalAnimation | `Vector3` | Whether skinned meshes is rendering or not.
|
||||
/// | fyrox_cameraPosition | `Vector3` | Position of the camera.
|
||||
/// | fyrox_usePOM | `bool` | Whether to use parallax mapping or not.
|
||||
/// | fyrox_lightPosition | `Vector3` | Light position.
|
||||
///
|
||||
/// To use any of the variables, just define a uniform with appropriate name:
|
||||
///
|
||||
/// ```glsl
|
||||
/// uniform mat4 fyrox_worldMatrix;
|
||||
/// uniform vec3 fyrox_cameraPosition;
|
||||
/// ```
|
||||
///
|
||||
/// This list will be extended in future releases.
|
||||
///
|
||||
/// # Drawing parameters
|
||||
///
|
||||
/// Drawing parameters defines which GPU functions to use and at which state. For example, to render
|
||||
/// transparent objects you need to enable blending with specific blending rules. Or you need to disable
|
||||
/// culling to draw objects from both sides. This is when draw parameters comes in handy.
|
||||
///
|
||||
/// There are relatively large list of drawing parameters and it could confuse a person who didn't get
|
||||
/// used to work with graphics. The following list should help you to use drawing parameters correctly.
|
||||
///
|
||||
/// - cull_face
|
||||
/// - Defines which side of polygon should be culled.
|
||||
/// - **Possible values:** `None`, [Some(CullFace::XXX)](crate::renderer::framework::state::CullFace)
|
||||
///
|
||||
/// - color_write:
|
||||
/// - Defines which components of color should be written to a render target
|
||||
/// - **Possible values:** [ColorMask](crate::renderer::framework::state::ColorMask)(...)
|
||||
///
|
||||
/// - depth_write:
|
||||
/// - Whether to modify depth buffer or not.
|
||||
/// - **Possible values:** `true/false`
|
||||
///
|
||||
/// - stencil_test:
|
||||
/// - Whether to use stencil test or not.
|
||||
/// - **Possible values:**
|
||||
/// - `None`
|
||||
/// - Some([StencilFunc](crate::renderer::framework::state::StencilFunc))
|
||||
///
|
||||
/// - depth_test:
|
||||
/// - Whether to perform depth test when drawing.
|
||||
/// - **Possible values:** `true/false`
|
||||
///
|
||||
/// - blend:
|
||||
/// - Blending options.
|
||||
/// - **Possible values:**
|
||||
/// - `None`
|
||||
/// - Some([BlendFunc](crate::renderer::framework::state::BlendFunc))
|
||||
///
|
||||
/// - stencil_op:
|
||||
/// - Stencil options.
|
||||
/// - **Possible values:** [StencilOp](crate::renderer::framework::state::StencilOp)
|
||||
///
|
||||
/// # Standard shader
|
||||
///
|
||||
/// By default Fyrox uses standard material for rendering, it covers 95% of uses cases and it is very
|
||||
/// flexible. To get standard shader instance, use [`Shader::standard`]
|
||||
///
|
||||
/// ```no_run
|
||||
/// # use fyrox::material::shader::Shader;
|
||||
///
|
||||
/// let standard_shader = Shader::standard();
|
||||
/// ```
|
||||
///
|
||||
/// Usually you don't need to get this shader manually, using of [Material::standard](super::Material::standard)
|
||||
/// is enough.
|
||||
#[derive(Reflect)]
|
||||
#[reflect(hide_all)]
|
||||
Shader<ShaderState>
|
||||
);
|
||||
pub type ShaderResource = Resource<Shader>;
|
||||
|
||||
impl Shader {
|
||||
pub trait ShaderResourceExtension: Sized {
|
||||
/// Creates new shader from given string. Input string must have the format defined in
|
||||
/// examples for [`Shader`].
|
||||
pub fn from_str<P: AsRef<Path>>(str: &str, path: P) -> Result<Self, ShaderError> {
|
||||
Ok(Self(Resource::new_ok(ShaderState::from_str(
|
||||
str,
|
||||
path.as_ref(),
|
||||
)?)))
|
||||
/// examples for [`ShaderResource`].
|
||||
fn from_str<P: AsRef<Path>>(str: &str, path: P) -> Result<Self, ShaderError>;
|
||||
|
||||
/// Returns an instance of standard shader.
|
||||
fn standard() -> Self;
|
||||
|
||||
/// Returns an instance of standard terrain shader.
|
||||
fn standard_terrain() -> Self;
|
||||
|
||||
/// Returns an instance of standard two-sides terrain shader.
|
||||
fn standard_twosides() -> Self;
|
||||
|
||||
/// Returns a list of standard shader.
|
||||
fn standard_shaders() -> Vec<ShaderResource>;
|
||||
}
|
||||
|
||||
impl ShaderResourceExtension for ShaderResource {
|
||||
/// Creates new shader from given string. Input string must have the format defined in
|
||||
/// examples for [`ShaderResource`].
|
||||
fn from_str<P: AsRef<Path>>(str: &str, path: P) -> Result<Self, ShaderError> {
|
||||
Ok(Resource::new_ok(Shader::from_str(str, path.as_ref())?))
|
||||
}
|
||||
|
||||
/// Returns an instance of standard shader.
|
||||
pub fn standard() -> Self {
|
||||
fn standard() -> Self {
|
||||
STANDARD.clone()
|
||||
}
|
||||
|
||||
/// Returns an instance of standard terrain shader.
|
||||
pub fn standard_terrain() -> Self {
|
||||
fn standard_terrain() -> Self {
|
||||
STANDARD_TERRAIN.clone()
|
||||
}
|
||||
|
||||
/// Returns an instance of standard two-sides terrain shader.
|
||||
pub fn standard_twosides() -> Self {
|
||||
fn standard_twosides() -> Self {
|
||||
STANDARD_TWOSIDES.clone()
|
||||
}
|
||||
|
||||
/// Returns a list of standard shader.
|
||||
pub fn standard_shaders() -> Vec<Shader> {
|
||||
fn standard_shaders() -> Vec<ShaderResource> {
|
||||
vec![
|
||||
Self::standard(),
|
||||
Self::standard_terrain(),
|
||||
@@ -593,28 +625,28 @@ pub struct ShaderImportOptions {}
|
||||
impl ImportOptions for ShaderImportOptions {}
|
||||
|
||||
lazy_static! {
|
||||
static ref STANDARD: Shader = Shader(Resource::new_ok(
|
||||
ShaderState::from_str(STANDARD_SHADER_SRC, STANDARD_SHADER_NAME).unwrap(),
|
||||
));
|
||||
static ref STANDARD: ShaderResource = ShaderResource::new_ok(
|
||||
Shader::from_str(STANDARD_SHADER_SRC, STANDARD_SHADER_NAME).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref STANDARD_TERRAIN: Shader = Shader(Resource::new_ok(
|
||||
ShaderState::from_str(STANDARD_TERRAIN_SHADER_SRC, STANDARD_TERRAIN_SHADER_NAME).unwrap(),
|
||||
));
|
||||
static ref STANDARD_TERRAIN: ShaderResource = ShaderResource::new_ok(
|
||||
Shader::from_str(STANDARD_TERRAIN_SHADER_SRC, STANDARD_TERRAIN_SHADER_NAME).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref STANDARD_TWOSIDES: Shader = Shader(Resource::new_ok(
|
||||
ShaderState::from_str(STANDARD_TWOSIDES_SHADER_SRC, STANDARD_TWOSIDES_SHADER_NAME).unwrap(),
|
||||
));
|
||||
static ref STANDARD_TWOSIDES: ShaderResource = ShaderResource::new_ok(
|
||||
Shader::from_str(STANDARD_TWOSIDES_SHADER_SRC, STANDARD_TWOSIDES_SHADER_NAME).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::material::shader::{
|
||||
PropertyDefinition, PropertyKind, RenderPassDefinition, SamplerFallback, Shader,
|
||||
ShaderDefinition,
|
||||
PropertyDefinition, PropertyKind, RenderPassDefinition, SamplerFallback, ShaderDefinition,
|
||||
ShaderResource,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -659,7 +691,7 @@ mod test {
|
||||
)
|
||||
"##;
|
||||
|
||||
let shader = Shader::from_str(code, "test").unwrap();
|
||||
let shader = ShaderResource::from_str(code, "test").unwrap();
|
||||
let data = shader.data_ref();
|
||||
|
||||
let reference_definition = ShaderDefinition {
|
||||
|
||||
+2
-4
@@ -3,11 +3,9 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use crate::{
|
||||
asset::manager::ResourceManager,
|
||||
core::pool::Handle,
|
||||
engine::{
|
||||
resource_manager::ResourceManager, GraphicsContext, PerformanceStatistics,
|
||||
SerializationContext,
|
||||
},
|
||||
engine::{GraphicsContext, PerformanceStatistics, SerializationContext},
|
||||
event::Event,
|
||||
event_loop::ControlFlow,
|
||||
gui::{message::UiMessage, UserInterface},
|
||||
|
||||
Vendored
+2
-3
@@ -1,12 +1,11 @@
|
||||
use crate::scene::mesh::surface::SurfaceData;
|
||||
use crate::{
|
||||
asset::container::entry::DEFAULT_RESOURCE_LIFETIME,
|
||||
core::{scope_profile, sparse::SparseBuffer},
|
||||
engine::resource_manager::container::entry::DEFAULT_RESOURCE_LIFETIME,
|
||||
renderer::framework::{
|
||||
geometry_buffer::{GeometryBuffer, GeometryBufferKind},
|
||||
state::PipelineState,
|
||||
},
|
||||
scene::mesh::surface::SurfaceSharedData,
|
||||
scene::mesh::surface::{SurfaceData, SurfaceSharedData},
|
||||
};
|
||||
use fyrox_core::sparse::AtomicIndex;
|
||||
|
||||
|
||||
Vendored
+7
-7
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
asset::container::entry::DEFAULT_RESOURCE_LIFETIME,
|
||||
core::{scope_profile, sparse::SparseBuffer, sstorage::ImmutableString},
|
||||
engine::resource_manager::container::entry::DEFAULT_RESOURCE_LIFETIME,
|
||||
material::shader::{Shader, ShaderState},
|
||||
material::shader::{Shader, ShaderResource},
|
||||
renderer::{
|
||||
cache::CacheEntry,
|
||||
framework::{framebuffer::DrawParameters, gpu_program::GpuProgram, state::PipelineState},
|
||||
@@ -21,7 +21,7 @@ pub struct ShaderSet {
|
||||
}
|
||||
|
||||
impl ShaderSet {
|
||||
pub fn new(state: &mut PipelineState, shader: &ShaderState) -> Option<Self> {
|
||||
pub fn new(state: &mut PipelineState, shader: &Shader) -> Option<Self> {
|
||||
let mut map = FxHashMap::default();
|
||||
for render_pass in shader.definition.passes.iter() {
|
||||
let program_name = format!("{}_{}", shader.definition.name, render_pass.name);
|
||||
@@ -63,8 +63,8 @@ pub struct ShaderCache {
|
||||
}
|
||||
|
||||
impl ShaderCache {
|
||||
pub fn remove(&mut self, shader: &Shader) {
|
||||
let state = shader.state();
|
||||
pub fn remove(&mut self, shader: &ShaderResource) {
|
||||
let mut state = shader.state();
|
||||
if let ResourceStateRef::Ok(shader_state) = state.get() {
|
||||
self.buffer.free(&shader_state.cache_index);
|
||||
}
|
||||
@@ -73,12 +73,12 @@ impl ShaderCache {
|
||||
pub fn get(
|
||||
&mut self,
|
||||
pipeline_state: &mut PipelineState,
|
||||
shader: &Shader,
|
||||
shader: &ShaderResource,
|
||||
) -> Option<&ShaderSet> {
|
||||
scope_profile!();
|
||||
|
||||
let key = shader.key();
|
||||
let shader_state = shader.state();
|
||||
let mut shader_state = shader.state();
|
||||
|
||||
if let ResourceStateRef::Ok(shader_state) = shader_state.get() {
|
||||
if self.buffer.is_index_valid(&shader_state.cache_index) {
|
||||
|
||||
Vendored
+8
-8
@@ -1,7 +1,7 @@
|
||||
use crate::renderer::framework::error::FrameworkError;
|
||||
use crate::{
|
||||
asset::container::entry::DEFAULT_RESOURCE_LIFETIME,
|
||||
core::scope_profile,
|
||||
engine::resource_manager::container::entry::DEFAULT_RESOURCE_LIFETIME,
|
||||
renderer::{
|
||||
cache::CacheEntry,
|
||||
framework::{
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
state::PipelineState,
|
||||
},
|
||||
},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
utils::log::{Log, MessageKind},
|
||||
};
|
||||
use fxhash::FxHashMap;
|
||||
@@ -27,10 +27,10 @@ impl TextureCache {
|
||||
pub fn upload(
|
||||
&mut self,
|
||||
state: &mut PipelineState,
|
||||
texture: &Texture,
|
||||
texture: &TextureResource,
|
||||
) -> Result<(), FrameworkError> {
|
||||
let key = texture.key();
|
||||
let texture = texture.state();
|
||||
let mut texture = texture.state();
|
||||
|
||||
if let ResourceStateRef::Ok(texture) = texture.get() {
|
||||
let gpu_texture = GpuTexture::new(
|
||||
@@ -67,13 +67,13 @@ impl TextureCache {
|
||||
pub fn get(
|
||||
&mut self,
|
||||
state: &mut PipelineState,
|
||||
texture_resource: &Texture,
|
||||
texture_resource: &TextureResource,
|
||||
) -> Option<Rc<RefCell<GpuTexture>>> {
|
||||
scope_profile!();
|
||||
|
||||
let key = texture_resource.key();
|
||||
|
||||
let texture_data_guard = texture_resource.state();
|
||||
let mut texture_data_guard = texture_resource.state();
|
||||
|
||||
if let ResourceStateRef::Ok(texture) = texture_data_guard.get() {
|
||||
let entry = match self.map.entry(key) {
|
||||
@@ -160,7 +160,7 @@ impl TextureCache {
|
||||
|
||||
Log::writeln(
|
||||
MessageKind::Error,
|
||||
format!("Failed to create GPU texture from {:?} engine texture. Reason: {:?}", texture_resource.state().path(), e),
|
||||
format!("Failed to create GPU texture from {:?} engine texture. Reason: {:?}", texture_resource.path(), e),
|
||||
);
|
||||
return None;
|
||||
}
|
||||
@@ -194,7 +194,7 @@ impl TextureCache {
|
||||
self.map.clear();
|
||||
}
|
||||
|
||||
pub fn unload(&mut self, texture: Texture) {
|
||||
pub fn unload(&mut self, texture: TextureResource) {
|
||||
self.map.remove(&texture.key());
|
||||
}
|
||||
}
|
||||
|
||||
+37
-35
@@ -34,10 +34,10 @@ mod skybox_shader;
|
||||
mod sprite_renderer;
|
||||
mod ssao;
|
||||
|
||||
use crate::renderer::batch::ObserverInfo;
|
||||
use crate::renderer::framework::geometry_buffer::ElementRange;
|
||||
use crate::renderer::framework::state::{PolygonFace, PolygonFillMode};
|
||||
use crate::material::shader::Shader;
|
||||
use crate::resource::texture::Texture;
|
||||
use crate::{
|
||||
asset::{container::event::ResourceEvent, manager::ResourceManager},
|
||||
core::{
|
||||
algebra::{Matrix4, Vector2, Vector3},
|
||||
color::Color,
|
||||
@@ -47,14 +47,10 @@ use crate::{
|
||||
reflect::prelude::*,
|
||||
scope_profile,
|
||||
},
|
||||
engine::resource_manager::{container::event::ResourceEvent, ResourceManager},
|
||||
gui::{draw::DrawingContext, UserInterface},
|
||||
material::{
|
||||
shader::{SamplerFallback, Shader},
|
||||
Material, PropertyValue,
|
||||
},
|
||||
material::{shader::SamplerFallback, Material, PropertyValue},
|
||||
renderer::{
|
||||
batch::RenderDataBatchStorage,
|
||||
batch::{ObserverInfo, RenderDataBatchStorage},
|
||||
bloom::BloomRenderer,
|
||||
cache::{geometry::GeometryCache, shader::ShaderCache, texture::TextureCache, CacheEntry},
|
||||
debug_renderer::DebugRenderer,
|
||||
@@ -63,13 +59,15 @@ use crate::{
|
||||
framework::{
|
||||
error::FrameworkError,
|
||||
framebuffer::{Attachment, AttachmentKind, DrawParameters, FrameBuffer},
|
||||
geometry_buffer::{DrawCallStatistics, GeometryBuffer, GeometryBufferKind},
|
||||
geometry_buffer::{
|
||||
DrawCallStatistics, ElementRange, GeometryBuffer, GeometryBufferKind,
|
||||
},
|
||||
gpu_program::{BuiltInUniform, GpuProgramBinding},
|
||||
gpu_texture::{
|
||||
Coordinate, GpuTexture, GpuTextureKind, MagnificationFilter, MinificationFilter,
|
||||
PixelKind, WrapMode,
|
||||
},
|
||||
state::{PipelineState, PipelineStatistics},
|
||||
state::{PipelineState, PipelineStatistics, PolygonFace, PolygonFillMode},
|
||||
},
|
||||
fxaa::FxaaRenderer,
|
||||
gbuffer::{GBuffer, GBufferRenderContext},
|
||||
@@ -81,7 +79,7 @@ use crate::{
|
||||
storage::MatrixStorage,
|
||||
ui_renderer::{UiRenderContext, UiRenderer},
|
||||
},
|
||||
resource::texture::{Texture, TextureKind},
|
||||
resource::texture::{TextureKind, TextureResource},
|
||||
scene::{camera::Camera, mesh::surface::SurfaceData, Scene, SceneContainer},
|
||||
utils::log::{Log, MessageKind},
|
||||
};
|
||||
@@ -728,8 +726,8 @@ pub struct Renderer {
|
||||
forward_renderer: ForwardRenderer,
|
||||
fxaa_renderer: FxaaRenderer,
|
||||
renderer2d: Renderer2d,
|
||||
texture_event_receiver: Receiver<ResourceEvent<Texture>>,
|
||||
shader_event_receiver: Receiver<ResourceEvent<Shader>>,
|
||||
texture_event_receiver: Receiver<ResourceEvent>,
|
||||
shader_event_receiver: Receiver<ResourceEvent>,
|
||||
matrix_storage: MatrixStorage,
|
||||
// TextureId -> FrameBuffer mapping. This mapping is used for temporal frame buffers
|
||||
// like ones used to render UI instances.
|
||||
@@ -944,7 +942,7 @@ pub(crate) struct MaterialContext<'a, 'b, 'c> {
|
||||
pub camera_position: &'a Vector3<f32>,
|
||||
pub use_pom: bool,
|
||||
pub light_position: &'a Vector3<f32>,
|
||||
pub blend_shapes_storage: Option<&'a Texture>,
|
||||
pub blend_shapes_storage: Option<&'a TextureResource>,
|
||||
pub blend_shapes_weights: &'a [f32],
|
||||
|
||||
// Fallback samplers.
|
||||
@@ -1107,7 +1105,7 @@ impl Renderer {
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.textures
|
||||
.resources
|
||||
.event_broadcaster
|
||||
.add(texture_event_sender);
|
||||
|
||||
@@ -1116,7 +1114,7 @@ impl Renderer {
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.shaders
|
||||
.resources
|
||||
.event_broadcaster
|
||||
.add(shader_event_sender);
|
||||
|
||||
@@ -1275,7 +1273,7 @@ impl Renderer {
|
||||
}
|
||||
|
||||
/// Unloads texture from GPU memory.
|
||||
pub fn unload_texture(&mut self, texture: Texture) {
|
||||
pub fn unload_texture(&mut self, texture: TextureResource) {
|
||||
self.texture_cache.unload(texture)
|
||||
}
|
||||
|
||||
@@ -1347,7 +1345,7 @@ impl Renderer {
|
||||
/// to have off-screen UIs (like interactive touch-screen in Doom 3, Dead Space, etc).
|
||||
pub fn render_ui_to_texture(
|
||||
&mut self,
|
||||
render_target: Texture,
|
||||
render_target: TextureResource,
|
||||
ui: &mut UserInterface,
|
||||
) -> Result<(), FrameworkError> {
|
||||
let new_width = ui.screen_size().x as usize;
|
||||
@@ -1421,19 +1419,21 @@ impl Renderer {
|
||||
|
||||
let mut uploaded = 0;
|
||||
while let Ok(event) = self.texture_event_receiver.try_recv() {
|
||||
if let ResourceEvent::Loaded(texture) | ResourceEvent::Reloaded(texture) = event {
|
||||
match self.texture_cache.upload(&mut self.state, &texture) {
|
||||
Ok(_) => {
|
||||
uploaded += 1;
|
||||
if uploaded >= THROUGHPUT {
|
||||
break;
|
||||
if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
|
||||
if let Some(texture) = resource.try_cast::<Texture>() {
|
||||
match self.texture_cache.upload(&mut self.state, &texture) {
|
||||
Ok(_) => {
|
||||
uploaded += 1;
|
||||
if uploaded >= THROUGHPUT {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
Log::writeln(
|
||||
MessageKind::Error,
|
||||
format!("Failed to upload texture to GPU. Reason: {:?}", e),
|
||||
);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
Log::writeln(
|
||||
MessageKind::Error,
|
||||
format!("Failed to upload texture to GPU. Reason: {:?}", e),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1444,10 +1444,12 @@ impl Renderer {
|
||||
|
||||
fn update_shader_cache(&mut self, dt: f32) {
|
||||
while let Ok(event) = self.shader_event_receiver.try_recv() {
|
||||
if let ResourceEvent::Loaded(shader) | ResourceEvent::Reloaded(shader) = event {
|
||||
// Remove and immediately "touch" the shader cache to force upload shader.
|
||||
self.shader_cache.remove(&shader);
|
||||
let _ = self.shader_cache.get(&mut self.state, &shader);
|
||||
if let ResourceEvent::Loaded(resource) | ResourceEvent::Reloaded(resource) = event {
|
||||
if let Some(shader) = resource.try_cast::<Shader>() {
|
||||
// Remove and immediately "touch" the shader cache to force upload shader.
|
||||
self.shader_cache.remove(&shader);
|
||||
let _ = self.shader_cache.get(&mut self.state, &shader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use crate::{
|
||||
asset::container::entry::TimedEntry,
|
||||
core::{
|
||||
algebra::{Matrix4, Vector2},
|
||||
color::Color,
|
||||
math::TriangleDefinition,
|
||||
scope_profile,
|
||||
},
|
||||
engine::resource_manager::container::entry::TimedEntry,
|
||||
renderer::framework::{
|
||||
geometry_buffer::{
|
||||
AttributeDefinition, AttributeKind, BufferBuilder, ElementKind, GeometryBuffer,
|
||||
|
||||
+21
-20
@@ -1,9 +1,7 @@
|
||||
//! See [`UiRenderer`] docs.
|
||||
|
||||
use crate::renderer::framework::framebuffer::BlendParameters;
|
||||
use crate::renderer::framework::geometry_buffer::ElementRange;
|
||||
use crate::{
|
||||
asset::Resource,
|
||||
asset::{state::ResourceState, untyped::UntypedResource},
|
||||
core::{
|
||||
algebra::{Matrix4, Vector2, Vector4},
|
||||
color::Color,
|
||||
@@ -19,10 +17,10 @@ use crate::{
|
||||
renderer::{
|
||||
framework::{
|
||||
error::FrameworkError,
|
||||
framebuffer::{DrawParameters, FrameBuffer},
|
||||
framebuffer::{BlendParameters, DrawParameters, FrameBuffer},
|
||||
geometry_buffer::{
|
||||
AttributeDefinition, AttributeKind, BufferBuilder, ElementKind, GeometryBuffer,
|
||||
GeometryBufferBuilder, GeometryBufferKind,
|
||||
AttributeDefinition, AttributeKind, BufferBuilder, ElementKind, ElementRange,
|
||||
GeometryBuffer, GeometryBufferBuilder, GeometryBufferKind,
|
||||
},
|
||||
gpu_program::{GpuProgram, UniformLocation},
|
||||
gpu_texture::GpuTexture,
|
||||
@@ -33,7 +31,7 @@ use crate::{
|
||||
},
|
||||
RenderPassStatistics, TextureCache,
|
||||
},
|
||||
resource::texture::{Texture, TextureData, TextureKind, TexturePixelKind},
|
||||
resource::texture::{Texture, TextureKind, TexturePixelKind},
|
||||
};
|
||||
use std::{cell::RefCell, rc::Rc, sync::Arc};
|
||||
|
||||
@@ -267,7 +265,7 @@ impl UiRenderer {
|
||||
let mut font = font_arc.0.lock();
|
||||
if font.texture.is_none() {
|
||||
let size = font.atlas_size() as u32;
|
||||
if let Some(details) = TextureData::from_bytes(
|
||||
if let Some(details) = Texture::from_bytes(
|
||||
TextureKind::Rectangle {
|
||||
width: size,
|
||||
height: size,
|
||||
@@ -277,26 +275,29 @@ impl UiRenderer {
|
||||
false,
|
||||
) {
|
||||
font.texture = Some(SharedTexture(Arc::new(Mutex::new(
|
||||
TextureState::Ok(details),
|
||||
ResourceState::new_ok(details),
|
||||
))));
|
||||
}
|
||||
}
|
||||
let tex = font
|
||||
.texture
|
||||
.clone()
|
||||
.unwrap()
|
||||
.0
|
||||
.downcast::<Mutex<TextureState>>()
|
||||
.unwrap();
|
||||
if let Some(texture) = texture_cache.get(state, &Texture(Resource::from(tex))) {
|
||||
let tex = UntypedResource(
|
||||
font.texture
|
||||
.clone()
|
||||
.unwrap()
|
||||
.0
|
||||
.downcast::<Mutex<ResourceState>>()
|
||||
.unwrap(),
|
||||
);
|
||||
if let Some(texture) =
|
||||
texture_cache.get(state, &tex.try_cast::<Texture>().unwrap())
|
||||
{
|
||||
diffuse_texture = texture;
|
||||
}
|
||||
is_font_texture = true;
|
||||
}
|
||||
CommandTexture::Texture(texture) => {
|
||||
if let Ok(texture) = texture.clone().0.downcast::<Mutex<TextureState>>() {
|
||||
let resource = Resource::from(texture);
|
||||
if let Some(texture) = texture_cache.get(state, &Texture(resource)) {
|
||||
if let Ok(texture) = texture.clone().0.downcast::<Mutex<ResourceState>>() {
|
||||
let resource = UntypedResource(texture).try_cast::<Texture>().unwrap();
|
||||
if let Some(texture) = texture_cache.get(state, &resource) {
|
||||
diffuse_texture = texture;
|
||||
}
|
||||
}
|
||||
|
||||
+25
-9
@@ -1,12 +1,15 @@
|
||||
//! Curve resource holds a [`Curve`]
|
||||
|
||||
use crate::{
|
||||
asset::{define_new_resource, Resource, ResourceData},
|
||||
core::reflect::prelude::*,
|
||||
asset::options::ImportOptions,
|
||||
asset::{Resource, ResourceData},
|
||||
core::{curve::Curve, io::FileLoadError, visitor::prelude::*},
|
||||
engine::resource_manager::options::ImportOptions,
|
||||
};
|
||||
use fyrox_core::uuid::Uuid;
|
||||
use fyrox_core::TypeUuidProvider;
|
||||
use fyrox_resource::CURVE_RESOURCE_UUID;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
@@ -67,6 +70,24 @@ impl ResourceData for CurveResourceState {
|
||||
fn set_path(&mut self, path: PathBuf) {
|
||||
self.path = path;
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn type_uuid(&self) -> Uuid {
|
||||
<Self as TypeUuidProvider>::type_uuid()
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeUuidProvider for CurveResourceState {
|
||||
fn type_uuid() -> Uuid {
|
||||
CURVE_RESOURCE_UUID
|
||||
}
|
||||
}
|
||||
|
||||
impl CurveResourceState {
|
||||
@@ -82,12 +103,7 @@ impl CurveResourceState {
|
||||
}
|
||||
}
|
||||
|
||||
define_new_resource!(
|
||||
/// See module docs.
|
||||
#[derive(Reflect)]
|
||||
#[reflect(hide_all)]
|
||||
CurveResource<CurveResourceState>
|
||||
);
|
||||
pub type CurveResource = Resource<Curve>;
|
||||
|
||||
/// Import options for curve resource.
|
||||
#[derive(Serialize, Deserialize, Default, Clone)]
|
||||
|
||||
@@ -10,9 +10,11 @@ mod document;
|
||||
pub mod error;
|
||||
mod scene;
|
||||
|
||||
use crate::resource::texture::Texture;
|
||||
use crate::scene::mesh::surface::{BlendShape, InputBlendShapeData};
|
||||
use crate::{
|
||||
animation::{track::Track, Animation, AnimationContainer},
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
algebra::{Matrix4, Point3, UnitQuaternion, Vector2, Vector3, Vector4},
|
||||
curve::{CurveKey, CurveKeyKind},
|
||||
@@ -23,7 +25,6 @@ use crate::{
|
||||
sstorage::ImmutableString,
|
||||
uuid::Uuid,
|
||||
},
|
||||
engine::resource_manager::ResourceManager,
|
||||
material::{shader::SamplerFallback, PropertyValue},
|
||||
resource::{
|
||||
fbx::{
|
||||
@@ -351,7 +352,8 @@ async fn create_surfaces(
|
||||
};
|
||||
|
||||
if let Some(texture_path) = texture_path {
|
||||
let texture = resource_manager.request_texture(texture_path.as_path());
|
||||
let texture =
|
||||
resource_manager.request::<Texture, _>(texture_path.as_path());
|
||||
|
||||
// Make up your mind, Autodesk and Blender.
|
||||
// Handle all possible combinations of links to auto-import materials.
|
||||
|
||||
+67
-32
@@ -20,7 +20,7 @@
|
||||
|
||||
use crate::{
|
||||
animation::Animation,
|
||||
asset::{define_new_resource, Resource, ResourceData},
|
||||
asset::{manager::ResourceManager, options::ImportOptions, Resource, ResourceData},
|
||||
core::{
|
||||
algebra::{UnitQuaternion, Vector3},
|
||||
pool::Handle,
|
||||
@@ -28,10 +28,7 @@ use crate::{
|
||||
variable::reset_inheritable_properties,
|
||||
visitor::{Visit, VisitError, VisitResult, Visitor},
|
||||
},
|
||||
engine::{
|
||||
resource_manager::{options::ImportOptions, ResourceManager},
|
||||
SerializationContext,
|
||||
},
|
||||
engine::SerializationContext,
|
||||
resource::fbx::{self, error::FbxError},
|
||||
scene::{
|
||||
animation::AnimationPlayer,
|
||||
@@ -41,7 +38,11 @@ use crate::{
|
||||
},
|
||||
utils::log::{Log, MessageKind},
|
||||
};
|
||||
use fyrox_core::uuid::Uuid;
|
||||
use fyrox_core::TypeUuidProvider;
|
||||
use fyrox_resource::MODEL_RESOURCE_UUID;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{Display, Formatter},
|
||||
@@ -59,7 +60,7 @@ pub(crate) enum NodeMapping {
|
||||
|
||||
/// See module docs.
|
||||
#[derive(Debug, Visit)]
|
||||
pub struct ModelData {
|
||||
pub struct Model {
|
||||
pub(crate) path: PathBuf,
|
||||
#[visit(skip)]
|
||||
pub(crate) mapping: NodeMapping,
|
||||
@@ -67,17 +68,47 @@ pub struct ModelData {
|
||||
scene: Scene,
|
||||
}
|
||||
|
||||
define_new_resource!(
|
||||
/// See module docs.
|
||||
#[derive(Reflect)]
|
||||
#[reflect(hide_all)]
|
||||
Model<ModelData>
|
||||
);
|
||||
impl TypeUuidProvider for Model {
|
||||
fn type_uuid() -> Uuid {
|
||||
MODEL_RESOURCE_UUID
|
||||
}
|
||||
}
|
||||
|
||||
impl Model {
|
||||
pub(crate) fn instantiate_from(
|
||||
model: Self,
|
||||
model_data: &ModelData,
|
||||
pub type ModelResource = Resource<Model>;
|
||||
|
||||
pub trait ModelResourceExtension: Sized {
|
||||
fn instantiate_from(
|
||||
model: ModelResource,
|
||||
model_data: &Model,
|
||||
handle: Handle<Node>,
|
||||
dest_graph: &mut Graph,
|
||||
) -> (Handle<Node>, NodeHandleMap);
|
||||
|
||||
fn instantiate(&self, dest_scene: &mut Scene) -> Handle<Node>;
|
||||
|
||||
fn instantiate_at(
|
||||
&self,
|
||||
scene: &mut Scene,
|
||||
position: Vector3<f32>,
|
||||
orientation: UnitQuaternion<f32>,
|
||||
) -> Handle<Node>;
|
||||
|
||||
fn retarget_animations_directly(&self, root: Handle<Node>, graph: &Graph) -> Vec<Animation>;
|
||||
|
||||
fn retarget_animations_to_player(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
dest_animation_player: Handle<Node>,
|
||||
graph: &mut Graph,
|
||||
) -> Vec<Handle<Animation>>;
|
||||
|
||||
fn retarget_animations(&self, root: Handle<Node>, graph: &mut Graph) -> Vec<Handle<Animation>>;
|
||||
}
|
||||
|
||||
impl ModelResourceExtension for ModelResource {
|
||||
fn instantiate_from(
|
||||
model: ModelResource,
|
||||
model_data: &Model,
|
||||
handle: Handle<Node>,
|
||||
dest_graph: &mut Graph,
|
||||
) -> (Handle<Node>, NodeHandleMap) {
|
||||
@@ -115,7 +146,7 @@ impl Model {
|
||||
}
|
||||
|
||||
/// Tries to instantiate model from given resource.
|
||||
pub fn instantiate(&self, dest_scene: &mut Scene) -> Handle<Node> {
|
||||
fn instantiate(&self, dest_scene: &mut Scene) -> Handle<Node> {
|
||||
let data = self.data_ref();
|
||||
|
||||
let instance_root = Self::instantiate_from(
|
||||
@@ -133,7 +164,7 @@ impl Model {
|
||||
}
|
||||
|
||||
/// Instantiates a prefab and places it at specified position and orientation in global coordinates.
|
||||
pub fn instantiate_at(
|
||||
fn instantiate_at(
|
||||
&self,
|
||||
scene: &mut Scene,
|
||||
position: Vector3<f32>,
|
||||
@@ -172,11 +203,7 @@ impl Model {
|
||||
///
|
||||
/// Most of the 3d model formats can contain only one animation, so in most cases
|
||||
/// this function will return vector with only one animation.
|
||||
pub fn retarget_animations_directly(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
graph: &Graph,
|
||||
) -> Vec<Animation> {
|
||||
fn retarget_animations_directly(&self, root: Handle<Node>, graph: &Graph) -> Vec<Animation> {
|
||||
let mut retargetted_animations = Vec::new();
|
||||
|
||||
let data = self.data_ref();
|
||||
@@ -228,7 +255,7 @@ impl Model {
|
||||
///
|
||||
/// Panics if `dest_animation_player` is invalid handle, or the node does not have [`AnimationPlayer`]
|
||||
/// component.
|
||||
pub fn retarget_animations_to_player(
|
||||
fn retarget_animations_to_player(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
dest_animation_player: Handle<Node>,
|
||||
@@ -256,11 +283,7 @@ impl Model {
|
||||
/// # Panic
|
||||
///
|
||||
/// Panics if there's no animation player in the given hierarchy (descendant nodes of `root`).
|
||||
pub fn retarget_animations(
|
||||
&self,
|
||||
root: Handle<Node>,
|
||||
graph: &mut Graph,
|
||||
) -> Vec<Handle<Animation>> {
|
||||
fn retarget_animations(&self, root: Handle<Node>, graph: &mut Graph) -> Vec<Handle<Animation>> {
|
||||
if let Some((animation_player, _)) = graph.find(root, &mut |n| {
|
||||
n.query_component_ref::<AnimationPlayer>().is_some()
|
||||
}) {
|
||||
@@ -271,7 +294,7 @@ impl Model {
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceData for ModelData {
|
||||
impl ResourceData for Model {
|
||||
fn path(&self) -> Cow<Path> {
|
||||
Cow::Borrowed(&self.path)
|
||||
}
|
||||
@@ -279,9 +302,21 @@ impl ResourceData for ModelData {
|
||||
fn set_path(&mut self, path: PathBuf) {
|
||||
self.path = path;
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn type_uuid(&self) -> Uuid {
|
||||
<Self as TypeUuidProvider>::type_uuid()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ModelData {
|
||||
impl Default for Model {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
path: PathBuf::new(),
|
||||
@@ -426,7 +461,7 @@ impl From<VisitError> for ModelLoadError {
|
||||
}
|
||||
}
|
||||
|
||||
impl ModelData {
|
||||
impl Model {
|
||||
pub(crate) async fn load<P: AsRef<Path>>(
|
||||
path: P,
|
||||
serialization_context: Arc<SerializationContext>,
|
||||
|
||||
+67
-33
@@ -21,23 +21,25 @@
|
||||
//! access to pixels of render target.
|
||||
|
||||
use crate::{
|
||||
asset::{define_new_resource, Resource, ResourceData},
|
||||
asset::{options::ImportOptions, Resource, ResourceData},
|
||||
core::{
|
||||
futures::io::Error,
|
||||
io::{self, FileLoadError},
|
||||
reflect::prelude::*,
|
||||
visitor::{PodVecView, Visit, VisitError, VisitResult, Visitor},
|
||||
},
|
||||
engine::resource_manager::options::ImportOptions,
|
||||
};
|
||||
use ddsfile::{Caps2, D3DFormat};
|
||||
use fxhash::FxHasher;
|
||||
use fyrox_core::uuid::Uuid;
|
||||
use fyrox_core::TypeUuidProvider;
|
||||
use fyrox_resource::TEXTURE_RESOURCE_UUID;
|
||||
use image::{imageops::FilterType, ColorType, DynamicImage, ImageError, ImageFormat};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::Display;
|
||||
use std::any::Any;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{Debug, Formatter},
|
||||
fmt::{Debug, Display, Formatter},
|
||||
hash::{Hash, Hasher},
|
||||
io::Cursor,
|
||||
ops::{Deref, DerefMut},
|
||||
@@ -186,7 +188,7 @@ impl DerefMut for TextureBytes {
|
||||
|
||||
/// Actual texture data.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TextureData {
|
||||
pub struct Texture {
|
||||
path: PathBuf,
|
||||
kind: TextureKind,
|
||||
bytes: TextureBytes,
|
||||
@@ -202,7 +204,13 @@ pub struct TextureData {
|
||||
is_render_target: bool,
|
||||
}
|
||||
|
||||
impl ResourceData for TextureData {
|
||||
impl TypeUuidProvider for Texture {
|
||||
fn type_uuid() -> Uuid {
|
||||
TEXTURE_RESOURCE_UUID
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceData for Texture {
|
||||
fn path(&self) -> Cow<Path> {
|
||||
Cow::Borrowed(&self.path)
|
||||
}
|
||||
@@ -210,9 +218,21 @@ impl ResourceData for TextureData {
|
||||
fn set_path(&mut self, path: PathBuf) {
|
||||
self.path = path;
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn type_uuid(&self) -> Uuid {
|
||||
<Self as TypeUuidProvider>::type_uuid()
|
||||
}
|
||||
}
|
||||
|
||||
impl Visit for TextureData {
|
||||
impl Visit for Texture {
|
||||
fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
|
||||
let mut region = visitor.enter_region(name)?;
|
||||
|
||||
@@ -246,7 +266,7 @@ impl Visit for TextureData {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TextureData {
|
||||
impl Default for Texture {
|
||||
/// It is very important to mention that defaults may be different for texture when you
|
||||
/// importing them through resource manager, see
|
||||
/// [TextureImportOptions](../engine/resource_manager/struct.TextureImportOptions.html) for more info.
|
||||
@@ -404,19 +424,33 @@ impl TextureImportOptions {
|
||||
}
|
||||
}
|
||||
|
||||
define_new_resource!(
|
||||
/// See module docs.
|
||||
#[derive(Reflect)]
|
||||
#[reflect(hide_all)]
|
||||
Texture<TextureData>
|
||||
);
|
||||
pub type TextureResource = Resource<Texture>;
|
||||
|
||||
impl Texture {
|
||||
pub trait TextureResourceExtension: Sized {
|
||||
fn new_render_target(width: u32, height: u32) -> Self;
|
||||
|
||||
fn load_from_memory(
|
||||
data: &[u8],
|
||||
compression: CompressionOptions,
|
||||
gen_mip_maps: bool,
|
||||
) -> Result<Self, TextureError>;
|
||||
|
||||
fn from_bytes(
|
||||
kind: TextureKind,
|
||||
pixel_kind: TexturePixelKind,
|
||||
bytes: Vec<u8>,
|
||||
serialize_content: bool,
|
||||
) -> Option<Self>;
|
||||
|
||||
fn deep_clone(&self) -> Self;
|
||||
}
|
||||
|
||||
impl TextureResourceExtension for TextureResource {
|
||||
/// Creates new render target for a scene. This method automatically configures GPU texture
|
||||
/// to correct settings, after render target was created, it must not be modified, otherwise
|
||||
/// result is undefined.
|
||||
pub fn new_render_target(width: u32, height: u32) -> Self {
|
||||
Self(Resource::new_ok(TextureData {
|
||||
fn new_render_target(width: u32, height: u32) -> Self {
|
||||
Resource::new_ok(Texture {
|
||||
path: Default::default(),
|
||||
// Render target will automatically set width and height before rendering.
|
||||
kind: TextureKind::Rectangle { width, height },
|
||||
@@ -431,7 +465,7 @@ impl Texture {
|
||||
serialize_content: false,
|
||||
data_hash: 0,
|
||||
is_render_target: true,
|
||||
}))
|
||||
})
|
||||
}
|
||||
|
||||
/// Tries to load a texture from given data. Use this method if you want to
|
||||
@@ -451,38 +485,38 @@ impl Texture {
|
||||
/// loading. You should use `ResourceManager::request_texture` in majority of cases!
|
||||
///
|
||||
/// Main use cases for this method are: procedural textures, icons for GUI.
|
||||
pub fn load_from_memory(
|
||||
fn load_from_memory(
|
||||
data: &[u8],
|
||||
compression: CompressionOptions,
|
||||
gen_mip_maps: bool,
|
||||
) -> Result<Self, TextureError> {
|
||||
Ok(Self(Resource::new_ok(TextureData::load_from_memory(
|
||||
Ok(Resource::new_ok(Texture::load_from_memory(
|
||||
data,
|
||||
compression,
|
||||
gen_mip_maps,
|
||||
)?)))
|
||||
)?))
|
||||
}
|
||||
|
||||
/// Tries to create new texture from given parameters, it may fail only if size of data passed
|
||||
/// in does not match with required.
|
||||
pub fn from_bytes(
|
||||
fn from_bytes(
|
||||
kind: TextureKind,
|
||||
pixel_kind: TexturePixelKind,
|
||||
bytes: Vec<u8>,
|
||||
serialize_content: bool,
|
||||
) -> Option<Self> {
|
||||
Some(Self(Resource::new_ok(TextureData::from_bytes(
|
||||
Some(Resource::new_ok(Texture::from_bytes(
|
||||
kind,
|
||||
pixel_kind,
|
||||
bytes,
|
||||
serialize_content,
|
||||
)?)))
|
||||
)?))
|
||||
}
|
||||
|
||||
/// Creates a deep clone of the texture. Unlike [`Texture::clone`], this method clones the actual texture data,
|
||||
/// Creates a deep clone of the texture. Unlike [`TextureResource::clone`], this method clones the actual texture data,
|
||||
/// which could be slow.
|
||||
pub fn deep_clone(&self) -> Self {
|
||||
Self(Resource::new_ok(self.data_ref().clone()))
|
||||
fn deep_clone(&self) -> Self {
|
||||
Resource::new_ok(self.data_ref().clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1051,7 +1085,7 @@ fn bytes_in_first_mip(kind: TextureKind, pixel_kind: TexturePixelKind) -> u32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl TextureData {
|
||||
impl Texture {
|
||||
/// Tries to load a texture from given data in one of the following formats: PNG, BMP, TGA, JPG, DDS, GIF. Use
|
||||
/// this method if you want to load a texture from embedded data.
|
||||
///
|
||||
@@ -1468,7 +1502,7 @@ impl TextureData {
|
||||
/// A special reference holder that provides mutable access to content of the
|
||||
/// texture and automatically calculates hash of the data in its destructor.
|
||||
pub struct TextureDataRefMut<'a> {
|
||||
texture: &'a mut TextureData,
|
||||
texture: &'a mut Texture,
|
||||
}
|
||||
|
||||
impl<'a> Drop for TextureDataRefMut<'a> {
|
||||
@@ -1478,7 +1512,7 @@ impl<'a> Drop for TextureDataRefMut<'a> {
|
||||
}
|
||||
|
||||
impl<'a> Deref for TextureDataRefMut<'a> {
|
||||
type Target = TextureData;
|
||||
type Target = Texture;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.texture
|
||||
@@ -1515,10 +1549,10 @@ impl<'a> TextureDataRefMut<'a> {
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use crate::resource::texture::{Texture, TextureKind, TexturePixelKind};
|
||||
use crate::resource::texture::{TextureKind, TexturePixelKind, TextureResource};
|
||||
|
||||
pub fn create_test_texture() -> Texture {
|
||||
Texture::from_bytes(
|
||||
pub fn create_test_texture() -> TextureResource {
|
||||
TextureResource::from_bytes(
|
||||
TextureKind::Rectangle {
|
||||
width: 1,
|
||||
height: 1,
|
||||
|
||||
@@ -10,12 +10,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
animation::AnimationPlayer,
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, UpdateContext},
|
||||
Scene,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -10,11 +10,12 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, UpdateContext},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
+6
-7
@@ -13,7 +13,7 @@ use crate::{
|
||||
visitor::{Visit, VisitError, VisitResult, Visitor},
|
||||
},
|
||||
engine::SerializationContext,
|
||||
resource::model::Model,
|
||||
resource::model::ModelResource,
|
||||
scene::{node::Node, transform::Transform},
|
||||
script::{Script, ScriptTrait},
|
||||
utils::log::Log,
|
||||
@@ -382,7 +382,7 @@ pub struct Base {
|
||||
// A resource from which this node was instantiated from, can work in pair
|
||||
// with `original` handle to get corresponding node from resource.
|
||||
#[reflect(read_only)]
|
||||
pub(crate) resource: Option<Model>,
|
||||
pub(crate) resource: Option<ModelResource>,
|
||||
|
||||
// Handle to node in scene of model resource from which this node
|
||||
// was instantiated from.
|
||||
@@ -540,7 +540,7 @@ impl Base {
|
||||
|
||||
/// Returns resource from which this node was instantiated from.
|
||||
#[inline]
|
||||
pub fn resource(&self) -> Option<Model> {
|
||||
pub fn resource(&self) -> Option<ModelResource> {
|
||||
self.resource.clone()
|
||||
}
|
||||
|
||||
@@ -866,10 +866,9 @@ fn visit_opt_script(name: &str, script: &mut Option<Script>, visitor: &mut Visit
|
||||
None
|
||||
} else {
|
||||
let serialization_context = region
|
||||
.environment
|
||||
.as_ref()
|
||||
.and_then(|e| e.downcast_ref::<SerializationContext>())
|
||||
.expect("Visitor environment must contain serialization context!");
|
||||
.blackboard
|
||||
.get::<SerializationContext>()
|
||||
.expect("Visitor blackboard must contain serialization context!");
|
||||
|
||||
Some(
|
||||
serialization_context
|
||||
|
||||
+64
-54
@@ -14,6 +14,7 @@
|
||||
//! Each camera forces engine to re-render same scene one more time, which may cause
|
||||
//! almost double load of your GPU.
|
||||
|
||||
use crate::resource::texture::TextureResourceExtension;
|
||||
use crate::{
|
||||
core::{
|
||||
algebra::{Matrix4, Point3, Vector2, Vector3, Vector4},
|
||||
@@ -24,18 +25,19 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
TypeUuidProvider,
|
||||
},
|
||||
resource::texture::{Texture, TextureError, TextureKind, TexturePixelKind, TextureWrapMode},
|
||||
resource::texture::{TextureKind, TexturePixelKind, TextureResource, TextureWrapMode},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
debug::SceneDrawingContext,
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, UpdateContext},
|
||||
visibility::VisibilityCache,
|
||||
},
|
||||
utils::log::Log,
|
||||
};
|
||||
use fyrox_resource::ResourceStateRef;
|
||||
use fyrox_resource::{ResourceLoadError, ResourceStateRef};
|
||||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
ops::{Deref, DerefMut},
|
||||
@@ -306,7 +308,7 @@ pub struct Camera {
|
||||
sky_box: InheritableVariable<Option<SkyBox>>,
|
||||
|
||||
#[reflect(setter = "set_environment")]
|
||||
environment: InheritableVariable<Option<Texture>>,
|
||||
environment: InheritableVariable<Option<TextureResource>>,
|
||||
|
||||
#[reflect(setter = "set_exposure")]
|
||||
exposure: InheritableVariable<Exposure>,
|
||||
@@ -492,22 +494,25 @@ impl Camera {
|
||||
}
|
||||
|
||||
/// Sets new environment.
|
||||
pub fn set_environment(&mut self, environment: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_environment(
|
||||
&mut self,
|
||||
environment: Option<TextureResource>,
|
||||
) -> Option<TextureResource> {
|
||||
self.environment.set_value_and_mark_modified(environment)
|
||||
}
|
||||
|
||||
/// Return optional mutable reference to current environment.
|
||||
pub fn environment_mut(&mut self) -> Option<&mut Texture> {
|
||||
pub fn environment_mut(&mut self) -> Option<&mut TextureResource> {
|
||||
self.environment.get_value_mut_and_mark_modified().as_mut()
|
||||
}
|
||||
|
||||
/// Return optional shared reference to current environment.
|
||||
pub fn environment_ref(&self) -> Option<&Texture> {
|
||||
pub fn environment_ref(&self) -> Option<&TextureResource> {
|
||||
self.environment.as_ref()
|
||||
}
|
||||
|
||||
/// Return current environment map.
|
||||
pub fn environment_map(&self) -> Option<Texture> {
|
||||
pub fn environment_map(&self) -> Option<TextureResource> {
|
||||
(*self.environment).clone()
|
||||
}
|
||||
|
||||
@@ -649,7 +654,7 @@ pub enum ColorGradingLutCreationError {
|
||||
InvalidPixelFormat(TexturePixelKind),
|
||||
|
||||
/// Texture error.
|
||||
Texture(Option<Arc<TextureError>>),
|
||||
Texture(Option<Arc<dyn ResourceLoadError>>),
|
||||
}
|
||||
|
||||
impl Display for ColorGradingLutCreationError {
|
||||
@@ -684,11 +689,11 @@ impl Display for ColorGradingLutCreationError {
|
||||
/// See [more info in Unreal engine docs](https://docs.unrealengine.com/4.26/en-US/RenderingAndGraphics/PostProcessEffects/UsingLUTs/)
|
||||
#[derive(Visit, Clone, Default, PartialEq, Debug, Reflect, Eq)]
|
||||
pub struct ColorGradingLut {
|
||||
unwrapped_lut: Option<Texture>,
|
||||
unwrapped_lut: Option<TextureResource>,
|
||||
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
lut: Option<Texture>,
|
||||
lut: Option<TextureResource>,
|
||||
}
|
||||
|
||||
impl ColorGradingLut {
|
||||
@@ -719,7 +724,7 @@ impl ColorGradingLut {
|
||||
///
|
||||
/// Then pass LUT to either CameraBuilder or to camera instance, and don't forget to enable
|
||||
/// color grading.
|
||||
pub async fn new(unwrapped_lut: Texture) -> Result<Self, ColorGradingLutCreationError> {
|
||||
pub async fn new(unwrapped_lut: TextureResource) -> Result<Self, ColorGradingLutCreationError> {
|
||||
match unwrapped_lut.await {
|
||||
Ok(unwrapped_lut) => {
|
||||
let data = unwrapped_lut.data_ref();
|
||||
@@ -772,7 +777,7 @@ impl ColorGradingLut {
|
||||
}
|
||||
}
|
||||
|
||||
let lut = Texture::from_bytes(
|
||||
let lut = TextureResource::from_bytes(
|
||||
TextureKind::Volume {
|
||||
width: 16,
|
||||
height: 16,
|
||||
@@ -803,17 +808,17 @@ impl ColorGradingLut {
|
||||
|
||||
/// Returns color grading unwrapped look-up table. This is initial texture that was
|
||||
/// used to create the look-up table.
|
||||
pub fn unwrapped_lut(&self) -> Texture {
|
||||
pub fn unwrapped_lut(&self) -> TextureResource {
|
||||
self.unwrapped_lut.clone().unwrap()
|
||||
}
|
||||
|
||||
/// Returns 3D color grading look-up table ready for use on GPU.
|
||||
pub fn lut(&self) -> Texture {
|
||||
pub fn lut(&self) -> TextureResource {
|
||||
self.lut.clone().unwrap()
|
||||
}
|
||||
|
||||
/// Returns 3D color grading look-up table by ref ready for use on GPU.
|
||||
pub fn lut_ref(&self) -> &Texture {
|
||||
pub fn lut_ref(&self) -> &TextureResource {
|
||||
self.lut.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
@@ -828,7 +833,7 @@ pub struct CameraBuilder {
|
||||
viewport: Rect<f32>,
|
||||
enabled: bool,
|
||||
skybox: Option<SkyBox>,
|
||||
environment: Option<Texture>,
|
||||
environment: Option<TextureResource>,
|
||||
exposure: Exposure,
|
||||
color_grading_lut: Option<ColorGradingLut>,
|
||||
color_grading_enabled: bool,
|
||||
@@ -891,7 +896,7 @@ impl CameraBuilder {
|
||||
}
|
||||
|
||||
/// Sets desired environment map.
|
||||
pub fn with_environment(mut self, environment: Texture) -> Self {
|
||||
pub fn with_environment(mut self, environment: TextureResource) -> Self {
|
||||
self.environment = Some(environment);
|
||||
self
|
||||
}
|
||||
@@ -954,52 +959,52 @@ impl CameraBuilder {
|
||||
/// SkyBox builder is used to create new skybox in declarative manner.
|
||||
pub struct SkyBoxBuilder {
|
||||
/// Texture for front face.
|
||||
pub front: Option<Texture>,
|
||||
pub front: Option<TextureResource>,
|
||||
/// Texture for back face.
|
||||
pub back: Option<Texture>,
|
||||
pub back: Option<TextureResource>,
|
||||
/// Texture for left face.
|
||||
pub left: Option<Texture>,
|
||||
pub left: Option<TextureResource>,
|
||||
/// Texture for right face.
|
||||
pub right: Option<Texture>,
|
||||
pub right: Option<TextureResource>,
|
||||
/// Texture for top face.
|
||||
pub top: Option<Texture>,
|
||||
pub top: Option<TextureResource>,
|
||||
/// Texture for bottom face.
|
||||
pub bottom: Option<Texture>,
|
||||
pub bottom: Option<TextureResource>,
|
||||
}
|
||||
|
||||
impl SkyBoxBuilder {
|
||||
/// Sets desired front face of cubemap.
|
||||
pub fn with_front(mut self, texture: Texture) -> Self {
|
||||
pub fn with_front(mut self, texture: TextureResource) -> Self {
|
||||
self.front = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired back face of cubemap.
|
||||
pub fn with_back(mut self, texture: Texture) -> Self {
|
||||
pub fn with_back(mut self, texture: TextureResource) -> Self {
|
||||
self.back = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired left face of cubemap.
|
||||
pub fn with_left(mut self, texture: Texture) -> Self {
|
||||
pub fn with_left(mut self, texture: TextureResource) -> Self {
|
||||
self.left = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired right face of cubemap.
|
||||
pub fn with_right(mut self, texture: Texture) -> Self {
|
||||
pub fn with_right(mut self, texture: TextureResource) -> Self {
|
||||
self.right = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired top face of cubemap.
|
||||
pub fn with_top(mut self, texture: Texture) -> Self {
|
||||
pub fn with_top(mut self, texture: TextureResource) -> Self {
|
||||
self.top = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired front face of cubemap.
|
||||
pub fn with_bottom(mut self, texture: Texture) -> Self {
|
||||
pub fn with_bottom(mut self, texture: TextureResource) -> Self {
|
||||
self.bottom = Some(texture);
|
||||
self
|
||||
}
|
||||
@@ -1031,32 +1036,32 @@ impl SkyBoxBuilder {
|
||||
pub struct SkyBox {
|
||||
/// Texture for front face.
|
||||
#[reflect(setter = "set_front")]
|
||||
pub(crate) front: Option<Texture>,
|
||||
pub(crate) front: Option<TextureResource>,
|
||||
|
||||
/// Texture for back face.
|
||||
#[reflect(setter = "set_back")]
|
||||
pub(crate) back: Option<Texture>,
|
||||
pub(crate) back: Option<TextureResource>,
|
||||
|
||||
/// Texture for left face.
|
||||
#[reflect(setter = "set_left")]
|
||||
pub(crate) left: Option<Texture>,
|
||||
pub(crate) left: Option<TextureResource>,
|
||||
|
||||
/// Texture for right face.
|
||||
#[reflect(setter = "set_right")]
|
||||
pub(crate) right: Option<Texture>,
|
||||
pub(crate) right: Option<TextureResource>,
|
||||
|
||||
/// Texture for top face.
|
||||
#[reflect(setter = "set_top")]
|
||||
pub(crate) top: Option<Texture>,
|
||||
pub(crate) top: Option<TextureResource>,
|
||||
|
||||
/// Texture for bottom face.
|
||||
#[reflect(setter = "set_bottom")]
|
||||
pub(crate) bottom: Option<Texture>,
|
||||
pub(crate) bottom: Option<TextureResource>,
|
||||
|
||||
/// Cubemap texture
|
||||
#[reflect(hidden)]
|
||||
#[visit(skip)]
|
||||
pub(crate) cubemap: Option<Texture>,
|
||||
pub(crate) cubemap: Option<TextureResource>,
|
||||
}
|
||||
|
||||
/// An error that may occur during skybox creation.
|
||||
@@ -1101,12 +1106,12 @@ pub enum SkyBoxError {
|
||||
|
||||
impl SkyBox {
|
||||
/// Returns cubemap texture
|
||||
pub fn cubemap(&self) -> Option<Texture> {
|
||||
pub fn cubemap(&self) -> Option<TextureResource> {
|
||||
self.cubemap.clone()
|
||||
}
|
||||
|
||||
/// Returns cubemap texture
|
||||
pub fn cubemap_ref(&self) -> Option<&Texture> {
|
||||
pub fn cubemap_ref(&self) -> Option<&TextureResource> {
|
||||
self.cubemap.as_ref()
|
||||
}
|
||||
|
||||
@@ -1213,8 +1218,13 @@ impl SkyBox {
|
||||
}
|
||||
|
||||
self.cubemap = Some(
|
||||
Texture::from_bytes(TextureKind::Cube { width, height }, pixel_kind, data, false)
|
||||
.ok_or(SkyBoxError::UnableToBuildCubeMap)?,
|
||||
TextureResource::from_bytes(
|
||||
TextureKind::Cube { width, height },
|
||||
pixel_kind,
|
||||
data,
|
||||
false,
|
||||
)
|
||||
.ok_or(SkyBoxError::UnableToBuildCubeMap)?,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -1228,7 +1238,7 @@ impl SkyBox {
|
||||
/// These textures are **not** used for rendering! The renderer uses cube map made of these
|
||||
/// textures. Public access for these textures is needed in case you need to read internals
|
||||
/// of the textures.
|
||||
pub fn textures(&self) -> [Option<Texture>; 6] {
|
||||
pub fn textures(&self) -> [Option<TextureResource>; 6] {
|
||||
[
|
||||
self.left.clone(),
|
||||
self.right.clone(),
|
||||
@@ -1240,7 +1250,7 @@ impl SkyBox {
|
||||
}
|
||||
|
||||
/// Set new texture for the left side of the skybox.
|
||||
pub fn set_left(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_left(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
let prev = std::mem::replace(&mut self.left, texture);
|
||||
Log::verify(self.create_cubemap());
|
||||
prev
|
||||
@@ -1251,12 +1261,12 @@ impl SkyBox {
|
||||
/// # Important notes.
|
||||
///
|
||||
/// This textures is not used for rendering! The renderer uses cube map made of face textures.
|
||||
pub fn left(&self) -> Option<Texture> {
|
||||
pub fn left(&self) -> Option<TextureResource> {
|
||||
self.left.clone()
|
||||
}
|
||||
|
||||
/// Set new texture for the right side of the skybox.
|
||||
pub fn set_right(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_right(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
let prev = std::mem::replace(&mut self.right, texture);
|
||||
Log::verify(self.create_cubemap());
|
||||
prev
|
||||
@@ -1267,12 +1277,12 @@ impl SkyBox {
|
||||
/// # Important notes.
|
||||
///
|
||||
/// This textures is not used for rendering! The renderer uses cube map made of face textures.
|
||||
pub fn right(&self) -> Option<Texture> {
|
||||
pub fn right(&self) -> Option<TextureResource> {
|
||||
self.right.clone()
|
||||
}
|
||||
|
||||
/// Set new texture for the top side of the skybox.
|
||||
pub fn set_top(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_top(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
let prev = std::mem::replace(&mut self.top, texture);
|
||||
Log::verify(self.create_cubemap());
|
||||
prev
|
||||
@@ -1283,12 +1293,12 @@ impl SkyBox {
|
||||
/// # Important notes.
|
||||
///
|
||||
/// This textures is not used for rendering! The renderer uses cube map made of face textures.
|
||||
pub fn top(&self) -> Option<Texture> {
|
||||
pub fn top(&self) -> Option<TextureResource> {
|
||||
self.top.clone()
|
||||
}
|
||||
|
||||
/// Set new texture for the bottom side of the skybox.
|
||||
pub fn set_bottom(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_bottom(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
let prev = std::mem::replace(&mut self.bottom, texture);
|
||||
Log::verify(self.create_cubemap());
|
||||
prev
|
||||
@@ -1299,12 +1309,12 @@ impl SkyBox {
|
||||
/// # Important notes.
|
||||
///
|
||||
/// This textures is not used for rendering! The renderer uses cube map made of face textures.
|
||||
pub fn bottom(&self) -> Option<Texture> {
|
||||
pub fn bottom(&self) -> Option<TextureResource> {
|
||||
self.bottom.clone()
|
||||
}
|
||||
|
||||
/// Set new texture for the front side of the skybox.
|
||||
pub fn set_front(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_front(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
let prev = std::mem::replace(&mut self.front, texture);
|
||||
Log::verify(self.create_cubemap());
|
||||
prev
|
||||
@@ -1315,12 +1325,12 @@ impl SkyBox {
|
||||
/// # Important notes.
|
||||
///
|
||||
/// This textures is not used for rendering! The renderer uses cube map made of face textures.
|
||||
pub fn front(&self) -> Option<Texture> {
|
||||
pub fn front(&self) -> Option<TextureResource> {
|
||||
self.front.clone()
|
||||
}
|
||||
|
||||
/// Set new texture for the back side of the skybox.
|
||||
pub fn set_back(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_back(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
let prev = std::mem::replace(&mut self.back, texture);
|
||||
Log::verify(self.create_cubemap());
|
||||
prev
|
||||
@@ -1331,7 +1341,7 @@ impl SkyBox {
|
||||
/// # Important notes.
|
||||
///
|
||||
/// This textures is not used for rendering! The renderer uses cube map made of face textures.
|
||||
pub fn back(&self) -> Option<Texture> {
|
||||
pub fn back(&self) -> Option<TextureResource> {
|
||||
self.back.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
@@ -18,7 +19,7 @@ use crate::{
|
||||
physics::{CoefficientCombineRule, ContactPair, IntersectionPair, PhysicsWorld},
|
||||
Graph,
|
||||
},
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider},
|
||||
node::{Node, NodeTrait, SyncContext},
|
||||
rigidbody::RigidBody,
|
||||
Scene,
|
||||
},
|
||||
|
||||
+21
-14
@@ -11,12 +11,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@@ -86,10 +87,10 @@ pub struct Decal {
|
||||
base: Base,
|
||||
|
||||
#[reflect(setter = "set_diffuse_texture")]
|
||||
diffuse_texture: InheritableVariable<Option<Texture>>,
|
||||
diffuse_texture: InheritableVariable<Option<TextureResource>>,
|
||||
|
||||
#[reflect(setter = "set_normal_texture")]
|
||||
normal_texture: InheritableVariable<Option<Texture>>,
|
||||
normal_texture: InheritableVariable<Option<TextureResource>>,
|
||||
|
||||
#[reflect(setter = "set_color")]
|
||||
color: InheritableVariable<Color>,
|
||||
@@ -121,7 +122,10 @@ impl TypeUuidProvider for Decal {
|
||||
|
||||
impl Decal {
|
||||
/// Sets new diffuse texture.
|
||||
pub fn set_diffuse_texture(&mut self, diffuse_texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_diffuse_texture(
|
||||
&mut self,
|
||||
diffuse_texture: Option<TextureResource>,
|
||||
) -> Option<TextureResource> {
|
||||
std::mem::replace(
|
||||
self.diffuse_texture.get_value_mut_and_mark_modified(),
|
||||
diffuse_texture,
|
||||
@@ -129,17 +133,20 @@ impl Decal {
|
||||
}
|
||||
|
||||
/// Returns current diffuse texture.
|
||||
pub fn diffuse_texture(&self) -> Option<&Texture> {
|
||||
pub fn diffuse_texture(&self) -> Option<&TextureResource> {
|
||||
self.diffuse_texture.as_ref()
|
||||
}
|
||||
|
||||
/// Returns current diffuse texture.
|
||||
pub fn diffuse_texture_value(&self) -> Option<Texture> {
|
||||
pub fn diffuse_texture_value(&self) -> Option<TextureResource> {
|
||||
(*self.diffuse_texture).clone()
|
||||
}
|
||||
|
||||
/// Sets new normal texture.
|
||||
pub fn set_normal_texture(&mut self, normal_texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_normal_texture(
|
||||
&mut self,
|
||||
normal_texture: Option<TextureResource>,
|
||||
) -> Option<TextureResource> {
|
||||
std::mem::replace(
|
||||
self.normal_texture.get_value_mut_and_mark_modified(),
|
||||
normal_texture,
|
||||
@@ -147,12 +154,12 @@ impl Decal {
|
||||
}
|
||||
|
||||
/// Returns current normal texture.
|
||||
pub fn normal_texture(&self) -> Option<&Texture> {
|
||||
pub fn normal_texture(&self) -> Option<&TextureResource> {
|
||||
self.normal_texture.as_ref()
|
||||
}
|
||||
|
||||
/// Returns current normal texture.
|
||||
pub fn normal_texture_value(&self) -> Option<Texture> {
|
||||
pub fn normal_texture_value(&self) -> Option<TextureResource> {
|
||||
(*self.normal_texture).clone()
|
||||
}
|
||||
|
||||
@@ -204,8 +211,8 @@ impl NodeTrait for Decal {
|
||||
/// Allows you to create a Decal in a declarative manner.
|
||||
pub struct DecalBuilder {
|
||||
base_builder: BaseBuilder,
|
||||
diffuse_texture: Option<Texture>,
|
||||
normal_texture: Option<Texture>,
|
||||
diffuse_texture: Option<TextureResource>,
|
||||
normal_texture: Option<TextureResource>,
|
||||
color: Color,
|
||||
layer: u8,
|
||||
}
|
||||
@@ -223,13 +230,13 @@ impl DecalBuilder {
|
||||
}
|
||||
|
||||
/// Sets desired diffuse texture.
|
||||
pub fn with_diffuse_texture(mut self, diffuse_texture: Texture) -> Self {
|
||||
pub fn with_diffuse_texture(mut self, diffuse_texture: TextureResource) -> Self {
|
||||
self.diffuse_texture = Some(diffuse_texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired normal texture.
|
||||
pub fn with_normal_texture(mut self, normal_texture: Texture) -> Self {
|
||||
pub fn with_normal_texture(mut self, normal_texture: TextureResource) -> Self {
|
||||
self.normal_texture = Some(normal_texture);
|
||||
self
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
@@ -19,7 +20,7 @@ use crate::{
|
||||
rigidbody::RigidBody,
|
||||
},
|
||||
graph::{physics::CoefficientCombineRule, Graph},
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider},
|
||||
node::{Node, NodeTrait, SyncContext},
|
||||
Scene,
|
||||
},
|
||||
utils::log::Log,
|
||||
|
||||
@@ -9,12 +9,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
dim2::rigidbody::RigidBody,
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider},
|
||||
node::{Node, NodeTrait, SyncContext},
|
||||
Scene,
|
||||
},
|
||||
utils::log::Log,
|
||||
|
||||
@@ -12,12 +12,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@@ -104,7 +105,7 @@ pub struct Rectangle {
|
||||
|
||||
#[reflect(setter = "set_texture")]
|
||||
#[visit(optional)] // Backward compatibility
|
||||
texture: InheritableVariable<Option<Texture>>,
|
||||
texture: InheritableVariable<Option<TextureResource>>,
|
||||
|
||||
#[reflect(setter = "set_color")]
|
||||
color: InheritableVariable<Color>,
|
||||
@@ -147,17 +148,17 @@ impl TypeUuidProvider for Rectangle {
|
||||
|
||||
impl Rectangle {
|
||||
/// Returns a texture used by the rectangle.
|
||||
pub fn texture(&self) -> Option<&Texture> {
|
||||
pub fn texture(&self) -> Option<&TextureResource> {
|
||||
self.texture.as_ref()
|
||||
}
|
||||
|
||||
/// Returns a texture used by the rectangle.
|
||||
pub fn texture_value(&self) -> Option<Texture> {
|
||||
pub fn texture_value(&self) -> Option<TextureResource> {
|
||||
(*self.texture).clone()
|
||||
}
|
||||
|
||||
/// Sets new texture for the rectangle.
|
||||
pub fn set_texture(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_texture(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
self.texture.set_value_and_mark_modified(texture)
|
||||
}
|
||||
|
||||
@@ -211,7 +212,7 @@ impl NodeTrait for Rectangle {
|
||||
/// Allows you to create rectangle in declarative manner.
|
||||
pub struct RectangleBuilder {
|
||||
base_builder: BaseBuilder,
|
||||
texture: Option<Texture>,
|
||||
texture: Option<TextureResource>,
|
||||
color: Color,
|
||||
uv_rect: Rect<f32>,
|
||||
}
|
||||
@@ -228,7 +229,7 @@ impl RectangleBuilder {
|
||||
}
|
||||
|
||||
/// Sets desired texture of the rectangle.
|
||||
pub fn with_texture(mut self, texture: Texture) -> Self {
|
||||
pub fn with_texture(mut self, texture: TextureResource) -> Self {
|
||||
self.texture = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
@@ -18,12 +18,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
dim2::collider::Collider,
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, SyncContext, UpdateContext},
|
||||
rigidbody::RigidBodyType,
|
||||
Scene,
|
||||
},
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
//! just by linking nodes to each other. Good example of this is skeleton which
|
||||
//! is used in skinning (animating 3d model by set of bones).
|
||||
|
||||
use crate::resource::model::ModelResourceExtension;
|
||||
use crate::{
|
||||
core::{
|
||||
algebra::{Matrix4, Rotation3, UnitQuaternion, Vector2, Vector3},
|
||||
@@ -33,7 +34,7 @@ use crate::{
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
},
|
||||
material::SharedMaterial,
|
||||
resource::model::{Model, NodeMapping},
|
||||
resource::model::{ModelResource, NodeMapping},
|
||||
scene::{
|
||||
self,
|
||||
base::NodeScriptMessage,
|
||||
@@ -771,7 +772,7 @@ impl Graph {
|
||||
// if needed and copy surfaces from originals.
|
||||
for node in self.pool.iter_mut() {
|
||||
if let Some(model) = node.resource() {
|
||||
let model = model.state();
|
||||
let mut model = model.state();
|
||||
match model.get() {
|
||||
ResourceStateRef::Ok(data) => {
|
||||
let resource_graph = &data.get_scene().graph;
|
||||
@@ -841,7 +842,7 @@ impl Graph {
|
||||
//
|
||||
// To do so, we at first, build node handle mapping (original handle -> instance handle) starting from
|
||||
// instance root. Then we must find all inheritable properties and try to remap them to instance handles.
|
||||
fn remap_handles(&mut self, instances: &[(Handle<Node>, Model)]) {
|
||||
fn remap_handles(&mut self, instances: &[(Handle<Node>, ModelResource)]) {
|
||||
for (instance_root, resource) in instances {
|
||||
// Prepare old -> new handle mapping first by walking over the graph
|
||||
// starting from instance root.
|
||||
@@ -877,7 +878,7 @@ impl Graph {
|
||||
}
|
||||
}
|
||||
|
||||
fn restore_integrity(&mut self) -> Vec<(Handle<Node>, Model)> {
|
||||
fn restore_integrity(&mut self) -> Vec<(Handle<Node>, ModelResource)> {
|
||||
Log::writeln(MessageKind::Information, "Checking integrity...");
|
||||
|
||||
// Check integrity - if a node was added in resource, it must be also added in the graph.
|
||||
@@ -900,7 +901,7 @@ impl Graph {
|
||||
let mut restored_count = 0;
|
||||
|
||||
for (instance_root, resource) in instances.iter().cloned() {
|
||||
let model = resource.state();
|
||||
let mut model = resource.state();
|
||||
if let ResourceStateRef::Ok(data) = model.get() {
|
||||
let resource_graph = &data.get_scene().graph;
|
||||
|
||||
@@ -942,7 +943,7 @@ impl Graph {
|
||||
);
|
||||
|
||||
// Instantiate missing node.
|
||||
let (copy, old_to_new_mapping) = Model::instantiate_from(
|
||||
let (copy, old_to_new_mapping) = ModelResource::instantiate_from(
|
||||
resource.clone(),
|
||||
data,
|
||||
resource_node_handle,
|
||||
|
||||
+2
-1
@@ -9,11 +9,12 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider},
|
||||
node::{Node, NodeTrait, SyncContext},
|
||||
rigidbody::RigidBody,
|
||||
Scene,
|
||||
},
|
||||
|
||||
@@ -15,12 +15,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::Base,
|
||||
graph::Graph,
|
||||
light::{BaseLight, BaseLightBuilder},
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
@@ -26,13 +26,14 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::Base,
|
||||
debug::SceneDrawingContext,
|
||||
graph::Graph,
|
||||
light::{BaseLight, BaseLightBuilder},
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
+12
-8
@@ -32,14 +32,15 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
TypeUuidProvider,
|
||||
},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
scene::{
|
||||
base::Base,
|
||||
debug::SceneDrawingContext,
|
||||
graph::Graph,
|
||||
light::{BaseLight, BaseLightBuilder},
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@@ -66,7 +67,7 @@ pub struct SpotLight {
|
||||
distance: InheritableVariable<f32>,
|
||||
|
||||
#[reflect(setter = "set_cookie_texture")]
|
||||
cookie_texture: InheritableVariable<Option<Texture>>,
|
||||
cookie_texture: InheritableVariable<Option<TextureResource>>,
|
||||
}
|
||||
|
||||
impl Deref for SpotLight {
|
||||
@@ -171,21 +172,24 @@ impl SpotLight {
|
||||
/// Set cookie texture. Also called gobo this texture gets projected
|
||||
/// by the spot light.
|
||||
#[inline]
|
||||
pub fn set_cookie_texture(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_cookie_texture(
|
||||
&mut self,
|
||||
texture: Option<TextureResource>,
|
||||
) -> Option<TextureResource> {
|
||||
self.cookie_texture.set_value_and_mark_modified(texture)
|
||||
}
|
||||
|
||||
/// Get cookie texture. Also called gobo this texture gets projected
|
||||
/// by the spot light.
|
||||
#[inline]
|
||||
pub fn cookie_texture(&self) -> Option<Texture> {
|
||||
pub fn cookie_texture(&self) -> Option<TextureResource> {
|
||||
(*self.cookie_texture).clone()
|
||||
}
|
||||
|
||||
/// Get cookie texture by ref. Also called gobo this texture gets projected
|
||||
/// by the spot light.
|
||||
#[inline]
|
||||
pub fn cookie_texture_ref(&self) -> Option<&Texture> {
|
||||
pub fn cookie_texture_ref(&self) -> Option<&TextureResource> {
|
||||
self.cookie_texture.as_ref()
|
||||
}
|
||||
}
|
||||
@@ -233,7 +237,7 @@ pub struct SpotLightBuilder {
|
||||
falloff_angle_delta: f32,
|
||||
shadow_bias: f32,
|
||||
distance: f32,
|
||||
cookie_texture: Option<Texture>,
|
||||
cookie_texture: Option<TextureResource>,
|
||||
}
|
||||
|
||||
impl SpotLightBuilder {
|
||||
@@ -274,7 +278,7 @@ impl SpotLightBuilder {
|
||||
}
|
||||
|
||||
/// Sets the desired cookie/gobo texture.
|
||||
pub fn with_cookie_texture(mut self, texture: Texture) -> Self {
|
||||
pub fn with_cookie_texture(mut self, texture: TextureResource) -> Self {
|
||||
self.cookie_texture = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,8 +1,9 @@
|
||||
//! Async scene loader helper. See [`AsyncSceneLoader`] docs for more info.
|
||||
|
||||
use crate::{
|
||||
asset::manager::ResourceManager,
|
||||
core::parking_lot::Mutex,
|
||||
engine::{resource_manager::ResourceManager, SerializationContext},
|
||||
engine::SerializationContext,
|
||||
scene::{Scene, SceneLoader},
|
||||
};
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
@@ -18,6 +18,7 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
TypeUuidProvider,
|
||||
},
|
||||
renderer::{
|
||||
self,
|
||||
@@ -32,7 +33,7 @@ use crate::{
|
||||
buffer::{VertexAttributeUsage, VertexReadTrait},
|
||||
surface::{BlendShape, Surface},
|
||||
},
|
||||
node::{Node, NodeTrait, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, UpdateContext},
|
||||
},
|
||||
};
|
||||
use std::{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//! Surfaces can use the same data source across many instances, this is a memory optimization for
|
||||
//! being able to re-use data when you need to draw the same mesh in many places.
|
||||
|
||||
use crate::resource::texture::TextureResourceExtension;
|
||||
use crate::{
|
||||
core::{
|
||||
algebra::{Matrix4, Point3, Vector2, Vector3, Vector4},
|
||||
@@ -17,7 +18,7 @@ use crate::{
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
},
|
||||
material::{Material, SharedMaterial},
|
||||
resource::texture::{Texture, TextureKind, TexturePixelKind},
|
||||
resource::texture::{TextureKind, TexturePixelKind, TextureResource},
|
||||
scene::{
|
||||
mesh::{
|
||||
buffer::{
|
||||
@@ -63,7 +64,7 @@ pub struct BlendShapesContainer {
|
||||
/// A list of blend shapes.
|
||||
pub blend_shapes: Vec<BlendShape>,
|
||||
/// A volume texture that stores all blend shapes at once.
|
||||
pub blend_shape_storage: Option<Texture>,
|
||||
pub blend_shape_storage: Option<TextureResource>,
|
||||
}
|
||||
|
||||
/// A set of offsets for particular vertices.
|
||||
@@ -173,7 +174,7 @@ impl BlendShapesContainer {
|
||||
})
|
||||
.collect(),
|
||||
blend_shape_storage: Some(
|
||||
Texture::from_bytes(
|
||||
TextureResource::from_bytes(
|
||||
TextureKind::Volume {
|
||||
width: width * 3,
|
||||
height,
|
||||
|
||||
+16
-210
@@ -30,6 +30,7 @@ pub mod visibility;
|
||||
|
||||
use crate::renderer::framework::state::PolygonFillMode;
|
||||
use crate::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
algebra::Vector2,
|
||||
color::Color,
|
||||
@@ -39,12 +40,9 @@ use crate::{
|
||||
sstorage::ImmutableString,
|
||||
visitor::{Visit, VisitError, VisitResult, Visitor},
|
||||
},
|
||||
engine::{resource_manager::ResourceManager, SerializationContext},
|
||||
material::{
|
||||
shader::{SamplerFallback, Shader, STANDARD_SHADER_NAMES},
|
||||
PropertyValue,
|
||||
},
|
||||
resource::{curve::CurveResource, model::Model, texture::Texture},
|
||||
engine::SerializationContext,
|
||||
material::{shader::SamplerFallback, PropertyValue},
|
||||
resource::texture::TextureResource,
|
||||
scene::{
|
||||
base::BaseBuilder,
|
||||
camera::Camera,
|
||||
@@ -64,8 +62,7 @@ use crate::{
|
||||
utils::{lightmap::Lightmap, log::Log, log::MessageKind, navmesh::Navmesh},
|
||||
};
|
||||
use fxhash::{FxHashMap, FxHashSet};
|
||||
use fyrox_resource::ResourceStateRef;
|
||||
use fyrox_sound::buffer::SoundBufferResource;
|
||||
use fyrox_resource::untyped::UntypedResource;
|
||||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
ops::{Index, IndexMut},
|
||||
@@ -166,7 +163,7 @@ pub struct Scene {
|
||||
/// monitor. Other usage could be previewer of models, like pictogram of character
|
||||
/// in real-time strategies, in other words there are plenty of possible uses.
|
||||
#[reflect(hidden)]
|
||||
pub render_target: Option<Texture>,
|
||||
pub render_target: Option<TextureResource>,
|
||||
|
||||
/// Drawing context for simple graphics.
|
||||
#[reflect(hidden)]
|
||||
@@ -254,190 +251,16 @@ pub struct SceneLoader {
|
||||
|
||||
#[derive(Default)]
|
||||
struct UsedResourcesSet {
|
||||
models: FxHashSet<Model>,
|
||||
curves: FxHashSet<CurveResource>,
|
||||
shaders: FxHashSet<Shader>,
|
||||
textures: FxHashSet<Texture>,
|
||||
sound_buffers: FxHashSet<SoundBufferResource>,
|
||||
models: FxHashSet<UntypedResource>,
|
||||
}
|
||||
|
||||
impl UsedResourcesSet {
|
||||
/// Waits asynchronously.
|
||||
async fn wait_async(self) {
|
||||
join_all(self.curves).await;
|
||||
join_all(self.shaders).await;
|
||||
join_all(self.textures).await;
|
||||
join_all(self.sound_buffers).await;
|
||||
join_all(self.models).await;
|
||||
}
|
||||
}
|
||||
|
||||
fn restore_resources(
|
||||
entity: &mut dyn Reflect,
|
||||
resource_manager: &ResourceManager,
|
||||
used_resources: &mut UsedResourcesSet,
|
||||
) {
|
||||
let mut mapped = false;
|
||||
|
||||
entity.as_inheritable_variable_mut(&mut |result| {
|
||||
if let Some(inheritable) = result {
|
||||
restore_resources(
|
||||
inheritable.inner_value_mut(),
|
||||
resource_manager,
|
||||
used_resources,
|
||||
);
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
|
||||
if !mapped {
|
||||
entity.as_hash_map_mut(&mut |result| {
|
||||
if let Some(hash_map) = result {
|
||||
let len = hash_map.reflect_len();
|
||||
for i in 0..len {
|
||||
let (_, value) = hash_map
|
||||
.reflect_get_at_mut(i)
|
||||
.expect("Hash maps cannot have sparse structure!");
|
||||
restore_resources(value, resource_manager, used_resources)
|
||||
}
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if !mapped {
|
||||
entity.as_array_mut(&mut |result| {
|
||||
if let Some(array) = result {
|
||||
let len = array.reflect_len();
|
||||
for i in 0..len {
|
||||
// Support sparse arrays (Pool) too.
|
||||
if let Some(value) = array.reflect_index_mut(i) {
|
||||
restore_resources(value, resource_manager, used_resources)
|
||||
}
|
||||
}
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if !mapped {
|
||||
// Textures are special - there could be procedural textures which must not be resolved.
|
||||
entity.downcast_mut::<Texture>(&mut |result| {
|
||||
if let Some(texture) = result {
|
||||
let data_guard = texture.state();
|
||||
match data_guard.get() {
|
||||
// Try to restore the texture even if it failed to load or loading.
|
||||
ResourceStateRef::LoadError { .. } | ResourceStateRef::Pending { .. } => {
|
||||
drop(data_guard);
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.textures
|
||||
.try_restore_resource(texture);
|
||||
}
|
||||
ResourceStateRef::Ok(texture_state) => {
|
||||
// Do not resolve procedural textures.
|
||||
if !texture_state.is_procedural() {
|
||||
drop(data_guard);
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.textures
|
||||
.try_restore_resource(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
used_resources.textures.insert(texture.clone());
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if !mapped {
|
||||
entity.downcast_mut::<Model>(&mut |result| {
|
||||
if let Some(model) = result {
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.models
|
||||
.try_restore_resource(model);
|
||||
|
||||
used_resources.models.insert(model.clone());
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if !mapped {
|
||||
entity.downcast_mut::<SoundBufferResource>(&mut |result| {
|
||||
if let Some(sound_buffer) = result {
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.sound_buffers
|
||||
.try_restore_resource(sound_buffer);
|
||||
|
||||
used_resources.sound_buffers.insert(sound_buffer.clone());
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if !mapped {
|
||||
entity.downcast_mut::<Shader>(&mut |result| {
|
||||
if let Some(shader) = result {
|
||||
let shader_path = shader.state().path().to_path_buf();
|
||||
|
||||
// Do not try to restore any of the built-in standard shaders.
|
||||
if STANDARD_SHADER_NAMES
|
||||
.iter()
|
||||
.all(|name| Path::new(*name) != shader_path)
|
||||
{
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.shaders
|
||||
.try_restore_resource(shader);
|
||||
|
||||
used_resources.shaders.insert(shader.clone());
|
||||
}
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if !mapped {
|
||||
entity.downcast_mut::<CurveResource>(&mut |result| {
|
||||
if let Some(curve) = result {
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.curves
|
||||
.try_restore_resource(curve);
|
||||
|
||||
used_resources.curves.insert(curve.clone());
|
||||
|
||||
mapped = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
entity.fields_mut(&mut |fields| {
|
||||
for field in fields {
|
||||
// Continue resolving.
|
||||
restore_resources(field, resource_manager, used_resources);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
impl SceneLoader {
|
||||
/// Tries to load scene from given file. File can contain any scene in native engine format.
|
||||
/// Such scenes can be made in rusty editor.
|
||||
@@ -461,7 +284,7 @@ impl SceneLoader {
|
||||
));
|
||||
}
|
||||
|
||||
visitor.environment = Some(serialization_context);
|
||||
visitor.blackboard.register(serialization_context);
|
||||
|
||||
let mut scene = Scene::default();
|
||||
scene.visit(region_name, visitor)?;
|
||||
@@ -473,32 +296,15 @@ impl SceneLoader {
|
||||
pub async fn finish(self, resource_manager: ResourceManager) -> Scene {
|
||||
let mut scene = self.scene;
|
||||
|
||||
// Collect all model resources and wait for them. This step is crucial, because
|
||||
// later on resolve stage we'll extensively access parent resources to inherit
|
||||
// data from them and we can't read data of a resource being loading.
|
||||
let mut used_resources = UsedResourcesSet::default();
|
||||
for node in scene.graph.linear_iter_mut() {
|
||||
restore_resources(
|
||||
node as &mut dyn Reflect,
|
||||
&resource_manager,
|
||||
&mut used_resources,
|
||||
);
|
||||
}
|
||||
|
||||
// Wait everything.
|
||||
used_resources.wait_async().await;
|
||||
|
||||
if let Some(lightmap) = scene.lightmap.as_mut() {
|
||||
for entries in lightmap.map.values_mut() {
|
||||
for entry in entries.iter_mut() {
|
||||
resource_manager
|
||||
.state()
|
||||
.containers_mut()
|
||||
.textures
|
||||
.try_restore_optional_resource(&mut entry.texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
let resource_handles = resource_manager
|
||||
.state()
|
||||
.containers()
|
||||
.resources
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
join_all(resource_handles.into_iter()).await;
|
||||
|
||||
// TODO: Move into Camera::restore_resources?
|
||||
// We have to wait until skybox textures are all loaded, because we need to read their data
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
#![allow(missing_docs)] // TODO
|
||||
|
||||
use crate::scene::base::BaseBuilder;
|
||||
use crate::scene::graph::Graph;
|
||||
use crate::scene::node::Node;
|
||||
use crate::{
|
||||
core::{
|
||||
math::aabb::AxisAlignedBoundingBox,
|
||||
pool::Handle,
|
||||
reflect::prelude::*,
|
||||
uuid::{uuid, Uuid},
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::Base,
|
||||
node::{NodeTrait, TypeUuidProvider},
|
||||
},
|
||||
scene::{base::Base, base::BaseBuilder, graph::Graph, node::Node, node::NodeTrait},
|
||||
utils::navmesh::Navmesh,
|
||||
};
|
||||
use fyrox_core::pool::Handle;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
#[derive(Debug, Clone, Visit, Reflect, Default)]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//! A special container that is able to create nodes by their type UUID.
|
||||
|
||||
use crate::{
|
||||
core::{parking_lot::Mutex, uuid::Uuid},
|
||||
core::{parking_lot::Mutex, uuid::Uuid, TypeUuidProvider},
|
||||
scene::{
|
||||
self,
|
||||
animation::{absm::AnimationBlendingStateMachine, AnimationPlayer},
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
light::{directional::DirectionalLight, point::PointLight, spot::SpotLight},
|
||||
mesh::Mesh,
|
||||
navmesh::NavigationalMesh,
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
particle_system::ParticleSystem,
|
||||
pivot::Pivot,
|
||||
sound::{listener::Listener, Sound},
|
||||
|
||||
@@ -92,9 +92,8 @@ fn read_node(name: &str, visitor: &mut Visitor) -> Result<Node, VisitError> {
|
||||
id.visit("TypeUuid", &mut region)?;
|
||||
|
||||
let serialization_context = region
|
||||
.environment
|
||||
.as_ref()
|
||||
.and_then(|e| e.downcast_ref::<SerializationContext>())
|
||||
.blackboard
|
||||
.get::<SerializationContext>()
|
||||
.expect("Visitor environment must contain serialization context!");
|
||||
|
||||
let mut node = serialization_context
|
||||
|
||||
@@ -41,12 +41,6 @@ use std::{
|
||||
pub mod constructor;
|
||||
pub mod container;
|
||||
|
||||
/// A trait for an entity that has unique type identifier.
|
||||
pub trait TypeUuidProvider: Sized {
|
||||
/// Return type UUID.
|
||||
fn type_uuid() -> Uuid;
|
||||
}
|
||||
|
||||
/// A set of useful methods that is possible to auto-implement.
|
||||
pub trait BaseNodeTrait: Any + Debug + Deref<Target = Base> + DerefMut + Send {
|
||||
/// This method creates raw copy of a node, it should never be called in normal circumstances
|
||||
|
||||
@@ -81,13 +81,14 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
rand::{prelude::StdRng, SeedableRng},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, UpdateContext},
|
||||
particle_system::{
|
||||
draw::{DrawData, Vertex},
|
||||
emitter::{Emit, Emitter},
|
||||
@@ -207,7 +208,7 @@ pub struct ParticleSystem {
|
||||
pub emitters: InheritableVariable<Vec<EmitterWrapper>>,
|
||||
|
||||
#[reflect(setter = "set_texture")]
|
||||
texture: InheritableVariable<Option<Texture>>,
|
||||
texture: InheritableVariable<Option<TextureResource>>,
|
||||
|
||||
#[reflect(setter = "set_acceleration")]
|
||||
acceleration: InheritableVariable<Vector3<f32>>,
|
||||
@@ -408,17 +409,17 @@ impl ParticleSystem {
|
||||
}
|
||||
|
||||
/// Sets new texture for particle system.
|
||||
pub fn set_texture(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_texture(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
self.texture.set_value_and_mark_modified(texture)
|
||||
}
|
||||
|
||||
/// Returns current texture used by particle system.
|
||||
pub fn texture(&self) -> Option<Texture> {
|
||||
pub fn texture(&self) -> Option<TextureResource> {
|
||||
(*self.texture).clone()
|
||||
}
|
||||
|
||||
/// Returns current texture used by particle system by ref.
|
||||
pub fn texture_ref(&self) -> Option<&Texture> {
|
||||
pub fn texture_ref(&self) -> Option<&TextureResource> {
|
||||
self.texture.as_ref()
|
||||
}
|
||||
|
||||
@@ -526,7 +527,7 @@ impl NodeTrait for ParticleSystem {
|
||||
pub struct ParticleSystemBuilder {
|
||||
base_builder: BaseBuilder,
|
||||
emitters: Vec<EmitterWrapper>,
|
||||
texture: Option<Texture>,
|
||||
texture: Option<TextureResource>,
|
||||
acceleration: Vector3<f32>,
|
||||
particles: Vec<Particle>,
|
||||
color_over_lifetime: ColorGradient,
|
||||
@@ -558,13 +559,13 @@ impl ParticleSystemBuilder {
|
||||
}
|
||||
|
||||
/// Sets desired texture for particle system.
|
||||
pub fn with_texture(mut self, texture: Texture) -> Self {
|
||||
pub fn with_texture(mut self, texture: TextureResource) -> Self {
|
||||
self.texture = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired texture for particle system.
|
||||
pub fn with_opt_texture(mut self, texture: Option<Texture>) -> Self {
|
||||
pub fn with_opt_texture(mut self, texture: Option<TextureResource>) -> Self {
|
||||
self.texture = texture;
|
||||
self
|
||||
}
|
||||
|
||||
+2
-1
@@ -6,11 +6,12 @@ use crate::{
|
||||
reflect::prelude::*,
|
||||
uuid::{uuid, Uuid},
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
@@ -18,12 +18,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
collider::Collider,
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, SyncContext, UpdateContext},
|
||||
Scene,
|
||||
},
|
||||
utils::log::Log,
|
||||
|
||||
@@ -10,11 +10,12 @@ use crate::{
|
||||
reflect::prelude::*,
|
||||
uuid::{uuid, Uuid},
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider},
|
||||
node::{Node, NodeTrait, SyncContext},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
@@ -9,18 +9,19 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::prelude::*,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
define_with,
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, SyncContext, TypeUuidProvider, UpdateContext},
|
||||
node::{Node, NodeTrait, SyncContext, UpdateContext},
|
||||
},
|
||||
};
|
||||
|
||||
// Re-export some the fyrox_sound entities.
|
||||
pub use fyrox_sound::{
|
||||
buffer::{DataSource, SoundBufferResource, SoundBufferResourceLoadError, SoundBufferState},
|
||||
buffer::{DataSource, SoundBuffer, SoundBufferResource, SoundBufferResourceLoadError},
|
||||
bus::*,
|
||||
context::{DistanceModel, SAMPLE_RATE},
|
||||
dsp::{filters::*, DelayLine},
|
||||
@@ -400,7 +401,7 @@ impl NodeTrait for Sound {
|
||||
fn validate(&self, _scene: &Scene) -> Result<(), String> {
|
||||
match self.buffer.as_ref() {
|
||||
Some(buffer) => {
|
||||
let state = buffer.state();
|
||||
let mut state = buffer.state();
|
||||
match state.get() {
|
||||
ResourceStateRef::Pending { .. } | ResourceStateRef::Ok(_) => Ok(()),
|
||||
ResourceStateRef::LoadError { error, .. } => {
|
||||
@@ -409,7 +410,7 @@ impl NodeTrait for Sound {
|
||||
.to_string()),
|
||||
Some(err) => Err(format!(
|
||||
"Sound buffer is failed to load. Reason: {:?}",
|
||||
**err
|
||||
*err
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
+10
-9
@@ -11,12 +11,13 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
TypeUuidProvider,
|
||||
},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
graph::Graph,
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
},
|
||||
};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
@@ -65,7 +66,7 @@ pub struct Sprite {
|
||||
base: Base,
|
||||
|
||||
#[reflect(setter = "set_texture")]
|
||||
texture: InheritableVariable<Option<Texture>>,
|
||||
texture: InheritableVariable<Option<TextureResource>>,
|
||||
|
||||
#[reflect(setter = "set_color")]
|
||||
color: InheritableVariable<Color>,
|
||||
@@ -139,17 +140,17 @@ impl Sprite {
|
||||
}
|
||||
|
||||
/// Sets new texture for sprite. Default is None.
|
||||
pub fn set_texture(&mut self, texture: Option<Texture>) -> Option<Texture> {
|
||||
pub fn set_texture(&mut self, texture: Option<TextureResource>) -> Option<TextureResource> {
|
||||
self.texture.set_value_and_mark_modified(texture)
|
||||
}
|
||||
|
||||
/// Returns current texture of sprite. Can be None if sprite has no texture.
|
||||
pub fn texture(&self) -> Option<Texture> {
|
||||
pub fn texture(&self) -> Option<TextureResource> {
|
||||
(*self.texture).clone()
|
||||
}
|
||||
|
||||
/// Returns current texture of sprite by ref. Can be None if sprite has no texture.
|
||||
pub fn texture_ref(&self) -> Option<&Texture> {
|
||||
pub fn texture_ref(&self) -> Option<&TextureResource> {
|
||||
self.texture.as_ref()
|
||||
}
|
||||
}
|
||||
@@ -174,7 +175,7 @@ impl NodeTrait for Sprite {
|
||||
/// This is typical implementation of Builder pattern.
|
||||
pub struct SpriteBuilder {
|
||||
base_builder: BaseBuilder,
|
||||
texture: Option<Texture>,
|
||||
texture: Option<TextureResource>,
|
||||
color: Color,
|
||||
size: f32,
|
||||
rotation: f32,
|
||||
@@ -193,13 +194,13 @@ impl SpriteBuilder {
|
||||
}
|
||||
|
||||
/// Sets desired texture.
|
||||
pub fn with_texture(mut self, texture: Texture) -> Self {
|
||||
pub fn with_texture(mut self, texture: TextureResource) -> Self {
|
||||
self.texture = Some(texture);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets desired texture.
|
||||
pub fn with_opt_texture(mut self, texture: Option<Texture>) -> Self {
|
||||
pub fn with_opt_texture(mut self, texture: Option<TextureResource>) -> Self {
|
||||
self.texture = texture;
|
||||
self
|
||||
}
|
||||
|
||||
+20
-18
@@ -1,5 +1,6 @@
|
||||
//! Everything related to terrains.
|
||||
|
||||
use crate::resource::texture::TextureResourceExtension;
|
||||
use crate::{
|
||||
asset::Resource,
|
||||
core::{
|
||||
@@ -12,6 +13,7 @@ use crate::{
|
||||
uuid::{uuid, Uuid},
|
||||
variable::InheritableVariable,
|
||||
visitor::{prelude::*, PodVecView},
|
||||
TypeUuidProvider,
|
||||
},
|
||||
material::{Material, PropertyValue, SharedMaterial},
|
||||
renderer::{
|
||||
@@ -19,13 +21,13 @@ use crate::{
|
||||
batch::{RenderContext, SurfaceInstanceData},
|
||||
framework::geometry_buffer::ElementRange,
|
||||
},
|
||||
resource::texture::{Texture, TextureData, TextureKind, TexturePixelKind, TextureWrapMode},
|
||||
resource::texture::{Texture, TextureKind, TexturePixelKind, TextureResource, TextureWrapMode},
|
||||
scene::{
|
||||
base::{Base, BaseBuilder},
|
||||
debug::SceneDrawingContext,
|
||||
graph::Graph,
|
||||
mesh::RenderPath,
|
||||
node::{Node, NodeTrait, TypeUuidProvider},
|
||||
node::{Node, NodeTrait},
|
||||
terrain::{geometry::TerrainGeometry, quadtree::QuadTree},
|
||||
},
|
||||
utils::{self, log::Log},
|
||||
@@ -77,7 +79,7 @@ impl Default for Layer {
|
||||
}
|
||||
|
||||
fn make_quad_tree(
|
||||
texture: &Option<Texture>,
|
||||
texture: &Option<TextureResource>,
|
||||
height_map_size: Vector2<u32>,
|
||||
block_size: Vector2<u32>,
|
||||
) -> QuadTree {
|
||||
@@ -86,8 +88,8 @@ fn make_quad_tree(
|
||||
QuadTree::new(height_map, height_map_size, block_size)
|
||||
}
|
||||
|
||||
fn make_height_map_texture(height_map: Vec<f32>, size: Vector2<u32>) -> Texture {
|
||||
let mut data = TextureData::from_bytes(
|
||||
fn make_height_map_texture(height_map: Vec<f32>, size: Vector2<u32>) -> TextureResource {
|
||||
let mut data = Texture::from_bytes(
|
||||
TextureKind::Rectangle {
|
||||
width: size.x,
|
||||
height: size.y,
|
||||
@@ -101,7 +103,7 @@ fn make_height_map_texture(height_map: Vec<f32>, size: Vector2<u32>) -> Texture
|
||||
data.set_t_wrap_mode(TextureWrapMode::ClampToEdge);
|
||||
data.set_s_wrap_mode(TextureWrapMode::ClampToEdge);
|
||||
|
||||
Texture(Resource::new_ok(data))
|
||||
Resource::new_ok(data)
|
||||
}
|
||||
|
||||
/// Chunk is smaller block of a terrain. Terrain can have as many chunks as you need.
|
||||
@@ -116,7 +118,7 @@ pub struct Chunk {
|
||||
#[reflect(hidden)]
|
||||
version: u8,
|
||||
#[reflect(hidden)]
|
||||
heightmap: Option<Texture>,
|
||||
heightmap: Option<TextureResource>,
|
||||
#[reflect(hidden)]
|
||||
position: Vector3<f32>,
|
||||
#[reflect(hidden)]
|
||||
@@ -129,7 +131,7 @@ pub struct Chunk {
|
||||
grid_position: Vector2<i32>,
|
||||
/// Layer blending masks of the chunk.
|
||||
#[reflect(hidden)]
|
||||
pub layer_masks: Vec<Texture>,
|
||||
pub layer_masks: Vec<TextureResource>,
|
||||
}
|
||||
|
||||
impl Clone for Chunk {
|
||||
@@ -237,7 +239,7 @@ impl Chunk {
|
||||
}
|
||||
|
||||
/// Returns a reference to height map.
|
||||
pub fn heightmap(&self) -> &Texture {
|
||||
pub fn heightmap(&self) -> &TextureResource {
|
||||
self.heightmap.as_ref().unwrap()
|
||||
}
|
||||
|
||||
@@ -253,7 +255,7 @@ impl Chunk {
|
||||
}
|
||||
|
||||
/// Sets new height map. New height map must be equal with size of current.
|
||||
pub fn set_heightmap(&mut self, heightmap: Texture) -> Result<(), Texture> {
|
||||
pub fn set_heightmap(&mut self, heightmap: TextureResource) -> Result<(), TextureResource> {
|
||||
let data = heightmap.data_ref();
|
||||
if let TextureKind::Rectangle { width, height } = data.kind() {
|
||||
if data.pixel_kind() == TexturePixelKind::R32F
|
||||
@@ -405,7 +407,7 @@ impl Default for Terrain {
|
||||
struct OldLayer {
|
||||
pub material: SharedMaterial,
|
||||
pub mask_property_name: String,
|
||||
pub chunk_masks: Vec<Texture>,
|
||||
pub chunk_masks: Vec<TextureResource>,
|
||||
}
|
||||
|
||||
impl Default for OldLayer {
|
||||
@@ -964,12 +966,12 @@ impl Terrain {
|
||||
/// Adds new layer to the chunk. It is possible to have different layer count per chunk
|
||||
/// in the same terrain, however it seems to not have practical usage, so try to keep
|
||||
/// equal layer count per each chunk in your terrains.
|
||||
pub fn add_layer(&mut self, layer: Layer, masks: Vec<Texture>) {
|
||||
pub fn add_layer(&mut self, layer: Layer, masks: Vec<TextureResource>) {
|
||||
self.insert_layer(layer, masks, self.layers.len())
|
||||
}
|
||||
|
||||
/// Removes a layer at the given index together with its respective blending masks from each chunk.
|
||||
pub fn remove_layer(&mut self, layer_index: usize) -> (Layer, Vec<Texture>) {
|
||||
pub fn remove_layer(&mut self, layer_index: usize) -> (Layer, Vec<TextureResource>) {
|
||||
let layer = self
|
||||
.layers
|
||||
.get_value_mut_and_mark_modified()
|
||||
@@ -982,7 +984,7 @@ impl Terrain {
|
||||
}
|
||||
|
||||
/// Removes last terrain layer together with its respective blending masks from each chunk.
|
||||
pub fn pop_layer(&mut self) -> Option<(Layer, Vec<Texture>)> {
|
||||
pub fn pop_layer(&mut self) -> Option<(Layer, Vec<TextureResource>)> {
|
||||
if self.layers.is_empty() {
|
||||
None
|
||||
} else {
|
||||
@@ -991,7 +993,7 @@ impl Terrain {
|
||||
}
|
||||
|
||||
/// Inserts the layer at the given index together with its blending masks for each chunk.
|
||||
pub fn insert_layer(&mut self, layer: Layer, mut masks: Vec<Texture>, index: usize) {
|
||||
pub fn insert_layer(&mut self, layer: Layer, mut masks: Vec<TextureResource>, index: usize) {
|
||||
self.layers
|
||||
.get_value_mut_and_mark_modified()
|
||||
.insert(index, layer);
|
||||
@@ -1034,7 +1036,7 @@ impl Terrain {
|
||||
);
|
||||
|
||||
let new_mask = resampled_mask_image.into_raw();
|
||||
let new_mask_texture = Texture::from_bytes(
|
||||
let new_mask_texture = TextureResource::from_bytes(
|
||||
TextureKind::Rectangle {
|
||||
width: new_size.x,
|
||||
height: new_size.y,
|
||||
@@ -1374,8 +1376,8 @@ pub struct TerrainBuilder {
|
||||
decal_layer_index: u8,
|
||||
}
|
||||
|
||||
fn create_layer_mask(width: u32, height: u32, value: u8) -> Texture {
|
||||
let mask = Texture::from_bytes(
|
||||
fn create_layer_mask(width: u32, height: u32, value: u8) -> TextureResource {
|
||||
let mask = TextureResource::from_bytes(
|
||||
TextureKind::Rectangle { width, height },
|
||||
TexturePixelKind::R8,
|
||||
vec![value; (width * height) as usize],
|
||||
|
||||
@@ -4,8 +4,8 @@ use crate::{
|
||||
core::{
|
||||
parking_lot::{Mutex, MutexGuard},
|
||||
uuid::Uuid,
|
||||
TypeUuidProvider,
|
||||
},
|
||||
scene::node::TypeUuidProvider,
|
||||
script::{Script, ScriptTrait},
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
+3
-3
@@ -3,13 +3,14 @@
|
||||
//! Script is used to add custom logic to scene nodes. See [ScriptTrait] for more info.
|
||||
|
||||
use crate::{
|
||||
asset::manager::ResourceManager,
|
||||
core::{
|
||||
pool::Handle,
|
||||
reflect::{FieldInfo, Reflect, ReflectArray, ReflectList},
|
||||
uuid::Uuid,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
},
|
||||
engine::{resource_manager::ResourceManager, ScriptMessageDispatcher},
|
||||
engine::ScriptMessageDispatcher,
|
||||
event::Event,
|
||||
plugin::Plugin,
|
||||
scene::{node::Node, Scene},
|
||||
@@ -391,8 +392,7 @@ pub trait ScriptTrait: BaseScript + ComponentProvider {
|
||||
/// ```rust
|
||||
/// use std::str::FromStr;
|
||||
/// use fyrox::{
|
||||
/// scene::node::TypeUuidProvider,
|
||||
/// core::visitor::prelude::*,
|
||||
/// /// core::visitor::prelude::*,
|
||||
/// core::reflect::prelude::*,
|
||||
/// core::uuid::Uuid,
|
||||
/// script::ScriptTrait,
|
||||
|
||||
+20
-10
@@ -9,9 +9,8 @@
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use crate::material::PropertyValue;
|
||||
use crate::{
|
||||
asset::Resource,
|
||||
asset::manager::{ResourceManager, ResourceRegistrationError},
|
||||
core::{
|
||||
algebra::{Matrix3, Matrix4, Point3, Vector2, Vector3, Vector4},
|
||||
arrayvec::ArrayVec,
|
||||
@@ -20,8 +19,8 @@ use crate::{
|
||||
pool::Handle,
|
||||
visitor::{Visit, VisitResult, Visitor},
|
||||
},
|
||||
engine::resource_manager::{ResourceManager, TextureRegistrationError},
|
||||
resource::texture::{Texture, TextureData, TextureKind, TexturePixelKind},
|
||||
material::PropertyValue,
|
||||
resource::texture::{Texture, TextureKind, TexturePixelKind, TextureResource},
|
||||
scene::{
|
||||
light::{directional::DirectionalLight, point::PointLight, spot::SpotLight},
|
||||
mesh::{
|
||||
@@ -55,7 +54,7 @@ pub struct LightmapEntry {
|
||||
/// TODO: Is single texture enough? There may be surfaces with huge amount of faces
|
||||
/// which may not fit into texture, because there is hardware limit on most GPUs
|
||||
/// up to 8192x8192 pixels.
|
||||
pub texture: Option<Texture>,
|
||||
pub texture: Option<TextureResource>,
|
||||
/// List of lights that were used to generate this lightmap. This list is used for
|
||||
/// masking when applying dynamic lights for surfaces with light, it prevents double
|
||||
/// lighting.
|
||||
@@ -457,7 +456,7 @@ impl Lightmap {
|
||||
|
||||
let lightmap = generate_lightmap(instance, &instances, &lights, texels_per_unit);
|
||||
map.entry(instance.owner).or_default().push(LightmapEntry {
|
||||
texture: Some(Texture(Resource::new_ok(lightmap))),
|
||||
texture: Some(TextureResource::new_ok(lightmap)),
|
||||
lights: lights.iter().map(|light| light.handle()).collect(),
|
||||
});
|
||||
|
||||
@@ -472,7 +471,7 @@ impl Lightmap {
|
||||
&self,
|
||||
base_path: P,
|
||||
resource_manager: ResourceManager,
|
||||
) -> Result<(), TextureRegistrationError> {
|
||||
) -> Result<(), ResourceRegistrationError> {
|
||||
if !base_path.as_ref().exists() {
|
||||
std::fs::create_dir(base_path.as_ref()).unwrap();
|
||||
}
|
||||
@@ -482,7 +481,18 @@ impl Lightmap {
|
||||
for (i, entry) in entries.iter().enumerate() {
|
||||
let file_path = handle_path.clone() + "_" + i.to_string().as_str() + ".png";
|
||||
let texture = entry.texture.clone().unwrap();
|
||||
resource_manager.register_texture(texture, base_path.as_ref().join(file_path))?;
|
||||
resource_manager.register(
|
||||
texture.into_inner(),
|
||||
base_path.as_ref().join(file_path),
|
||||
|texture, _| {
|
||||
texture
|
||||
.as_any()
|
||||
.downcast_ref::<Texture>()
|
||||
.unwrap()
|
||||
.save()
|
||||
.is_ok()
|
||||
},
|
||||
)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -707,7 +717,7 @@ fn generate_lightmap(
|
||||
other_instances: &[Instance],
|
||||
lights: &[LightDefinition],
|
||||
texels_per_unit: u32,
|
||||
) -> TextureData {
|
||||
) -> Texture {
|
||||
// We have to re-generate new set of world-space vertices because UV generator
|
||||
// may add new vertices on seams.
|
||||
let atlas_size = estimate_size(instance.data(), texels_per_unit);
|
||||
@@ -895,7 +905,7 @@ fn generate_lightmap(
|
||||
}
|
||||
}
|
||||
|
||||
TextureData::from_bytes(
|
||||
Texture::from_bytes(
|
||||
TextureKind::Rectangle {
|
||||
width: atlas_size,
|
||||
height: atlas_size,
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@ use crate::{
|
||||
draw,
|
||||
message::{ButtonState, KeyCode, KeyboardModifiers, OsEvent},
|
||||
},
|
||||
resource::texture::Texture,
|
||||
resource::texture::TextureResource,
|
||||
};
|
||||
use fyrox_core::algebra::Vector3;
|
||||
use half::f16;
|
||||
@@ -474,8 +474,8 @@ pub fn into_any_arc<T: Any + Send + Sync>(
|
||||
}
|
||||
|
||||
/// Converts engine's optional texture "pointer" to fyrox-ui's.
|
||||
pub fn into_gui_texture(this: Texture) -> draw::SharedTexture {
|
||||
draw::SharedTexture(this.0.into_inner())
|
||||
pub fn into_gui_texture(this: TextureResource) -> draw::SharedTexture {
|
||||
draw::SharedTexture(this.into_inner().0)
|
||||
}
|
||||
|
||||
/// "Transmutes" array of any sized type to a slice of bytes.
|
||||
|
||||
Reference in New Issue
Block a user