Merge branch 'master' into 1.5
This commit is contained in:
@@ -18,6 +18,7 @@ float TimeParam;
|
|||||||
float4 ViewInfo;
|
float4 ViewInfo;
|
||||||
float4 ScreenSize;
|
float4 ScreenSize;
|
||||||
float4 TemporalAAJitter;
|
float4 TemporalAAJitter;
|
||||||
|
float4x4 InverseViewProjectionMatrix;
|
||||||
@1META_CB_END
|
@1META_CB_END
|
||||||
|
|
||||||
// Shader resources
|
// Shader resources
|
||||||
@@ -62,6 +63,14 @@ MaterialInput GetMaterialInput(PixelInput input)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets world space position at given pixel coordinate with given device depth
|
||||||
|
float3 GetWorldPos(float2 uv, float deviceDepth)
|
||||||
|
{
|
||||||
|
float4 clipPos = float4(uv * float2(2.0, -2.0) + float2(-1.0, 1.0), deviceDepth, 1.0);
|
||||||
|
float4 wsPos = mul(clipPos, InverseViewProjectionMatrix);
|
||||||
|
return wsPos.xyz / wsPos.w;
|
||||||
|
}
|
||||||
|
|
||||||
// Transforms a vector from tangent space to world space
|
// Transforms a vector from tangent space to world space
|
||||||
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
|
float3 TransformTangentVectorToWorld(MaterialInput input, float3 tangentVector)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer
|
|||||||
goto End
|
goto End
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
for /f "delims=" %%i in ('"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere" -latest -prerelease -products * -requires Microsoft.Component.MSBuild -property installationPath') do (
|
||||||
|
if exist "%%i\MSBuild\15.0\Bin\MSBuild.exe" (
|
||||||
|
set MSBUILD_PATH="%%i\MSBuild\15.0\Bin\MSBuild.exe"
|
||||||
|
goto End
|
||||||
|
)
|
||||||
|
if exist "%%i\MSBuild\Current\Bin\MSBuild.exe" (
|
||||||
|
set MSBUILD_PATH="%%i\MSBuild\Current\Bin\MSBuild.exe"
|
||||||
|
goto End
|
||||||
|
)
|
||||||
|
)
|
||||||
:VsWhereNotFound
|
:VsWhereNotFound
|
||||||
|
|
||||||
if exist "%ProgramFiles(x86)%\MSBuild\14.0\bin\MSBuild.exe" (
|
if exist "%ProgramFiles(x86)%\MSBuild\14.0\bin\MSBuild.exe" (
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="AnimationGraphFunction"/> asset proxy object.
|
/// A <see cref="AnimationGraphFunction"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Animation/Animation Graph Function")]
|
||||||
public class AnimationGraphFunctionProxy : BinaryAssetProxy
|
public class AnimationGraphFunctionProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="AnimationGraph"/> asset proxy object.
|
/// A <see cref="AnimationGraph"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Animation/Animation Graph")]
|
||||||
public class AnimationGraphProxy : BinaryAssetProxy
|
public class AnimationGraphProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="Animation"/> asset proxy object.
|
/// A <see cref="Animation"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Animation/Animation")]
|
||||||
public class AnimationProxy : BinaryAssetProxy
|
public class AnimationProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Context proxy object for C# script files.
|
/// Context proxy object for C# script files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
||||||
|
[ContentContextMenu("New/C# Script")]
|
||||||
public class CSharpScriptProxy : ScriptProxy
|
public class CSharpScriptProxy : ScriptProxy
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="CollisionData"/> asset proxy object.
|
/// A <see cref="CollisionData"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Physics/Collision Data")]
|
||||||
class CollisionDataProxy : BinaryAssetProxy
|
class CollisionDataProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Context proxy object for C++ script files.
|
/// Context proxy object for C++ script files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
||||||
|
[ContentContextMenu("New/C++/C++ Script")]
|
||||||
public class CppScriptProxy : CppProxy
|
public class CppScriptProxy : CppProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -98,6 +99,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Context proxy object for C++ Json Asset files.
|
/// Context proxy object for C++ Json Asset files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
||||||
|
[ContentContextMenu("New/C++/C++ Function Library")]
|
||||||
public class CppStaticClassProxy : CppProxy
|
public class CppStaticClassProxy : CppProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -115,6 +117,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Context proxy object for C++ Json Asset files.
|
/// Context proxy object for C++ Json Asset files.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
/// <seealso cref="FlaxEditor.Content.CSharpScriptProxy" />
|
||||||
|
[ContentContextMenu("New/C++/C++ Json Asset")]
|
||||||
public class CppAssetProxy : CppProxy
|
public class CppAssetProxy : CppProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="GameplayGlobals"/> asset proxy object.
|
/// A <see cref="GameplayGlobals"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Gameplay Globals")]
|
||||||
public class GameplayGlobalsProxy : BinaryAssetProxy
|
public class GameplayGlobalsProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Json assets proxy.
|
/// Json assets proxy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
||||||
|
[ContentContextMenu("New/Json Asset")]
|
||||||
public abstract class JsonAssetProxy : JsonAssetBaseProxy
|
public abstract class JsonAssetProxy : JsonAssetBaseProxy
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="MaterialFunction"/> asset proxy object.
|
/// A <see cref="MaterialFunction"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Material/Material Function")]
|
||||||
public class MaterialFunctionProxy : BinaryAssetProxy
|
public class MaterialFunctionProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="MaterialInstance"/> asset proxy object.
|
/// A <see cref="MaterialInstance"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Material/Material Instance")]
|
||||||
public class MaterialInstanceProxy : BinaryAssetProxy
|
public class MaterialInstanceProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
private MaterialPreview _preview;
|
private MaterialPreview _preview;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="Material"/> asset proxy object.
|
/// A <see cref="Material"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Material/Material")]
|
||||||
public class MaterialProxy : BinaryAssetProxy
|
public class MaterialProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
private MaterialPreview _preview;
|
private MaterialPreview _preview;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="ParticleEmitterFunction"/> asset proxy object.
|
/// A <see cref="ParticleEmitterFunction"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Particles/Particle Emitter Function")]
|
||||||
public class ParticleEmitterFunctionProxy : BinaryAssetProxy
|
public class ParticleEmitterFunctionProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="ParticleEmitter"/> asset proxy object.
|
/// A <see cref="ParticleEmitter"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Particles/Particle Emitter")]
|
||||||
public class ParticleEmitterProxy : BinaryAssetProxy
|
public class ParticleEmitterProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
private ParticleEmitterPreview _preview;
|
private ParticleEmitterPreview _preview;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="ParticleSystem"/> asset proxy object.
|
/// A <see cref="ParticleSystem"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Particles/Particle System")]
|
||||||
public class ParticleSystemProxy : BinaryAssetProxy
|
public class ParticleSystemProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
private ParticleSystemPreview _preview;
|
private ParticleSystemPreview _preview;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Content proxy for <see cref="PrefabItem"/>.
|
/// Content proxy for <see cref="PrefabItem"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
||||||
|
[ContentContextMenu("New/Prefab")]
|
||||||
public sealed class PrefabProxy : JsonAssetBaseProxy
|
public sealed class PrefabProxy : JsonAssetBaseProxy
|
||||||
{
|
{
|
||||||
private PrefabPreview _preview;
|
private PrefabPreview _preview;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Content proxy for <see cref="SceneItem"/>.
|
/// Content proxy for <see cref="SceneItem"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetBaseProxy" />
|
||||||
|
[ContentContextMenu("New/Scene")]
|
||||||
public sealed class SceneProxy : JsonAssetBaseProxy
|
public sealed class SceneProxy : JsonAssetBaseProxy
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Content proxy for json settings assets (e.g <see cref="GameSettings"/> or <see cref="TimeSettings"/>).
|
/// Content proxy for json settings assets (e.g <see cref="GameSettings"/> or <see cref="TimeSettings"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.JsonAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.JsonAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Settings")]
|
||||||
public class SettingsProxy : JsonAssetProxy
|
public class SettingsProxy : JsonAssetProxy
|
||||||
{
|
{
|
||||||
private readonly Type _type;
|
private readonly Type _type;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace FlaxEditor.Content
|
|||||||
/// Context proxy object for shader source files (represented by <see cref="ShaderSourceItem"/>).
|
/// Context proxy object for shader source files (represented by <see cref="ShaderSourceItem"/>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
|
/// <seealso cref="FlaxEditor.Content.ContentProxy" />
|
||||||
|
[ContentContextMenu("New/Shader Source")]
|
||||||
public class ShaderSourceProxy : ContentProxy
|
public class ShaderSourceProxy : ContentProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="SkeletonMask"/> asset proxy object.
|
/// A <see cref="SkeletonMask"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Animation/Skeleton Mask")]
|
||||||
public class SkeletonMaskProxy : BinaryAssetProxy
|
public class SkeletonMaskProxy : BinaryAssetProxy
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ namespace FlaxEditor.Content
|
|||||||
/// A <see cref="VisualScript"/> asset proxy object.
|
/// A <see cref="VisualScript"/> asset proxy object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
/// <seealso cref="FlaxEditor.Content.BinaryAssetProxy" />
|
||||||
|
[ContentContextMenu("New/Visual Script")]
|
||||||
public class VisualScriptProxy : BinaryAssetProxy, IScriptTypesContainer
|
public class VisualScriptProxy : BinaryAssetProxy, IScriptTypesContainer
|
||||||
{
|
{
|
||||||
internal VisualScriptProxy()
|
internal VisualScriptProxy()
|
||||||
|
|||||||
@@ -94,6 +94,12 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
|||||||
}
|
}
|
||||||
Refresh();
|
Refresh();
|
||||||
var parameters = effect.Parameters;
|
var parameters = effect.Parameters;
|
||||||
|
if (parameters.Length == 0)
|
||||||
|
{
|
||||||
|
base.RefreshRootChild();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < ChildrenEditors.Count; i++)
|
for (int i = 0; i < ChildrenEditors.Count; i++)
|
||||||
{
|
{
|
||||||
if (_isActive != effect.IsActive || _parametersVersion != effect.ParametersVersion)
|
if (_isActive != effect.IsActive || _parametersVersion != effect.ParametersVersion)
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
|
|
||||||
// Hide cursor and cache location
|
// Hide cursor and cache location
|
||||||
Cursor = CursorType.Hidden;
|
Cursor = CursorType.Hidden;
|
||||||
_mouseClickedPosition = location;
|
_mouseClickedPosition = PointToWindow(location);
|
||||||
_cursorChanged = true;
|
_cursorChanged = true;
|
||||||
|
|
||||||
SlidingStart?.Invoke();
|
SlidingStart?.Invoke();
|
||||||
@@ -293,7 +293,7 @@ namespace FlaxEditor.GUI.Input
|
|||||||
if (button == MouseButton.Left && _isSliding)
|
if (button == MouseButton.Left && _isSliding)
|
||||||
{
|
{
|
||||||
// End sliding and return mouse to original location
|
// End sliding and return mouse to original location
|
||||||
Root.MousePosition = ScreenPos + _mouseClickedPosition;
|
RootWindow.MousePosition = _mouseClickedPosition;
|
||||||
EndSliding();
|
EndSliding();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing
|
|||||||
_list.Clear();
|
_list.Clear();
|
||||||
_hasValidData = true;
|
_hasValidData = true;
|
||||||
|
|
||||||
Editor.Log("Searching for valid " + _type);
|
Editor.Log("Searching for valid " + (_type != ScriptType.Null ? _type.ToString() : "types"));
|
||||||
Profiler.BeginEvent("Search " + _type);
|
Profiler.BeginEvent("Search " + _type);
|
||||||
var start = DateTime.Now;
|
var start = DateTime.Now;
|
||||||
|
|
||||||
|
|||||||
@@ -738,9 +738,10 @@ namespace FlaxEditor.Utilities
|
|||||||
|
|
||||||
var settings = CreateWindowSettings.Default;
|
var settings = CreateWindowSettings.Default;
|
||||||
settings.ActivateWhenFirstShown = true;
|
settings.ActivateWhenFirstShown = true;
|
||||||
settings.AllowMaximize = false;
|
settings.AllowMaximize = true;
|
||||||
settings.AllowMinimize = false;
|
settings.AllowMinimize = false;
|
||||||
settings.HasSizingFrame = false;
|
settings.HasSizingFrame = true;
|
||||||
|
settings.HasBorder = true;
|
||||||
settings.StartPosition = WindowStartPosition.CenterParent;
|
settings.StartPosition = WindowStartPosition.CenterParent;
|
||||||
settings.Size = new Float2(500, 600) * (parentWindow?.DpiScale ?? Platform.DpiScale);
|
settings.Size = new Float2(500, 600) * (parentWindow?.DpiScale ?? Platform.DpiScale);
|
||||||
settings.Parent = parentWindow;
|
settings.Parent = parentWindow;
|
||||||
@@ -754,10 +755,25 @@ namespace FlaxEditor.Utilities
|
|||||||
};
|
};
|
||||||
copyButton.Clicked += () => Clipboard.Text = source;
|
copyButton.Clicked += () => Clipboard.Text = source;
|
||||||
|
|
||||||
var sourceTextBox = new TextBox(true, 2, copyButton.Bottom + 4, settings.Size.X - 4);
|
var backPanel = new Panel
|
||||||
sourceTextBox.Height = settings.Size.Y - sourceTextBox.Top - 2;
|
{
|
||||||
|
AnchorPreset = AnchorPresets.StretchAll,
|
||||||
|
Offsets = new Margin(0, 0, copyButton.Bottom + 4, 0),
|
||||||
|
ScrollBars = ScrollBars.Both,
|
||||||
|
IsScrollable = true,
|
||||||
|
Parent = dialog.GUI,
|
||||||
|
};
|
||||||
|
|
||||||
|
var sourceTextBox = new TextBox(true, 0, 0, 0);
|
||||||
|
sourceTextBox.Parent = backPanel;
|
||||||
|
sourceTextBox.AnchorPreset = AnchorPresets.HorizontalStretchTop;
|
||||||
sourceTextBox.Text = source;
|
sourceTextBox.Text = source;
|
||||||
sourceTextBox.Parent = dialog.GUI;
|
sourceTextBox.Height = sourceTextBox.TextSize.Y;
|
||||||
|
sourceTextBox.IsReadOnly = true;
|
||||||
|
sourceTextBox.IsMultilineScrollable = false;
|
||||||
|
sourceTextBox.IsScrollable = true;
|
||||||
|
|
||||||
|
backPanel.SizeChanged += control => { sourceTextBox.Width = (control.Size.X >= sourceTextBox.TextSize.X) ? control.Width : sourceTextBox.TextSize.X + 30; };
|
||||||
|
|
||||||
dialog.Show();
|
dialog.Show();
|
||||||
dialog.Focus();
|
dialog.Focus();
|
||||||
|
|||||||
@@ -539,6 +539,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Orthographic
|
// Orthographic
|
||||||
{
|
{
|
||||||
var ortho = ViewWidgetButtonMenu.AddButton("Orthographic");
|
var ortho = ViewWidgetButtonMenu.AddButton("Orthographic");
|
||||||
|
ortho.CloseMenuOnClick = false;
|
||||||
var orthoValue = new CheckBox(90, 2, _isOrtho)
|
var orthoValue = new CheckBox(90, 2, _isOrtho)
|
||||||
{
|
{
|
||||||
Parent = ortho
|
Parent = ortho
|
||||||
@@ -578,6 +579,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Field of View
|
// Field of View
|
||||||
{
|
{
|
||||||
var fov = ViewWidgetButtonMenu.AddButton("Field Of View");
|
var fov = ViewWidgetButtonMenu.AddButton("Field Of View");
|
||||||
|
fov.CloseMenuOnClick = false;
|
||||||
var fovValue = new FloatValueBox(1, 90, 2, 70.0f, 35.0f, 160.0f, 0.1f)
|
var fovValue = new FloatValueBox(1, 90, 2, 70.0f, 35.0f, 160.0f, 0.1f)
|
||||||
{
|
{
|
||||||
Parent = fov
|
Parent = fov
|
||||||
@@ -594,6 +596,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Ortho Scale
|
// Ortho Scale
|
||||||
{
|
{
|
||||||
var orthoSize = ViewWidgetButtonMenu.AddButton("Ortho Scale");
|
var orthoSize = ViewWidgetButtonMenu.AddButton("Ortho Scale");
|
||||||
|
orthoSize.CloseMenuOnClick = false;
|
||||||
var orthoSizeValue = new FloatValueBox(_orthoSize, 90, 2, 70.0f, 0.001f, 100000.0f, 0.01f)
|
var orthoSizeValue = new FloatValueBox(_orthoSize, 90, 2, 70.0f, 0.001f, 100000.0f, 0.01f)
|
||||||
{
|
{
|
||||||
Parent = orthoSize
|
Parent = orthoSize
|
||||||
@@ -610,6 +613,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Near Plane
|
// Near Plane
|
||||||
{
|
{
|
||||||
var nearPlane = ViewWidgetButtonMenu.AddButton("Near Plane");
|
var nearPlane = ViewWidgetButtonMenu.AddButton("Near Plane");
|
||||||
|
nearPlane.CloseMenuOnClick = false;
|
||||||
var nearPlaneValue = new FloatValueBox(2.0f, 90, 2, 70.0f, 0.001f, 1000.0f)
|
var nearPlaneValue = new FloatValueBox(2.0f, 90, 2, 70.0f, 0.001f, 1000.0f)
|
||||||
{
|
{
|
||||||
Parent = nearPlane
|
Parent = nearPlane
|
||||||
@@ -621,6 +625,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Far Plane
|
// Far Plane
|
||||||
{
|
{
|
||||||
var farPlane = ViewWidgetButtonMenu.AddButton("Far Plane");
|
var farPlane = ViewWidgetButtonMenu.AddButton("Far Plane");
|
||||||
|
farPlane.CloseMenuOnClick = false;
|
||||||
var farPlaneValue = new FloatValueBox(1000, 90, 2, 70.0f, 10.0f)
|
var farPlaneValue = new FloatValueBox(1000, 90, 2, 70.0f, 10.0f)
|
||||||
{
|
{
|
||||||
Parent = farPlane
|
Parent = farPlane
|
||||||
@@ -632,6 +637,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Brightness
|
// Brightness
|
||||||
{
|
{
|
||||||
var brightness = ViewWidgetButtonMenu.AddButton("Brightness");
|
var brightness = ViewWidgetButtonMenu.AddButton("Brightness");
|
||||||
|
brightness.CloseMenuOnClick = false;
|
||||||
var brightnessValue = new FloatValueBox(1.0f, 90, 2, 70.0f, 0.001f, 10.0f, 0.001f)
|
var brightnessValue = new FloatValueBox(1.0f, 90, 2, 70.0f, 0.001f, 10.0f, 0.001f)
|
||||||
{
|
{
|
||||||
Parent = brightness
|
Parent = brightness
|
||||||
@@ -643,6 +649,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Resolution
|
// Resolution
|
||||||
{
|
{
|
||||||
var resolution = ViewWidgetButtonMenu.AddButton("Resolution");
|
var resolution = ViewWidgetButtonMenu.AddButton("Resolution");
|
||||||
|
resolution.CloseMenuOnClick = false;
|
||||||
var resolutionValue = new FloatValueBox(1.0f, 90, 2, 70.0f, 0.1f, 4.0f, 0.001f)
|
var resolutionValue = new FloatValueBox(1.0f, 90, 2, 70.0f, 0.1f, 4.0f, 0.001f)
|
||||||
{
|
{
|
||||||
Parent = resolution
|
Parent = resolution
|
||||||
@@ -654,6 +661,7 @@ namespace FlaxEditor.Viewport
|
|||||||
// Invert Panning
|
// Invert Panning
|
||||||
{
|
{
|
||||||
var invert = ViewWidgetButtonMenu.AddButton("Invert Panning");
|
var invert = ViewWidgetButtonMenu.AddButton("Invert Panning");
|
||||||
|
invert.CloseMenuOnClick = false;
|
||||||
var invertValue = new CheckBox(90, 2, _invertPanning)
|
var invertValue = new CheckBox(90, 2, _invertPanning)
|
||||||
{
|
{
|
||||||
Parent = invert
|
Parent = invert
|
||||||
|
|||||||
@@ -263,21 +263,22 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
}
|
}
|
||||||
if (attribute == null)
|
if (attribute == null)
|
||||||
continue;
|
continue;
|
||||||
var splitPath = attribute.Path.Split('/');
|
var parts = attribute.Path.Split('/');
|
||||||
ContextMenuChildMenu childCM = null;
|
ContextMenuChildMenu childCM = null;
|
||||||
bool mainCM = true;
|
bool mainCM = true;
|
||||||
for (int i = 0; i < splitPath?.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
{
|
{
|
||||||
if (i == splitPath.Length - 1)
|
var part = parts[i].Trim();
|
||||||
|
if (i == parts.Length - 1)
|
||||||
{
|
{
|
||||||
if (mainCM)
|
if (mainCM)
|
||||||
{
|
{
|
||||||
contextMenu.AddButton(splitPath[i].Trim(), () => Spawn(actorType.Type));
|
contextMenu.AddButton(part, () => Spawn(actorType.Type));
|
||||||
mainCM = false;
|
mainCM = false;
|
||||||
}
|
}
|
||||||
else
|
else if (childCM != null)
|
||||||
{
|
{
|
||||||
childCM?.ContextMenu.AddButton(splitPath[i].Trim(), () => Spawn(actorType.Type));
|
childCM.ContextMenu.AddButton(part, () => Spawn(actorType.Type));
|
||||||
childCM.ContextMenu.AutoSort = true;
|
childCM.ContextMenu.AutoSort = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,17 +286,18 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
{
|
{
|
||||||
if (mainCM)
|
if (mainCM)
|
||||||
{
|
{
|
||||||
childCM = contextMenu.GetOrAddChildMenu(splitPath[i].Trim());
|
childCM = contextMenu.GetOrAddChildMenu(part);
|
||||||
|
childCM.ContextMenu.AutoSort = true;
|
||||||
mainCM = false;
|
mainCM = false;
|
||||||
}
|
}
|
||||||
else
|
else if (childCM != null)
|
||||||
{
|
{
|
||||||
childCM = childCM?.ContextMenu.GetOrAddChildMenu(splitPath[i].Trim());
|
childCM = childCM.ContextMenu.GetOrAddChildMenu(part);
|
||||||
}
|
|
||||||
childCM.ContextMenu.AutoSort = true;
|
childCM.ContextMenu.AutoSort = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Custom options
|
// Custom options
|
||||||
bool showCustomNodeOptions = Editor.SceneEditing.Selection.Count == 1;
|
bool showCustomNodeOptions = Editor.SceneEditing.Selection.Count == 1;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using FlaxEditor.Content;
|
using FlaxEditor.Content;
|
||||||
using FlaxEditor.GUI.ContextMenu;
|
using FlaxEditor.GUI.ContextMenu;
|
||||||
|
using FlaxEditor.Scripting;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.Assertions;
|
using FlaxEngine.Assertions;
|
||||||
using FlaxEngine.Json;
|
using FlaxEngine.Json;
|
||||||
@@ -39,7 +40,6 @@ namespace FlaxEditor.Windows
|
|||||||
|
|
||||||
// Create context menu
|
// Create context menu
|
||||||
ContextMenuButton b;
|
ContextMenuButton b;
|
||||||
ContextMenuChildMenu c;
|
|
||||||
ContextMenu cm = new ContextMenu
|
ContextMenu cm = new ContextMenu
|
||||||
{
|
{
|
||||||
Tag = item
|
Tag = item
|
||||||
@@ -150,20 +150,83 @@ namespace FlaxEditor.Windows
|
|||||||
cm.AddButton("New folder", NewFolder);
|
cm.AddButton("New folder", NewFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
c = cm.AddChildMenu("New");
|
// Loop through each proxy and user defined json type and add them to the context menu
|
||||||
c.ContextMenu.Tag = item;
|
var actorType = new ScriptType(typeof(Actor));
|
||||||
c.ContextMenu.AutoSort = true;
|
var scriptType = new ScriptType(typeof(Script));
|
||||||
int newItems = 0;
|
foreach (var type in Editor.CodeEditing.All.Get())
|
||||||
for (int i = 0; i < Editor.ContentDatabase.Proxy.Count; i++)
|
|
||||||
{
|
{
|
||||||
var p = Editor.ContentDatabase.Proxy[i];
|
if (type.IsAbstract)
|
||||||
|
continue;
|
||||||
|
if (actorType.IsAssignableFrom(type) || scriptType.IsAssignableFrom(type))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get attribute
|
||||||
|
ContentContextMenuAttribute attribute = null;
|
||||||
|
foreach (var typeAttribute in type.GetAttributes(true))
|
||||||
|
{
|
||||||
|
if (typeAttribute is ContentContextMenuAttribute contentContextMenuAttribute)
|
||||||
|
{
|
||||||
|
attribute = contentContextMenuAttribute;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (attribute == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Get context proxy
|
||||||
|
ContentProxy p;
|
||||||
|
if (type.Type.IsSubclassOf(typeof(ContentProxy)))
|
||||||
|
{
|
||||||
|
p = Editor.ContentDatabase.Proxy.Find(x => x.GetType() == type.Type);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// User can use attribute to put their own assets into the content context menu
|
||||||
|
var generic = typeof(SpawnableJsonAssetProxy<>).MakeGenericType(type.Type);
|
||||||
|
var instance = Activator.CreateInstance(generic);
|
||||||
|
p = instance as AssetProxy;
|
||||||
|
}
|
||||||
|
if (p == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (p.CanCreate(folder))
|
if (p.CanCreate(folder))
|
||||||
{
|
{
|
||||||
c.ContextMenu.AddButton(p.Name, () => NewItem(p));
|
var parts = attribute.Path.Split('/');
|
||||||
newItems++;
|
ContextMenuChildMenu childCM = null;
|
||||||
|
bool mainCM = true;
|
||||||
|
for (int i = 0; i < parts?.Length; i++)
|
||||||
|
{
|
||||||
|
var part = parts[i].Trim();
|
||||||
|
if (i == parts.Length - 1)
|
||||||
|
{
|
||||||
|
if (mainCM)
|
||||||
|
{
|
||||||
|
cm.AddButton(part, () => NewItem(p));
|
||||||
|
mainCM = false;
|
||||||
|
}
|
||||||
|
else if (childCM != null)
|
||||||
|
{
|
||||||
|
childCM.ContextMenu.AddButton(part, () => NewItem(p));
|
||||||
|
childCM.ContextMenu.AutoSort = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (mainCM)
|
||||||
|
{
|
||||||
|
childCM = cm.GetOrAddChildMenu(part);
|
||||||
|
childCM.ContextMenu.AutoSort = true;
|
||||||
|
mainCM = false;
|
||||||
|
}
|
||||||
|
else if (childCM != null)
|
||||||
|
{
|
||||||
|
childCM = childCM.ContextMenu.GetOrAddChildMenu(part);
|
||||||
|
childCM.ContextMenu.AutoSort = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Enabled = newItems > 0;
|
|
||||||
|
|
||||||
if (folder.CanHaveAssets)
|
if (folder.CanHaveAssets)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ namespace FlaxEditor.Windows
|
|||||||
{
|
{
|
||||||
if (actorType.IsAbstract)
|
if (actorType.IsAbstract)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ActorContextMenuAttribute attribute = null;
|
ActorContextMenuAttribute attribute = null;
|
||||||
foreach (var e in actorType.GetAttributes(true))
|
foreach (var e in actorType.GetAttributes(true))
|
||||||
{
|
{
|
||||||
@@ -77,44 +76,46 @@ namespace FlaxEditor.Windows
|
|||||||
}
|
}
|
||||||
if (attribute == null)
|
if (attribute == null)
|
||||||
continue;
|
continue;
|
||||||
var splitPath = attribute?.Path.Split('/');
|
var parts = attribute.Path.Split('/');
|
||||||
ContextMenuChildMenu childCM = convertMenu;
|
ContextMenuChildMenu childCM = convertMenu;
|
||||||
bool mainCM = true;
|
bool mainCM = true;
|
||||||
for (int i = 0; i < splitPath?.Length; i++)
|
for (int i = 0; i < parts.Length; i++)
|
||||||
{
|
{
|
||||||
if (i == splitPath.Length - 1)
|
var part = parts[i].Trim();
|
||||||
|
if (i == parts.Length - 1)
|
||||||
{
|
{
|
||||||
if (mainCM)
|
if (mainCM)
|
||||||
{
|
{
|
||||||
convertMenu.ContextMenu.AddButton(splitPath[i].Trim(), () => Editor.SceneEditing.Convert(actorType.Type));
|
convertMenu.ContextMenu.AddButton(part, () => Editor.SceneEditing.Convert(actorType.Type));
|
||||||
mainCM = false;
|
mainCM = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
childCM?.ContextMenu.AddButton(splitPath[i].Trim(), () => Editor.SceneEditing.Convert(actorType.Type));
|
childCM.ContextMenu.AddButton(part, () => Editor.SceneEditing.Convert(actorType.Type));
|
||||||
childCM.ContextMenu.AutoSort = true;
|
childCM.ContextMenu.AutoSort = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Remove new path for converting menu
|
// Remove new path for converting menu
|
||||||
if (splitPath[i] == "New")
|
if (parts[i] == "New")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mainCM)
|
if (mainCM)
|
||||||
{
|
{
|
||||||
childCM = convertMenu.ContextMenu.GetOrAddChildMenu(splitPath[i].Trim());
|
childCM = convertMenu.ContextMenu.GetOrAddChildMenu(part);
|
||||||
|
childCM.ContextMenu.AutoSort = true;
|
||||||
mainCM = false;
|
mainCM = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
childCM = childCM?.ContextMenu.GetOrAddChildMenu(splitPath[i].Trim());
|
childCM = childCM.ContextMenu.GetOrAddChildMenu(part);
|
||||||
}
|
|
||||||
childCM.ContextMenu.AutoSort = true;
|
childCM.ContextMenu.AutoSort = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
b = contextMenu.AddButton("Delete", Editor.SceneEditing.Delete);
|
b = contextMenu.AddButton("Delete", Editor.SceneEditing.Delete);
|
||||||
b.Enabled = hasSthSelected;
|
b.Enabled = hasSthSelected;
|
||||||
|
|
||||||
|
|||||||
@@ -435,6 +435,11 @@ API_ENUM() enum class MaterialSceneTextures
|
|||||||
/// The material shading mode.
|
/// The material shading mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ShadingModel = 10,
|
ShadingModel = 10,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scene world-space position (relative to the render view origin).
|
||||||
|
/// </summary>
|
||||||
|
WorldPosition = 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -439,6 +439,7 @@ void MaterialParameter::Bind(BindMeta& meta) const
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case MaterialSceneTextures::SceneDepth:
|
case MaterialSceneTextures::SceneDepth:
|
||||||
|
case MaterialSceneTextures::WorldPosition:
|
||||||
view = meta.CanSampleDepth
|
view = meta.CanSampleDepth
|
||||||
? meta.Buffers->DepthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView
|
? meta.Buffers->DepthBuffer->GetDescription().Flags & GPUTextureFlags::ReadOnlyDepthView
|
||||||
? meta.Buffers->DepthBuffer->ViewReadOnlyDepth()
|
? meta.Buffers->DepthBuffer->ViewReadOnlyDepth()
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ PACK_STRUCT(struct PostFxMaterialShaderData {
|
|||||||
Float4 ViewInfo;
|
Float4 ViewInfo;
|
||||||
Float4 ScreenSize;
|
Float4 ScreenSize;
|
||||||
Float4 TemporalAAJitter;
|
Float4 TemporalAAJitter;
|
||||||
|
Matrix InverseViewProjectionMatrix;
|
||||||
});
|
});
|
||||||
|
|
||||||
void PostFxMaterialShader::Bind(BindParameters& params)
|
void PostFxMaterialShader::Bind(BindParameters& params)
|
||||||
@@ -44,6 +45,7 @@ void PostFxMaterialShader::Bind(BindParameters& params)
|
|||||||
// Setup material constants
|
// Setup material constants
|
||||||
{
|
{
|
||||||
Matrix::Transpose(view.View, materialData->ViewMatrix);
|
Matrix::Transpose(view.View, materialData->ViewMatrix);
|
||||||
|
Matrix::Transpose(view.IVP, materialData->InverseViewProjectionMatrix);
|
||||||
materialData->ViewPos = view.Position;
|
materialData->ViewPos = view.Position;
|
||||||
materialData->ViewFar = view.Far;
|
materialData->ViewFar = view.Far;
|
||||||
materialData->ViewDir = view.Direction;
|
materialData->ViewDir = view.Direction;
|
||||||
|
|||||||
@@ -113,6 +113,11 @@ bool ShaderAssetBase::Save()
|
|||||||
|
|
||||||
bool IsValidShaderCache(DataContainer<byte>& shaderCache, Array<String>& includes)
|
bool IsValidShaderCache(DataContainer<byte>& shaderCache, Array<String>& includes)
|
||||||
{
|
{
|
||||||
|
if (shaderCache.Length() == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MemoryReadStream stream(shaderCache.Get(), shaderCache.Length());
|
MemoryReadStream stream(shaderCache.Get(), shaderCache.Length());
|
||||||
|
|
||||||
// Read cache format version
|
// Read cache format version
|
||||||
|
|||||||
@@ -245,6 +245,9 @@ void ParticleEmitterGPUGenerator::ProcessGroupTextures(Box* box, Node* node, Val
|
|||||||
value = writeLocal(VariantType::Int, String::Format(TEXT("(int)({0}.a * 3.999)"), gBuffer1Sample.Value), node);
|
value = writeLocal(VariantType::Int, String::Format(TEXT("(int)({0}.a * 3.999)"), gBuffer1Sample.Value), node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MaterialSceneTextures::WorldPosition:
|
||||||
|
value = Value::Zero; // Not implemented
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// Sample single texture
|
// Sample single texture
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Physical materials are used to define the response of a physical object when interacting dynamically with the world.
|
/// Physical materials are used to define the response of a physical object when interacting dynamically with the world.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_CLASS() class FLAXENGINE_API PhysicalMaterial final : public ISerializable
|
API_CLASS(Attributes = "ContentContextMenu(\"New/Physics/Physical Material\")") class FLAXENGINE_API PhysicalMaterial final : public ISerializable
|
||||||
{
|
{
|
||||||
API_AUTO_SERIALIZATION();
|
API_AUTO_SERIALIZATION();
|
||||||
DECLARE_SCRIPTING_TYPE_MINIMAL(PhysicalMaterial);
|
DECLARE_SCRIPTING_TYPE_MINIMAL(PhysicalMaterial);
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FlaxEngine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This attribute is used to show content items that can be created in the content browser context menu. Separate the subcontext menus with a /.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class ContentContextMenuAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The path to be used in the context menu
|
||||||
|
/// </summary>
|
||||||
|
public string Path;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ContentContextMenuAttribute"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to use to create the context menu</param>
|
||||||
|
public ContentContextMenuAttribute(string path)
|
||||||
|
{
|
||||||
|
Path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#if COMPILE_WITH_MATERIAL_GRAPH
|
|
||||||
|
|
||||||
#include "MaterialGenerator.h"
|
|
||||||
|
|
||||||
MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
|
||||||
{
|
|
||||||
ASSERT(texture && box);
|
|
||||||
|
|
||||||
// Cache data
|
|
||||||
const auto parent = box->GetParent<ShaderGraphNode<>>();
|
|
||||||
const bool isCubemap = texture->Type == MaterialParameterType::CubeTexture;
|
|
||||||
const bool isArray = texture->Type == MaterialParameterType::GPUTextureArray;
|
|
||||||
const bool isVolume = texture->Type == MaterialParameterType::GPUTextureVolume;
|
|
||||||
const bool isNormalMap = texture->Type == MaterialParameterType::NormalMap;
|
|
||||||
const bool canUseSample = CanUseSample(_treeType);
|
|
||||||
MaterialGraphBox* valueBox = parent->GetBox(1);
|
|
||||||
|
|
||||||
// Check if has variable assigned
|
|
||||||
if (texture->Type != MaterialParameterType::Texture
|
|
||||||
&& texture->Type != MaterialParameterType::NormalMap
|
|
||||||
&& texture->Type != MaterialParameterType::SceneTexture
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTexture
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTextureVolume
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTextureCube
|
|
||||||
&& texture->Type != MaterialParameterType::GPUTextureArray
|
|
||||||
&& texture->Type != MaterialParameterType::CubeTexture)
|
|
||||||
{
|
|
||||||
OnError(caller, box, TEXT("No parameter for texture sample node."));
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if it's 'Object' box that is using only texture object without sampling
|
|
||||||
if (box->ID == 6)
|
|
||||||
{
|
|
||||||
// Return texture object
|
|
||||||
value.Value = texture->ShaderName;
|
|
||||||
value.Type = VariantType::Object;
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if hasn't been sampled during that tree eating
|
|
||||||
if (valueBox->Cache.IsInvalid())
|
|
||||||
{
|
|
||||||
// Check if use custom UVs
|
|
||||||
String uv;
|
|
||||||
MaterialGraphBox* uvBox = parent->GetBox(0);
|
|
||||||
bool useCustomUVs = uvBox->HasConnection();
|
|
||||||
bool use3dUVs = isCubemap || isArray || isVolume;
|
|
||||||
if (useCustomUVs)
|
|
||||||
{
|
|
||||||
// Get custom UVs
|
|
||||||
auto textureParamId = texture->ID;
|
|
||||||
ASSERT(textureParamId.IsValid());
|
|
||||||
MaterialValue v = tryGetValue(uvBox, getUVs);
|
|
||||||
uv = MaterialValue::Cast(v, use3dUVs ? VariantType::Float3 : VariantType::Float2).Value;
|
|
||||||
|
|
||||||
// Restore texture (during tryGetValue pointer could go invalid)
|
|
||||||
texture = findParam(textureParamId);
|
|
||||||
ASSERT(texture);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Use default UVs
|
|
||||||
uv = use3dUVs ? TEXT("float3(input.TexCoord.xy, 0)") : TEXT("input.TexCoord.xy");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select sampler
|
|
||||||
// TODO: add option for texture groups and per texture options like wrap mode etc.
|
|
||||||
// TODO: changing texture sampler option
|
|
||||||
const Char* sampler = TEXT("SamplerLinearWrap");
|
|
||||||
|
|
||||||
// Sample texture
|
|
||||||
if (isNormalMap)
|
|
||||||
{
|
|
||||||
const Char* format = canUseSample ? TEXT("{0}.Sample({1}, {2}).xyz") : TEXT("{0}.SampleLevel({1}, {2}, 0).xyz");
|
|
||||||
|
|
||||||
// Sample encoded normal map
|
|
||||||
const String sampledValue = String::Format(format, texture->ShaderName, sampler, uv);
|
|
||||||
const auto normalVector = writeLocal(VariantType::Float3, sampledValue, parent);
|
|
||||||
|
|
||||||
// Decode normal vector
|
|
||||||
_writer.Write(TEXT("\t{0}.xy = {0}.xy * 2.0 - 1.0;\n"), normalVector.Value);
|
|
||||||
_writer.Write(TEXT("\t{0}.z = sqrt(saturate(1.0 - dot({0}.xy, {0}.xy)));\n"), normalVector.Value);
|
|
||||||
valueBox->Cache = normalVector;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Select format string based on texture type
|
|
||||||
const Char* format;
|
|
||||||
/*if (isCubemap)
|
|
||||||
{
|
|
||||||
MISSING_CODE("sampling cube maps and 3d texture in material generator");
|
|
||||||
//format = TEXT("SAMPLE_CUBEMAP({0}, {1})");
|
|
||||||
}
|
|
||||||
else*/
|
|
||||||
{
|
|
||||||
/*if (useCustomUVs)
|
|
||||||
{
|
|
||||||
createGradients(writer, parent);
|
|
||||||
format = TEXT("SAMPLE_TEXTURE_GRAD({0}, {1}, {2}, {3})");
|
|
||||||
}
|
|
||||||
else*/
|
|
||||||
{
|
|
||||||
format = canUseSample ? TEXT("{0}.Sample({1}, {2})") : TEXT("{0}.SampleLevel({1}, {2}, 0)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sample texture
|
|
||||||
String sampledValue = String::Format(format, texture->ShaderName, sampler, uv, _ddx.Value, _ddy.Value);
|
|
||||||
valueBox->Cache = writeLocal(VariantType::Float4, sampledValue, parent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return &valueBox->Cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialGenerator::sampleTexture(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
|
||||||
{
|
|
||||||
const auto sample = sampleTextureRaw(caller, value, box, texture);
|
|
||||||
if (sample == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Set result values based on box ID
|
|
||||||
switch (box->ID)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
value = *sample;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
value.Value = sample->Value + _subs[0];
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
value.Value = sample->Value + _subs[1];
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
value.Value = sample->Value + _subs[2];
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
value.Value = sample->Value + _subs[3];
|
|
||||||
break;
|
|
||||||
default: CRASH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
value.Type = box->Type.Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialGenerator::sampleSceneDepth(Node* caller, Value& value, Box* box)
|
|
||||||
{
|
|
||||||
// Sample depth buffer
|
|
||||||
auto param = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
|
|
||||||
const auto depthSample = sampleTextureRaw(caller, value, box, ¶m);
|
|
||||||
if (depthSample == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Linearize raw device depth
|
|
||||||
linearizeSceneDepth(caller, *depthSample, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MaterialGenerator::linearizeSceneDepth(Node* caller, const Value& depth, Value& value)
|
|
||||||
{
|
|
||||||
value = writeLocal(VariantType::Float, String::Format(TEXT("ViewInfo.w / ({0}.x - ViewInfo.z)"), depth.Value), caller);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -4,6 +4,165 @@
|
|||||||
|
|
||||||
#include "MaterialGenerator.h"
|
#include "MaterialGenerator.h"
|
||||||
|
|
||||||
|
MaterialValue* MaterialGenerator::sampleTextureRaw(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
||||||
|
{
|
||||||
|
ASSERT(texture && box);
|
||||||
|
|
||||||
|
// Cache data
|
||||||
|
const auto parent = box->GetParent<ShaderGraphNode<>>();
|
||||||
|
const bool isCubemap = texture->Type == MaterialParameterType::CubeTexture;
|
||||||
|
const bool isArray = texture->Type == MaterialParameterType::GPUTextureArray;
|
||||||
|
const bool isVolume = texture->Type == MaterialParameterType::GPUTextureVolume;
|
||||||
|
const bool isNormalMap = texture->Type == MaterialParameterType::NormalMap;
|
||||||
|
const bool canUseSample = CanUseSample(_treeType);
|
||||||
|
MaterialGraphBox* valueBox = parent->GetBox(1);
|
||||||
|
|
||||||
|
// Check if has variable assigned
|
||||||
|
if (texture->Type != MaterialParameterType::Texture
|
||||||
|
&& texture->Type != MaterialParameterType::NormalMap
|
||||||
|
&& texture->Type != MaterialParameterType::SceneTexture
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTexture
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTextureVolume
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTextureCube
|
||||||
|
&& texture->Type != MaterialParameterType::GPUTextureArray
|
||||||
|
&& texture->Type != MaterialParameterType::CubeTexture)
|
||||||
|
{
|
||||||
|
OnError(caller, box, TEXT("No parameter for texture sample node."));
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if it's 'Object' box that is using only texture object without sampling
|
||||||
|
if (box->ID == 6)
|
||||||
|
{
|
||||||
|
// Return texture object
|
||||||
|
value.Value = texture->ShaderName;
|
||||||
|
value.Type = VariantType::Object;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if hasn't been sampled during that tree eating
|
||||||
|
if (valueBox->Cache.IsInvalid())
|
||||||
|
{
|
||||||
|
// Check if use custom UVs
|
||||||
|
String uv;
|
||||||
|
MaterialGraphBox* uvBox = parent->GetBox(0);
|
||||||
|
bool useCustomUVs = uvBox->HasConnection();
|
||||||
|
bool use3dUVs = isCubemap || isArray || isVolume;
|
||||||
|
if (useCustomUVs)
|
||||||
|
{
|
||||||
|
// Get custom UVs
|
||||||
|
auto textureParamId = texture->ID;
|
||||||
|
ASSERT(textureParamId.IsValid());
|
||||||
|
MaterialValue v = tryGetValue(uvBox, getUVs);
|
||||||
|
uv = MaterialValue::Cast(v, use3dUVs ? VariantType::Float3 : VariantType::Float2).Value;
|
||||||
|
|
||||||
|
// Restore texture (during tryGetValue pointer could go invalid)
|
||||||
|
texture = findParam(textureParamId);
|
||||||
|
ASSERT(texture);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Use default UVs
|
||||||
|
uv = use3dUVs ? TEXT("float3(input.TexCoord.xy, 0)") : TEXT("input.TexCoord.xy");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select sampler
|
||||||
|
// TODO: add option for texture groups and per texture options like wrap mode etc.
|
||||||
|
// TODO: changing texture sampler option
|
||||||
|
const Char* sampler = TEXT("SamplerLinearWrap");
|
||||||
|
|
||||||
|
// Sample texture
|
||||||
|
if (isNormalMap)
|
||||||
|
{
|
||||||
|
const Char* format = canUseSample ? TEXT("{0}.Sample({1}, {2}).xyz") : TEXT("{0}.SampleLevel({1}, {2}, 0).xyz");
|
||||||
|
|
||||||
|
// Sample encoded normal map
|
||||||
|
const String sampledValue = String::Format(format, texture->ShaderName, sampler, uv);
|
||||||
|
const auto normalVector = writeLocal(VariantType::Float3, sampledValue, parent);
|
||||||
|
|
||||||
|
// Decode normal vector
|
||||||
|
_writer.Write(TEXT("\t{0}.xy = {0}.xy * 2.0 - 1.0;\n"), normalVector.Value);
|
||||||
|
_writer.Write(TEXT("\t{0}.z = sqrt(saturate(1.0 - dot({0}.xy, {0}.xy)));\n"), normalVector.Value);
|
||||||
|
valueBox->Cache = normalVector;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Select format string based on texture type
|
||||||
|
const Char* format;
|
||||||
|
/*if (isCubemap)
|
||||||
|
{
|
||||||
|
MISSING_CODE("sampling cube maps and 3d texture in material generator");
|
||||||
|
//format = TEXT("SAMPLE_CUBEMAP({0}, {1})");
|
||||||
|
}
|
||||||
|
else*/
|
||||||
|
{
|
||||||
|
/*if (useCustomUVs)
|
||||||
|
{
|
||||||
|
createGradients(writer, parent);
|
||||||
|
format = TEXT("SAMPLE_TEXTURE_GRAD({0}, {1}, {2}, {3})");
|
||||||
|
}
|
||||||
|
else*/
|
||||||
|
{
|
||||||
|
format = canUseSample ? TEXT("{0}.Sample({1}, {2})") : TEXT("{0}.SampleLevel({1}, {2}, 0)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample texture
|
||||||
|
String sampledValue = String::Format(format, texture->ShaderName, sampler, uv, _ddx.Value, _ddy.Value);
|
||||||
|
valueBox->Cache = writeLocal(VariantType::Float4, sampledValue, parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &valueBox->Cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialGenerator::sampleTexture(Node* caller, Value& value, Box* box, SerializedMaterialParam* texture)
|
||||||
|
{
|
||||||
|
const auto sample = sampleTextureRaw(caller, value, box, texture);
|
||||||
|
if (sample == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Set result values based on box ID
|
||||||
|
switch (box->ID)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
value = *sample;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value.Value = sample->Value + _subs[0];
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value.Value = sample->Value + _subs[1];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
value.Value = sample->Value + _subs[2];
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
value.Value = sample->Value + _subs[3];
|
||||||
|
break;
|
||||||
|
default: CRASH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
value.Type = box->Type.Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialGenerator::sampleSceneDepth(Node* caller, Value& value, Box* box)
|
||||||
|
{
|
||||||
|
// Sample depth buffer
|
||||||
|
auto param = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
|
||||||
|
const auto depthSample = sampleTextureRaw(caller, value, box, ¶m);
|
||||||
|
if (depthSample == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Linearize raw device depth
|
||||||
|
linearizeSceneDepth(caller, *depthSample, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialGenerator::linearizeSceneDepth(Node* caller, const Value& depth, Value& value)
|
||||||
|
{
|
||||||
|
value = writeLocal(VariantType::Float, String::Format(TEXT("ViewInfo.w / ({0}.x - ViewInfo.z)"), depth.Value), caller);
|
||||||
|
}
|
||||||
|
|
||||||
void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
||||||
{
|
{
|
||||||
switch (node->TypeID)
|
switch (node->TypeID)
|
||||||
@@ -257,6 +416,23 @@ void MaterialGenerator::ProcessGroupTextures(Box* box, Node* node, Value& value)
|
|||||||
value = writeLocal(VariantType::Int, String::Format(TEXT("(int)({0}.a * 3.999)"), gBuffer1Sample->Value), node);
|
value = writeLocal(VariantType::Int, String::Format(TEXT("(int)({0}.a * 3.999)"), gBuffer1Sample->Value), node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MaterialSceneTextures::WorldPosition:
|
||||||
|
{
|
||||||
|
auto depthParam = findOrAddSceneTexture(MaterialSceneTextures::SceneDepth);
|
||||||
|
auto depthSample = sampleTextureRaw(node, value, box, &depthParam);
|
||||||
|
if (depthSample == nullptr)
|
||||||
|
break;
|
||||||
|
const auto parent = box->GetParent<ShaderGraphNode<>>();
|
||||||
|
MaterialGraphBox* uvBox = parent->GetBox(0);
|
||||||
|
bool useCustomUVs = uvBox->HasConnection();
|
||||||
|
String uv;
|
||||||
|
if (useCustomUVs)
|
||||||
|
uv = MaterialValue::Cast(tryGetValue(uvBox, getUVs), VariantType::Float2).Value;
|
||||||
|
else
|
||||||
|
uv = TEXT("input.TexCoord.xy");
|
||||||
|
value = writeLocal(VariantType::Float3, String::Format(TEXT("GetWorldPos({1}, {0}.rgb)"), depthSample->Value, uv), node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// Sample single texture
|
// Sample single texture
|
||||||
|
|||||||
@@ -229,6 +229,11 @@ namespace FlaxEngine.GUI
|
|||||||
[EditorOrder(529)]
|
[EditorOrder(529)]
|
||||||
public bool ClipText { get; set; } = true;
|
public bool ClipText { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether you can scroll the text in the text box (eg. with a mouse wheel).
|
||||||
|
/// </summary>
|
||||||
|
public bool IsMultilineScrollable { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets textbox background color when the control is selected (has focus).
|
/// Gets or sets textbox background color when the control is selected (has focus).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -1157,7 +1162,7 @@ namespace FlaxEngine.GUI
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Multiline scroll
|
// Multiline scroll
|
||||||
if (IsMultiline && _text.Length != 0)
|
if (IsMultiline && _text.Length != 0 && IsMultilineScrollable)
|
||||||
{
|
{
|
||||||
TargetViewOffset = Float2.Clamp(_targetViewOffset - new Float2(0, delta * 10.0f), Float2.Zero, new Float2(_targetViewOffset.X, _textSize.Y));
|
TargetViewOffset = Float2.Clamp(_targetViewOffset - new Float2(0, delta * 10.0f), Float2.Zero, new Float2(_targetViewOffset.X, _textSize.Y));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user