Merge remote-tracking branch 'origin/master' into sdl_platform
This commit is contained in:
@@ -26,6 +26,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
|||||||
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
|
new OptionType("Texture 9-Slicing", typeof(Texture9SlicingBrush)),
|
||||||
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
new OptionType("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
||||||
new OptionType("Video", typeof(VideoBrush)),
|
new OptionType("Video", typeof(VideoBrush)),
|
||||||
|
new OptionType("UI Brush", typeof(UIBrush)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -287,10 +287,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// <returns>The created element.</returns>
|
/// <returns>The created element.</returns>
|
||||||
public ImageElement Image(SpriteHandle sprite)
|
public ImageElement Image(SpriteHandle sprite)
|
||||||
{
|
{
|
||||||
var element = new ImageElement();
|
return Image(new SpriteBrush(sprite));
|
||||||
element.Image.Brush = new SpriteBrush(sprite);
|
|
||||||
OnAddElement(element);
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -300,10 +297,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// <returns>The created element.</returns>
|
/// <returns>The created element.</returns>
|
||||||
public ImageElement Image(Texture texture)
|
public ImageElement Image(Texture texture)
|
||||||
{
|
{
|
||||||
var element = new ImageElement();
|
return Image(new TextureBrush(texture));
|
||||||
element.Image.Brush = new TextureBrush(texture);
|
|
||||||
OnAddElement(element);
|
|
||||||
return element;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -312,9 +306,19 @@ namespace FlaxEditor.CustomEditors
|
|||||||
/// <param name="texture">The GPU texture.</param>
|
/// <param name="texture">The GPU texture.</param>
|
||||||
/// <returns>The created element.</returns>
|
/// <returns>The created element.</returns>
|
||||||
public ImageElement Image(GPUTexture texture)
|
public ImageElement Image(GPUTexture texture)
|
||||||
|
{
|
||||||
|
return Image(new GPUTextureBrush(texture));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds brush image to the layout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="brush">The brush.</param>
|
||||||
|
/// <returns>The created element.</returns>
|
||||||
|
public ImageElement Image(IBrush brush)
|
||||||
{
|
{
|
||||||
var element = new ImageElement();
|
var element = new ImageElement();
|
||||||
element.Image.Brush = new GPUTextureBrush(texture);
|
element.Image.Brush = brush;
|
||||||
OnAddElement(element);
|
OnAddElement(element);
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
AlternativeTitles = new string[] { "Lightmap TexCoord" },
|
AlternativeTitles = new string[] { "Lightmap TexCoord" },
|
||||||
Description = "Lightmap UVs",
|
Description = "Lightmap UVs",
|
||||||
Flags = NodeFlags.MaterialGraph,
|
Flags = NodeFlags.MaterialGraph,
|
||||||
Size = new Float2(110, 30),
|
Size = new Float2(110, 20),
|
||||||
Elements = new []
|
Elements = new []
|
||||||
{
|
{
|
||||||
NodeElementArchetype.Factory.Output(0, "UVs", typeof(Float2), 0)
|
NodeElementArchetype.Factory.Output(0, "UVs", typeof(Float2), 0)
|
||||||
@@ -493,6 +493,19 @@ namespace FlaxEditor.Surface.Archetypes
|
|||||||
NodeElementArchetype.Factory.Bool(190, Surface.Constants.LayoutOffsetY * 4, 4),
|
NodeElementArchetype.Factory.Bool(190, Surface.Constants.LayoutOffsetY * 4, 4),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
new NodeArchetype
|
||||||
|
{
|
||||||
|
TypeID = 24,
|
||||||
|
Title = "Texture Size",
|
||||||
|
Description = "Gets the size of the texture (in pixels). If texture is during streaming, then returns size of the highest resident mip.",
|
||||||
|
Flags = NodeFlags.ParticleEmitterGraph,
|
||||||
|
Size = new Float2(160, 20),
|
||||||
|
Elements = new[]
|
||||||
|
{
|
||||||
|
NodeElementArchetype.Factory.Input(0, "Texture", true, typeof(FlaxEngine.Object), 0),
|
||||||
|
NodeElementArchetype.Factory.Output(0, "Size", typeof(Float3), 1),
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ void EnvironmentProbe::Draw(RenderContext& renderContext)
|
|||||||
data.Position = position;
|
data.Position = position;
|
||||||
data.Radius = radius;
|
data.Radius = radius;
|
||||||
data.Brightness = Brightness;
|
data.Brightness = Brightness;
|
||||||
|
data.SortOrder = SortOrder;
|
||||||
data.HashID = GetHash(_id);
|
data.HashID = GetHash(_id);
|
||||||
renderContext.List->EnvironmentProbes.Add(data);
|
renderContext.List->EnvironmentProbes.Add(data);
|
||||||
}
|
}
|
||||||
@@ -234,6 +235,7 @@ void EnvironmentProbe::Serialize(SerializeStream& stream, const void* otherObj)
|
|||||||
SERIALIZE_MEMBER(Radius, _radius);
|
SERIALIZE_MEMBER(Radius, _radius);
|
||||||
SERIALIZE(CubemapResolution);
|
SERIALIZE(CubemapResolution);
|
||||||
SERIALIZE(Brightness);
|
SERIALIZE(Brightness);
|
||||||
|
SERIALIZE(SortOrder);
|
||||||
SERIALIZE(UpdateMode);
|
SERIALIZE(UpdateMode);
|
||||||
SERIALIZE(CaptureNearPlane);
|
SERIALIZE(CaptureNearPlane);
|
||||||
SERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
|
SERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
|
||||||
@@ -248,6 +250,7 @@ void EnvironmentProbe::Deserialize(DeserializeStream& stream, ISerializeModifier
|
|||||||
DESERIALIZE_MEMBER(Radius, _radius);
|
DESERIALIZE_MEMBER(Radius, _radius);
|
||||||
DESERIALIZE(CubemapResolution);
|
DESERIALIZE(CubemapResolution);
|
||||||
DESERIALIZE(Brightness);
|
DESERIALIZE(Brightness);
|
||||||
|
DESERIALIZE(SortOrder);
|
||||||
DESERIALIZE(UpdateMode);
|
DESERIALIZE(UpdateMode);
|
||||||
DESERIALIZE(CaptureNearPlane);
|
DESERIALIZE(CaptureNearPlane);
|
||||||
DESERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
|
DESERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ public:
|
|||||||
API_FIELD(Attributes="EditorOrder(10), Limit(0, 1000, 0.01f), EditorDisplay(\"Probe\")")
|
API_FIELD(Attributes="EditorOrder(10), Limit(0, 1000, 0.01f), EditorDisplay(\"Probe\")")
|
||||||
float Brightness = 1.0f;
|
float Brightness = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The probe rendering order. The higher values are render later (on top).
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes = "EditorOrder(25), EditorDisplay(\"Probe\")")
|
||||||
|
int32 SortOrder = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The probe update mode.
|
/// The probe update mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -162,6 +162,13 @@ void ParticleEmitterGraphCPUExecutor::ProcessGroupTextures(Box* box, Node* node,
|
|||||||
value = Value::Zero;
|
value = Value::Zero;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Texture Size
|
||||||
|
case 24:
|
||||||
|
{
|
||||||
|
// TODO: support sampling textures in CPU particles
|
||||||
|
value = Value::Zero;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ bool ParticleEmitterGPUGenerator::loadTexture(Node* caller, Box* box, const Seri
|
|||||||
Value location = tryGetValue(locationBox, Value::InitForZero(VariantType::Float2));
|
Value location = tryGetValue(locationBox, Value::InitForZero(VariantType::Float2));
|
||||||
|
|
||||||
// Convert into a proper type
|
// Convert into a proper type
|
||||||
if (isCubemap || isVolume || isArray)
|
if (isVolume || isArray)
|
||||||
location = Value::Cast(location, VariantType::Float3);
|
location = Value::Cast(location, VariantType::Float4);
|
||||||
else
|
else
|
||||||
location = Value::Cast(location, VariantType::Float3);
|
location = Value::Cast(location, VariantType::Float3);
|
||||||
|
|
||||||
@@ -332,6 +332,21 @@ void ParticleEmitterGPUGenerator::ProcessGroupTextures(Box* box, Node* node, Val
|
|||||||
value = box == gradientBox ? gradient : distance;
|
value = box == gradientBox ? gradient : distance;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// Texture Size
|
||||||
|
case 24:
|
||||||
|
{
|
||||||
|
value = Value::Zero;
|
||||||
|
auto textureBox = node->GetBox(0);
|
||||||
|
if (!textureBox->HasConnection())
|
||||||
|
break;
|
||||||
|
const auto texture = eatBox(textureBox->GetParent<Node>(), textureBox->FirstConnection());
|
||||||
|
const auto textureParam = findParam(texture.Value);
|
||||||
|
if (!textureParam)
|
||||||
|
break;
|
||||||
|
value = writeLocal(VariantType::Float2, node);
|
||||||
|
_writer.Write(TEXT("\t{0}.GetDimensions({1}.x, {1}.y);\n"), textureParam->ShaderName, value.Value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
#include "Engine/Core/Log.h"
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Core/Types/DataContainer.h"
|
#include "Engine/Core/Types/DataContainer.h"
|
||||||
#include "Engine/Graphics/Shaders/Cache/ShaderCacheManager.h"
|
#include "Engine/Graphics/Shaders/Cache/ShaderCacheManager.h"
|
||||||
|
#include "Engine/Graphics/Textures/GPUTexture.h"
|
||||||
#include "Engine/Level/Level.h"
|
#include "Engine/Level/Level.h"
|
||||||
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "Engine/Serialization/MemoryReadStream.h"
|
#include "Engine/Serialization/MemoryReadStream.h"
|
||||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
@@ -58,6 +60,35 @@ ParticleEffect* ParticleEmitter::Spawn(Actor* parent, const Transform& transform
|
|||||||
return effect;
|
return effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParticleEmitter::WaitForAsset(Asset* asset)
|
||||||
|
{
|
||||||
|
// TODO: make a tool for it?
|
||||||
|
if (auto* texture = Cast<TextureBase>(asset))
|
||||||
|
{
|
||||||
|
// Wait for asset to be loaded
|
||||||
|
if (!texture->WaitForLoaded() && !IsInMainThread() && texture->GetTexture())
|
||||||
|
{
|
||||||
|
PROFILE_CPU_NAMED("WaitForTexture");
|
||||||
|
|
||||||
|
// Mark as used by rendering and wait for streaming to load it in
|
||||||
|
double waitTimeSeconds = 10000;
|
||||||
|
double now = Platform::GetTimeSeconds();
|
||||||
|
double end = now + waitTimeSeconds;
|
||||||
|
const int32 mipLevels = texture->GetMipLevels();
|
||||||
|
constexpr float requestedResidency = 0.7f;
|
||||||
|
const int32 minMipLevels = Math::Max(Math::Min(mipLevels, 7), (int32)(requestedResidency * (float)mipLevels));
|
||||||
|
while (texture->GetResidentMipLevels() < minMipLevels &&
|
||||||
|
now < end &&
|
||||||
|
!texture->HasStreamingError())
|
||||||
|
{
|
||||||
|
texture->GetTexture()->LastRenderTime = now;
|
||||||
|
Platform::Sleep(1);
|
||||||
|
now = Platform::GetTimeSeconds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if COMPILE_WITH_PARTICLE_GPU_GRAPH && COMPILE_WITH_SHADER_COMPILER
|
#if COMPILE_WITH_PARTICLE_GPU_GRAPH && COMPILE_WITH_SHADER_COMPILER
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -294,6 +325,40 @@ Asset::LoadResult ParticleEmitter::load()
|
|||||||
SimulationMode = ParticlesSimulationMode::CPU;
|
SimulationMode = ParticlesSimulationMode::CPU;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Wait for resources used by the emitter to be loaded
|
||||||
|
// eg. texture used to place particles on spawn needs to be available
|
||||||
|
bool waitForAsset = false;
|
||||||
|
for (const auto& node : Graph.Nodes)
|
||||||
|
{
|
||||||
|
if ((node.Type == GRAPH_NODE_MAKE_TYPE(5, 1) || node.Type == GRAPH_NODE_MAKE_TYPE(5, 2)) && node.Assets.Count() > 0)
|
||||||
|
{
|
||||||
|
const auto texture = node.Assets[0].As<TextureBase>();
|
||||||
|
if (texture)
|
||||||
|
{
|
||||||
|
if (!waitForAsset)
|
||||||
|
{
|
||||||
|
waitForAsset = true;
|
||||||
|
Particles::SystemLocker.End(true);
|
||||||
|
}
|
||||||
|
WaitForAsset(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto& parameter : Graph.Parameters)
|
||||||
|
{
|
||||||
|
if (parameter.Type.Type == VariantType::Asset)
|
||||||
|
{
|
||||||
|
if (!waitForAsset)
|
||||||
|
{
|
||||||
|
waitForAsset = true;
|
||||||
|
Particles::SystemLocker.End(true);
|
||||||
|
}
|
||||||
|
WaitForAsset((Asset*)parameter.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (waitForAsset)
|
||||||
|
Particles::SystemLocker.Begin(true);
|
||||||
|
|
||||||
return LoadResult::Ok;
|
return LoadResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,6 +168,9 @@ public:
|
|||||||
/// <returns>The spawned effect.</returns>
|
/// <returns>The spawned effect.</returns>
|
||||||
API_FUNCTION() ParticleEffect* Spawn(Actor* parent, const Transform& transform, float duration = MAX_float, bool autoDestroy = false);
|
API_FUNCTION() ParticleEffect* Spawn(Actor* parent, const Transform& transform, float duration = MAX_float, bool autoDestroy = false);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void WaitForAsset(Asset* asset);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// [BinaryAsset]
|
// [BinaryAsset]
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
|
|||||||
@@ -335,12 +335,17 @@ void ReflectionsPass::Dispose()
|
|||||||
|
|
||||||
bool SortProbes(RenderEnvironmentProbeData const& p1, RenderEnvironmentProbeData const& p2)
|
bool SortProbes(RenderEnvironmentProbeData const& p1, RenderEnvironmentProbeData const& p2)
|
||||||
{
|
{
|
||||||
// Compare by radius
|
// Compare by Sort Order
|
||||||
int32 res = static_cast<int32>(p2.Radius - p1.Radius);
|
int32 res = p1.SortOrder - p2.SortOrder;
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
// Compare by ID to prevent flickering
|
// Compare by radius
|
||||||
res = p2.HashID - p1.HashID;
|
res = static_cast<int32>(p2.Radius - p1.Radius);
|
||||||
|
if (res == 0)
|
||||||
|
{
|
||||||
|
// Compare by ID to prevent flickering
|
||||||
|
res = p2.HashID - p1.HashID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res < 0;
|
return res < 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ struct RenderEnvironmentProbeData
|
|||||||
Float3 Position;
|
Float3 Position;
|
||||||
float Radius;
|
float Radius;
|
||||||
float Brightness;
|
float Brightness;
|
||||||
|
int32 SortOrder;
|
||||||
uint32 HashID;
|
uint32 HashID;
|
||||||
|
|
||||||
void SetShaderData(ShaderEnvProbeData& data) const;
|
void SetShaderData(ShaderEnvProbeData& data) const;
|
||||||
|
|||||||
75
Source/Engine/UI/GUI/Brushes/UIBrush.cs
Normal file
75
Source/Engine/UI/GUI/Brushes/UIBrush.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
namespace FlaxEngine.GUI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Asset with <see cref="IBrush"/> that can be reused in different UI controls.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IBrush" />
|
||||||
|
/// <seealso cref="UIBrush" />
|
||||||
|
public class UIBrushAsset
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Brush object.
|
||||||
|
/// </summary>
|
||||||
|
public IBrush Brush;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of <see cref="IBrush"/> for <see cref="FlaxEngine.VideoPlayer"/> frame displaying.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IBrush" />
|
||||||
|
/// <seealso cref="UIBrushAsset" />
|
||||||
|
public sealed class UIBrush : IBrush
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The UI Brush asset to use.
|
||||||
|
/// </summary>
|
||||||
|
public JsonAssetReference<UIBrushAsset> Asset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UIBrush"/> class.
|
||||||
|
/// </summary>
|
||||||
|
public UIBrush()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UIBrush"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">The UI Brush asset to use.</param>
|
||||||
|
public UIBrush(JsonAssetReference<UIBrushAsset> asset)
|
||||||
|
{
|
||||||
|
Asset = asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UIBrush"/> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="asset">The UI Brush asset to use.</param>
|
||||||
|
public UIBrush(JsonAsset asset)
|
||||||
|
{
|
||||||
|
Asset = asset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public Float2 Size
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var asset = (UIBrushAsset)Asset.Asset?.Instance;
|
||||||
|
if (asset != null && asset.Brush != null)
|
||||||
|
return asset.Brush.Size;
|
||||||
|
return Float2.Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Draw(Rectangle rect, Color color)
|
||||||
|
{
|
||||||
|
var asset = (UIBrushAsset)Asset.Asset?.Instance;
|
||||||
|
if (asset != null && asset.Brush != null)
|
||||||
|
asset.Brush.Draw(rect, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user