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("Sprite 9-Slicing", typeof(Sprite9SlicingBrush)),
|
||||
new OptionType("Video", typeof(VideoBrush)),
|
||||
new OptionType("UI Brush", typeof(UIBrush)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -287,10 +287,7 @@ namespace FlaxEditor.CustomEditors
|
||||
/// <returns>The created element.</returns>
|
||||
public ImageElement Image(SpriteHandle sprite)
|
||||
{
|
||||
var element = new ImageElement();
|
||||
element.Image.Brush = new SpriteBrush(sprite);
|
||||
OnAddElement(element);
|
||||
return element;
|
||||
return Image(new SpriteBrush(sprite));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -300,10 +297,7 @@ namespace FlaxEditor.CustomEditors
|
||||
/// <returns>The created element.</returns>
|
||||
public ImageElement Image(Texture texture)
|
||||
{
|
||||
var element = new ImageElement();
|
||||
element.Image.Brush = new TextureBrush(texture);
|
||||
OnAddElement(element);
|
||||
return element;
|
||||
return Image(new TextureBrush(texture));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -312,9 +306,19 @@ namespace FlaxEditor.CustomEditors
|
||||
/// <param name="texture">The GPU texture.</param>
|
||||
/// <returns>The created element.</returns>
|
||||
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();
|
||||
element.Image.Brush = new GPUTextureBrush(texture);
|
||||
element.Image.Brush = brush;
|
||||
OnAddElement(element);
|
||||
return element;
|
||||
}
|
||||
|
||||
@@ -459,7 +459,7 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
AlternativeTitles = new string[] { "Lightmap TexCoord" },
|
||||
Description = "Lightmap UVs",
|
||||
Flags = NodeFlags.MaterialGraph,
|
||||
Size = new Float2(110, 30),
|
||||
Size = new Float2(110, 20),
|
||||
Elements = new []
|
||||
{
|
||||
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),
|
||||
}
|
||||
},
|
||||
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.Radius = radius;
|
||||
data.Brightness = Brightness;
|
||||
data.SortOrder = SortOrder;
|
||||
data.HashID = GetHash(_id);
|
||||
renderContext.List->EnvironmentProbes.Add(data);
|
||||
}
|
||||
@@ -234,6 +235,7 @@ void EnvironmentProbe::Serialize(SerializeStream& stream, const void* otherObj)
|
||||
SERIALIZE_MEMBER(Radius, _radius);
|
||||
SERIALIZE(CubemapResolution);
|
||||
SERIALIZE(Brightness);
|
||||
SERIALIZE(SortOrder);
|
||||
SERIALIZE(UpdateMode);
|
||||
SERIALIZE(CaptureNearPlane);
|
||||
SERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
|
||||
@@ -248,6 +250,7 @@ void EnvironmentProbe::Deserialize(DeserializeStream& stream, ISerializeModifier
|
||||
DESERIALIZE_MEMBER(Radius, _radius);
|
||||
DESERIALIZE(CubemapResolution);
|
||||
DESERIALIZE(Brightness);
|
||||
DESERIALIZE(SortOrder);
|
||||
DESERIALIZE(UpdateMode);
|
||||
DESERIALIZE(CaptureNearPlane);
|
||||
DESERIALIZE_MEMBER(IsCustomProbe, _isUsingCustomProbe);
|
||||
|
||||
@@ -51,6 +51,12 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(10), Limit(0, 1000, 0.01f), EditorDisplay(\"Probe\")")
|
||||
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>
|
||||
/// The probe update mode.
|
||||
/// </summary>
|
||||
|
||||
@@ -162,6 +162,13 @@ void ParticleEmitterGraphCPUExecutor::ProcessGroupTextures(Box* box, Node* node,
|
||||
value = Value::Zero;
|
||||
break;
|
||||
}
|
||||
// Texture Size
|
||||
case 24:
|
||||
{
|
||||
// TODO: support sampling textures in CPU particles
|
||||
value = Value::Zero;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ bool ParticleEmitterGPUGenerator::loadTexture(Node* caller, Box* box, const Seri
|
||||
Value location = tryGetValue(locationBox, Value::InitForZero(VariantType::Float2));
|
||||
|
||||
// Convert into a proper type
|
||||
if (isCubemap || isVolume || isArray)
|
||||
location = Value::Cast(location, VariantType::Float3);
|
||||
if (isVolume || isArray)
|
||||
location = Value::Cast(location, VariantType::Float4);
|
||||
else
|
||||
location = Value::Cast(location, VariantType::Float3);
|
||||
|
||||
@@ -332,6 +332,21 @@ void ParticleEmitterGPUGenerator::ProcessGroupTextures(Box* box, Node* node, Val
|
||||
value = box == gradientBox ? gradient : distance;
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Core/Types/DataContainer.h"
|
||||
#include "Engine/Graphics/Shaders/Cache/ShaderCacheManager.h"
|
||||
#include "Engine/Graphics/Textures/GPUTexture.h"
|
||||
#include "Engine/Level/Level.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
@@ -58,6 +60,35 @@ ParticleEffect* ParticleEmitter::Spawn(Actor* parent, const Transform& transform
|
||||
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
|
||||
|
||||
namespace
|
||||
@@ -294,6 +325,40 @@ Asset::LoadResult ParticleEmitter::load()
|
||||
SimulationMode = ParticlesSimulationMode::CPU;
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,9 @@ public:
|
||||
/// <returns>The spawned effect.</returns>
|
||||
API_FUNCTION() ParticleEffect* Spawn(Actor* parent, const Transform& transform, float duration = MAX_float, bool autoDestroy = false);
|
||||
|
||||
private:
|
||||
void WaitForAsset(Asset* asset);
|
||||
|
||||
public:
|
||||
// [BinaryAsset]
|
||||
#if USE_EDITOR
|
||||
|
||||
@@ -335,12 +335,17 @@ void ReflectionsPass::Dispose()
|
||||
|
||||
bool SortProbes(RenderEnvironmentProbeData const& p1, RenderEnvironmentProbeData const& p2)
|
||||
{
|
||||
// Compare by radius
|
||||
int32 res = static_cast<int32>(p2.Radius - p1.Radius);
|
||||
// Compare by Sort Order
|
||||
int32 res = p1.SortOrder - p2.SortOrder;
|
||||
if (res == 0)
|
||||
{
|
||||
// Compare by ID to prevent flickering
|
||||
res = p2.HashID - p1.HashID;
|
||||
// Compare by radius
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -155,6 +155,7 @@ struct RenderEnvironmentProbeData
|
||||
Float3 Position;
|
||||
float Radius;
|
||||
float Brightness;
|
||||
int32 SortOrder;
|
||||
uint32 HashID;
|
||||
|
||||
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