134 Commits
wip ... goake

Author SHA1 Message Date
cdbb9baeb8 Fix custom content and importers blocking scripting reload
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
Continuous Deployment / Editor (Windows) (push) Has been cancelled
Continuous Deployment / Game (Windows) (push) Has been cancelled
Continuous Deployment / Editor (Linux) (push) Has been cancelled
Continuous Deployment / Game (Linux) (push) Has been cancelled
Continuous Deployment / Editor (Mac) (push) Has been cancelled
Continuous Deployment / Game (Mac) (push) Has been cancelled
2024-05-01 18:53:20 +03:00
e12bb0ffe7 Fix error when ContentDatabase gets rebuilt while initializing editor 2024-05-01 18:53:19 +03:00
27e45554a4 _prefab unloadfix 2024-05-01 18:53:19 +03:00
bdb28b8589 Clear VisjectSurface node caches and context menus during scripts reload 2024-05-01 18:53:19 +03:00
83b301684d Refactor NativeInterop.GetTypeSize 2024-05-01 18:53:19 +03:00
d70aa20a7a Release Prefab assets when reloading Scripting service 2024-05-01 18:53:19 +03:00
b958ecc64f Close and restore Prefab windows during scripting reload 2024-05-01 18:53:18 +03:00
e573703c4a Clear references holding on to types in game assemblies 2024-05-01 18:53:18 +03:00
48fa41fc58 Fix wrong prefab event unregistration 2024-05-01 18:53:18 +03:00
25036be05f Fix scripting AssemblyLoadContext not getting unloaded
# Conflicts:
#	Source/Engine/Engine/NativeInterop.Managed.cs
2024-05-01 18:53:18 +03:00
c16ec763c2 Revert "Initialize ScriptingService earlier"
This reverts commit 0566e17b23273feffed0c41ed61f7e56d6e8f1a8.
2024-05-01 18:53:17 +03:00
a986ede53f Revert "_init script earlier fixup"
This reverts commit daee7b77ffd3d3e641b0881b874fc0a2180dbffa.
2024-05-01 18:53:17 +03:00
5c110fe154 _pr enforce ; 2024-05-01 18:53:17 +03:00
460128dd82 _font fixes 2024-05-01 18:53:17 +03:00
75d83a2ef3 _dotnet events 2024-05-01 18:53:16 +03:00
91a6450c94 _interpolate 2024-05-01 18:53:16 +03:00
440ecea5ca _prebuilt thingy 2024-05-01 18:53:16 +03:00
d32f690eac _font whiteline skip fix 2024-05-01 18:53:16 +03:00
f7677b6ab8 _debug log binding fixies 2024-05-01 18:53:15 +03:00
6d9c6fecf7 _net8 wip 2024-05-01 18:53:15 +03:00
81f94e08a9 Cleanup 2024-05-01 18:53:15 +03:00
a5ffe8893a _gchandle string intern 2024-05-01 18:53:15 +03:00
8a41e04641 Revert "_assetref setunsafe (unstable buggy)"
This reverts commit 89d359e0078bbec8c84cad07950ad5df6df46fc3.
2024-05-01 18:53:14 +03:00
22132d550c _assetref setunsafe (unstable buggy) 2024-05-01 18:53:14 +03:00
9f2016b619 _windowfps fixx 2024-05-01 18:53:14 +03:00
43e85e58ee _fixup 2024-05-01 18:53:14 +03:00
e50f87a5fb _fixup 2024-05-01 18:53:13 +03:00
79135e596a Throttle rendering in static content windows 2024-05-01 18:53:13 +03:00
63d298ca84 _guh 2024-05-01 18:53:13 +03:00
db318b56e3 Throttle tooltip window rendering 2024-05-01 18:53:13 +03:00
0fb0492738 Show Editor window true framerate in the fps counter widget 2024-05-01 18:53:13 +03:00
7ed59a4426 Add setting for specifying custom framerate when window is not active 2024-05-01 18:53:12 +03:00
a818f39464 Implement custom rendering framerate for RenderTask 2024-05-01 18:53:12 +03:00
d83220aad6 Fix window focus propagating to all windows when application is focused 2024-05-01 18:53:12 +03:00
70d7e9204a _line fixes 2024-05-01 18:53:12 +03:00
84da819f30 _font fixups
_font fixup

_font visject scaling fix

_font scaling dpi fixes

_font fix wrapping
2024-05-01 18:53:11 +03:00
f29a014aec _line render small opt 2024-05-01 18:53:11 +03:00
a2edead792 _font cache whitespace 2024-05-01 18:53:11 +03:00
479b65fab5 _font getchar opt2 2024-05-01 18:53:11 +03:00
e175c2ce3a _matrix experiments 2024-05-01 18:53:10 +03:00
9d1b65730f _font drawtext transform opt 2024-05-01 18:53:10 +03:00
dea5f7aa4e _matrix3x3 multiply unrolling 2024-05-01 18:53:10 +03:00
0c8064fb0c _font small opt 2024-05-01 18:53:10 +03:00
49497d1a78 _font array storage 2024-05-01 18:53:10 +03:00
674d5b9709 _font drawcall opt 2024-05-01 18:53:09 +03:00
26ae90a999 _font cached transform 2024-05-01 18:53:09 +03:00
cad96d8131 _font writereserve 2024-05-01 18:53:09 +03:00
df62892725 _font kerning cache 2024-05-01 18:53:09 +03:00
43b2348d62 _font cache v2 2024-05-01 18:53:08 +03:00
54761f40fe _font cache processtext entry 2024-05-01 18:53:08 +03:00
4ad78fdb80 Use SIMD-instructions in half-precision floats with AVX instruction set 2024-05-01 18:53:08 +03:00
e8cb1686c3 Add build setting for target CPU architecture in C++ compile environment 2024-05-01 18:53:08 +03:00
20a92a994e _gchandle list final 2024-05-01 18:53:08 +03:00
3df1e86ecb _gchandle weak v2 2024-05-01 18:53:07 +03:00
70edfbb146 _gchandle 2024-05-01 18:53:07 +03:00
a8ef6e69fe RawInput: Vector2 to Float2 refactor 2024-05-01 18:53:07 +03:00
753a6c73f8 RawInput: fix input latching when dragging and switching between windows 2024-05-01 18:53:07 +03:00
66b0b4c965 Use separate WndProc for raw input handling 2024-05-01 18:53:06 +03:00
57ab58608e RawInput: fix double keyboard input and incorrect mouse wheel input 2024-05-01 18:53:06 +03:00
210dd603b0 RawInput: handle more mouse events and fix double mouse events 2024-05-01 18:53:06 +03:00
44e726ceca Implement RawInput (WIP) 2024-05-01 18:53:06 +03:00
e8c50ec442 _init script earlier fixup 2024-05-01 18:53:06 +03:00
983c22a3a6 Initialize ScriptingService earlier 2024-05-01 18:53:05 +03:00
9e8865bd12 Support BytesContainer as a structure field in scripting 2024-05-01 18:53:05 +03:00
203cede21d Require semicolon after most engine API macros 2024-05-01 18:53:05 +03:00
e21c06e595 _asset locking 2024-05-01 18:53:04 +03:00
279badf0f9 _setidealprocessor 2024-05-01 18:53:04 +03:00
af326f934c _time build cache 2024-05-01 18:53:04 +03:00
68c9ff92b9 _fix tests 2024-05-01 18:53:04 +03:00
d65af4c621 _enet timeout 2024-05-01 18:53:04 +03:00
d3f14efbbd _adaptive sleep 2024-05-01 18:53:03 +03:00
07c34fa70b _time CreateScenes 2024-05-01 18:53:03 +03:00
19b5da4338 _xaudio2 2024-05-01 18:53:03 +03:00
9b68acd648 Remove texturereferences in default materials 2024-05-01 18:53:03 +03:00
1f265bddf4 Fix XAudio2 DequeueProcessedBuffers
Some checks failed
Build Android / Game (Android, Release ARM64) (push) Has been cancelled
Build iOS / Game (iOS, Release ARM64) (push) Has been cancelled
Build Linux / Editor (Linux, Development x64) (push) Has been cancelled
Build Linux / Game (Linux, Release x64) (push) Has been cancelled
Build macOS / Editor (Mac, Development ARM64) (push) Has been cancelled
Build macOS / Game (Mac, Release ARM64) (push) Has been cancelled
Build Windows / Editor (Windows, Development x64) (push) Has been cancelled
Build Windows / Game (Windows, Release x64) (push) Has been cancelled
Tests / Tests (Linux) (push) Has been cancelled
Tests / Tests (Windows) (push) Has been cancelled
FlushSourceBuffers flushes all the pending buffers, not only just the
processed buffers.
2024-05-01 18:48:32 +03:00
3237849132 Fix looping audio sources not looping seamlessly 2024-05-01 18:48:31 +03:00
2be4d2b717 Optimize RichTextBox rendering with long text 2024-05-01 18:45:31 +03:00
dc3a1e142a Refactor native interop internal type lookup 2024-05-01 18:45:20 +03:00
b6d375e9a3 Move generated marshallers into separate namespace
Avoid polluting the `FlaxEngine` namespace with interop related
marshallers, move those to nested namespace called `Interop` where most
of the common marshallers are placed already.
2024-05-01 18:45:20 +03:00
495b6d6abc Include original type of the fields in blittable struct in comments 2024-05-01 18:45:20 +03:00
a49b398c7f Refactor struct custom marshalling generation 2024-05-01 18:45:20 +03:00
c8e893d2ec Fix assigning null values into value types in Custom Editor
Resets back to previous value instead of setting the editor value to
empty.
2024-05-01 18:44:58 +03:00
3a665199e7 Avoid deserializing clipboard content in Custom Editor paste checks 2024-05-01 18:44:58 +03:00
ca1aa89ba1 Update Editor options when window is shown 2024-05-01 18:44:27 +03:00
d92aaeb2b0 Fix Editor options data applying in realtime after first save
Reclone the data in order to not modify the currently applied options
data after save.
2024-05-01 18:44:27 +03:00
5f950cbb7e Store Debug Log view options in Editor options 2024-05-01 18:44:26 +03:00
8f613774cb Expose GPUTexture::DownloadData to Scripting API 2024-05-01 18:43:45 +03:00
c5c440469e Increase Editor profiler depth 2024-05-01 18:43:32 +03:00
1e6ed32c63 Update to enet 2.3.6 2024-05-01 18:43:31 +03:00
3ee6bffef7 Always run fixed update ticks at fixed deltatime
The random variance in fixed updates makes it impossible to do anything deterministic during physics ticks.
2024-05-01 18:43:31 +03:00
6105323ecc Update Transform component separately when applying Gizmo transform 2024-05-01 18:43:31 +03:00
23f8707927 Disable LFS override 2024-05-01 18:42:58 +03:00
761c8415dc Merge branch 'master' into signalgame
# Conflicts:
#	Flax.flaxproj
2024-05-01 18:42:14 +03:00
Wojtek Figat
cdeb9a3b15 Merge remote-tracking branch 'origin/master' into 1.9
# Conflicts:
#	Content/Editor/Camera/M_Camera.flax
#	Content/Editor/CubeTexturePreviewMaterial.flax
#	Content/Editor/DebugMaterials/DDGIDebugProbes.flax
#	Content/Editor/DebugMaterials/SingleColor/Decal.flax
#	Content/Editor/DebugMaterials/SingleColor/Particle.flax
#	Content/Editor/DebugMaterials/SingleColor/Surface.flax
#	Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax
#	Content/Editor/DebugMaterials/SingleColor/Terrain.flax
#	Content/Editor/DefaultFontMaterial.flax
#	Content/Editor/Gizmo/FoliageBrushMaterial.flax
#	Content/Editor/Gizmo/Material.flax
#	Content/Editor/Gizmo/MaterialWire.flax
#	Content/Editor/Gizmo/SelectionOutlineMaterial.flax
#	Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax
#	Content/Editor/Highlight Material.flax
#	Content/Editor/Icons/IconsMaterial.flax
#	Content/Editor/IesProfilePreviewMaterial.flax
#	Content/Editor/Particles/Particle Material Color.flax
#	Content/Editor/Particles/Smoke Material.flax
#	Content/Editor/SpriteMaterial.flax
#	Content/Editor/Terrain/Circle Brush Material.flax
#	Content/Editor/Terrain/Highlight Terrain Material.flax
#	Content/Editor/TexturePreviewMaterial.flax
#	Content/Editor/Wires Debug Material.flax
#	Content/Engine/DefaultDeformableMaterial.flax
#	Content/Engine/DefaultMaterial.flax
#	Content/Engine/DefaultTerrainMaterial.flax
#	Content/Engine/SingleColorMaterial.flax
#	Content/Engine/SkyboxMaterial.flax
#	Source/Engine/Graphics/Materials/MaterialShader.h
2024-04-23 10:30:01 +02:00
Wojtek Figat
60e8d73079 Merge remote-tracking branch 'origin/master' into 1.9
# Conflicts:
#	Source/Engine/Renderer/RenderList.cpp
#	Source/Engine/Renderer/RenderList.h
2024-04-17 09:58:59 +02:00
Wojtek Figat
cf23892bd4 Fix sun shadows invalidate when view rotates 2024-04-14 23:51:20 +02:00
Wojtek Figat
25f3cef8c3 Fix artifacts due to light shape culling and use depth test to improve perf 2024-04-14 23:44:08 +02:00
Wojtek Figat
00f2a0b825 Improve doc 2024-04-12 11:29:21 +02:00
Wojtek Figat
7342629a86 Add dynamic resolution for static shadow map tiles limited by current dynamic res 2024-04-11 18:47:32 +02:00
Wojtek Figat
5f860db6a5 Fix typo 2024-04-11 17:34:21 +02:00
Wojtek Figat
6233718b06 Update engine shaders 2024-04-11 17:33:42 +02:00
Wojtek Figat
62444315de Add METERS_TO_UNITS and impl metric units in shadows rendering 2024-04-11 16:38:43 +02:00
Wojtek Figat
a532ea7b42 Add InvalidateShadow for manual shadow cache refresh 2024-04-11 16:34:42 +02:00
Wojtek Figat
803249f126 Minor tweaks 2024-04-11 16:19:35 +02:00
Wojtek Figat
4e65b76b8c Optimize BoundingSphere.Intersects to be inlined by the compiler 2024-04-11 15:58:34 +02:00
Wojtek Figat
890b2da108 Add **shadows caching for static geometry** 2024-04-11 15:35:18 +02:00
Wojtek Figat
eac1d19a09 Add additional StaticFlagsCompare to Render View for dynamic or static only drawing 2024-04-11 10:21:13 +02:00
Wojtek Figat
c4949de28f Add new Static Flag Shadow for cached shadow maps 2024-04-11 10:20:21 +02:00
Wojtek Figat
340ef194d3 Add grey out to obsolete/deprecated members in properties panel 2024-04-10 13:36:59 +02:00
Wojtek Figat
b4547ec4d2 Minor fixes 2024-04-10 11:03:33 +02:00
Wojtek Figat
89f7e442f7 Fix point light seams due to missing shadow map borders 2024-04-10 11:03:18 +02:00
Wojtek Figat
e7bef5e880 Bring back Optimized PCF sampling for shadow maps
61323f8526
2024-04-09 17:55:29 +02:00
Wojtek Figat
ff7c986fb1 Add better stability to Cascaded Shadow Maps projection 2024-04-09 16:58:22 +02:00
Wojtek Figat
708fba5136 Add variable rate update for shadow maps atlas based on distance to light 2024-04-08 00:04:57 +02:00
Wojtek Figat
7d92779e99 Merge remote-tracking branch 'origin/master' into 1.9 2024-04-05 21:50:42 +02:00
Wojtek Figat
4c8528dcae Remove branch macro as it's just texture sample in lights shader 2024-04-05 12:48:34 +02:00
Wojtek Figat
3efd1e4e84 Optimize local lights sphere mesh rendering to match the area better 2024-04-05 12:48:09 +02:00
Wojtek Figat
0cc6669cbd Reimplement cascaded shadow maps blending via dithering 2024-04-05 10:59:34 +02:00
Wojtek Figat
8bd409e95d DIsable certain shader features in Volumetric Fog shader 2024-04-04 14:35:22 +02:00
Wojtek Figat
3d0d41ebff Add reducing shadows quality for smaller local lights 2024-04-04 13:29:38 +02:00
Wojtek Figat
61323f8526 Refactor shadows rendering to use Shadow Map Atlas 2024-04-04 12:54:07 +02:00
Wojtek Figat
017def29d4 Rename ShadowSamplerPCF to ShadowSamplerLinear 2024-04-03 13:29:45 +02:00
Wojtek Figat
13a04c2941 Add stencilValue for stencil buffer clearing 2024-04-02 14:56:26 +02:00
Wojtek Figat
bc9cdf5cdb Update version 2024-04-02 14:34:43 +02:00
Wojtek Figat
f7470af42d Optimize depth pass rendering to batch simple materials together 2024-03-26 18:04:08 +01:00
Wojtek Figat
5c356ec22a Fix Global Surface Atlas defragmentation flicker when atlas it nearly full 2024-03-26 16:50:58 +01:00
Wojtek Figat
06a35da0a8 Merge remote-tracking branch 'origin/master' into 1.9 2024-03-26 16:45:31 +01:00
Wojtek Figat
55af307c43 Optimize env probes data storage in renderer 2024-03-26 15:01:12 +01:00
Wojtek Figat
4ab572426d Various renamings 2024-03-26 14:27:10 +01:00
Wojtek Figat
01d91bf102 Optimize decals rendering 2024-03-26 14:05:24 +01:00
Wojtek Figat
2dfb1058b2 Optimize world matrix storage for drawable objects to use Matrix3x4 instead of full matrix 2024-03-26 11:29:01 +01:00
Wojtek Figat
cdbb2cc813 Refactor shader structures naming with a prefix 2024-03-25 17:52:48 +01:00
Wojtek Figat
0e00f1e0eb Refactor lights data in renderer storage 2024-03-25 17:13:40 +01:00
Wojtek Figat
d13621e631 Skip CloseFileHandles if file is not in use 2024-03-25 16:50:48 +01:00
256 changed files with 5755 additions and 4084 deletions

View File

@@ -1,4 +1,4 @@
# Redirect to our own Git LFS server
[lfs]
url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false
#url="https://gitlab.flaxengine.com/flax/flaxengine.git/info/lfs"
locksverify = false

BIN
Content/Editor/Camera/M_Camera.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Gizmo/Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Gizmo/MaterialWire.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
Content/Editor/Highlight Material.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Editor/Icons/IconsMaterial.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@@ -16,7 +16,6 @@
#include "./Flax/ExponentialHeightFog.hlsl"
@2// Forward Shading: Constants
LightData DirectionalLight;
LightShadowData DirectionalLightShadow;
LightData SkyLight;
ProbeData EnvironmentProbe;
ExponentialHeightFogData ExponentialHeightFog;
@@ -26,9 +25,9 @@ LightData LocalLights[MAX_LOCAL_LIGHTS];
@3// Forward Shading: Resources
TextureCube EnvProbe : register(t__SRV__);
TextureCube SkyLightTexture : register(t__SRV__);
Texture2DArray DirectionalLightShadowMap : register(t__SRV__);
Buffer<float4> ShadowsBuffer : register(t__SRV__);
Texture2D<float> ShadowMap : register(t__SRV__);
@4// Forward Shading: Utilities
DECLARE_LIGHTSHADOWDATA_ACCESS(DirectionalLightShadow);
@5// Forward Shading: Shaders
// Pixel Shader function for Forward Pass
@@ -80,11 +79,8 @@ void PS_Forward(
// Calculate lighting from a single directional light
float4 shadowMask = 1.0f;
if (DirectionalLight.CastShadows > 0)
{
LightShadowData directionalLightShadowData = GetDirectionalLightShadowData();
shadowMask.r = SampleShadow(DirectionalLight, directionalLightShadowData, DirectionalLightShadowMap, gBuffer, shadowMask.g);
}
ShadowSample shadow = SampleDirectionalLightShadow(DirectionalLight, ShadowsBuffer, ShadowMap, gBuffer);
shadowMask = GetShadowMask(shadow);
float4 light = GetLighting(ViewPos, DirectionalLight, gBuffer, shadowMask, false, false);
// Calculate lighting from sky light

View File

@@ -26,7 +26,7 @@ struct RibbonInput
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x3 WorldMatrix;
uint SortedIndicesOffset;
float PerInstanceRandom;
int ParticleStride;
@@ -45,7 +45,7 @@ int RibbonWidthOffset;
int RibbonTwistOffset;
int RibbonFacingVectorOffset;
uint RibbonSegmentCount;
float4x4 WorldMatrixInverseTransposed;
float4x3 WorldMatrixInverseTransposed;
@1META_CB_END
// Particles attributes buffer
@@ -138,7 +138,7 @@ MaterialInput GetMaterialInput(PixelInput input)
#if USE_INSTANCING
#define GetInstanceTransform(input) float4x4(float4(input.InstanceTransform1.xyz, 0.0f), float4(input.InstanceTransform2.xyz, 0.0f), float4(input.InstanceTransform3.xyz, 0.0f), float4(input.InstanceOrigin.xyz, 1.0f))
#else
#define GetInstanceTransform(input) WorldMatrix;
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
#endif
// Removes the scale vector from the local to world transformation matrix (supports instancing)
@@ -264,12 +264,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
float3 TransformParticlePosition(float3 input)
{
return mul(float4(input, 1.0f), WorldMatrix).xyz;
return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
}
float3 TransformParticleVector(float3 input)
{
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
}
@8
@@ -333,7 +333,7 @@ VertexOutput VS_Sprite(SpriteInput input, uint particleIndex : SV_InstanceID)
float2 spriteSize = GetParticleVec2(particleIndex, SpriteSizeOffset);
int spriteFacingMode = SpriteFacingModeOffset != -1 ? GetParticleInt(particleIndex, SpriteFacingModeOffset) : -1;
float4x4 world = WorldMatrix;
float4x4 world = ToMatrix4x4(WorldMatrix);
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
float3x3 viewRot = transpose((float3x3)ViewMatrix);
float3 position = mul(float4(particlePosition, 1), world).xyz;
@@ -463,11 +463,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
}
// Read particle data
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
float3 particlePosition = GetParticleVec3(particleIndex, PositionOffset);
float3 particleScale = GetParticleVec3(particleIndex, ScaleOffset);
float3 particleRotation = GetParticleVec3(particleIndex, RotationOffset);
int modelFacingMode = ModelFacingModeOffset != -1 ? GetParticleInt(particleIndex, ModelFacingModeOffset) : -1;
float3 position = mul(float4(particlePosition, 1), WorldMatrix).xyz;
float3 position = mul(float4(particlePosition, 1), worldMatrix).xyz;
// Compute final vertex position in the world
float3x3 eulerMatrix = EulerMatrix(radians(particleRotation));
@@ -506,7 +507,7 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
world = mul(world, scaleMatrix);
}
world = transpose(world);
world = mul(world, WorldMatrix);
world = mul(world, worldMatrix);
// Calculate the vertex position in world space
output.WorldPosition = mul(float4(input.Position, 1), world).xyz;
@@ -520,12 +521,12 @@ VertexOutput VS_Model(ModelInput input, uint particleIndex : SV_InstanceID)
#if USE_VERTEX_COLOR
output.VertexColor = input.Color;
#endif
output.InstanceOrigin = WorldMatrix[3].xyz;
output.InstanceOrigin = worldMatrix[3].xyz;
output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = CalcTangentToLocal(input);
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
half3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
output.TBN = tangentToWorld;
// Get material input params if need to evaluate any material property
@@ -625,12 +626,13 @@ VertexOutput VS_Ribbon(RibbonInput input, uint vertexIndex : SV_VertexID)
#if USE_VERTEX_COLOR
output.VertexColor = 1;
#endif
output.InstanceOrigin = WorldMatrix[3].xyz;
float4x4 world = ToMatrix4x4(WorldMatrix);
output.InstanceOrigin = world[3].xyz;
output.InstanceParams = PerInstanceRandom;
// Calculate tanget space to world space transformation matrix for unit vectors
half3x3 tangentToLocal = float3x3(tangentRight, tangentUp, cross(tangentRight, tangentUp));
half3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
half3x3 tangentToWorld = CalcTangentToWorld(world, tangentToLocal);
output.TBN = tangentToWorld;
// Get material input params if need to evaluate any material property

View File

@@ -10,8 +10,8 @@
@7
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x4 PrevWorldMatrix;
float4x3 WorldMatrix;
float4x3 PrevWorldMatrix;
float2 Dummy0;
float LODDitherFactor;
float PerInstanceRandom;
@@ -171,7 +171,7 @@ MaterialInput GetMaterialInput(PixelInput input)
#if USE_INSTANCING
#define CalculateInstanceTransform(input) float4x4 world = GetInstanceTransform(input); output.Geometry.InstanceTransform1 = input.InstanceTransform1.xyz; output.Geometry.InstanceTransform2 = input.InstanceTransform2.xyz; output.Geometry.InstanceTransform3 = input.InstanceTransform3.xyz;
#else
#define CalculateInstanceTransform(input) float4x4 world = WorldMatrix; output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
#define CalculateInstanceTransform(input) float4x4 world = ToMatrix4x4(WorldMatrix); output.Geometry.InstanceTransform1 = world[0].xyz; output.Geometry.InstanceTransform2 = world[1].xyz; output.Geometry.InstanceTransform3 = world[2].xyz;
#endif
// Removes the scale vector from the local to world transformation matrix (supports instancing)
@@ -328,7 +328,7 @@ VertexOutput VS(ModelInput input)
// Compute world space vertex position
CalculateInstanceTransform(input);
output.Geometry.WorldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), PrevWorldMatrix).xyz;
output.Geometry.PrevWorldPosition = mul(float4(input.Position.xyz, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
// Compute clip space position
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
@@ -402,7 +402,7 @@ float4 VS_Depth(ModelInput_PosOnly input) : SV_Position
#if USE_INSTANCING
float4x4 world = GetInstanceTransform(input);
#else
float4x4 world = WorldMatrix;
float4x4 world = ToMatrix4x4(WorldMatrix);
#endif
float3 worldPosition = mul(float4(input.Position.xyz, 1), world).xyz;
float4 position = mul(float4(worldPosition, 1), ViewProjectionMatrix);
@@ -508,9 +508,9 @@ VertexOutput VS_Skinned(ModelInput_Skinned input)
output.Geometry.WorldPosition = mul(float4(position, 1), world).xyz;
#if PER_BONE_MOTION_BLUR
float3 prevPosition = SkinPrevPosition(input);
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), PrevWorldMatrix).xyz;
output.Geometry.PrevWorldPosition = mul(float4(prevPosition, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
#else
output.Geometry.PrevWorldPosition = mul(float4(position, 1), PrevWorldMatrix).xyz;
output.Geometry.PrevWorldPosition = mul(float4(position, 1), ToMatrix4x4(PrevWorldMatrix)).xyz;
#endif
// Compute clip space position

View File

@@ -17,7 +17,7 @@
@7
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 WorldMatrix;
float4x3 WorldMatrix;
float3 WorldInvScale;
float WorldDeterminantSign;
float PerInstanceRandom;
@@ -194,7 +194,7 @@ float3 TransformViewVectorToWorld(MaterialInput input, float3 viewVector)
// Transforms a vector from local space to world space
float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
{
float3x3 localToWorld = (float3x3)WorldMatrix;
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
return mul(localVector, localToWorld);
}
@@ -202,7 +202,7 @@ float3 TransformLocalVectorToWorld(MaterialInput input, float3 localVector)
// Transforms a vector from local space to world space
float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
{
float3x3 localToWorld = (float3x3)WorldMatrix;
float3x3 localToWorld = (float3x3)ToMatrix4x4(WorldMatrix);
//localToWorld = RemoveScaleFromLocalToWorld(localToWorld);
return mul(localToWorld, worldVector);
}
@@ -210,7 +210,7 @@ float3 TransformWorldVectorToLocal(MaterialInput input, float3 worldVector)
// Gets the current object position
float3 GetObjectPosition(MaterialInput input)
{
return WorldMatrix[3].xyz;
return ToMatrix4x4(WorldMatrix)[3].xyz;
}
// Gets the current object size
@@ -365,7 +365,8 @@ VertexOutput VS(TerrainVertexInput input)
float3 position = float3(positionXZ.x, height, positionXZ.y);
// Compute world space vertex position
output.Geometry.WorldPosition = mul(float4(position, 1), WorldMatrix).xyz;
float4x4 worldMatrix = ToMatrix4x4(WorldMatrix);
output.Geometry.WorldPosition = mul(float4(position, 1), worldMatrix).xyz;
// Compute clip space position
output.Position = mul(float4(output.Geometry.WorldPosition, 1), ViewProjectionMatrix);
@@ -389,7 +390,7 @@ VertexOutput VS(TerrainVertexInput input)
// Compute world space normal vector
float3x3 tangentToLocal = CalcTangentBasisFromWorldNormal(normal);
float3x3 tangentToWorld = CalcTangentToWorld(WorldMatrix, tangentToLocal);
float3x3 tangentToWorld = CalcTangentToWorld(worldMatrix, tangentToLocal);
output.Geometry.WorldNormal = tangentToWorld[2];
// Get material input params if need to evaluate any material property

View File

@@ -13,8 +13,8 @@
// Primary constant buffer (with additional material parameters)
META_CB_BEGIN(0, Data)
float4x4 InverseViewProjectionMatrix;
float4x4 WorldMatrix;
float4x4 WorldMatrixInverseTransposed;
float4x3 WorldMatrix;
float4x3 WorldMatrixInverseTransposed;
float3 GridSize;
float PerInstanceRandom;
float Dummy0;
@@ -49,7 +49,7 @@ struct MaterialInput
#endif
};
#define GetInstanceTransform(input) WorldMatrix;
#define GetInstanceTransform(input) ToMatrix4x4(WorldMatrix);
// Removes the scale vector from the local to world transformation matrix (supports instancing)
float3x3 RemoveScaleFromLocalToWorld(float3x3 localToWorld)
@@ -170,12 +170,12 @@ float4 GetParticleVec4(uint particleIndex, int offset)
float3 TransformParticlePosition(float3 input)
{
return mul(float4(input, 1.0f), WorldMatrix).xyz;
return mul(float4(input, 1.0f), ToMatrix4x4(WorldMatrix)).xyz;
}
float3 TransformParticleVector(float3 input)
{
return mul(float4(input, 0.0f), WorldMatrixInverseTransposed).xyz;
return mul(float4(input, 0.0f), ToMatrix4x4(WorldMatrixInverseTransposed)).xyz;
}
@8
@@ -219,7 +219,7 @@ void PS_VolumetricFog(Quad_GS2PS input, out float4 VBufferA : SV_Target0, out fl
materialInput.ParticleIndex = ParticleIndex;
materialInput.TBN = float3x3(float3(1, 0, 0), float3(0, 1, 0), float3(0, 0, 1));
materialInput.TwoSidedSign = 1.0f;
materialInput.InstanceOrigin = WorldMatrix[3].xyz;
materialInput.InstanceOrigin = ToMatrix4x4(WorldMatrix)[3].xyz;
materialInput.InstanceParams = PerInstanceRandom;
materialInput.SvPosition = clipPos;
Material material = GetMaterialPS(materialInput);

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

BIN
Content/Editor/Wires Debug Material.flax (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
Content/Engine/DefaultMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/DefaultTerrainMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SingleColorMaterial.flax (Stored with Git LFS)

Binary file not shown.

BIN
Content/Engine/SkyboxMaterial.flax (Stored with Git LFS)

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

View File

@@ -2,9 +2,9 @@
"Name": "Flax",
"Version": {
"Major": 1,
"Minor": 8,
"Revision": 1,
"Build": 6511
"Minor": 9,
"Revision": 0,
"Build": 6601
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.",

View File

@@ -1246,6 +1246,8 @@ bool CookAssetsStep::Perform(CookingData& data)
assetStats.Count++;
assetStats.ContentSize += FileSystem::GetFileSize(cookedFilePath);
LOG(Info, "Cooked size of {0}: {1}KB", assetId, (FileSystem::GetFileSize(cookedFilePath) / (1024)));
if (packageBuilder.Add(data, i->Value, cookedFilePath))
return true;
}

View File

@@ -353,9 +353,9 @@ bool DeployDataStep::Perform(CookingData& data)
data.AddRootEngineAsset(TEXT("Engine/Textures/NormalTexture"));
data.AddRootEngineAsset(TEXT("Engine/Textures/BlackTexture"));
data.AddRootEngineAsset(TEXT("Engine/Textures/WhiteTexture"));
data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensStarburst"));
data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensColor"));
data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensDirt"));
//data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensStarburst"));
//data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensColor"));
//data.AddRootEngineAsset(TEXT("Engine/Textures/DefaultLensDirt"));
data.AddRootEngineAsset(TEXT("Engine/Textures/Bokeh/Circle"));
data.AddRootEngineAsset(TEXT("Engine/Textures/Bokeh/Hexagon"));
data.AddRootEngineAsset(TEXT("Engine/Textures/Bokeh/Octagon"));

View File

@@ -377,6 +377,10 @@ namespace FlaxEditor.CustomEditors
else if (Values.HasDefaultValue && CanRevertDefaultValue)
color = Color.Yellow * 0.8f;
LinkedLabel.HighlightStripColor = color;
// Grey out deprecated members
if (Values.IsObsolete)
LinkedLabel.TextColor = LinkedLabel.TextColorHighlighted = FlaxEngine.GUI.Style.Current.ForegroundGrey;
}
}
@@ -659,7 +663,7 @@ namespace FlaxEditor.CustomEditors
}
}
if (obj == null || Values.Type.IsInstanceOfType(obj))
if ((obj == null && !Values.Type.IsValueType) || Values.Type.IsInstanceOfType(obj))
{
result = obj;
return true;
@@ -671,20 +675,7 @@ namespace FlaxEditor.CustomEditors
/// <summary>
/// Gets a value indicating whether can paste value from the system clipboard to the property value container.
/// </summary>
public bool CanPaste
{
get
{
try
{
return GetClipboardObject(out _, false);
}
catch
{
return false;
}
}
}
public bool CanPaste => !string.IsNullOrEmpty(Clipboard.Text);
/// <summary>
/// Sets the value from the system clipboard.

View File

@@ -192,6 +192,15 @@ namespace FlaxEditor.CustomEditors
Presenter.AfterLayout?.Invoke(layout);
}
/// <inheritdoc />
protected override void Deinitialize()
{
Editor = null;
_overrideEditor = null;
base.Deinitialize();
}
/// <inheritdoc />
protected override void OnModified()
{

View File

@@ -186,7 +186,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
if (_linkedPrefabId != Guid.Empty)
{
_linkedPrefabId = Guid.Empty;
Editor.Instance.Prefabs.PrefabApplied -= OnPrefabApplying;
Editor.Instance.Prefabs.PrefabApplying -= OnPrefabApplying;
Editor.Instance.Prefabs.PrefabApplied -= OnPrefabApplied;
}
}

View File

@@ -1029,6 +1029,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
protected override void Deinitialize()
{
_scriptToggles = null;
_scripts.Clear();
base.Deinitialize();
}

View File

@@ -474,32 +474,7 @@ namespace FlaxEditor.CustomEditors.Editors
}
if (layout.Editors.Count != 0)
{
var sb = Clipboard.Text;
if (!string.IsNullOrEmpty(sb))
{
try
{
var data = JsonSerializer.Deserialize<string[]>(sb);
if (data == null || data.Length != layout.Editors.Count)
return false;
for (var i = 0; i < layout.Editors.Count; i++)
{
Clipboard.Text = data[i];
if (!layout.Editors[i].CanPaste)
return false;
}
return true;
}
catch
{
return false;
}
finally
{
Clipboard.Text = sb;
}
}
return false;
return !string.IsNullOrEmpty(Clipboard.Text);
}
if (layout.Children.Any(x => x is LayoutElementsContainer))
{
@@ -824,6 +799,15 @@ namespace FlaxEditor.CustomEditors.Editors
OnGroupsEnd();
}
/// <inheritdoc />
protected override void Deinitialize()
{
_visibleIfCaches = null;
_visibleIfPropertiesListsCache = null;
base.Deinitialize();
}
/// <inheritdoc />
public override void Refresh()
{

View File

@@ -139,6 +139,11 @@ namespace FlaxEditor.CustomEditors
/// </summary>
public bool IsArray => Type != ScriptType.Null && Type.IsArray;
/// <summary>
/// True if member or type has <see cref="System.ObsoleteAttribute"/> that marks it as obsolete.
/// </summary>
public bool IsObsolete { get; }
/// <summary>
/// Gets the values types array (without duplicates).
/// </summary>
@@ -160,6 +165,7 @@ namespace FlaxEditor.CustomEditors
{
Info = info;
Type = Info.ValueType;
IsObsolete = Info.HasAttribute(typeof(ObsoleteAttribute), true);
}
/// <summary>

View File

@@ -497,6 +497,8 @@ namespace FlaxEditor
Debug.LogException(ex);
}
ManagedHandle.ManagedHandlePool.TryCollectWeakHandles();
Profiler.EndEvent();
}

View File

@@ -235,6 +235,9 @@ namespace FlaxEditor.GUI.ContextMenu
_previouslyFocused = parentWin.FocusedControl;
Focus();
OnShow();
// Throttle rendering of static content
_window.RenderTask.RenderFPS = 2;
}
/// <summary>

View File

@@ -178,6 +178,9 @@ namespace FlaxEditor.GUI.Dialogs
windowGUI.PerformLayout();
OnShow();
// Throttle rendering of static content
_window.RenderTask.RenderFPS = 2;
}
private void OnClosing(ClosingReason reason, ref bool cancel)

View File

@@ -346,6 +346,10 @@ namespace FlaxEditor.GUI.Docking
{
if (button == MouseButton.Left)
{
// Workaround to make sure the mouse down event which initiated dragging in moved window gets properly
// released when this window gets destroyed.
_toMove.Window.Window.Internal_OnMouseUp(ref location, button);
Dispose();
}
}
@@ -447,6 +451,9 @@ namespace FlaxEditor.GUI.Docking
Window = Platform.CreateWindow(ref settings);
Window.Opacity = 0.6f;
Window.GUI.BackgroundColor = Style.Current.DragWindow;
// Throttle rendering of static content
Window.RenderTask.RenderFPS = 2;
}
else
{
@@ -480,6 +487,9 @@ namespace FlaxEditor.GUI.Docking
win = Platform.CreateWindow(ref settings);
win.Opacity = 0.6f;
win.GUI.BackgroundColor = Style.Current.DragWindow;
// Throttle rendering of static content
win.RenderTask.RenderFPS = 2;
}
/// <summary>

View File

@@ -88,6 +88,8 @@ namespace FlaxEditor.Modules
// Register AssetItems serialization helper (serialize ref ID only)
FlaxEngine.Json.JsonSerializer.Settings.Converters.Add(new AssetItemConverter());
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}
private void OnContentAssetDisposing(Asset asset)
@@ -1260,6 +1262,47 @@ namespace FlaxEditor.Modules
}
}
private void OnScriptsReloadBegin()
{
var enabledEvents = _enableEvents;
_enableEvents = false;
_isDuringFastSetup = true;
var startItems = _itemsCreated;
foreach (var project in Projects)
{
if (project.Content != null)
{
//Dispose(project.Content.Folder);
for (int i = 0; i < project.Content.Folder.Children.Count; i++)
{
Dispose(project.Content.Folder.Children[i]);
i--;
}
}
if (project.Source != null)
{
//Dispose(project.Source.Folder);
for (int i = 0; i < project.Source.Folder.Children.Count; i++)
{
Dispose(project.Source.Folder.Children[i]);
i--;
}
}
}
List<ContentProxy> removeProxies = new List<ContentProxy>();
foreach (var proxy in Editor.Instance.ContentDatabase.Proxy)
{
if (proxy.GetType().IsCollectible)
removeProxies.Add(proxy);
}
foreach (var proxy in removeProxies)
RemoveProxy(proxy, false);
_isDuringFastSetup = false;
_enableEvents = enabledEvents;
}
/// <inheritdoc />
public override void OnUpdate()
{
@@ -1285,6 +1328,7 @@ namespace FlaxEditor.Modules
public override void OnExit()
{
FlaxEngine.Content.AssetDisposing -= OnContentAssetDisposing;
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
// Disable events
_enableEvents = false;

View File

@@ -391,6 +391,20 @@ namespace FlaxEditor.Modules
public override void OnInit()
{
ImportFileEntry.RegisterDefaultTypes();
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}
private void OnScriptsReloadBegin()
{
// Remove import file types from scripting assemblies
List<string> removeFileTypes = new List<string>();
foreach (var pair in ImportFileEntry.FileTypes)
{
if (pair.Value.Method.IsCollectible || (pair.Value.Target != null && pair.Value.Target.GetType().IsCollectible))
removeFileTypes.Add(pair.Key);
}
foreach (var fileType in removeFileTypes)
ImportFileEntry.FileTypes.Remove(fileType);
}
/// <inheritdoc />
@@ -451,6 +465,7 @@ namespace FlaxEditor.Modules
/// <inheritdoc />
public override void OnExit()
{
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
EndWorker();
}
}

View File

@@ -5,10 +5,12 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml;
using FlaxEditor.Content;
using FlaxEditor.GUI.Dialogs;
using FlaxEditor.GUI.Docking;
using FlaxEditor.Windows;
using FlaxEditor.Windows.Assets;
using FlaxEditor.Windows.Profiler;
@@ -39,6 +41,7 @@ namespace FlaxEditor.Modules
public DockState DockState;
public DockPanel DockedTo;
public int DockedTabIndex;
public float? SplitterValue = null;
public bool SelectOnShow = false;
@@ -48,6 +51,8 @@ namespace FlaxEditor.Modules
public Float2 FloatSize;
public Float2 FloatPosition;
public AssetItem Item;
// Constructor, to allow for default values
public WindowRestoreData()
{
@@ -807,6 +812,56 @@ namespace FlaxEditor.Modules
Editor.StateMachine.StateChanged += OnEditorStateChanged;
}
internal void AddToRestore(PrefabWindow win)
{
var type = win.GetType();
var winData = new WindowRestoreData();
var panel = win.ParentDockPanel;
// Ensure that this window is only selected following recompilation
// if it was the active tab in its dock panel. Otherwise, there is a
// risk of interrupting the user's workflow by potentially selecting
// background tabs.
var window = win.RootWindow?.Window;
winData.SelectOnShow = panel.SelectedTab == win;
winData.DockedTabIndex = 0;
if (panel is FloatWindowDockPanel && window != null && panel.TabsCount == 1)
{
winData.DockState = DockState.Float;
winData.FloatPosition = window.Position;
winData.FloatSize = window.ClientSize;
winData.Maximize = window.IsMaximized;
winData.Minimize = window.IsMinimized;
winData.DockedTo = panel;
}
else
{
for (int i = 0; i < panel.Tabs.Count; i++)
{
if (panel.Tabs[i] == win)
{
winData.DockedTabIndex = i;
break;
}
}
if (panel.TabsCount > 1)
{
winData.DockState = DockState.DockFill;
winData.DockedTo = panel;
}
else
{
winData.DockState = panel.TryGetDockState(out var splitterValue);
winData.DockedTo = panel.ParentDockPanel;
winData.SplitterValue = splitterValue;
}
}
winData.AssemblyName = type.Assembly.GetName().Name;
winData.TypeName = type.FullName;
winData.Item = win.Item;
_restoreWindows.Add(winData);
}
internal void AddToRestore(CustomEditorWindow win)
{
var type = win.GetType();
@@ -839,7 +894,8 @@ namespace FlaxEditor.Modules
{
winData.DockState = DockState.DockFill;
winData.DockedTo = panel;
}else
}
else
{
winData.DockState = panel.TryGetDockState(out var splitterValue);
winData.DockedTo = panel.ParentDockPanel;
@@ -853,36 +909,89 @@ namespace FlaxEditor.Modules
private void OnScriptsReloadEnd()
{
for (int i = 0; i < _restoreWindows.Count; i++)
// Go in reverse order to create floating Prefab windows first before docked windows
for (int i = _restoreWindows.Count - 1; i >= 0; i--)
{
var winData = _restoreWindows[i];
try
{
var assembly = Utils.GetAssemblyByName(winData.AssemblyName);
if (assembly != null)
if (assembly == null)
continue;
var type = assembly.GetType(winData.TypeName);
if (type == null)
continue;
if (type == typeof(PrefabWindow))
{
var type = assembly.GetType(winData.TypeName);
if (type != null)
var win = new PrefabWindow(Editor.Instance, winData.Item);
win.Show(winData.DockState, winData.DockState != DockState.Float ? winData.DockedTo : null, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
{
var win = (CustomEditorWindow)Activator.CreateInstance(type);
win.Show(winData.DockState, winData.DockedTo, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
var window = win.RootWindow.Window;
window.Position = winData.FloatPosition;
if (winData.Maximize)
{
var window = win.Window.RootWindow.Window;
window.Position = winData.FloatPosition;
if (winData.Maximize)
{
window.Maximize();
}
else if (winData.Minimize)
{
window.Minimize();
}
else
{
window.ClientSize = winData.FloatSize;
}
window.Maximize();
}
else if (winData.Minimize)
{
window.Minimize();
}
else
{
window.ClientSize = winData.FloatSize;
}
// Update panel reference in other windows docked to this panel
foreach (ref var otherData in CollectionsMarshal.AsSpan(_restoreWindows))
{
if (otherData.DockedTo == winData.DockedTo)
otherData.DockedTo = win.ParentDockPanel;
}
}
var panel = win.ParentDockPanel;
int currentTabIndex = 0;
for (int pi = 0; pi < panel.TabsCount; pi++)
{
if (panel.Tabs[pi] == win)
{
currentTabIndex = pi;
break;
}
}
while (currentTabIndex > winData.DockedTabIndex)
{
win.ParentDockPanel.MoveTabLeft(currentTabIndex);
currentTabIndex--;
}
while (currentTabIndex < winData.DockedTabIndex)
{
win.ParentDockPanel.MoveTabRight(currentTabIndex);
currentTabIndex++;
}
}
else
{
var win = (CustomEditorWindow)Activator.CreateInstance(type);
win.Show(winData.DockState, winData.DockedTo, winData.SelectOnShow, winData.SplitterValue);
if (winData.DockState == DockState.Float)
{
var window = win.Window.RootWindow.Window;
window.Position = winData.FloatPosition;
if (winData.Maximize)
{
window.Maximize();
}
else if (winData.Minimize)
{
window.Minimize();
}
else
{
window.ClientSize = winData.FloatSize;
}
}
}

View File

@@ -175,13 +175,6 @@ namespace FlaxEditor.Options
[EditorDisplay("Interface", "New Window Location"), EditorOrder(150), Tooltip("Define the opening method for new windows, open in a new tab by default.")]
public DockStateProxy NewWindowLocation { get; set; } = DockStateProxy.Float;
/// <summary>
/// Gets or sets the timestamps prefix mode for debug log messages.
/// </summary>
[DefaultValue(TimestampsFormats.None)]
[EditorDisplay("Interface"), EditorOrder(210), Tooltip("The timestamps prefix mode for debug log messages.")]
public TimestampsFormats DebugLogTimestampsFormat { get; set; } = TimestampsFormats.None;
/// <summary>
/// Gets or sets the editor icons scale. Editor restart required.
/// </summary>
@@ -211,23 +204,72 @@ namespace FlaxEditor.Options
public bool SeparateValueAndUnit { get; set; }
/// <summary>
/// Gets or sets the timestamps prefix mode for output log messages.
/// Gets or sets the timestamps prefix mode for debug log messages.
/// </summary>
[DefaultValue(TimestampsFormats.TimeSinceStartup)]
[EditorDisplay("Output Log", "Timestamps Format"), EditorOrder(300), Tooltip("The timestamps prefix mode for output log messages.")]
public TimestampsFormats OutputLogTimestampsFormat { get; set; } = TimestampsFormats.TimeSinceStartup;
[DefaultValue(TimestampsFormats.None)]
[EditorDisplay("Debug Log"), EditorOrder(350), Tooltip("The timestamps prefix mode for debug log messages.")]
public TimestampsFormats DebugLogTimestampsFormat { get; set; } = TimestampsFormats.None;
/// <summary>
/// Gets or sets the clear on play for debug log messages.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Debug Log", "Clear on Play"), EditorOrder(360), Tooltip("Clears all log entries on enter playmode.")]
public bool DebugLogClearOnPlay { get; set; } = true;
/// <summary>
/// Gets or sets the collapse mode for debug log messages.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Debug Log"), EditorOrder(361), Tooltip("Collapses similar or repeating log entries.")]
public bool DebugLogCollapse { get; set; } = true;
/// <summary>
/// Gets or sets the automatic pause on error for debug log messages.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Debug Log", "Pause on Error"), EditorOrder(362), Tooltip("Performs auto pause on error.")]
public bool DebugLogPauseOnError { get; set; } = false;
/// <summary>
/// Gets or sets the automatic pause on error for debug log messages.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Debug Log", "Show error messages"), EditorOrder(370), Tooltip("Shows/hides error messages.")]
public bool DebugLogShowErrorMessages { get; set; } = true;
/// <summary>
/// Gets or sets the automatic pause on error for debug log messages.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Debug Log", "Show warning messages"), EditorOrder(371), Tooltip("Shows/hides warning messages.")]
public bool DebugLogShowWarningMessages { get; set; } = true;
/// <summary>
/// Gets or sets the automatic pause on error for debug log messages.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Debug Log", "Show info messages"), EditorOrder(372), Tooltip("Shows/hides info messages.")]
public bool DebugLogShowInfoMessages { get; set; } = true;
/// <summary>
/// Gets or sets the timestamps prefix mode for output log messages.
/// </summary>
[DefaultValue(TimestampsFormats.TimeSinceStartup)]
[EditorDisplay("Output Log", "Timestamps Format"), EditorOrder(400), Tooltip("The timestamps prefix mode for output log messages.")]
public TimestampsFormats OutputLogTimestampsFormat { get; set; } = TimestampsFormats.TimeSinceStartup;
/// <summary>
/// Gets or sets the log type prefix mode for output log messages.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Output Log", "Show Log Type"), EditorOrder(310), Tooltip("Determines whether show log type prefix in output log messages.")]
[EditorDisplay("Output Log", "Show Log Type"), EditorOrder(410), Tooltip("Determines whether show log type prefix in output log messages.")]
public bool OutputLogShowLogType { get; set; } = true;
/// <summary>
/// Gets or sets the output log text font.
/// </summary>
[EditorDisplay("Output Log", "Text Font"), EditorOrder(320), Tooltip("The output log text font.")]
[EditorDisplay("Output Log", "Text Font"), EditorOrder(420), Tooltip("The output log text font.")]
public FontReference OutputLogTextFont
{
get => _outputLogFont;
@@ -246,63 +288,70 @@ namespace FlaxEditor.Options
/// Gets or sets the output log text color.
/// </summary>
[DefaultValue(typeof(Color), "1,1,1,1")]
[EditorDisplay("Output Log", "Text Color"), EditorOrder(330), Tooltip("The output log text color.")]
[EditorDisplay("Output Log", "Text Color"), EditorOrder(430), Tooltip("The output log text color.")]
public Color OutputLogTextColor { get; set; } = Color.White;
/// <summary>
/// Gets or sets the output log text shadow color.
/// </summary>
[DefaultValue(typeof(Color), "0,0,0,0.5")]
[EditorDisplay("Output Log", "Text Shadow Color"), EditorOrder(340), Tooltip("The output log text shadow color.")]
[EditorDisplay("Output Log", "Text Shadow Color"), EditorOrder(440), Tooltip("The output log text shadow color.")]
public Color OutputLogTextShadowColor { get; set; } = new Color(0, 0, 0, 0.5f);
/// <summary>
/// Gets or sets the output log text shadow offset. Set to 0 to disable this feature.
/// </summary>
[DefaultValue(typeof(Float2), "1,1")]
[EditorDisplay("Output Log", "Text Shadow Offset"), EditorOrder(340), Tooltip("The output log text shadow offset. Set to 0 to disable this feature.")]
[EditorDisplay("Output Log", "Text Shadow Offset"), EditorOrder(445), Tooltip("The output log text shadow offset. Set to 0 to disable this feature.")]
public Float2 OutputLogTextShadowOffset { get; set; } = new Float2(1);
/// <summary>
/// Gets or sets a value indicating whether auto-focus output log window on code compilation error.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Output Log", "Focus Output Log On Compilation Error"), EditorOrder(350), Tooltip("Determines whether auto-focus output log window on code compilation error.")]
[EditorDisplay("Output Log", "Focus Output Log On Compilation Error"), EditorOrder(450), Tooltip("Determines whether auto-focus output log window on code compilation error.")]
public bool FocusOutputLogOnCompilationError { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether auto-focus output log window on game build error.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Output Log", "Focus Output Log On Game Build Error"), EditorOrder(360), Tooltip("Determines whether auto-focus output log window on game build error.")]
[EditorDisplay("Output Log", "Focus Output Log On Game Build Error"), EditorOrder(460), Tooltip("Determines whether auto-focus output log window on game build error.")]
public bool FocusOutputLogOnGameBuildError { get; set; } = true;
/// <summary>
/// Gets or sets the value for automatic scroll to bottom in output log.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Output Log", "Scroll to bottom"), EditorOrder(470), Tooltip("Scroll the output log view to bottom automatically after new lines are added.")]
public bool OutputLogScrollToBottom { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating whether auto-focus game window on play mode start.
/// </summary>
[DefaultValue(true)]
[EditorDisplay("Play In-Editor", "Focus Game Window On Play"), EditorOrder(400), Tooltip("Determines whether auto-focus game window on play mode start.")]
[EditorDisplay("Play In-Editor", "Focus Game Window On Play"), EditorOrder(500), Tooltip("Determines whether auto-focus game window on play mode start.")]
public bool FocusGameWinOnPlay { get; set; } = true;
/// <summary>
/// Gets or sets a value indicating what action should be taken upon pressing the play button.
/// </summary>
[DefaultValue(PlayAction.PlayScenes)]
[EditorDisplay("Play In-Editor", "Play Button Action"), EditorOrder(410)]
[EditorDisplay("Play In-Editor", "Play Button Action"), EditorOrder(510)]
public PlayAction PlayButtonAction { get; set; } = PlayAction.PlayScenes;
/// <summary>
/// Gets or sets a value indicating how the game window should be displayed when the game is launched.
/// </summary>
[DefaultValue(GameWindowMode.Docked)]
[EditorDisplay("Play In-Editor", "Game Window Mode"), EditorOrder(420), Tooltip("Determines how the game window is displayed when the game is launched.")]
[EditorDisplay("Play In-Editor", "Game Window Mode"), EditorOrder(520), Tooltip("Determines how the game window is displayed when the game is launched.")]
public GameWindowMode DefaultGameWindowMode { get; set; } = GameWindowMode.Docked;
/// <summary>
/// Gets or sets a value indicating the number of game clients to launch when building and/or running cooked game.
/// </summary>
[DefaultValue(1), Range(1, 4)]
[EditorDisplay("Cook & Run"), EditorOrder(500)]
[EditorDisplay("Cook & Run"), EditorOrder(600)]
public int NumberOfGameClientsToLaunch = 1;
private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.PrimaryFont);
@@ -317,13 +366,13 @@ namespace FlaxEditor.Options
/// <summary>
/// The list of fallback fonts to use when main text font is missing certain characters. Empty to use fonts from GraphicsSettings.
/// </summary>
[EditorDisplay("Fonts"), EditorOrder(650)]
[EditorDisplay("Fonts"), EditorOrder(750)]
public FontAsset[] FallbackFonts = new FontAsset[1] { FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.FallbackFont) };
/// <summary>
/// Gets or sets the title font for editor UI.
/// </summary>
[EditorDisplay("Fonts"), EditorOrder(600), Tooltip("The title font for editor UI.")]
[EditorDisplay("Fonts"), EditorOrder(700), Tooltip("The title font for editor UI.")]
public FontReference TitleFont
{
get => _titleFont;
@@ -341,7 +390,7 @@ namespace FlaxEditor.Options
/// <summary>
/// Gets or sets the large font for editor UI.
/// </summary>
[EditorDisplay("Fonts"), EditorOrder(610), Tooltip("The large font for editor UI.")]
[EditorDisplay("Fonts"), EditorOrder(710), Tooltip("The large font for editor UI.")]
public FontReference LargeFont
{
get => _largeFont;
@@ -359,7 +408,7 @@ namespace FlaxEditor.Options
/// <summary>
/// Gets or sets the medium font for editor UI.
/// </summary>
[EditorDisplay("Fonts"), EditorOrder(620), Tooltip("The medium font for editor UI.")]
[EditorDisplay("Fonts"), EditorOrder(720), Tooltip("The medium font for editor UI.")]
public FontReference MediumFont
{
get => _mediumFont;
@@ -377,7 +426,7 @@ namespace FlaxEditor.Options
/// <summary>
/// Gets or sets the small font for editor UI.
/// </summary>
[EditorDisplay("Fonts"), EditorOrder(630), Tooltip("The small font for editor UI.")]
[EditorDisplay("Fonts"), EditorOrder(730), Tooltip("The small font for editor UI.")]
public FontReference SmallFont
{
get => _smallFont;

View File

@@ -469,6 +469,7 @@ namespace FlaxEditor.SceneGraph
{
ChildNodes[i].OnDispose();
}
ChildNodes.Clear();
SceneGraphFactory.Nodes.Remove(ID);
}

View File

@@ -19,6 +19,8 @@ namespace FlaxEditor.Surface
[HideInEditor]
public class AnimGraphSurface : VisjectSurface
{
private static NodesCache _nodesCache = new NodesCache(IterateNodesCache);
private static readonly List<GroupArchetype> StateMachineGroupArchetypes = new List<GroupArchetype>(new[]
{
// Customized Animations group with special nodes to use here
@@ -87,8 +89,6 @@ namespace FlaxEditor.Surface
}
};
private static NodesCache _nodesCache = new NodesCache(IterateNodesCache);
/// <summary>
/// The state machine editing context menu.
/// </summary>
@@ -158,6 +158,8 @@ namespace FlaxEditor.Surface
private void OnScriptsReloadBegin()
{
_nodesCache.Clear();
// Check if any of the nodes comes from the game scripts - those can be reloaded at runtime so prevent crashes
bool hasTypeFromGameScripts = Editor.Instance.CodeEditing.AnimGraphNodes.HasTypeFromGameScripts;

View File

@@ -24,6 +24,7 @@ namespace FlaxEditor.Surface
public BehaviorTreeSurface(IVisjectSurfaceOwner owner, Action onSave, FlaxEditor.Undo undo)
: base(owner, onSave, undo, CreateStyle())
{
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}
private static SurfaceStyle CreateStyle()
@@ -35,6 +36,11 @@ namespace FlaxEditor.Surface
return style;
}
private void OnScriptsReloadBegin()
{
_nodesCache.Clear();
}
private static void DrawBox(Box box)
{
var rect = new Rectangle(Float2.Zero, box.Size);
@@ -186,6 +192,7 @@ namespace FlaxEditor.Surface
{
if (IsDisposing)
return;
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
_nodesCache.Wait();
base.OnDestroy();

View File

@@ -190,15 +190,7 @@ namespace FlaxEditor.Surface
if (data == null || data.Length < 2)
return false;
try
{
var model = JsonConvert.DeserializeObject<DataModel>(data);
return model?.Nodes != null && model.Nodes.Length != 0;
}
catch (Exception)
{
return false;
}
return true;
}
/// <summary>
@@ -215,7 +207,15 @@ namespace FlaxEditor.Surface
try
{
// Load Mr Json
var model = FlaxEngine.Json.JsonSerializer.Deserialize<DataModel>(data);
DataModel model;
try
{
model = FlaxEngine.Json.JsonSerializer.Deserialize<DataModel>(data);
}
catch
{
return;
}
if (model.Nodes == null)
model.Nodes = new DataModelNode[0];

View File

@@ -397,6 +397,15 @@ namespace FlaxEditor.Surface
// Init drag handlers
DragHandlers.Add(_dragAssets = new DragAssets<DragDropEventArgs>(ValidateDragItem));
DragHandlers.Add(_dragParameters = new DragNames<DragDropEventArgs>(SurfaceParameter.DragPrefix, ValidateDragParameter));
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}
private void OnScriptsReloadBegin()
{
_activeVisjectCM = null;
_cmPrimaryMenu?.Dispose();
_cmPrimaryMenu = null;
}
/// <summary>
@@ -995,6 +1004,8 @@ namespace FlaxEditor.Surface
_activeVisjectCM = null;
_cmPrimaryMenu?.Dispose();
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
base.OnDestroy();
}
}

View File

@@ -55,6 +55,12 @@ namespace FlaxEditor.Surface
{
_supportsImplicitCastFromObjectToBoolean = true;
DragHandlers.Add(_dragActors = new DragActors(ValidateDragActor));
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
}
private void OnScriptsReloadBegin()
{
_nodesCache.Clear();
}
private bool ValidateDragActor(ActorNode actor)
@@ -596,6 +602,7 @@ namespace FlaxEditor.Surface
{
if (IsDisposing)
return;
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
_nodesCache.Wait();
base.OnDestroy();

View File

@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using FlaxEngine;
@@ -101,6 +102,7 @@ namespace FlaxEditor.Utilities
Editor.Log("Creating scenes");
Stopwatch sw = Stopwatch.StartNew();
// Deserialize new scenes
int scenesCount = _scenesData.Count;
for (int i = 0; i < scenesCount; i++)
@@ -113,6 +115,9 @@ namespace FlaxEditor.Utilities
throw new Exception("Failed to deserialize scene");
}
}
sw.Stop();
Editor.Log("Creating scenes time: " + sw.Elapsed.TotalMilliseconds + "ms");
Profiler.EndEvent();
}

View File

@@ -7,7 +7,7 @@
enum class PixelFormat : unsigned;
enum class DirectorySearchOption;
class TextureData;
struct TextureData;
/// <summary>
/// Helper functions for the editor.

View File

@@ -1241,6 +1241,10 @@ namespace FlaxEditor.Viewport
private class FpsCounter : Control
{
private int fps;
private int accumFrames;
private float lastUpdate;
public FpsCounter(float x, float y)
: base(x, y, 64, 32)
{
@@ -1250,7 +1254,15 @@ namespace FlaxEditor.Viewport
{
base.Draw();
int fps = Engine.FramesPerSecond;
accumFrames++;
float timeNow = Time.TimeSinceStartup;
if (timeNow - lastUpdate >= 1.0f)
{
fps = accumFrames;
lastUpdate = timeNow;
accumFrames = 0;
}
Color color = Color.Green;
if (fps < 13)
color = Color.Red;

View File

@@ -471,7 +471,13 @@ namespace FlaxEditor.Viewport
trans.SetRotation(ref world);
trans.Translation += world.TranslationVector;
}
obj.Transform = trans;
if (obj is ActorNode actorNode)
{
actorNode.Actor.Position = trans.Translation;
actorNode.Actor.Orientation = trans.Orientation;
}
else
obj.Transform = trans;
}
TransformGizmo.EndTransforming();
}
@@ -520,7 +526,9 @@ namespace FlaxEditor.Viewport
/// <param name="scaleDelta">The scale delta.</param>
public void ApplyTransform(List<SceneGraphNode> selection, ref Vector3 translationDelta, ref Quaternion rotationDelta, ref Vector3 scaleDelta)
{
bool applyTranslation = !translationDelta.IsZero;
bool applyRotation = !rotationDelta.IsIdentity;
bool applyScale = !scaleDelta.IsZero;
bool useObjCenter = TransformGizmo.ActivePivot == TransformGizmoBase.PivotType.ObjectCenter;
Vector3 gizmoPosition = TransformGizmo.Position;
@@ -555,13 +563,29 @@ namespace FlaxEditor.Viewport
}
// Apply scale
const float scaleLimit = 99_999_999.0f;
trans.Scale = Float3.Clamp(trans.Scale + scaleDelta, new Float3(-scaleLimit), new Float3(scaleLimit));
if (applyScale)
{
const float scaleLimit = 99_999_999.0f;
trans.Scale = Float3.Clamp(trans.Scale + scaleDelta, new Float3(-scaleLimit), new Float3(scaleLimit)); ;
}
// Apply translation
trans.Translation += translationDelta;
if (applyTranslation)
{
trans.Translation += translationDelta;
}
obj.Transform = trans;
if (obj is ActorNode actorNode)
{
if (applyTranslation)
actorNode.Actor.Position = trans.Translation;
if (applyRotation)
actorNode.Actor.Orientation = trans.Orientation;
if (applyScale)
actorNode.Actor.Scale = trans.Scale;
}
else
obj.Transform = trans;
}
}

View File

@@ -357,7 +357,9 @@ namespace FlaxEditor.Viewport
/// <param name="scaleDelta">The scale delta.</param>
public void ApplyTransform(List<SceneGraphNode> selection, ref Vector3 translationDelta, ref Quaternion rotationDelta, ref Vector3 scaleDelta)
{
bool applyTranslation = !translationDelta.IsZero;
bool applyRotation = !rotationDelta.IsIdentity;
bool applyScale = !scaleDelta.IsZero;
bool useObjCenter = TransformGizmo.ActivePivot == TransformGizmoBase.PivotType.ObjectCenter;
Vector3 gizmoPosition = TransformGizmo.Position;
@@ -387,13 +389,29 @@ namespace FlaxEditor.Viewport
}
// Apply scale
const float scaleLimit = 99_999_999.0f;
trans.Scale = Float3.Clamp(trans.Scale + scaleDelta, new Float3(-scaleLimit), new Float3(scaleLimit));
if (applyScale)
{
const float scaleLimit = 99_999_999.0f;
trans.Scale = Float3.Clamp(trans.Scale + scaleDelta, new Float3(-scaleLimit), new Float3(scaleLimit));
}
// Apply translation
trans.Translation += translationDelta;
if (applyTranslation)
{
trans.Translation += translationDelta;
}
obj.Transform = trans;
if (obj is ActorNode actorNode)
{
if (applyTranslation)
actorNode.Actor.Position = trans.Translation;
if (applyRotation)
actorNode.Actor.Orientation = trans.Orientation;
if (applyScale)
actorNode.Actor.Scale = trans.Scale;
}
else
obj.Transform = trans;
}
}

View File

@@ -193,7 +193,6 @@ namespace FlaxEditor.Windows.Assets
Editor.Prefabs.PrefabApplied += OnPrefabApplied;
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
// Setup input actions
InputActions.Add(options => options.Undo, () =>
@@ -305,24 +304,18 @@ namespace FlaxEditor.Windows.Assets
}
}
if (!IsHidden)
{
Editor.Instance.Windows.AddToRestore(this);
}
// Cleanup
Deselect();
Graph.MainActor = null;
_viewport.Prefab = null;
_undo?.Clear(); // TODO: maybe don't clear undo?
}
private void OnScriptsReloadEnd()
{
_isScriptsReloading = false;
if (_asset == null || !_asset.IsLoaded)
return;
// Restore
OnPrefabOpened();
_undo.Clear();
ClearEditedFlag();
Close();
}
private void OnUndoEvent(IUndoAction action)
@@ -532,7 +525,6 @@ namespace FlaxEditor.Windows.Assets
{
Editor.Prefabs.PrefabApplied -= OnPrefabApplied;
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
_undo.Dispose();
Graph.Dispose();

View File

@@ -29,6 +29,7 @@ namespace FlaxEditor.Windows
private const string ProjectDataLastViewedFolder = "LastViewedFolder";
private bool _isWorkspaceDirty;
private string _workspaceRebuildLocation;
private string _lastViewedFolderBeforeReload;
private SplitPanel _split;
private Panel _contentViewPanel;
private Panel _contentTreePanel;
@@ -144,26 +145,6 @@ namespace FlaxEditor.Windows
FlaxEditor.Utilities.Utils.SetupCommonInputActions(this);
// Content database events
editor.ContentDatabase.WorkspaceModified += () => _isWorkspaceDirty = true;
editor.ContentDatabase.ItemRemoved += OnContentDatabaseItemRemoved;
editor.ContentDatabase.WorkspaceRebuilding += () => { _workspaceRebuildLocation = SelectedNode?.Path; };
editor.ContentDatabase.WorkspaceRebuilt += () =>
{
var selected = Editor.ContentDatabase.Find(_workspaceRebuildLocation);
if (selected is ContentFolder selectedFolder)
{
_navigationUnlocked = false;
RefreshView(selectedFolder.Node);
_tree.Select(selectedFolder.Node);
UpdateItemsSearch();
_navigationUnlocked = true;
UpdateUI();
}
else
ShowRoot();
};
var options = Editor.Options;
options.OptionsChanged += OnOptionsChanged;
@@ -1028,6 +1009,61 @@ namespace FlaxEditor.Windows
/// <inheritdoc />
public override void OnInit()
{
// Content database events
Editor.ContentDatabase.WorkspaceModified += () => _isWorkspaceDirty = true;
Editor.ContentDatabase.ItemRemoved += OnContentDatabaseItemRemoved;
Editor.ContentDatabase.WorkspaceRebuilding += () => { _workspaceRebuildLocation = SelectedNode?.Path; };
Editor.ContentDatabase.WorkspaceRebuilt += () =>
{
var selected = Editor.ContentDatabase.Find(_workspaceRebuildLocation);
if (selected is ContentFolder selectedFolder)
{
_navigationUnlocked = false;
RefreshView(selectedFolder.Node);
_tree.Select(selectedFolder.Node);
UpdateItemsSearch();
_navigationUnlocked = true;
UpdateUI();
}
else if (_root != null)
ShowRoot();
};
Refresh();
// Load last viewed folder
if (Editor.ProjectCache.TryGetCustomData(ProjectDataLastViewedFolder, out var lastViewedFolder))
{
if (Editor.ContentDatabase.Find(lastViewedFolder) is ContentFolder folder)
_tree.Select(folder.Node);
}
ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin;
ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd;
}
private void OnScriptsReloadBegin()
{
var lastViewedFolder = _tree.Selection.Count == 1 ? _tree.SelectedNode as ContentTreeNode : null;
_lastViewedFolderBeforeReload = lastViewedFolder?.Path ?? string.Empty;
_tree.RemoveChild(_root);
_root = null;
}
private void OnScriptsReloadEnd()
{
Refresh();
if (!string.IsNullOrEmpty(_lastViewedFolderBeforeReload))
{
if (Editor.ContentDatabase.Find(_lastViewedFolderBeforeReload) is ContentFolder folder)
_tree.Select(folder.Node);
}
}
private void Refresh()
{
// Setup content root node
_root = new RootContentTreeNode
@@ -1064,13 +1100,6 @@ namespace FlaxEditor.Windows
// Update UI layout
_isLayoutLocked = false;
PerformLayout();
// Load last viewed folder
if (Editor.ProjectCache.TryGetCustomData(ProjectDataLastViewedFolder, out var lastViewedFolder))
{
if (Editor.ContentDatabase.Find(lastViewedFolder) is ContentFolder folder)
_tree.Select(folder.Node);
}
}
/// <inheritdoc />
@@ -1218,6 +1247,8 @@ namespace FlaxEditor.Windows
_viewDropdown = null;
Editor.Options.OptionsChanged -= OnOptionsChanged;
ScriptsBuilder.ScriptsReloadBegin -= OnScriptsReloadBegin;
ScriptsBuilder.ScriptsReloadEnd -= OnScriptsReloadEnd;
base.OnDestroy();
}

View File

@@ -318,7 +318,6 @@ namespace FlaxEditor.Windows
{
Title = "Debug Log";
Icon = IconInfo;
OnEditorOptionsChanged(Editor.Options.Options);
FlaxEditor.Utilities.Utils.SetupCommonInputActions(this);
// Toolstrip
@@ -327,14 +326,42 @@ namespace FlaxEditor.Windows
Parent = this,
};
toolstrip.AddButton("Clear", Clear).LinkTooltip("Clears all log entries");
_clearOnPlayButton = (ToolStripButton)toolstrip.AddButton("Clear on Play").SetAutoCheck(true).SetChecked(true).LinkTooltip("Clears all log entries on enter playmode");
_collapseLogsButton = (ToolStripButton)toolstrip.AddButton("Collapse").SetAutoCheck(true).SetChecked(true).LinkTooltip("Collapses similar logs.");
_pauseOnErrorButton = (ToolStripButton)toolstrip.AddButton("Pause on Error").SetAutoCheck(true).LinkTooltip("Performs auto pause on error");
_clearOnPlayButton = (ToolStripButton)toolstrip.AddButton("Clear on Play", () =>
{
editor.Options.Options.Interface.DebugLogClearOnPlay = _clearOnPlayButton.Checked;
editor.Options.Apply(editor.Options.Options);
}).SetAutoCheck(true).LinkTooltip("Clears all log entries on enter playmode");
_collapseLogsButton = (ToolStripButton)toolstrip.AddButton("Collapse", () =>
{
editor.Options.Options.Interface.DebugLogCollapse = _collapseLogsButton.Checked;
editor.Options.Apply(editor.Options.Options);
}).SetAutoCheck(true).LinkTooltip("Collapses similar logs.");
_pauseOnErrorButton = (ToolStripButton)toolstrip.AddButton("Pause on Error", () =>
{
editor.Options.Options.Interface.DebugLogPauseOnError = _pauseOnErrorButton.Checked;
editor.Options.Apply(editor.Options.Options);
}).SetAutoCheck(true).LinkTooltip("Performs auto pause on error");
toolstrip.AddSeparator();
_groupButtons[0] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Error32, () => UpdateLogTypeVisibility(LogGroup.Error, _groupButtons[0].Checked)).SetAutoCheck(true).SetChecked(true).LinkTooltip("Shows/hides error messages");
_groupButtons[1] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Warning32, () => UpdateLogTypeVisibility(LogGroup.Warning, _groupButtons[1].Checked)).SetAutoCheck(true).SetChecked(true).LinkTooltip("Shows/hides warning messages");
_groupButtons[2] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Info32, () => UpdateLogTypeVisibility(LogGroup.Info, _groupButtons[2].Checked)).SetAutoCheck(true).SetChecked(true).LinkTooltip("Shows/hides info messages");
_groupButtons[0] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Error32, () =>
{
UpdateLogTypeVisibility(LogGroup.Error, _groupButtons[0].Checked);
editor.Options.Options.Interface.DebugLogShowErrorMessages = _groupButtons[0].Checked;
editor.Options.Apply(editor.Options.Options);
}).SetAutoCheck(true).LinkTooltip("Shows/hides error messages");
_groupButtons[1] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Warning32, () =>
{
UpdateLogTypeVisibility(LogGroup.Warning, _groupButtons[1].Checked);
editor.Options.Options.Interface.DebugLogShowWarningMessages = _groupButtons[1].Checked;
editor.Options.Apply(editor.Options.Options);
}).SetAutoCheck(true).LinkTooltip("Shows/hides warning messages");
_groupButtons[2] = (ToolStripButton)toolstrip.AddButton(editor.Icons.Info32, () =>
{
UpdateLogTypeVisibility(LogGroup.Info, _groupButtons[2].Checked);
editor.Options.Options.Interface.DebugLogShowInfoMessages = _groupButtons[2].Checked;
editor.Options.Apply(editor.Options.Options);
}).SetAutoCheck(true).LinkTooltip("Shows/hides info messages");
UpdateCount();
OnEditorOptionsChanged(Editor.Options.Options);
// Split panel
_split = new SplitPanel(Orientation.Vertical, ScrollBars.Vertical, ScrollBars.Both)
@@ -380,6 +407,12 @@ namespace FlaxEditor.Windows
private void OnEditorOptionsChanged(EditorOptions options)
{
_timestampsFormats = options.Interface.DebugLogTimestampsFormat;
_clearOnPlayButton.Checked = options.Interface.DebugLogClearOnPlay;
_collapseLogsButton.Checked = options.Interface.DebugLogCollapse;
_pauseOnErrorButton.Checked = options.Interface.DebugLogPauseOnError;
_groupButtons[0].Checked = options.Interface.DebugLogShowErrorMessages;
_groupButtons[1].Checked = options.Interface.DebugLogShowWarningMessages;
_groupButtons[2].Checked = options.Interface.DebugLogShowInfoMessages;
}
/// <summary>

View File

@@ -162,7 +162,7 @@ namespace FlaxEditor.Windows
Editor.Options.Apply(_options);
ClearDirtyFlag();
GatherData();
}
private void SetupCustomTabs()
@@ -234,6 +234,18 @@ namespace FlaxEditor.Windows
base.OnDestroy();
}
/// <inheritdoc />
protected override void OnShow()
{
if (!_isDataDirty)
{
// Refresh the data, skip when data is modified during window docking
GatherData();
}
base.OnShow();
}
/// <inheritdoc />
protected override bool OnClosing(ClosingReason reason)
{

View File

@@ -1,6 +1,5 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System.Collections.Generic;
using System.ComponentModel;
using FlaxEditor.CustomEditors;
using FlaxEngine;
@@ -96,14 +95,6 @@ namespace FlaxEditor.Windows
set => Graphics.ShadowMapsQuality = value;
}
[DefaultValue(false)]
[EditorOrder(1320), EditorDisplay("Quality", "Allow CSM Blending"), Tooltip("Enables cascades splits blending for directional light shadows.")]
public bool AllowCSMBlending
{
get => Graphics.AllowCSMBlending;
set => Graphics.AllowCSMBlending = value;
}
[NoSerialize, DefaultValue(1.0f), Limit(0.05f, 5, 0)]
[EditorOrder(1400), EditorDisplay("Quality")]
[Tooltip("The scale of the rendering resolution relative to the output dimensions. If lower than 1 the scene and postprocessing will be rendered at a lower resolution and upscaled to the output backbuffer.")]

View File

@@ -561,7 +561,7 @@ namespace FlaxEditor.Windows
{
ref var line = ref lines[j];
textBlock.Range.StartIndex = startIndex + line.FirstCharIndex;
textBlock.Range.EndIndex = startIndex + line.LastCharIndex + 1;
textBlock.Range.EndIndex = startIndex + line.LastCharIndex;
textBlock.Bounds = new Rectangle(new Float2(0.0f, prevBlockBottom), line.Size);
if (textBlock.Range.Length > 0)
@@ -570,7 +570,7 @@ namespace FlaxEditor.Windows
var regexStart = line.FirstCharIndex;
if (j == 0)
regexStart += prefixLength;
var regexLength = line.LastCharIndex + 1 - regexStart;
var regexLength = line.LastCharIndex - regexStart;
if (regexLength > 0)
{
var match = _compileRegex.Match(entryText, regexStart, regexLength);

View File

@@ -526,7 +526,7 @@ namespace FlaxEditor.Windows.Profiler
}
row.Depth = e.Depth;
row.Width = _table.Width;
row.Visible = e.Depth < 2;
row.Visible = e.Depth < 10;
row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent;
row.Parent = _table;
}

View File

@@ -370,7 +370,7 @@ namespace FlaxEditor.Windows.Profiler
}
row.Depth = e.Depth;
row.Width = _table.Width;
row.Visible = e.Depth < 3;
row.Visible = e.Depth < 13;
row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent;
row.Parent = _table;
}

View File

@@ -150,6 +150,22 @@ namespace FlaxEditor.Windows
_searchBox.Clear();
_groupSearch.DisposeChildren();
_groupSearch.PerformLayout();
// Remove tabs
var tabs = new List<Tab>();
foreach (var child in _actorGroups.Children)
{
if (child is Tab tab)
{
if (tab.Text != "Search")
tabs.Add(tab);
}
}
foreach (var tab in tabs)
{
var group = _actorGroups.Children.Find(T => T == tab);
group.Dispose();
}
}
private void OnScriptsReloadEnd()

View File

@@ -3,6 +3,7 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using FlaxEngine.Interop;
namespace FlaxEngine
{

View File

@@ -28,8 +28,8 @@ public class Audio : EngineModule
{
case TargetPlatform.Windows:
useNone = true;
useOpenAL = true;
//useXAudio2 = true;
//useOpenAL = true;
useXAudio2 = true;
break;
case TargetPlatform.XboxOne:
case TargetPlatform.UWP:

View File

@@ -428,23 +428,23 @@ void AudioSource::Update()
// Handle streaming buffers queue submit (ensure that clip has loaded the first chunk with audio data)
if (_needToUpdateStreamingBuffers && clip->Buffers[_streamingFirstChunk] != AUDIO_BUFFER_ID_INVALID)
{
// Clear flag
_needToUpdateStreamingBuffers = false;
// Get buffers in a queue count
int32 numQueuedBuffers;
AudioBackend::Source::GetQueuedBuffersCount(this, numQueuedBuffers);
// Queue missing buffers
// Queue missing buffers, make sure there is at least two buffers in queue to avoid gaps in playback
uint32 bufferId;
if (numQueuedBuffers < 1 && (bufferId = clip->Buffers[_streamingFirstChunk]) != AUDIO_BUFFER_ID_INVALID)
for (int i = numQueuedBuffers; i < 2; i++)
{
AudioBackend::Source::QueueBuffer(this, bufferId);
int bufferIndex = (_streamingFirstChunk + i) % clip->Buffers.Count();
if ((bufferId = clip->Buffers[bufferIndex]) != AUDIO_BUFFER_ID_INVALID)
AudioBackend::Source::QueueBuffer(this, bufferId);
else
_needToUpdateStreamingBuffers = true; // The buffer has not been streamed yet, try again later
}
if (numQueuedBuffers < 2 && _streamingFirstChunk + 1 < clip->Buffers.Count() && (bufferId = clip->Buffers[_streamingFirstChunk + 1]) != AUDIO_BUFFER_ID_INVALID)
{
AudioBackend::Source::QueueBuffer(this, bufferId);
}
// Clear flag
_needToUpdateStreamingBuffers = false;
// Play it if need to
if (!_isActuallyPlayingSth)
@@ -469,18 +469,25 @@ void AudioSource::Update()
// Move the chunk pointer (AudioStreamingHandler will request new chunks streaming)
_streamingFirstChunk += numProcessedBuffers;
if (GetIsLooping())
{
int32 numQueuedBuffers;
AudioBackend::Source::GetQueuedBuffersCount(this, numQueuedBuffers);
if (numQueuedBuffers < 1)
{
// Audio engine unexpectedly stopped playing the clip after queue emptied, restart the clip
_isActuallyPlayingSth = false;
}
}
// Check if reached the end
if (_streamingFirstChunk >= clip->Buffers.Count())
{
// Loop over the clip or end play
if (GetIsLooping())
{
// Move to the begin
// Move to the beginning
_streamingFirstChunk = 0;
// Stop audio and request buffers re-sync and then play continue
Stop();
Play();
}
else
{

View File

@@ -686,8 +686,6 @@ void AudioBackendXAudio2::Source_DequeueProcessedBuffers(AudioSource* source)
auto aSource = XAudio2::GetSource(source);
if (aSource && aSource->Voice)
{
const HRESULT hr = aSource->Voice->FlushSourceBuffers();
XAUDIO2_CHECK_ERROR(FlushSourceBuffers);
aSource->BuffersProcessed = 0;
}
}

View File

@@ -872,6 +872,13 @@ void VisualScriptExecutor::ProcessGroupFunction(Box* boxBase, Node* node, Value&
// Find event binding callback
auto eventBinder = ScriptingEvents::EventsTable.TryGet(Pair<ScriptingTypeHandle, StringView>(eventType, eventName));
if (!eventBinder)
{
const StringAnsiView eventNameAnsi(node->Values[1]);
auto managedEvent = eventType.GetClass()->GetEvent(eventNameAnsi.GetText());
//eventBinder = (void(**)(ScriptingObject*, void*, bool))managedEvent;
}
if (!eventBinder)
{
LOG(Error, "Cannot bind to missing event {0} from type {1}.", eventName, eventTypeName);

View File

@@ -477,7 +477,7 @@ const String& BinaryAsset::GetPath() const
uint64 BinaryAsset::GetMemoryUsage() const
{
Locker.Lock();
//ScopeLock lock(Locker);
uint64 result = Asset::GetMemoryUsage();
result += sizeof(BinaryAsset) - sizeof(Asset);
result += _dependantAssets.Capacity() * sizeof(BinaryAsset*);
@@ -487,7 +487,6 @@ uint64 BinaryAsset::GetMemoryUsage() const
if (chunk != nullptr && chunk->IsLoaded())
result += chunk->Size();
}
Locker.Unlock();
return result;
}

View File

@@ -10,7 +10,8 @@
#define DECLARE_BINARY_ASSET_HEADER(type, serializedVersion) \
DECLARE_ASSET_HEADER(type); \
static const uint32 SerializedVersion = serializedVersion; \
uint32 GetSerializedVersion() const override { return SerializedVersion; }
uint32 GetSerializedVersion() const override { return SerializedVersion; } \
static_assert(true, "")
#define REGISTER_BINARY_ASSET_ABSTRACT(type, typeName) \
const String type::TypeName = TEXT(typeName)

View File

@@ -1336,6 +1336,11 @@ FileReadStream* FlaxStorage::OpenFile()
bool FlaxStorage::CloseFileHandles()
{
// Early out if no handles are opened
Array<FileReadStream*> streams;
_file.GetValues(streams);
if (streams.IsEmpty() && Platform::AtomicRead(&_chunksLock) == 0)
return false;
PROFILE_CPU();
// Note: this is usually called by the content manager when this file is not used or on exit
@@ -1367,7 +1372,7 @@ bool FlaxStorage::CloseFileHandles()
return true; // Failed, someone is still accessing the file
// Close file handles (from all threads)
Array<FileReadStream*> streams;
streams.Clear();
_file.GetValues(streams);
for (FileReadStream* stream : streams)
{

View File

@@ -149,6 +149,6 @@ public:
CreateAssetFunction Callback;
};
#define IMPORT_SETUP(type, serializedVersion) context.Data.Header.TypeName = type::TypeName; context.Data.SerializedVersion = serializedVersion;
#define IMPORT_SETUP(type, serializedVersion) context.Data.Header.TypeName = type::TypeName; context.Data.SerializedVersion = serializedVersion
#endif

View File

@@ -53,5 +53,5 @@
#define API_PARAM(...)
#define API_TYPEDEF(...)
#define API_INJECT_CODE(...)
#define API_AUTO_SERIALIZATION(...) public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
#define DECLARE_SCRIPTING_TYPE_MINIMAL(type) public: friend class type##Internal; static struct ScriptingTypeInitializer TypeInitializer;
#define API_AUTO_SERIALIZATION(...) public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override
#define DECLARE_SCRIPTING_TYPE_MINIMAL(type) public: friend class type##Internal; static struct ScriptingTypeInitializer TypeInitializer

View File

@@ -61,9 +61,10 @@ public:
/// <summary>
/// Enables cascades splits blending for directional light shadows.
/// [Deprecated in v1.9]
/// </summary>
API_FIELD(Attributes="EditorOrder(1320), DefaultValue(false), EditorDisplay(\"Quality\", \"Allow CSM Blending\")")
bool AllowCSMBlending = false;
DEPRECATED bool AllowCSMBlending = false;
/// <summary>
/// Default probes cubemap resolution (use for Environment Probes, can be overriden per-actor).

View File

@@ -45,7 +45,7 @@ public:
} \
} \
return result; \
}
} static_assert(true, "")
// [Deprecated on 20.01.2022, expires on 20.01.2024]
#define IMPLEMENT_SETTINGS_GETTER(type, field) IMPLEMENT_ENGINE_SETTINGS_GETTER(type, field)
@@ -69,6 +69,6 @@ public:
} \
} \
return result; \
}
} static_assert(true, "")
#define DECLARE_SETTINGS_GETTER(type) static type* Get()

View File

@@ -4,9 +4,9 @@
#include "Compiler.h"
#define SAFE_DISPOSE(x) if(x) { (x)->Dispose(); (x) = nullptr; }
#define SAFE_RELEASE(x) if(x) { (x)->Release(); (x) = nullptr; }
#define SAFE_DELETE(x) if(x) { ::Delete(x); (x) = nullptr; }
#define SAFE_DISPOSE(x) if(x) { (x)->Dispose(); (x) = nullptr; } static_assert(true, "")
#define SAFE_RELEASE(x) if(x) { (x)->Release(); (x) = nullptr; } static_assert(true, "")
#define SAFE_DELETE(x) if(x) { ::Delete(x); (x) = nullptr; } static_assert(true, "")
#define INVALID_INDEX (-1)
#define _INTERNAL_CONCAT_MACROS(a, b) a ## b
#define CONCAT_MACROS(a, b) _INTERNAL_CONCAT_MACROS(a, b)
@@ -22,4 +22,9 @@
}
#define OUT_OF_MEMORY Platform::OutOfMemory(__LINE__, __FILE__)
#define MISSING_CODE(info) Platform::MissingCode(__LINE__, __FILE__, info)
#define NON_COPYABLE(type) type(type&&) = delete; type(const type&) = delete; type& operator=(const type&) = delete; type& operator=(type&&) = delete;
#define NON_COPYABLE(type) type(type&&) = delete; type(const type&) = delete; type& operator=(const type&) = delete; type& operator=(type&&) = delete
#define POD_COPYABLE(type) \
type(const type& other) { Platform::MemoryCopy(this, &other, sizeof(type)); } \
type(type&& other) noexcept { Platform::MemoryCopy(this, &other, sizeof(type)); } \
type& operator=(const type& other) { Platform::MemoryCopy(this, &other, sizeof(type)); return *this; } \
type& operator=(type&& other) noexcept { Platform::MemoryCopy(this, &other, sizeof(type)); return *this; } static_assert(true, "")

View File

@@ -13,154 +13,154 @@
#define DECLARE_ENUM_1(name, t0) enum class name{t0=0};\
static const int name##_Count = 1;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_2(name, t0, t1) enum class name{t0=0,t1};\
static const int name##_Count = 2;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_3(name, t0, t1, t2) enum class name{t0=0,t1,t2};\
static const int name##_Count = 3;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_4(name, t0, t1, t2, t3) enum class name{t0=0,t1,t2,t3};\
static const int name##_Count = 4;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_5(name, t0, t1, t2, t3, t4) enum class name{t0=0,t1,t2,t3,t4};\
static const int name##_Count = 5;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_6(name, t0, t1, t2, t3, t4, t5) enum class name{t0=0,t1,t2,t3,t4,t5};\
static const int name##_Count = 6;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_7(name, t0, t1, t2, t3, t4, t5, t6) enum class name{t0=0,t1,t2,t3,t4,t5,t6};\
static const int name##_Count = 7;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_8(name, t0, t1, t2, t3, t4, t5, t6, t7) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7};\
static const int name##_Count = 8;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_9(name, t0, t1, t2, t3, t4, t5, t6, t7, t8) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8};\
static const int name##_Count = 9;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_10(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9};\
static const int name##_Count = 10;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_11(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10};\
static const int name##_Count = 11;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_12(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11};\
static const int name##_Count = 12;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_13(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12};\
static const int name##_Count = 13;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11),ENUM_TO_STR(t12)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_14(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13};\
static const int name##_Count = 14;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11),ENUM_TO_STR(t12),ENUM_TO_STR(t13)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_15(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14};\
static const int name##_Count = 15;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11),ENUM_TO_STR(t12),ENUM_TO_STR(t13),ENUM_TO_STR(t14)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_16(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15};\
static const int name##_Count = 16;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11),ENUM_TO_STR(t12),ENUM_TO_STR(t13),ENUM_TO_STR(t14),ENUM_TO_STR(t15)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_17(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16};\
static const int name##_Count = 17;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11),ENUM_TO_STR(t12),ENUM_TO_STR(t13),ENUM_TO_STR(t14),ENUM_TO_STR(t15),ENUM_TO_STR(t16)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
#define DECLARE_ENUM_18(name, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17) enum class name{t0=0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16,t17};\
static const int name##_Count = 17;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11),ENUM_TO_STR(t12),ENUM_TO_STR(t13),ENUM_TO_STR(t14),ENUM_TO_STR(t15),ENUM_TO_STR(t16),ENUM_TO_STR(t17)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e];}static_assert(true, "")
// ..and those with base type and base value
#define DECLARE_ENUM_EX_1(name, baseType, baseVal, t0) enum class name:baseType{t0=baseVal};\
static const int name##_Count = 1;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_2(name, baseType, baseVal, t0, t1) enum class name:baseType{t0=baseVal,t1};\
static const int name##_Count = 2;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_3(name, baseType, baseVal, t0, t1, t2) enum class name:baseType{t0=baseVal,t1,t2};\
static const int name##_Count = 3;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_4(name, baseType, baseVal, t0, t1, t2, t3) enum class name:baseType{t0=baseVal,t1,t2,t3};\
static const int name##_Count = 4;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_5(name, baseType, baseVal, t0, t1, t2, t3, t4) enum class name:baseType{t0=baseVal,t1,t2,t3,t4};\
static const int name##_Count = 5;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_6(name, baseType, baseVal, t0, t1, t2, t3, t4, t5) enum class name:baseType{t0=baseVal,t1,t2,t3,t4,t5};\
static const int name##_Count = 6;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_7(name, baseType, baseVal, t0, t1, t2, t3, t4, t5, t6) enum class name:baseType{t0=baseVal,t1,t2,t3,t4,t5,t6};\
static const int name##_Count = 7;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_8(name, baseType, baseVal, t0, t1, t2, t3, t4, t5, t6, t7) enum class name:baseType{t0=baseVal,t1,t2,t3,t4,t5,t6,t7};\
static const int name##_Count = 8;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_9(name, baseType, baseVal, t0, t1, t2, t3, t4, t5, t6, t7, t8) enum class name:baseType{t0=baseVal,t1,t2,t3,t4,t5,t6,t7,t8};\
static const int name##_Count = 9;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_10(name, baseType, baseVal, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) enum class name:baseType{t0=baseVal,t1,t2,t3,t4,t5,t6,t7,t8,t9};\
static const int name##_Count = 10;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_11(name, baseType, baseVal, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) enum class name:baseType{t0=baseVal,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10};\
static const int name##_Count = 11;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
#define DECLARE_ENUM_EX_12(name, baseType, baseVal, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) enum class name:baseType{t0=baseVal,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11};\
static const int name##_Count = 11;static const Char**name##_Str(){static const Char* str[]={\
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9),ENUM_TO_STR(t10),ENUM_TO_STR(t11)};\
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}
return str;}static inline const Char*ToString(name e){return name##_Str()[(int)e - baseVal];}static_assert(true, "")
// ..and those for flags
@@ -170,7 +170,7 @@ static const int name##_Count = 1;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_2(name, baseType, t0, v0, t1, v1) \
enum class name:baseType{t0=v0,t1=v1};\
@@ -178,7 +178,7 @@ static const int name##_Count = 2;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_3(name, baseType, t0, v0, t1, v1, t2, v2) \
enum class name:baseType{t0=v0,t1=v1,t2=v2};\
@@ -186,7 +186,7 @@ static const int name##_Count = 3;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_4(name, baseType, t0, v0, t1, v1, t2, v2, t3, v3) \
enum class name:baseType{t0=v0,t1=v1,t2=v2,t3=v3};\
@@ -194,7 +194,7 @@ static const int name##_Count = 4;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2), (baseType)(v3)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_5(name, baseType, t0, v0, t1, v1, t2, v2, t3, v3, t4, v4) \
enum class name:baseType{t0=v0,t1=v1,t2=v2,t3=v3,t4=v4};\
@@ -202,7 +202,7 @@ static const int name##_Count = 5;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2), (baseType)(v3), (baseType)(v4)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_6(name, baseType, t0, v0, t1, v1, t2, v2, t3, v3, t4, v4, t5, v5) \
enum class name:baseType{t0=v0,t1=v1,t2=v2,t3=v3,t4=v4,t5=v5};\
@@ -210,7 +210,7 @@ static const int name##_Count = 6;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2), (baseType)(v3), (baseType)(v4), (baseType)(v5)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_7(name, baseType, t0, v0, t1, v1, t2, v2, t3, v3, t4, v4, t5, v5, t6, v6) \
enum class name:baseType{t0=v0,t1=v1,t2=v2,t3=v3,t4=v4,t5=v5,t6=v6};\
@@ -218,7 +218,7 @@ static const int name##_Count = 7;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2), (baseType)(v3), (baseType)(v4), (baseType)(v5), (baseType)(v6)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_8(name, baseType, t0, v0, t1, v1, t2, v2, t3, v3, t4, v4, t5, v5, t6, v6, t7, v7) \
enum class name:baseType{t0=v0,t1=v1,t2=v2,t3=v3,t4=v4,t5=v5,t6=v6,t7=v7};\
@@ -226,7 +226,7 @@ static const int name##_Count = 8;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2), (baseType)(v3), (baseType)(v4), (baseType)(v5), (baseType)(v6), (baseType)(v7)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_9(name, baseType, t0, v0, t1, v1, t2, v2, t3, v3, t4, v4, t5, v5, t6, v6, t7, v7, t8, v8) \
enum class name:baseType{t0=v0,t1=v1,t2=v2,t3=v3,t4=v4,t5=v5,t6=v6,t7=v7,t8=v8};\
@@ -234,7 +234,7 @@ static const int name##_Count = 9;static const Char**name##_Str(){static const C
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2), (baseType)(v3), (baseType)(v4), (baseType)(v5), (baseType)(v6), (baseType)(v7), (baseType)(v8)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")
#define DECLARE_ENUM_FLAGS_10(name, baseType, t0, v0, t1, v1, t2, v2, t3, v3, t4, v4, t5, v5, t6, v6, t7, v7, t8, v8, t9, v9) \
enum class name:baseType{t0=v0,t1=v1,t2=v2,t3=v3,t4=v4,t5=v5,t6=v6,t7=v7,t8=v8,t9=v9};\
@@ -242,4 +242,4 @@ static const int name##_Count = 10;static const Char**name##_Str(){static const
ENUM_TO_STR(t0),ENUM_TO_STR(t1),ENUM_TO_STR(t2),ENUM_TO_STR(t3),ENUM_TO_STR(t4),ENUM_TO_STR(t5),ENUM_TO_STR(t6),ENUM_TO_STR(t7),ENUM_TO_STR(t8),ENUM_TO_STR(t9)};\
return str;}static inline const Char*ToString(name e){static baseType val[]={\
(baseType)(v0), (baseType)(v1), (baseType)(v2), (baseType)(v3), (baseType)(v4), (baseType)(v5), (baseType)(v6), (baseType)(v7), (baseType)(v8), (baseType)(v9)}; \
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }
for (baseType i = 0; i < name##_Count; i++) { if (val[i] == (baseType)e) return name##_Str()[(int)i]; } return ENUM_TO_STR_FALLBACK; }static_assert(true, "")

View File

@@ -39,7 +39,7 @@ namespace fmt_flax
return fmt::format_to(ctx.out(), basic_string_view<Char>(TEXT(formatText)), ##__VA_ARGS__); \
} \
}; \
}
} static_assert(true, "")
#define DEFINE_DEFAULT_FORMATTING_VIA_TO_STRING(type) \
namespace fmt \
@@ -59,4 +59,4 @@ namespace fmt_flax
return fmt::detail::copy_str<Char>(str.Get(), str.Get() + str.Length(), ctx.out()); \
} \
}; \
}
} static_assert(true, "")

View File

@@ -51,7 +51,11 @@ bool BoundingSphere::Intersects(const BoundingBox& box) const
bool BoundingSphere::Intersects(const BoundingSphere& sphere) const
{
return CollisionsHelper::SphereIntersectsSphere(*this, sphere);
const Real radiisum = Radius + sphere.Radius;
const Real x = Center.X - sphere.Center.X;
const Real y = Center.Y - sphere.Center.Y;
const Real z = Center.Z - sphere.Center.Z;
return x * x + y * y + z * z <= radiisum * radiisum;
}
ContainmentType BoundingSphere::Contains(const Vector3& point) const

View File

@@ -10,9 +10,23 @@ static_assert(sizeof(Half2) == 4, "Invalid Half2 type size.");
static_assert(sizeof(Half3) == 6, "Invalid Half3 type size.");
static_assert(sizeof(Half4) == 8, "Invalid Half4 type size.");
Half2 Half2::Zero(0.0f, 0.0f);
Half3 Half3::Zero(0.0f, 0.0f, 0.0f);
Half4 Half4::Zero(0.0f, 0.0f, 0.0f, 0.0f);
const Half2 Half2::Zero(0.0f, 0.0f);
const Half2 Half2::One(1.0f, 1.0f);
const Half2 Half2::UnitX(1.0f, 0.0f);
const Half2 Half2::UnitY(0.0f, 1.0f);
const Half3 Half3::Zero(0.0f, 0.0f, 0.0f);
const Half3 Half3::One(1.0f, 1.0f, 1.0f);
const Half3 Half3::UnitX(1.0f, 0.0f, 0.0f);
const Half3 Half3::UnitY(0.0f, 1.0f, 0.0f);
const Half3 Half3::UnitZ(0.0f, 0.0f, 1.0f);
const Half4 Half4::Zero(0.0f, 0.0f, 0.0f, 0.0f);
const Half4 Half4::One(1.0f, 1.0f, 1.0f, 1.0f);
const Half4 Half4::UnitX(1.0f, 0.0f, 0.0f, 0.0f);
const Half4 Half4::UnitY(0.0f, 1.0f, 0.0f, 0.0f);
const Half4 Half4::UnitZ(0.0f, 0.0f, 1.0f, 0.0f);
const Half4 Half4::UnitW(0.0f, 0.0f, 0.0f, 1.0f);
#if !USE_SSE_HALF_CONVERSION

View File

@@ -6,13 +6,23 @@
#include "Vector2.h"
#include "Vector3.h"
#if PLATFORM_SIMD_AVX
// MSVC generates slower code without AVX
#define USE_SSE_HALF_CONVERSION 1
#else
#define USE_SSE_HALF_CONVERSION 0
#endif
#if USE_SSE_HALF_CONVERSION
#include <intrin.h>
#include <emmintrin.h>
#endif
/// <summary>
/// Half-precision 16 bit floating point number consisting of a sign bit, a 5 bit biased exponent, and a 10 bit mantissa
/// </summary>
typedef uint16 Half;
#define USE_SSE_HALF_CONVERSION 0
/// <summary>
/// Utility for packing/unpacking floating point value from single precision (32 bit) to half precision (16 bit).
/// </summary>
@@ -72,10 +82,17 @@ public:
struct FLAXENGINE_API Half2
{
public:
/// <summary>
/// Zero vector
/// </summary>
static Half2 Zero;
// Vector with all components equal 0
static const Half2 Zero;
// Vector with all components equal 1
static const Half2 One;
// Vector X=1, Y=0
static const Half2 UnitX;
// Vector X=0, Y=1
static const Half2 UnitY;
public:
/// <summary>
@@ -136,10 +153,20 @@ public:
struct FLAXENGINE_API Half3
{
public:
/// <summary>
/// Zero vector
/// </summary>
static Half3 Zero;
// Vector with all components equal 0
static const Half3 Zero;
// Vector with all components equal 1
static const Half3 One;
// Vector X=1, Y=0, Z=0
static const Half3 UnitX;
// Vector X=0, Y=1, Z=0
static const Half3 UnitY;
// Vector X=0, Y=0, Z=1
static const Half3 UnitZ;
public:
/// <summary>
@@ -191,10 +218,23 @@ public:
struct FLAXENGINE_API Half4
{
public:
/// <summary>
/// Zero vector
/// </summary>
static Half4 Zero;
// Vector with all components equal 0
static const Half4 Zero;
// Vector with all components equal 1
static const Half4 One;
// Vector X=1, Y=0, Z=0, W=0
static const Half4 UnitX;
// Vector X=0, Y=1, Z=0, W=0
static const Half4 UnitY;
// Vector X=0, Y=0, Z=1, W=0
static const Half4 UnitZ;
// Vector X=0, Y=0, Z=0, W=1
static const Half4 UnitW;
public:
/// <summary>

View File

@@ -2,6 +2,7 @@
#include "Matrix.h"
#include "Matrix3x3.h"
#include "Matrix3x4.h"
#include "Vector2.h"
#include "Quaternion.h"
#include "Transform.h"
@@ -887,3 +888,39 @@ Float4 Matrix::TransformPosition(const Matrix& m, const Float4& v)
m.Values[0][3] * v.Raw[0] + m.Values[1][3] * v.Raw[1] + m.Values[2][3] * v.Raw[2] + m.Values[3][3] * v.Raw[3]
);
}
void Matrix3x4::SetMatrix(const Matrix& m)
{
const float* src = m.Raw;
float* dst = Raw;
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
dst[4] = src[4];
dst[5] = src[5];
dst[6] = src[6];
dst[7] = src[7];
dst[8] = src[8];
dst[9] = src[9];
dst[10] = src[10];
dst[11] = src[11];
}
void Matrix3x4::SetMatrixTranspose(const Matrix& m)
{
const float* src = m.Raw;
float* dst = Raw;
dst[0] = src[0];
dst[1] = src[4];
dst[2] = src[8];
dst[3] = src[12];
dst[4] = src[1];
dst[5] = src[5];
dst[6] = src[9];
dst[7] = src[13];
dst[8] = src[2];
dst[9] = src[6];
dst[10] = src[10];
dst[11] = src[14];
}

View File

@@ -890,7 +890,7 @@ public:
/// <param name="translation">The translation.</param>
/// <param name="rotation">Angle of rotation in radians. Angles are measured clockwise when looking along the rotation axis toward the origin.</param>
/// <param name="scaling">The scaling.</param>
/// <param name="result">When the method completes, contains the created rotation matrix.</param>
/// <param name="result">When the method completes, contains the created transformation matrix.</param>
static void Transformation(const Float3& scaling, const Quaternion& rotation, const Float3& translation, Matrix& result);
// Creates a 3D affine transformation matrix.

View File

@@ -5,6 +5,9 @@
#include "Quaternion.h"
#include "../Types/String.h"
#include <intrin.h>
#include <emmintrin.h>
const Matrix3x3 Matrix3x3::Zero(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
const Matrix3x3 Matrix3x3::Identity(
1.0f, 0.0f, 0.0f,
@@ -139,6 +142,67 @@ void Matrix3x3::Multiply(const Matrix3x3& left, float right, Matrix3x3& result)
void Matrix3x3::Multiply(const Matrix3x3& left, const Matrix3x3& right, Matrix3x3& result)
{
#if true
{
// First : naive solution with but with some tricks to make compiler (MSVC) behave
//* Note that, in this case, manually unrolling the loop helps
//* as the compiler can't auto-vectorize non-contagious memory access
float* __restrict const matData = result.Raw;
//Mat matC{ matB.width, matA.height, matB.rowSpan, matData };
for (int rowC = 0; rowC < 3; ++rowC) {
for (int colC = 0; colC < 3; ++colC) {
// an independent, local accumulator.
float accumulate = 0;
int pos = 0;
// manual unrolling IS helpful in this case
for (; pos < 3 - 4; pos += 4) {
accumulate += left.Raw[rowC * 3 + pos] *
right.Raw[pos * 3 + colC] +
left.Raw[rowC * 3 + pos + 1] *
right.Raw[(pos + 1) * 3 + colC] +
left.Raw[rowC * 3 + pos + 2] *
right.Raw[(pos + 2) * 3 + colC] +
left.Raw[rowC * 3 + pos + 3] *
right.Raw[(pos + 3) * 3 + colC];
}
for (; pos < 3; ++pos) {
accumulate += left.Raw[rowC * 3 + pos] *
right.Raw[pos * 3 + colC];
}
matData[rowC * 3 + colC] = accumulate;
}
}
}
#else
/*
__m256i vec_multi_res = _mm256_setzero_si256();
__m256i vec_mat1 = _mm256_setzero_si256();
__m256i vec_mat2 = _mm256_setzero_si256();
int i, j, k;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; ++j)
{
//Stores one element in mat1 and use it in all computations needed before proceeding
//Stores as vector to increase computations per cycle
vec_mat1 = _mm256_set1_epi32(left.Values[j][i]);
for (k = 0; k < 3; k += 8)
{
vec_mat2 = _mm256_loadu_si256((__m256i*) & right.Values[k][j]); //Stores row of second matrix (eight in each iteration)
vec_multi_res = _mm256_loadu_si256((__m256i*) & result.Values[k][i]); //Loads the result matrix row as a vector
vec_multi_res = _mm256_add_epi32(vec_multi_res, _mm256_mullo_epi32(vec_mat1, vec_mat2));//Multiplies the vectors and adds to th the result vector
_mm256_storeu_si256((__m256i*) & result.Values[k][i], vec_multi_res); //Stores the result vector into the result array
}
}
}
*/
result = Matrix3x3(
left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31,
left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32,
@@ -150,6 +214,19 @@ void Matrix3x3::Multiply(const Matrix3x3& left, const Matrix3x3& right, Matrix3x
left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32,
left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33
);
/*Matrix3x3 result2 = Matrix3x3(
left.M11 * right.M11 + left.M12 * right.M21 + left.M13 * right.M31,
left.M11 * right.M12 + left.M12 * right.M22 + left.M13 * right.M32,
left.M11 * right.M13 + left.M12 * right.M23 + left.M13 * right.M33,
left.M21 * right.M11 + left.M22 * right.M21 + left.M23 * right.M31,
left.M21 * right.M12 + left.M22 * right.M22 + left.M23 * right.M32,
left.M21 * right.M13 + left.M22 * right.M23 + left.M23 * right.M33,
left.M31 * right.M11 + left.M32 * right.M21 + left.M33 * right.M31,
left.M31 * right.M12 + left.M32 * right.M22 + left.M33 * right.M32,
left.M31 * right.M13 + left.M32 * right.M23 + left.M33 * right.M33
);
ASSERT(result2 == result);*/
#endif
}
void Matrix3x3::Divide(const Matrix3x3& left, float right, Matrix3x3& result)

View File

@@ -4,6 +4,7 @@
#include "Vector2.h"
#include "Vector3.h"
#include "Vector4.h"
#include "Engine/Platform/Platform.h"
/// <summary>
@@ -538,6 +539,47 @@ public:
/// <param name="result">The result.</param>
static void Transform2DPoint(const Float2& point, const Matrix3x3& transform, Float2& result)
{
//Float4 pointVector = Float4(0.0f, 0.0f, point.Y, point.X);
/*
// Load the matrix into SIMD registers
const Float4 row1 = Float4((Float3)transform.Values[0], 0.0f);
const Float4 row2 = Float4((Float3)transform.Values[1], 0.0f);
const Float4 row3 = Float4((Float3)transform.Values[2], 0.0f);
const Float4 res(
point.X * row1.Raw[0] + point.Y * row2.Raw[0] + row3.Raw[0],
point.X * row1.Raw[1] + point.Y * row2.Raw[1] + row3.Raw[1], 0.0f, 0.0f
);
result = Float2(res.X, res.Y);
*/
/*
// Load the point into SIMD registers
__m128 pointVector = _mm_set_ps(0.0f, 0.0f, point.Y, point.X);
// Load the matrix into SIMD registers
__m128 row1 = _mm_loadu_ps(transform.Values[0]);
__m128 row2 = _mm_loadu_ps(transform.Values[1]);
__m128 row3 = _mm_loadu_ps(transform.Values[2]);
// Perform the matrix-vector multiplication
__m128 result2 = _mm_add_ps(
_mm_add_ps(_mm_mul_ps(row1, pointVector), _mm_mul_ps(row2, pointVector)),
row3
);
// Store the result back into a Point2D structure
_mm_storeu_ps(&result.X, result2);
*/
/*auto result3 = Float2(
point.X * transform.M11 + point.Y * transform.M21 + transform.M31,
point.X * transform.M12 + point.Y * transform.M22 + transform.M32);
ASSERT(result == result3);*/
result = Float2(
point.X * transform.M11 + point.Y * transform.M21 + transform.M31,
point.X * transform.M12 + point.Y * transform.M22 + transform.M32);
@@ -552,6 +594,39 @@ public:
/// <param name="result">The result.</param>
static void Transform2DVector(const Float2& vector, const Matrix3x3& transform, Float2& result)
{
//Float4 pointVector = Float4(0.0f, 0.0f, vector.Y, vector.X);
// Load the matrix into SIMD registers
/*const Float4 row1 = Float4((Float3)transform.Values[0], 0.0f);
const Float4 row2 = Float4((Float3)transform.Values[1], 0.0f);
const Float4 row3 = Float4((Float3)transform.Values[2], 0.0f);
const Float4 res(
vector.X * row1.Raw[0] + vector.Y * row2.Raw[0],
vector.X * row1.Raw[1] + vector.Y * row2.Raw[1], 0.0f, 0.0f
);
result = Float2(res.X, res.Y);*/
/*
// Load the point into SIMD registers
__m128 pointVector = _mm_set_ps(0.0f, 0.0f, vector.Y, vector.X);
// Load the matrix into SIMD registers
__m128 row1 = _mm_loadu_ps(transform.Values[0]);
__m128 row2 = _mm_loadu_ps(transform.Values[1]);
// Perform the matrix-vector multiplication
__m128 result2 = _mm_add_ps(_mm_mul_ps(row1, pointVector), _mm_mul_ps(row2, pointVector));
// Store the result back into a Point2D structure
_mm_storeu_ps(&result.X, result2);
*/
/*auto result3 = Float2(
vector.X * transform.M11 + vector.Y * transform.M21,
vector.X * transform.M12 + vector.Y * transform.M22);
ASSERT(result == result3);*/
result = Float2(
vector.X * transform.M11 + vector.Y * transform.M21,
vector.X * transform.M12 + vector.Y * transform.M22);

Some files were not shown because too many files have changed in this diff Show More