diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e8eb1eb47..236fa6d67 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,6 +18,8 @@ Go check out our [Trello](https://trello.com/b/NQjLXRCP/flax-roadmap). ## **Want to contribute?** +* Fork the FlaxEngine, create a new branch and push your changes there. Then, create a pull request. + * When creating a PR for fixing an issue/bug make sure to describe as to what led to the fix for better understanding, for small and obvious fixes this is not really needed. However make sure to mention the relevant issue where it was first reported if possible. diff --git a/Content/Editor/Primitives/Plane.flax b/Content/Editor/Primitives/Plane.flax index bf2052f02..1e5eaf76b 100644 --- a/Content/Editor/Primitives/Plane.flax +++ b/Content/Editor/Primitives/Plane.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8ab6d87b9f36f4ad231f38f415223130eea7b411be7ff8fd174b6ff7790258fb -size 2232 +oid sha256:5683a761f198d01d7189490d526b55e393eb01fffbd6761fb969d11067b3db73 +size 2277 diff --git a/Content/Shaders/BitonicSort.flax b/Content/Shaders/BitonicSort.flax index d5964fca9..1d5b8a581 100644 --- a/Content/Shaders/BitonicSort.flax +++ b/Content/Shaders/BitonicSort.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:df704c63770ee2b641f000726a3ec93c189685ffa149e484e961c9dba522baaf +oid sha256:f46a61cf8d5183230176e661a51208bfeece16cc7238655f406288ff448af64e size 6721 diff --git a/Development/Scripts/Linux/CallBuildTool.sh b/Development/Scripts/Linux/CallBuildTool.sh index 3b4568918..1a8affe20 100755 --- a/Development/Scripts/Linux/CallBuildTool.sh +++ b/Development/Scripts/Linux/CallBuildTool.sh @@ -3,6 +3,12 @@ set -e +testfilesize=$(wc -c < 'Source/Logo.png') +if [ $testfilesize -le 1000 ]; then + echo "CallBuildTool ERROR: Repository was not cloned using Git LFS" 1>&2 + exit 1 +fi + # Compile the build tool. xbuild /nologo /verbosity:quiet "Source/Tools/Flax.Build/Flax.Build.csproj" /property:Configuration=Release /property:Platform=AnyCPU /target:Build diff --git a/Development/Scripts/Windows/CallBuildTool.bat b/Development/Scripts/Windows/CallBuildTool.bat index 4d9124776..c9729cf55 100644 --- a/Development/Scripts/Windows/CallBuildTool.bat +++ b/Development/Scripts/Windows/CallBuildTool.bat @@ -4,6 +4,10 @@ rem Copyright (c) 2012-2020 Wojciech Figat. All rights reserved. if not exist "Development\Scripts\Windows\GetMSBuildPath.bat" goto Error_InvalidLocation +for %%I in (Source\Logo.png) do if %%~zI LSS 2000 ( + goto Error_MissingLFS +) + call "Development\Scripts\Windows\GetMSBuildPath.bat" if errorlevel 1 goto Error_NoVisualStudioEnvironment @@ -33,6 +37,9 @@ Binaries\Tools\Flax.Build.exe %* if errorlevel 1 goto Error_FlaxBuildFailed exit /B 0 +:Error_MissingLFS +echo CallBuildTool ERROR: Repository was not cloned using Git LFS +goto Exit :Error_InvalidLocation echo CallBuildTool ERROR: The script is in invalid directory. goto Exit diff --git a/Flax.flaxproj b/Flax.flaxproj index 26fb340ba..0c2683afb 100644 --- a/Flax.flaxproj +++ b/Flax.flaxproj @@ -3,7 +3,7 @@ "Version": { "Major": 1, "Minor": 0, - "Build": 6215 + "Build": 6216 }, "Company": "Flax", "Copyright": "Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.", diff --git a/GenerateProjectFiles.bat b/GenerateProjectFiles.bat index 5db8aaf55..aeeac1c67 100644 --- a/GenerateProjectFiles.bat +++ b/GenerateProjectFiles.bat @@ -16,6 +16,7 @@ exit /B 0 :BuildToolFailed echo Flax.Build tool failed. +pause goto Exit :Exit diff --git a/README.md b/README.md index 1ad9f7ce4..9c5b83aae 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,10 @@ This repository contains full source code of the Flax (excluding NDA-protected p Follow the instructions below to compile and run the engine from source. +## Flax plugin for Visual Studio + +Flax Visual Studio extension provides better programming workflow, C# scripts debugging functionality and allows to attach to running engine instance to debug C# source. This extension is available to download [here](https://marketplace.visualstudio.com/items?itemName=Flax.FlaxVS). + ## Windows * Install Visual Studio 2015 or newer @@ -34,7 +38,8 @@ Follow the instructions below to compile and run the engine from source. * Clone repo (with LFS) * Run **GenerateProjectFiles.bat** * Open `Flax.sln` and set solution configuration to **Editor.Development** and solution platform to **Win64** -* Compile Flax project (hit F7 key) +* Set Flax or FlaxEngine as startup project +* Compile Flax project (hit F7 or CTRL+Shift+B) * Run Flax (hit F5 key) ## Linux @@ -49,10 +54,6 @@ Follow the instructions below to compile and run the engine from source. * Open workspace with Visual Code * Build and run -# Flax plugin for Visual Studio - -Flax Visual Studio extension provides better programming workflow, C# scripts debugging functionality and allows to attach to running engine instance to debug C# source. This extension is available to download [here](https://marketplace.visualstudio.com/items?itemName=Flax.FlaxVS). - ## Workspace directory - **Binaries/** - executable files diff --git a/Source/Editor/Options/InputBinding.cs b/Source/Editor/Options/InputBinding.cs index e28e8fa0c..eddd76882 100644 --- a/Source/Editor/Options/InputBinding.cs +++ b/Source/Editor/Options/InputBinding.cs @@ -143,7 +143,31 @@ namespace FlaxEditor.Options { var root = control.Root; - if (root.GetKeyDown(Key)) + if (root.GetKey(Key)) + { + if (Modifier1 == KeyboardKeys.None || root.GetKey(Modifier1)) + { + if (Modifier2 == KeyboardKeys.None || root.GetKey(Modifier2)) + { + return true; + } + } + } + + return false; + } + + /// + /// Processes this input binding to check if state matches. + /// + /// The input providing control. + /// The input key. + /// True if input has been processed, otherwise false. + public bool Process(Control control, KeyboardKeys key) + { + var root = control.Root; + + if (key == Key) { if (Modifier1 == KeyboardKeys.None || root.GetKey(Modifier1)) { @@ -435,16 +459,10 @@ namespace FlaxEditor.Options for (int i = 0; i < _bindings.Count; i++) { var binding = _bindings[i].Binder(options); - if (binding.Key == key) + if (binding.Process(control, key)) { - if (binding.Modifier1 == KeyboardKeys.None || root.GetKey(binding.Modifier1)) - { - if (binding.Modifier2 == KeyboardKeys.None || root.GetKey(binding.Modifier2)) - { - _bindings[i].Callback(); - return true; - } - } + _bindings[i].Callback(); + return true; } } diff --git a/Source/Editor/Surface/Archetypes/Material.cs b/Source/Editor/Surface/Archetypes/Material.cs index 09fd8e5fa..6e828fca4 100644 --- a/Source/Editor/Surface/Archetypes/Material.cs +++ b/Source/Editor/Surface/Archetypes/Material.cs @@ -720,7 +720,39 @@ namespace FlaxEditor.Surface.Archetypes NodeElementArchetype.Factory.Input(2, "Offset", true, typeof(Vector2), 2, 1), NodeElementArchetype.Factory.Output(0, string.Empty, typeof(Vector2), 3), } - } + }, + new NodeArchetype + { + TypeID = 30, + Title = "DDX", + Description = "Returns the partial derivative of the specified value with respect to the screen-space x-coordinate.", + Flags = NodeFlags.MaterialGraph, + Size = new Vector2(90, 25), + ConnectionsHints = ConnectionsHint.Numeric, + IndependentBoxes = new[] { 0 }, + DependentBoxes = new[] { 1 }, + Elements = new[] + { + NodeElementArchetype.Factory.Input(0, "Value", true, null, 0), + NodeElementArchetype.Factory.Output(0, string.Empty, null, 1), + } + }, + new NodeArchetype + { + TypeID = 31, + Title = "DDY", + Description = "Returns the partial derivative of the specified value with respect to the screen-space y-coordinate.", + Flags = NodeFlags.MaterialGraph, + Size = new Vector2(90, 25), + ConnectionsHints = ConnectionsHint.Numeric, + IndependentBoxes = new[] { 0 }, + DependentBoxes = new[] { 1 }, + Elements = new[] + { + NodeElementArchetype.Factory.Input(0, "Value", true, null, 0), + NodeElementArchetype.Factory.Output(0, string.Empty, null, 1), + } + }, }; } } diff --git a/Source/Editor/Surface/Archetypes/Particles.cs b/Source/Editor/Surface/Archetypes/Particles.cs index 4d72bfa7b..1f3ee8ce6 100644 --- a/Source/Editor/Surface/Archetypes/Particles.cs +++ b/Source/Editor/Surface/Archetypes/Particles.cs @@ -338,7 +338,7 @@ namespace FlaxEditor.Surface.Archetypes Size = new Vector2(300, 600), DefaultValues = new object[] { - 500, // Capacity + 1000, // Capacity (int)ParticlesSimulationMode.Default, // Simulation Mode (int)ParticlesSimulationSpace.Local, // Simulation Space true, // Enable Pooling diff --git a/Source/Editor/Surface/Elements/SkeletonNodeNameSelectElement.cs b/Source/Editor/Surface/Elements/SkeletonNodeNameSelectElement.cs index d73590ac7..4321eabd0 100644 --- a/Source/Editor/Surface/Elements/SkeletonNodeNameSelectElement.cs +++ b/Source/Editor/Surface/Elements/SkeletonNodeNameSelectElement.cs @@ -32,8 +32,8 @@ namespace FlaxEditor.Surface.Elements } set { - if (!string.IsNullOrEmpty(value)) - SelectedIndex = _nodeNameToIndex[value]; + if (!string.IsNullOrEmpty(value) && _nodeNameToIndex.TryGetValue(value, out var index)) + SelectedIndex = index; else SelectedIndex = -1; } @@ -60,8 +60,8 @@ namespace FlaxEditor.Surface.Elements { _selectedIndices.Clear(); var selectedNode = (string)ParentNode.Values[Archetype.ValueIndex]; - if (!string.IsNullOrEmpty(selectedNode)) - _selectedIndices.Add(_nodeNameToIndex[selectedNode]); + if (!string.IsNullOrEmpty(selectedNode) && _nodeNameToIndex.TryGetValue(selectedNode, out var index)) + _selectedIndices.Add(index); OnSelectedIndexChanged(); } diff --git a/Source/Editor/Viewport/Cameras/ViewportCamera.cs b/Source/Editor/Viewport/Cameras/ViewportCamera.cs index a01000035..85b7a917c 100644 --- a/Source/Editor/Viewport/Cameras/ViewportCamera.cs +++ b/Source/Editor/Viewport/Cameras/ViewportCamera.cs @@ -32,9 +32,9 @@ namespace FlaxEditor.Viewport.Cameras /// /// The target object bounds. /// The margin distance scale of the orbit radius. - public void SerArcBallView(BoundingBox objectBounds, float marginDistanceScale = 2.0f) + public void SetArcBallView(BoundingBox objectBounds, float marginDistanceScale = 2.0f) { - SerArcBallView(BoundingSphere.FromBox(objectBounds), marginDistanceScale); + SetArcBallView(BoundingSphere.FromBox(objectBounds), marginDistanceScale); } /// @@ -42,18 +42,18 @@ namespace FlaxEditor.Viewport.Cameras /// /// The target object bounds. /// The margin distance scale of the orbit radius. - public void SerArcBallView(BoundingSphere objectBounds, float marginDistanceScale = 2.0f) + public void SetArcBallView(BoundingSphere objectBounds, float marginDistanceScale = 2.0f) { - SerArcBallView(new Quaternion(-0.08f, -0.92f, 0.31f, -0.23f), objectBounds.Center, objectBounds.Radius * marginDistanceScale); + SetArcBallView(new Quaternion(-0.08f, -0.92f, 0.31f, -0.23f), objectBounds.Center, objectBounds.Radius * marginDistanceScale); } /// /// Sets view orientation and position to match the arc ball camera style view for the given orbit radius. /// /// The orbit radius. - public void SerArcBallView(float orbitRadius) + public void SetArcBallView(float orbitRadius) { - SerArcBallView(new Quaternion(-0.08f, -0.92f, 0.31f, -0.23f), Vector3.Zero, orbitRadius); + SetArcBallView(new Quaternion(-0.08f, -0.92f, 0.31f, -0.23f), Vector3.Zero, orbitRadius); } /// @@ -62,7 +62,7 @@ namespace FlaxEditor.Viewport.Cameras /// The view rotation. /// The orbit center location. /// The orbit radius. - public void SerArcBallView(Quaternion orientation, Vector3 orbitCenter, float orbitRadius) + public void SetArcBallView(Quaternion orientation, Vector3 orbitCenter, float orbitRadius) { // Rotate Viewport.ViewOrientation = orientation; diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index a9a10c2d7..a19589c05 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -138,9 +138,7 @@ namespace FlaxEditor.Viewport private bool _isControllingMouse; private int _deltaFilteringStep; - private Vector2 _startPosMiddle; - private Vector2 _startPosRight; - private Vector2 _startPosLeft; + private Vector2 _startPos; private Vector2 _mouseDeltaRightLast; private Vector2[] _deltaFilteringBuffer = new Vector2[FpsCameraFilteringFrames]; @@ -850,7 +848,7 @@ namespace FlaxEditor.Viewport /// protected virtual void OnLeftMouseButtonDown() { - _startPosLeft = _viewMousePos; + _startPos = _viewMousePos; } /// @@ -865,7 +863,7 @@ namespace FlaxEditor.Viewport /// protected virtual void OnRightMouseButtonDown() { - _startPosRight = _viewMousePos; + _startPos = _viewMousePos; } /// @@ -880,7 +878,7 @@ namespace FlaxEditor.Viewport /// protected virtual void OnMiddleMouseButtonDown() { - _startPosMiddle = _viewMousePos; + _startPos = _viewMousePos; } /// @@ -1051,7 +1049,13 @@ namespace FlaxEditor.Viewport moveDelta *= 0.3f; // Calculate smooth mouse delta not dependant on viewport size - Vector2 offset = _viewMousePos - (_input.IsMouseMiddleDown ? _startPosMiddle : _startPosRight); + + Vector2 offset = _viewMousePos - _startPos; + if (_input.IsZooming && !_input.IsMouseRightDown && !_input.IsMouseLeftDown && !_input.IsMouseMiddleDown) + { + offset = Vector2.Zero; + } + offset.X = offset.X > 0 ? Mathf.Floor(offset.X) : Mathf.Ceil(offset.X); offset.Y = offset.Y > 0 ? Mathf.Floor(offset.Y) : Mathf.Ceil(offset.Y); _mouseDeltaRight = offset / size; @@ -1093,7 +1097,7 @@ namespace FlaxEditor.Viewport // Move mouse back to the root position if (centerMouse && (_input.IsMouseRightDown || _input.IsMouseLeftDown || _input.IsMouseMiddleDown)) { - Vector2 center = PointToWindow(_input.IsMouseMiddleDown ? _startPosMiddle : _startPosRight); + Vector2 center = PointToWindow(_startPos); win.MousePosition = center; } } @@ -1139,11 +1143,11 @@ namespace FlaxEditor.Viewport if (_input.IsMouseLeftDown) { // Calculate smooth mouse delta not dependant on viewport size - Vector2 offset = _viewMousePos - _startPosLeft; + Vector2 offset = _viewMousePos - _startPos; offset.X = offset.X > 0 ? Mathf.Floor(offset.X) : Mathf.Ceil(offset.X); offset.Y = offset.Y > 0 ? Mathf.Floor(offset.Y) : Mathf.Ceil(offset.Y); _mouseDeltaLeft = offset / size; - _startPosLeft = _viewMousePos; + _startPos = _viewMousePos; } else { diff --git a/Source/Editor/Viewport/Previews/AssetPreview.cs b/Source/Editor/Viewport/Previews/AssetPreview.cs index 012837f87..9bf3573a1 100644 --- a/Source/Editor/Viewport/Previews/AssetPreview.cs +++ b/Source/Editor/Viewport/Previews/AssetPreview.cs @@ -85,7 +85,7 @@ namespace FlaxEditor.Viewport.Previews var orbitRadius = 200.0f; if (camera is ArcBallCamera arcBallCamera) orbitRadius = arcBallCamera.OrbitRadius; - camera.SerArcBallView(new Quaternion(-0.08f, -0.92f, 0.31f, -0.23f), Vector3.Zero, orbitRadius); + camera.SetArcBallView(new Quaternion(-0.08f, -0.92f, 0.31f, -0.23f), Vector3.Zero, orbitRadius); if (useWidgets) { diff --git a/Source/Editor/Viewport/Previews/MaterialPreview.cs b/Source/Editor/Viewport/Previews/MaterialPreview.cs index a03598193..6ff695b69 100644 --- a/Source/Editor/Viewport/Previews/MaterialPreview.cs +++ b/Source/Editor/Viewport/Previews/MaterialPreview.cs @@ -23,6 +23,15 @@ namespace FlaxEditor.Viewport.Previews "Cone" }; + private static readonly Transform[] Transforms = + { + new Transform(Vector3.Zero, Quaternion.RotationY(Mathf.Pi), new Vector3(0.45f)), + new Transform(Vector3.Zero, Quaternion.RotationY(Mathf.Pi), new Vector3(0.45f)), + new Transform(Vector3.Zero, Quaternion.Identity, new Vector3(0.45f)), + new Transform(Vector3.Zero, Quaternion.RotationY(Mathf.Pi), new Vector3(0.45f)), + new Transform(Vector3.Zero, Quaternion.RotationY(Mathf.Pi), new Vector3(0.45f)), + }; + private StaticModel _previewModel; private Decal _decal; private Terrain _terrain; @@ -65,6 +74,7 @@ namespace FlaxEditor.Viewport.Previews _selectedModelIndex = value; _previewModel.Model = FlaxEngine.Content.LoadAsyncInternal("Editor/Primitives/" + Models[value]); + _previewModel.Transform = Transforms[value]; } } @@ -77,7 +87,6 @@ namespace FlaxEditor.Viewport.Previews { // Setup preview scene _previewModel = new StaticModel(); - _previewModel.Transform = new Transform(Vector3.Zero, Quaternion.RotationY(Mathf.Pi), new Vector3(0.45f)); SelectedModelIndex = 0; // Link actors for rendering diff --git a/Source/Editor/Viewport/Previews/TexturePreview.cs b/Source/Editor/Viewport/Previews/TexturePreview.cs index d1904027a..5e1024609 100644 --- a/Source/Editor/Viewport/Previews/TexturePreview.cs +++ b/Source/Editor/Viewport/Previews/TexturePreview.cs @@ -159,13 +159,14 @@ namespace FlaxEditor.Viewport.Previews float prevScale = _viewScale; _viewScale = Mathf.Clamp(_viewScale + delta * 0.24f, 0.001f, 20.0f); - // Move view to make use of the control much more soother - //float coeff = (prevScale + (_viewScale - prevScale)) / prevScale; - //_viewPos += (location * coeff - location) / _viewScale; - //_viewPos += location / _viewScale; - Vector2 sizeDelta = (_viewScale - prevScale) * _textureRect.Size; + // Compensate for the Rectangle.MakeScaled + Vector2 sizeDelta = (_viewScale - prevScale) * _textureRect.Size * 0.5f; _viewPos += sizeDelta * 0.5f; + // Move to zoom position + Vector2 locationOnTexture = (location - _textureRect.Location) / _textureRect.Size; + _viewPos -= sizeDelta * locationOnTexture; + return true; } diff --git a/Source/Editor/Windows/Assets/AssetEditorWindow.cs b/Source/Editor/Windows/Assets/AssetEditorWindow.cs index 92c697b88..8ad655d01 100644 --- a/Source/Editor/Windows/Assets/AssetEditorWindow.cs +++ b/Source/Editor/Windows/Assets/AssetEditorWindow.cs @@ -430,7 +430,7 @@ namespace FlaxEditor.Windows.Assets /// /// Gets the original asset. Note: is the cloned asset for local editing. Use to apply changes to the original asset. /// - public T OriginalAsset => (T)FlaxEngine.Content.GetAsset(_item.ID); + public T OriginalAsset => (T)FlaxEngine.Content.Load(_item.ID); /// protected ClonedAssetEditorWindowBase(Editor editor, AssetItem item) diff --git a/Source/Editor/Windows/Assets/ModelWindow.cs b/Source/Editor/Windows/Assets/ModelWindow.cs index 9910c6e7a..533c9694c 100644 --- a/Source/Editor/Windows/Assets/ModelWindow.cs +++ b/Source/Editor/Windows/Assets/ModelWindow.cs @@ -1004,7 +1004,7 @@ namespace FlaxEditor.Windows.Assets protected override void OnAssetLoaded() { _refreshOnLODsLoaded = true; - _preview.ViewportCamera.SerArcBallView(Asset.GetBox()); + _preview.ViewportCamera.SetArcBallView(Asset.GetBox()); UpdateEffectsOnAsset(); // TODO: disable streaming for this model diff --git a/Source/Editor/Windows/Assets/SceneAnimationWindow.cs b/Source/Editor/Windows/Assets/SceneAnimationWindow.cs index 95421585d..c18edc716 100644 --- a/Source/Editor/Windows/Assets/SceneAnimationWindow.cs +++ b/Source/Editor/Windows/Assets/SceneAnimationWindow.cs @@ -277,6 +277,7 @@ namespace FlaxEditor.Windows.Assets private readonly StagingTexture[] _stagingTextures = new StagingTexture[FrameLatency + 1]; private RenderProgress _progress; private RenderEditorState _editorState; + private GameWindow _gameWindow; public RenderOptions Options => _options; @@ -373,6 +374,9 @@ namespace FlaxEditor.Windows.Assets gameWin.Viewport.Task.PostRender += OnPostRender; if (!gameWin.Visible) gameWin.Show(); + else if (!gameWin.IsFocused) + gameWin.Focus(); + _gameWindow = gameWin; _warmUpTimeLeft = _options.WarmUpTime; _animationFrame = 0; var stagingTextureDesc = GPUTextureDescription.New2D(resolution.X, resolution.Y, gameWin.Viewport.Task.Output.Format, GPUTextureFlags.None); @@ -385,6 +389,12 @@ namespace FlaxEditor.Windows.Assets _stagingTextures[i].TaskFrame = -1; } _player.Play(); + if (!_player.IsPlaying) + { + Editor.LogError("Scene Animation Player failed to start playing."); + CancelRendering(); + return; + } if (_warmUpTimeLeft > 0.0f) { // Start warmup time @@ -438,8 +448,11 @@ namespace FlaxEditor.Windows.Assets _stagingTextures[i].Texture.ReleaseGPU(); Object.Destroy(ref _stagingTextures[i].Texture); } - _progress.End(); - editor.ProgressReporting.UnregisterHandler(_progress); + if (_progress != null) + { + _progress.End(); + editor.ProgressReporting.UnregisterHandler(_progress); + } if (_editorState != null) { editor.StateMachine.GoToState(editor.StateMachine.EditingSceneState); @@ -452,6 +465,7 @@ namespace FlaxEditor.Windows.Assets gameWin.Viewport.BackgroundColor = Color.Transparent; gameWin.Viewport.KeepAspectRatio = false; gameWin.Viewport.Task.PostRender -= OnPostRender; + _gameWindow = null; _isRendering = false; _presenter.Panel.Enabled = true; _presenter.BuildLayoutOnUpdate(); @@ -467,6 +481,11 @@ namespace FlaxEditor.Windows.Assets { // Render first frame _player.Play(); + if (!_player.IsPlaying) + { + Editor.LogError("Scene Animation Player failed to start playing."); + CancelRendering(); + } _warmUpTimeLeft = -1; _state = States.Render; } @@ -503,8 +522,7 @@ namespace FlaxEditor.Windows.Assets private void OnPostRender(GPUContext context, RenderContext renderContext) { - var gameWin = Editor.Instance.Windows.GameWin; - var task = gameWin.Viewport.Task; + var task = _gameWindow.Viewport.Task; var taskFrame = task.FrameCount; // Check all staging textures for finished GPU to CPU transfers @@ -540,7 +558,7 @@ namespace FlaxEditor.Windows.Assets ref var stagingTexture = ref _stagingTextures[textureIdx]; stagingTexture.AnimationFrame = _animationFrame; stagingTexture.TaskFrame = taskFrame; - _options.VideoOutputFormat.RenderFrame(context, ref stagingTexture, _options, gameWin.Viewport.Task.Output); + _options.VideoOutputFormat.RenderFrame(context, ref stagingTexture, _options, _gameWindow.Viewport.Task.Output); // Now wait for the next animation frame to be updated _state = States.Update; diff --git a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs index 2f6c952ba..c599e7e2a 100644 --- a/Source/Editor/Windows/Assets/SkinnedModelWindow.cs +++ b/Source/Editor/Windows/Assets/SkinnedModelWindow.cs @@ -1097,7 +1097,7 @@ namespace FlaxEditor.Windows.Assets protected override void OnAssetLoaded() { _refreshOnLODsLoaded = true; - _preview.ViewportCamera.SerArcBallView(Asset.GetBox()); + _preview.ViewportCamera.SetArcBallView(Asset.GetBox()); UpdateEffectsOnAsset(); // TODO: disable streaming for this model diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs index 35bc91bbe..2f9be0254 100644 --- a/Source/Editor/Windows/GameWindow.cs +++ b/Source/Editor/Windows/GameWindow.cs @@ -387,6 +387,12 @@ namespace FlaxEditor.Windows } } + // Prevent closing the game window tab during a play session + if (Editor.StateMachine.IsPlayMode && Editor.Options.Options.Input.CloseTab.Process(this, key)) + { + return true; + } + return base.OnKeyDown(key); } diff --git a/Source/Engine/Graphics/RenderTask.cpp b/Source/Engine/Graphics/RenderTask.cpp index e3e261c96..d30e8e37c 100644 --- a/Source/Engine/Graphics/RenderTask.cpp +++ b/Source/Engine/Graphics/RenderTask.cpp @@ -260,6 +260,11 @@ void SceneRenderTask::OnCollectDrawCalls(RenderContext& renderContext) CollectDrawCalls(renderContext); } +void SceneRenderTask::OnPreRender(GPUContext* context, RenderContext& renderContext) +{ + PreRender(context, renderContext); +} + void SceneRenderTask::OnPostRender(GPUContext* context, RenderContext& renderContext) { PostRender(context, renderContext); diff --git a/Source/Engine/Graphics/RenderTask.h b/Source/Engine/Graphics/RenderTask.h index b00d80a5f..265905e2a 100644 --- a/Source/Engine/Graphics/RenderTask.h +++ b/Source/Engine/Graphics/RenderTask.h @@ -313,6 +313,18 @@ public: /// The rendering context. virtual void OnCollectDrawCalls(RenderContext& renderContext); + /// + /// The action called after scene rendering. Can be used to perform custom pre-rendering or to modify the render view. + /// + API_EVENT() Delegate PreRender; + + /// + /// Called before scene rendering. Can be used to perform custom pre-rendering or to modify the render view. + /// + /// The GPU commands context. + /// The rendering context. + virtual void OnPreRender(GPUContext* context, RenderContext& renderContext); + /// /// The action called after scene rendering. Can be used to render additional visual elements to the output. /// diff --git a/Source/Engine/Input/Input.cpp b/Source/Engine/Input/Input.cpp index be11f091d..0f2bdf4e5 100644 --- a/Source/Engine/Input/Input.cpp +++ b/Source/Engine/Input/Input.cpp @@ -104,6 +104,201 @@ void InputSettings::Apply() Input::AxisMappings = AxisMappings; } +void Mouse::OnMouseMoved(const Vector2& newPosition) +{ + _prevState.MousePosition = newPosition; + _state.MousePosition = newPosition; +} + +void Mouse::OnMouseDown(const Vector2& position, const MouseButton button, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::MouseDown; + e.Target = target; + e.MouseData.Button = button; + e.MouseData.Position = position; +} + +void Mouse::OnMouseUp(const Vector2& position, const MouseButton button, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::MouseUp; + e.Target = target; + e.MouseData.Button = button; + e.MouseData.Position = position; +} + +void Mouse::OnMouseDoubleClick(const Vector2& position, const MouseButton button, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::MouseDoubleClick; + e.Target = target; + e.MouseData.Button = button; + e.MouseData.Position = position; +} + +void Mouse::OnMouseMove(const Vector2& position, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::MouseMove; + e.Target = target; + e.MouseData.Position = position; +} + +void Mouse::OnMouseLeave(Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::MouseLeave; + e.Target = target; +} + +void Mouse::OnMouseWheel(const Vector2& position, float delta, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::MouseWheel; + e.Target = target; + e.MouseWheelData.WheelDelta = delta; + e.MouseWheelData.Position = position; +} + +void Mouse::ResetState() +{ + InputDevice::ResetState(); + + _prevState.Clear(); + _state.Clear(); +} + +bool Mouse::Update(EventQueue& queue) +{ + // Move the current state to the previous + Platform::MemoryCopy(&_prevState, &_state, sizeof(State)); + + // Gather new events + if (UpdateState()) + return true; + + // Handle events + _state.MouseWheelDelta = 0; + for (int32 i = 0; i < _queue.Count(); i++) + { + const Event& e = _queue[i]; + switch (e.Type) + { + case EventType::MouseDown: + { + _state.MouseButtons[static_cast(e.MouseData.Button)] = true; + break; + } + case EventType::MouseUp: + { + _state.MouseButtons[static_cast(e.MouseData.Button)] = false; + break; + } + case EventType::MouseDoubleClick: + { + break; + } + case EventType::MouseWheel: + { + _state.MouseWheelDelta += e.MouseWheelData.WheelDelta; + break; + } + case EventType::MouseMove: + { + _state.MousePosition = e.MouseData.Position; + break; + } + case EventType::MouseLeave: + { + break; + } + } + } + + // Send events further + queue.Add(_queue); + _queue.Clear(); + return false; +} + +void Keyboard::OnCharInput(Char c, Window* target) +{ + // Skip control characters + if (c < 32) + return; + + Event& e = _queue.AddOne(); + e.Type = EventType::Char; + e.Target = target; + e.CharData.Char = c; +} + +void Keyboard::OnKeyUp(KeyboardKeys key, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::KeyUp; + e.Target = target; + e.KeyData.Key = key; +} + +void Keyboard::OnKeyDown(KeyboardKeys key, Window* target) +{ + Event& e = _queue.AddOne(); + e.Type = EventType::KeyDown; + e.Target = target; + e.KeyData.Key = key; +} + +void Keyboard::ResetState() +{ + InputDevice::ResetState(); + + _prevState.Clear(); + _state.Clear(); +} + +bool Keyboard::Update(EventQueue& queue) +{ + // Move the current state to the previous + Platform::MemoryCopy(&_prevState, &_state, sizeof(State)); + + // Gather new events + if (UpdateState()) + return true; + + // Handle events + _state.InputTextLength = 0; + for (int32 i = 0; i < _queue.Count(); i++) + { + const Event& e = _queue[i]; + switch (e.Type) + { + case EventType::Char: + { + if (_state.InputTextLength < ARRAY_COUNT(_state.InputText) - 1) + _state.InputText[_state.InputTextLength++] = e.CharData.Char; + break; + } + case EventType::KeyDown: + { + _state.Keys[static_cast(e.KeyData.Key)] = true; + break; + } + case EventType::KeyUp: + { + _state.Keys[static_cast(e.KeyData.Key)] = false; + break; + } + } + } + + // Send events further + queue.Add(_queue); + _queue.Clear(); + return false; +} + int32 Input::GetGamepadsCount() { return Gamepads.Count(); diff --git a/Source/Engine/Input/Keyboard.h b/Source/Engine/Input/Keyboard.h index ae958bd86..f182f9731 100644 --- a/Source/Engine/Input/Keyboard.h +++ b/Source/Engine/Input/Keyboard.h @@ -13,7 +13,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Keyboard); public: /// - /// The mouse state. + /// The keyboard state. /// struct State { @@ -94,97 +94,32 @@ public: return !_state.Keys[static_cast(key)] && _prevState.Keys[static_cast(key)]; } +public: + /// /// Called when keyboard enters input character. /// /// The Unicode character entered by the user. /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnCharInput(const Char c, Window* target = nullptr) - { - // Skip control characters - if (c < 32) - return; - - Event& e = _queue.AddOne(); - e.Type = EventType::Char; - e.Target = target; - e.CharData.Char = c; - } + void OnCharInput(Char c, Window* target = nullptr); /// /// Called when key goes up. /// /// The keyboard key. /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnKeyUp(const KeyboardKeys key, Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::KeyUp; - e.Target = target; - e.KeyData.Key = key; - } + void OnKeyUp(KeyboardKeys key, Window* target = nullptr); /// /// Called when key goes down. /// /// The keyboard key. /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnKeyDown(const KeyboardKeys key, Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::KeyDown; - e.Target = target; - e.KeyData.Key = key; - } + void OnKeyDown(KeyboardKeys key, Window* target = nullptr); public: // [InputDevice] - void ResetState() override - { - InputDevice::ResetState(); - - _prevState.Clear(); - _state.Clear(); - } - - bool Update(EventQueue& queue) final override - { - // Move the current state to the previous - Platform::MemoryCopy(&_prevState, &_state, sizeof(State)); - - // Gather new events - if (UpdateState()) - return true; - - // Handle events - for (int32 i = 0; i < _queue.Count(); i++) - { - const Event& e = _queue[i]; - switch (e.Type) - { - case EventType::Char: - { - if (_state.InputTextLength < ARRAY_COUNT(_state.InputText) - 1) - _state.InputText[_state.InputTextLength++] = e.CharData.Char; - break; - } - case EventType::KeyDown: - { - _state.Keys[static_cast(e.KeyData.Key)] = true; - break; - } - case EventType::KeyUp: - { - _state.Keys[static_cast(e.KeyData.Key)] = false; - break; - } - } - } - - // Send events further - queue.Add(_queue); - _queue.Clear(); - return false; - } + void ResetState() override;; + bool Update(EventQueue& queue) final override; }; diff --git a/Source/Engine/Input/Mouse.h b/Source/Engine/Input/Mouse.h index 94875ea3a..d58350956 100644 --- a/Source/Engine/Input/Mouse.h +++ b/Source/Engine/Input/Mouse.h @@ -127,11 +127,7 @@ public: /// Called when mouse cursor gets moved by the application. Invalidates the previous cached mouse position to prevent mouse jitter when locking the cursor programmatically. /// /// The new mouse position. - void OnMouseMoved(const Vector2& newPosition) - { - _prevState.MousePosition = newPosition; - _state.MousePosition = newPosition; - } + void OnMouseMoved(const Vector2& newPosition); /// /// Called when mouse button goes down. @@ -139,14 +135,7 @@ public: /// The mouse position. /// The button. /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnMouseDown(const Vector2& position, const MouseButton button, Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::MouseDown; - e.Target = target; - e.MouseData.Button = button; - e.MouseData.Position = position; - } + void OnMouseDown(const Vector2& position, const MouseButton button, Window* target = nullptr); /// /// Called when mouse button goes up. @@ -154,14 +143,7 @@ public: /// The mouse position. /// The button. /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnMouseUp(const Vector2& position, const MouseButton button, Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::MouseUp; - e.Target = target; - e.MouseData.Button = button; - e.MouseData.Position = position; - } + void OnMouseUp(const Vector2& position, const MouseButton button, Window* target = nullptr); /// /// Called when mouse double clicks. @@ -169,38 +151,20 @@ public: /// The mouse position. /// The button. /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnMouseDoubleClick(const Vector2& position, const MouseButton button, Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::MouseDoubleClick; - e.Target = target; - e.MouseData.Button = button; - e.MouseData.Position = position; - } + void OnMouseDoubleClick(const Vector2& position, const MouseButton button, Window* target = nullptr); /// /// Called when mouse moves. /// /// The mouse position. /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnMouseMove(const Vector2& position, Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::MouseMove; - e.Target = target; - e.MouseData.Position = position; - } + void OnMouseMove(const Vector2& position, Window* target = nullptr); /// /// Called when mouse leaves the input source area. /// /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnMouseLeave(Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::MouseLeave; - e.Target = target; - } + void OnMouseLeave(Window* target = nullptr); /// /// Called when mouse wheel moves. @@ -208,76 +172,11 @@ public: /// The mouse position. /// The normalized delta (range [-1;1]). /// The target window to receive this event, otherwise input system will pick the window automatically. - void OnMouseWheel(const Vector2& position, const float delta, Window* target = nullptr) - { - Event& e = _queue.AddOne(); - e.Type = EventType::MouseWheel; - e.Target = target; - e.MouseWheelData.WheelDelta = delta; - e.MouseWheelData.Position = position; - } + void OnMouseWheel(const Vector2& position, float delta, Window* target = nullptr); public: // [InputDevice] - void ResetState() override - { - InputDevice::ResetState(); - - _prevState.Clear(); - _state.Clear(); - } - - bool Update(EventQueue& queue) final override - { - // Move the current state to the previous - Platform::MemoryCopy(&_prevState, &_state, sizeof(State)); - - // Gather new events - if (UpdateState()) - return true; - - // Handle events - _state.MouseWheelDelta = 0; - for (int32 i = 0; i < _queue.Count(); i++) - { - const Event& e = _queue[i]; - switch (e.Type) - { - case EventType::MouseDown: - { - _state.MouseButtons[static_cast(e.MouseData.Button)] = true; - break; - } - case EventType::MouseUp: - { - _state.MouseButtons[static_cast(e.MouseData.Button)] = false; - break; - } - case EventType::MouseDoubleClick: - { - break; - } - case EventType::MouseWheel: - { - _state.MouseWheelDelta += e.MouseWheelData.WheelDelta; - break; - } - case EventType::MouseMove: - { - _state.MousePosition = e.MouseData.Position; - break; - } - case EventType::MouseLeave: - { - break; - } - } - } - - // Send events further - queue.Add(_queue); - _queue.Clear(); - return false; - } + void ResetState() override; + bool Update(EventQueue& queue) final override; }; diff --git a/Source/Engine/Level/Actors/Camera.h b/Source/Engine/Level/Actors/Camera.h index 8076e6a60..edf94ad22 100644 --- a/Source/Engine/Level/Actors/Camera.h +++ b/Source/Engine/Level/Actors/Camera.h @@ -211,7 +211,7 @@ public: /// The result camera view matrix. /// The result camera projection matrix. /// The custom output viewport. Use null to skip it. - API_FUNCTION() void GetMatrices(API_PARAM(Out) Matrix& view, API_PARAM(Out) Matrix& projection, API_PARAM(Ref) const Viewport& viewport) const; + API_FUNCTION() virtual void GetMatrices(API_PARAM(Out) Matrix& view, API_PARAM(Out) Matrix& projection, API_PARAM(Ref) const Viewport& viewport) const; #if USE_EDITOR // Intersection check for editor picking the camera diff --git a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp index 4305046e0..c0029aa93 100644 --- a/Source/Engine/Level/Prefabs/Prefab.Apply.cpp +++ b/Source/Engine/Level/Prefabs/Prefab.Apply.cpp @@ -850,7 +850,11 @@ bool Prefab::ApplyAllInternal(Actor* targetActor, bool linkTargetActorObjectToPr } // Keep root unlinked - root->_parent = nullptr; + if (root->_parent) + { + root->_parent->Children.Remove(root); + root->_parent = nullptr; + } } // Link objects hierarchy diff --git a/Source/Engine/Level/Prefabs/PrefabManager.cpp b/Source/Engine/Level/Prefabs/PrefabManager.cpp index f1fbf4766..44be0181b 100644 --- a/Source/Engine/Level/Prefabs/PrefabManager.cpp +++ b/Source/Engine/Level/Prefabs/PrefabManager.cpp @@ -173,6 +173,11 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent, DictionaryAt(0); + if (!root) + { + LOG(Warning, "Failed to load prefab root object."); + return nullptr; + } // Prepare parent linkage for prefab root actor root->_parent = parent; diff --git a/Source/Engine/Physics/Actors/IPhysicsActor.h b/Source/Engine/Physics/Actors/IPhysicsActor.h index 8aebe3aeb..28f7fddf4 100644 --- a/Source/Engine/Physics/Actors/IPhysicsActor.h +++ b/Source/Engine/Physics/Actors/IPhysicsActor.h @@ -2,7 +2,11 @@ #pragma once -#include +namespace physx +{ + class PxRigidActor; + class PxTransform; +} /// /// A base interface for all physical actors types/owners that can responds on transformation changed event. @@ -20,7 +24,7 @@ public: /// Gets the rigid actor (PhysX object) may be null. /// /// PhysX rigid actor or null if not using - virtual PxRigidActor* GetRigidActor() = 0; + virtual physx::PxRigidActor* GetRigidActor() = 0; /// /// Called when actor's active transformation gets changed after the physics simulation step. diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp index 73b653ee4..e0630573e 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.cpp +++ b/Source/Engine/Physics/Colliders/CharacterController.cpp @@ -29,6 +29,7 @@ CharacterController::CharacterController(const SpawnParams& params) , _nonWalkableMode(CharacterController::NonWalkableModes::PreventClimbing) , _lastFlags(CollisionFlags::None) { + static_assert(sizeof(_filterData) == sizeof(PxFilterData), "Invalid filter data size."); } void CharacterController::SetRadius(const float value) @@ -112,7 +113,7 @@ CharacterController::CollisionFlags CharacterController::Move(const Vector3& dis { const float deltaTime = Time::GetCurrentSafe()->DeltaTime.GetTotalSeconds(); PxControllerFilters filters; - filters.mFilterData = &_filterData; + filters.mFilterData = (PxFilterData*)&_filterData; filters.mFilterCallback = Physics::GetCharacterQueryFilterCallback(); filters.mFilterFlags = PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER; @@ -281,7 +282,7 @@ void CharacterController::UpdateLayerBits() Collider::UpdateLayerBits(); // Cache filter data - _filterData = _shape->getSimulationFilterData(); + *(PxFilterData*)&_filterData = _shape->getSimulationFilterData(); } void CharacterController::BeginPlay(SceneBeginData* data) diff --git a/Source/Engine/Physics/Colliders/CharacterController.h b/Source/Engine/Physics/Colliders/CharacterController.h index dda848cd5..15ca75a7e 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.h +++ b/Source/Engine/Physics/Colliders/CharacterController.h @@ -4,7 +4,6 @@ #include "Collider.h" #include "Engine/Physics/Actors/IPhysicsActor.h" -#include /// /// Physical objects that allows to easily do player movement constrained by collisions without having to deal with a rigidbody. @@ -68,7 +67,7 @@ private: bool _isUpdatingTransform; NonWalkableModes _nonWalkableMode; CollisionFlags _lastFlags; - PxFilterData _filterData; + uint32 _filterData[4]; public: diff --git a/Source/Engine/Renderer/MotionBlurPass.cpp b/Source/Engine/Renderer/MotionBlurPass.cpp index 46b2ccd8f..f10ef442b 100644 --- a/Source/Engine/Renderer/MotionBlurPass.cpp +++ b/Source/Engine/Renderer/MotionBlurPass.cpp @@ -337,8 +337,8 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP RenderTargetPool::Release(vMaxBuffer4); // Downscale motion vectors texture down to tileSize/tileSize (with max velocity calculation NxN kernel) - rtDesc.Width = motionVectorsWidth / tileSize; - rtDesc.Height = motionVectorsHeight / tileSize; + rtDesc.Width = Math::Max(motionVectorsWidth / tileSize, 1); + rtDesc.Height = Math::Max(motionVectorsHeight / tileSize, 1); auto vMaxBuffer = RenderTargetPool::Get(rtDesc); context->ResetRenderTarget(); context->SetRenderTarget(vMaxBuffer->View()); diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index c2a18f519..4d3241375 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -199,9 +199,8 @@ void Renderer::Render(SceneRenderTask* task) #endif // Perform the actual rendering + task->OnPreRender(context, renderContext); RenderInner(task, renderContext); - - // Custom additional rendering task->OnPostRender(context, renderContext); #if USE_EDITOR @@ -306,7 +305,6 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext) #endif renderContext.List->Settings.AntiAliasing.Mode = aaMode; - // Prepare renderContext.View.Prepare(renderContext); renderContext.Buffers->Prepare(); diff --git a/Source/Engine/Serialization/Stream.cpp b/Source/Engine/Serialization/Stream.cpp index 2d3ef8b30..269d49562 100644 --- a/Source/Engine/Serialization/Stream.cpp +++ b/Source/Engine/Serialization/Stream.cpp @@ -228,6 +228,8 @@ void ReadStream::ReadVariantType(VariantType* data) if (typeNameLength == MAX_int32) { ReadInt32(&typeNameLength); + if (typeNameLength == 0) + return; data->TypeName = static_cast(Allocator::Allocate(typeNameLength + 1)); char* ptr = data->TypeName; Read(ptr, typeNameLength); @@ -602,13 +604,21 @@ void WriteStream::WriteVariant(const Variant& data) break; case VariantType::Structure: case VariantType::Blob: - case VariantType::BoundingBox: - case VariantType::Transform: - case VariantType::Ray: - case VariantType::Matrix: WriteInt32(data.AsBlob.Length); WriteBytes(data.AsBlob.Data, data.AsBlob.Length); break; + case VariantType::BoundingBox: + WriteBytes(data.AsBlob.Data, sizeof(BoundingBox)); + break; + case VariantType::Transform: + WriteBytes(data.AsBlob.Data, sizeof(Transform)); + break; + case VariantType::Ray: + WriteBytes(data.AsBlob.Data, sizeof(Ray)); + break; + case VariantType::Matrix: + WriteBytes(data.AsBlob.Data, sizeof(Matrix)); + break; case VariantType::Asset: id = data.AsAsset ? data.AsAsset->GetID() : Guid::Empty; Write(&id); diff --git a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp index b042336ff..0d8a0e226 100644 --- a/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp +++ b/Source/Engine/Tools/MaterialGenerator/MaterialGenerator.Material.cpp @@ -391,6 +391,22 @@ void MaterialGenerator::ProcessGroupMaterial(Box* box, Node* node, Value& value) value = writeLocal(ValueType::Vector2, String::Format(TEXT("{0} * {1} + {2}"), uv.Value, tiling.Value, offset.Value), node); break; + } + // DDX + case 30: + { + auto inValue = tryGetValue(node->GetBox(0), 0, Value::Zero); + + value = writeLocal(inValue.Type, String::Format(TEXT("ddx({0})"), inValue.Value), node); + break; + } + // DDY + case 31: + { + auto inValue = tryGetValue(node->GetBox(0), 0, Value::Zero); + + value = writeLocal(inValue.Type, String::Format(TEXT("ddy({0})"), inValue.Value), node); + break; } default: break; diff --git a/Source/FlaxEngine.Gen.cs b/Source/FlaxEngine.Gen.cs index ceab5ff53..04aef0556 100644 --- a/Source/FlaxEngine.Gen.cs +++ b/Source/FlaxEngine.Gen.cs @@ -13,5 +13,5 @@ using System.Runtime.InteropServices; [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("095aaaed-cc57-6182-57cc-82617b3c2889")] -[assembly: AssemblyVersion("1.0.6215")] -[assembly: AssemblyFileVersion("1.0.6215")] +[assembly: AssemblyVersion("1.0.6216")] +[assembly: AssemblyFileVersion("1.0.6216")] diff --git a/Source/FlaxEngine.Gen.h b/Source/FlaxEngine.Gen.h index 4ceda354d..53a18990c 100644 --- a/Source/FlaxEngine.Gen.h +++ b/Source/FlaxEngine.Gen.h @@ -5,11 +5,11 @@ #include "Engine/Core/Compiler.h" #define FLAXENGINE_NAME "FlaxEngine" -#define FLAXENGINE_VERSION Version(1, 0, 6215) -#define FLAXENGINE_VERSION_TEXT "1.0.6215" +#define FLAXENGINE_VERSION Version(1, 0, 6216) +#define FLAXENGINE_VERSION_TEXT "1.0.6216" #define FLAXENGINE_VERSION_MAJOR 1 #define FLAXENGINE_VERSION_MINOR 0 -#define FLAXENGINE_VERSION_BUILD 6215 +#define FLAXENGINE_VERSION_BUILD 6216 #define FLAXENGINE_COMPANY "Flax" #define FLAXENGINE_COPYRIGHT "Copyright (c) 2012-2021 Wojciech Figat. All rights reserved."