Merge remote-tracking branch 'origin/master' into 1.1

# Conflicts:
#	Source/Engine/Input/Input.cpp
This commit is contained in:
Wojtek Figat
2021-02-02 10:29:52 +01:00
39 changed files with 450 additions and 262 deletions

View File

@@ -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.

BIN
Content/Editor/Primitives/Plane.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Shaders/BitonicSort.flax (Stored with Git LFS)

Binary file not shown.

View File

@@ -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

View File

@@ -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

View File

@@ -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.",

View File

@@ -16,6 +16,7 @@ exit /B 0
:BuildToolFailed
echo Flax.Build tool failed.
pause
goto Exit
:Exit

View File

@@ -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

View File

@@ -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;
}
/// <summary>
/// Processes this input binding to check if state matches.
/// </summary>
/// <param name="control">The input providing control.</param>
/// <param name="key">The input key.</param>
/// <returns>True if input has been processed, otherwise false.</returns>
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;
}
}

View File

@@ -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),
}
},
};
}
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -32,9 +32,9 @@ namespace FlaxEditor.Viewport.Cameras
/// </summary>
/// <param name="objectBounds">The target object bounds.</param>
/// <param name="marginDistanceScale">The margin distance scale of the orbit radius.</param>
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);
}
/// <summary>
@@ -42,18 +42,18 @@ namespace FlaxEditor.Viewport.Cameras
/// </summary>
/// <param name="objectBounds">The target object bounds.</param>
/// <param name="marginDistanceScale">The margin distance scale of the orbit radius.</param>
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);
}
/// <summary>
/// Sets view orientation and position to match the arc ball camera style view for the given orbit radius.
/// </summary>
/// <param name="orbitRadius">The orbit radius.</param>
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);
}
/// <summary>
@@ -62,7 +62,7 @@ namespace FlaxEditor.Viewport.Cameras
/// <param name="orientation">The view rotation.</param>
/// <param name="orbitCenter">The orbit center location.</param>
/// <param name="orbitRadius">The orbit radius.</param>
public void SerArcBallView(Quaternion orientation, Vector3 orbitCenter, float orbitRadius)
public void SetArcBallView(Quaternion orientation, Vector3 orbitCenter, float orbitRadius)
{
// Rotate
Viewport.ViewOrientation = orientation;

View File

@@ -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
/// </summary>
protected virtual void OnLeftMouseButtonDown()
{
_startPosLeft = _viewMousePos;
_startPos = _viewMousePos;
}
/// <summary>
@@ -865,7 +863,7 @@ namespace FlaxEditor.Viewport
/// </summary>
protected virtual void OnRightMouseButtonDown()
{
_startPosRight = _viewMousePos;
_startPos = _viewMousePos;
}
/// <summary>
@@ -880,7 +878,7 @@ namespace FlaxEditor.Viewport
/// </summary>
protected virtual void OnMiddleMouseButtonDown()
{
_startPosMiddle = _viewMousePos;
_startPos = _viewMousePos;
}
/// <summary>
@@ -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
{

View File

@@ -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)
{

View File

@@ -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<Model>("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

View File

@@ -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;
}

View File

@@ -430,7 +430,7 @@ namespace FlaxEditor.Windows.Assets
/// <summary>
/// Gets the original asset. Note: <see cref="AssetEditorWindowBase{T}.Asset"/> is the cloned asset for local editing. Use <see cref="SaveToOriginal"/> to apply changes to the original asset.
/// </summary>
public T OriginalAsset => (T)FlaxEngine.Content.GetAsset(_item.ID);
public T OriginalAsset => (T)FlaxEngine.Content.Load(_item.ID);
/// <inheritdoc />
protected ClonedAssetEditorWindowBase(Editor editor, AssetItem item)

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -313,6 +313,18 @@ public:
/// <param name="renderContext">The rendering context.</param>
virtual void OnCollectDrawCalls(RenderContext& renderContext);
/// <summary>
/// The action called after scene rendering. Can be used to perform custom pre-rendering or to modify the render view.
/// </summary>
API_EVENT() Delegate<GPUContext*, RenderContext&> PreRender;
/// <summary>
/// Called before scene rendering. Can be used to perform custom pre-rendering or to modify the render view.
/// </summary>
/// <param name="context">The GPU commands context.</param>
/// <param name="renderContext">The rendering context.</param>
virtual void OnPreRender(GPUContext* context, RenderContext& renderContext);
/// <summary>
/// The action called after scene rendering. Can be used to render additional visual elements to the output.
/// </summary>

View File

@@ -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<int32>(e.MouseData.Button)] = true;
break;
}
case EventType::MouseUp:
{
_state.MouseButtons[static_cast<int32>(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<int32>(e.KeyData.Key)] = true;
break;
}
case EventType::KeyUp:
{
_state.Keys[static_cast<int32>(e.KeyData.Key)] = false;
break;
}
}
}
// Send events further
queue.Add(_queue);
_queue.Clear();
return false;
}
int32 Input::GetGamepadsCount()
{
return Gamepads.Count();

View File

@@ -13,7 +13,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Keyboard);
public:
/// <summary>
/// The mouse state.
/// The keyboard state.
/// </summary>
struct State
{
@@ -94,97 +94,32 @@ public:
return !_state.Keys[static_cast<int32>(key)] && _prevState.Keys[static_cast<int32>(key)];
}
public:
/// <summary>
/// Called when keyboard enters input character.
/// </summary>
/// <param name="c">The Unicode character entered by the user.</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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);
/// <summary>
/// Called when key goes up.
/// </summary>
/// <param name="key">The keyboard key.</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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);
/// <summary>
/// Called when key goes down.
/// </summary>
/// <param name="key">The keyboard key.</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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<int32>(e.KeyData.Key)] = true;
break;
}
case EventType::KeyUp:
{
_state.Keys[static_cast<int32>(e.KeyData.Key)] = false;
break;
}
}
}
// Send events further
queue.Add(_queue);
_queue.Clear();
return false;
}
void ResetState() override;;
bool Update(EventQueue& queue) final override;
};

View File

@@ -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.
/// </summary>
/// <param name="newPosition">The new mouse position.</param>
void OnMouseMoved(const Vector2& newPosition)
{
_prevState.MousePosition = newPosition;
_state.MousePosition = newPosition;
}
void OnMouseMoved(const Vector2& newPosition);
/// <summary>
/// Called when mouse button goes down.
@@ -139,14 +135,7 @@ public:
/// <param name="position">The mouse position.</param>
/// <param name="button">The button.</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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);
/// <summary>
/// Called when mouse button goes up.
@@ -154,14 +143,7 @@ public:
/// <param name="position">The mouse position.</param>
/// <param name="button">The button.</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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);
/// <summary>
/// Called when mouse double clicks.
@@ -169,38 +151,20 @@ public:
/// <param name="position">The mouse position.</param>
/// <param name="button">The button.</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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);
/// <summary>
/// Called when mouse moves.
/// </summary>
/// <param name="position">The mouse position.</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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);
/// <summary>
/// Called when mouse leaves the input source area.
/// </summary>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
void OnMouseLeave(Window* target = nullptr)
{
Event& e = _queue.AddOne();
e.Type = EventType::MouseLeave;
e.Target = target;
}
void OnMouseLeave(Window* target = nullptr);
/// <summary>
/// Called when mouse wheel moves.
@@ -208,76 +172,11 @@ public:
/// <param name="position">The mouse position.</param>
/// <param name="delta">The normalized delta (range [-1;1]).</param>
/// <param name="target">The target window to receive this event, otherwise input system will pick the window automatically.</param>
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<int32>(e.MouseData.Button)] = true;
break;
}
case EventType::MouseUp:
{
_state.MouseButtons[static_cast<int32>(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;
};

View File

@@ -211,7 +211,7 @@ public:
/// <param name="view">The result camera view matrix.</param>
/// <param name="projection">The result camera projection matrix.</param>
/// <param name="viewport">The custom output viewport. Use null to skip it.</param>
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

View File

@@ -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

View File

@@ -173,6 +173,11 @@ Actor* PrefabManager::SpawnPrefab(Prefab* prefab, Actor* parent, Dictionary<Guid
return nullptr;
}
auto root = (Actor*)sceneObjects.Value->At(0);
if (!root)
{
LOG(Warning, "Failed to load prefab root object.");
return nullptr;
}
// Prepare parent linkage for prefab root actor
root->_parent = parent;

View File

@@ -2,7 +2,11 @@
#pragma once
#include <ThirdParty/PhysX/foundation/PxTransform.h>
namespace physx
{
class PxRigidActor;
class PxTransform;
}
/// <summary>
/// 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.
/// </summary>
/// <returns>PhysX rigid actor or null if not using</returns>
virtual PxRigidActor* GetRigidActor() = 0;
virtual physx::PxRigidActor* GetRigidActor() = 0;
/// <summary>
/// Called when actor's active transformation gets changed after the physics simulation step.

View File

@@ -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)

View File

@@ -4,7 +4,6 @@
#include "Collider.h"
#include "Engine/Physics/Actors/IPhysicsActor.h"
#include <PxFiltering.h>
/// <summary>
/// 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:

View File

@@ -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());

View File

@@ -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();

View File

@@ -228,6 +228,8 @@ void ReadStream::ReadVariantType(VariantType* data)
if (typeNameLength == MAX_int32)
{
ReadInt32(&typeNameLength);
if (typeNameLength == 0)
return;
data->TypeName = static_cast<char*>(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);

View File

@@ -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;

View File

@@ -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")]

View File

@@ -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."