Merge branch 'master' into 1.5

This commit is contained in:
Wojtek Figat
2022-11-29 23:19:01 +01:00
10 changed files with 136 additions and 25 deletions

View File

@@ -37,6 +37,16 @@ namespace FlaxEditor.GUI.Docking
// Focus window // Focus window
window.Focus(); window.Focus();
// Check if window is maximized and restore window.
if (window.IsMaximized)
{
// Restore window and set position to mouse.
var mousePos = window.MousePosition;
var previousSize = window.Size;
window.Restore();
window.Position = FlaxEngine.Input.MouseScreenPosition - mousePos * window.Size / previousSize;
}
// Calculate dragging offset and move window to the destination position // Calculate dragging offset and move window to the destination position
var mouseScreenPosition = FlaxEngine.Input.MouseScreenPosition; var mouseScreenPosition = FlaxEngine.Input.MouseScreenPosition;

View File

@@ -51,10 +51,6 @@ namespace FlaxEditor.GUI.Docking
if (_window == null) if (_window == null)
return; return;
// Check if window is maximized
if (_window.IsMaximized)
return;
// Create docking hint window // Create docking hint window
DockHintWindow.Create(this); DockHintWindow.Create(this);
} }

View File

@@ -131,7 +131,7 @@ namespace FlaxEditor.Windows
ScrollBars = ScrollBars.Both, ScrollBars = ScrollBars.Both,
Parent = _split.Panel1, Parent = _split.Panel1,
}; };
// Content structure tree // Content structure tree
_tree = new Tree(false) _tree = new Tree(false)
{ {
@@ -179,7 +179,7 @@ namespace FlaxEditor.Windows
ScrollBars = ScrollBars.Vertical, ScrollBars = ScrollBars.Vertical,
Parent = _split.Panel2, Parent = _split.Panel2,
}; };
// Content View // Content View
_view = new ContentView _view = new ContentView
{ {
@@ -895,6 +895,18 @@ namespace FlaxEditor.Windows
} }
} }
/// <inheritdoc />
public override bool OnMouseDown(Float2 location, MouseButton button)
{
// Navigate through directories using the side mouse buttons
if (button == MouseButton.Extended1)
NavigateBackward();
else if (button == MouseButton.Extended2)
NavigateForward();
return base.OnMouseDown(location, button);
}
/// <inheritdoc /> /// <inheritdoc />
public override bool OnMouseUp(Float2 location, MouseButton button) public override bool OnMouseUp(Float2 location, MouseButton button)
{ {

View File

@@ -132,7 +132,7 @@ void AudioSource::Play()
Clip->RequestStreamingUpdate(); Clip->RequestStreamingUpdate();
// If we are looping and streaming also update streaming buffers // If we are looping and streaming also update streaming buffers
if (_loop) if (_loop || state == States::Stopped)
RequestStreamingBuffersUpdate(); RequestStreamingBuffersUpdate();
} }
} }

View File

@@ -105,7 +105,9 @@ public:
FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const
{ {
if (capacity == 0) if (capacity < minCapacity)
capacity = minCapacity;
if (capacity < 8)
{ {
capacity = 8; capacity = 8;
} }
@@ -120,8 +122,6 @@ public:
capacity |= capacity >> 16; capacity |= capacity >> 16;
capacity = (capacity + 1) * 2; capacity = (capacity + 1) * 2;
} }
if (capacity < minCapacity)
capacity = minCapacity;
return capacity; return capacity;
} }

View File

@@ -26,6 +26,13 @@ TestsRunnerService TestsRunnerServiceInstance;
void TestsRunnerService::Update() void TestsRunnerService::Update()
{ {
// End if failed to perform a startup
if (ScriptsBuilder::LastCompilationFailed())
{
Engine::RequestExit(-1);
return;
}
// Wait for Editor to be ready for running tests (eg. scripting loaded) // Wait for Editor to be ready for running tests (eg. scripting loaded)
if (!ScriptsBuilder::IsReady() || if (!ScriptsBuilder::IsReady() ||
!Scripting::IsEveryAssemblyLoaded() || !Scripting::IsEveryAssemblyLoaded() ||

View File

@@ -23,11 +23,14 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info)
uint32 subChunkSize = 0; uint32 subChunkSize = 0;
mStream->ReadUint32(&subChunkSize); mStream->ReadUint32(&subChunkSize);
uint32 totalRead = 0;
// FMT chunk // FMT chunk
if (subChunkId[0] == 'f' && subChunkId[1] == 'm' && subChunkId[2] == 't' && subChunkId[3] == ' ') if (subChunkId[0] == 'f' && subChunkId[1] == 'm' && subChunkId[2] == 't' && subChunkId[3] == ' ')
{ {
uint16 format; uint16 format;
mStream->ReadUint16(&format); mStream->ReadUint16(&format);
totalRead += 2;
if (format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_IEEE_FLOAT && format != WAVE_FORMAT_EXTENDED) if (format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_IEEE_FLOAT && format != WAVE_FORMAT_EXTENDED)
{ {
@@ -37,18 +40,23 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info)
uint16 numChannels = 0; uint16 numChannels = 0;
mStream->ReadUint16(&numChannels); mStream->ReadUint16(&numChannels);
totalRead += 2;
uint32 sampleRate = 0; uint32 sampleRate = 0;
mStream->ReadUint32(&sampleRate); mStream->ReadUint32(&sampleRate);
totalRead += 4;
uint32 byteRate = 0; uint32 byteRate = 0;
mStream->ReadUint32(&byteRate); mStream->ReadUint32(&byteRate);
totalRead += 4;
uint16 blockAlign = 0; uint16 blockAlign = 0;
mStream->ReadUint16(&blockAlign); mStream->ReadUint16(&blockAlign);
totalRead += 2;
uint16 bitDepth = 0; uint16 bitDepth = 0;
mStream->ReadUint16(&bitDepth); mStream->ReadUint16(&bitDepth);
totalRead += 2;
if (bitDepth != 8 && bitDepth != 16 && bitDepth != 24 && bitDepth != 32) if (bitDepth != 8 && bitDepth != 16 && bitDepth != 24 && bitDepth != 32)
{ {
@@ -65,6 +73,7 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info)
{ {
uint16 extensionSize = 0; uint16 extensionSize = 0;
mStream->ReadUint16(&extensionSize); mStream->ReadUint16(&extensionSize);
totalRead += 2;
if (extensionSize != 22) if (extensionSize != 22)
{ {
@@ -74,12 +83,15 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info)
uint16 validBitDepth = 0; uint16 validBitDepth = 0;
mStream->ReadUint16(&validBitDepth); mStream->ReadUint16(&validBitDepth);
totalRead += 2;
uint32 channelMask = 0; uint32 channelMask = 0;
mStream->ReadUint32(&channelMask); mStream->ReadUint32(&channelMask);
totalRead += 4;
uint8 subFormat[16]; uint8 subFormat[16];
mStream->ReadBytes(subFormat, sizeof(subFormat)); mStream->ReadBytes(subFormat, sizeof(subFormat));
totalRead += 16;
Platform::MemoryCopy(&format, subFormat, sizeof(format)); Platform::MemoryCopy(&format, subFormat, sizeof(format));
if (format != WAVE_FORMAT_PCM) if (format != WAVE_FORMAT_PCM)
@@ -89,10 +101,18 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info)
} }
} }
// Support wav with "extra format bytes", just ignore not needed
while (totalRead < subChunkSize)
{
uint8 b;
mStream->ReadBytes(&b, sizeof(b));
totalRead++;
}
mBytesPerSample = bitDepth / 8; mBytesPerSample = bitDepth / 8;
mFormat = format; mFormat = format;
} }
// DATA chunk // DATA chunk
else if (subChunkId[0] == 'd' && subChunkId[1] == 'a' && subChunkId[2] == 't' && subChunkId[3] == 'a') else if (subChunkId[0] == 'd' && subChunkId[1] == 'a' && subChunkId[2] == 't' && subChunkId[3] == 'a')
{ {
info.NumSamples = subChunkSize / mBytesPerSample; info.NumSamples = subChunkSize / mBytesPerSample;
@@ -100,7 +120,7 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info)
foundData = true; foundData = true;
} }
// Unsupported chunk type // Unsupported chunk type
else else
{ {
if (mStream->GetPosition() + subChunkSize >= mStream->GetLength()) if (mStream->GetPosition() + subChunkSize >= mStream->GetLength())
@@ -147,7 +167,7 @@ void WaveDecoder::Read(byte* samples, uint32 numSamples)
samples[i] = *((uint8*)&val); samples[i] = *((uint8*)&val);
} }
} }
// IEEE float need to be converted into signed PCM data // IEEE float need to be converted into signed PCM data
else if (mFormat == WAVE_FORMAT_IEEE_FLOAT) else if (mFormat == WAVE_FORMAT_IEEE_FLOAT)
{ {
AudioTool::ConvertFromFloat((const float*)samples, (int32*)samples, numSamples); AudioTool::ConvertFromFloat((const float*)samples, (int32*)samples, numSamples);

View File

@@ -229,6 +229,63 @@ struct OpenFbxImporterData
ImportMaterialTexture(result, mat, ofbx::Texture::EMISSIVE, material.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, mat, ofbx::Texture::EMISSIVE, material.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB);
ImportMaterialTexture(result, mat, ofbx::Texture::NORMAL, material.Normals.TextureIndex, TextureEntry::TypeHint::Normals); ImportMaterialTexture(result, mat, ofbx::Texture::NORMAL, material.Normals.TextureIndex, TextureEntry::TypeHint::Normals);
// FBX don't always store normal maps inside the object
if (material.Diffuse.TextureIndex != -1 && material.Normals.TextureIndex == -1)
{
// If missing, try to locate a normal map in the same path as the diffuse
const String srcFolder = String(StringUtils::GetDirectoryName(result.Textures[material.Diffuse.TextureIndex].FilePath));
const String srcName = StringUtils::GetFileNameWithoutExtension(result.Textures[material.Diffuse.TextureIndex].FilePath);
String srcSearch;
const int32 num = srcName.FindLast('_');
String srcSmallName = srcName;
if (num != -1)
srcSmallName = srcName.Substring(0, num);
bool isNormal = false;
for (int32 iExt = 0; iExt < 6; iExt++)
{
String sExit = TEXT(".dds");
if (iExt == 1)
sExit = TEXT(".png");
else if (iExt == 2)
sExit = TEXT(".jpg");
else if (iExt == 3)
sExit = TEXT(".jpeg");
else if (iExt == 4)
sExit = TEXT(".tif");
else if (iExt == 5)
sExit = TEXT(".tga");
for (int32 i = 0; i < 5; i++)
{
String sFind = TEXT("_normal" + sExit);
if (i == 1)
sFind = TEXT("_n" + sExit);
else if (i == 2)
sFind = TEXT("_nm" + sExit);
else if (i == 3)
sFind = TEXT("_nmp" + sExit);
else if (i == 4)
sFind = TEXT("_nor" + sExit);
srcSearch = srcFolder + TEXT("/") + srcSmallName + sFind;
if (FileSystem::FileExists(srcSearch))
{
isNormal = true;
break;
}
}
if (isNormal)
break;
}
if (isNormal)
{
auto& texture = result.Textures.AddOne();
texture.FilePath = srcSearch;
texture.Type = TextureEntry::TypeHint::Normals;
texture.AssetID = Guid::Empty;
material.Normals.TextureIndex = result.Textures.Count() - 1;
}
}
if (material.Diffuse.TextureIndex != -1) if (material.Diffuse.TextureIndex != -1)
{ {
// Detect using alpha mask in diffuse texture // Detect using alpha mask in diffuse texture

View File

@@ -1275,17 +1275,17 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op
// Trim the animation keyframes range if need to // Trim the animation keyframes range if need to
if (options.Duration == AnimationDuration::Custom) if (options.Duration == AnimationDuration::Custom)
{ {
const float start = (float)(options.FramesRange.X / data.Animation.FramesPerSecond); // Custom animation import, frame index start and end
const float end = (float)(options.FramesRange.Y / data.Animation.FramesPerSecond); const float start = options.FramesRange.X;
const float end = options.FramesRange.Y;
for (int32 i = 0; i < data.Animation.Channels.Count(); i++) for (int32 i = 0; i < data.Animation.Channels.Count(); i++)
{ {
auto& anim = data.Animation.Channels[i]; auto& anim = data.Animation.Channels[i];
anim.Position.Trim(start, end); anim.Position.Trim(start, end);
anim.Rotation.Trim(start, end); anim.Rotation.Trim(start, end);
anim.Scale.Trim(start, end); anim.Scale.Trim(start, end);
} }
data.Animation.Duration = (end - start) * data.Animation.FramesPerSecond; data.Animation.Duration = end - start;
} }
// Change the sampling rate if need to // Change the sampling rate if need to

View File

@@ -623,8 +623,17 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
sliceData.Mips.Resize(mipLevels); sliceData.Mips.Resize(mipLevels);
} }
bool keepAsIs = false;
if (!options.FlipY && options.Compress && type == ImageType::DDS && mipLevels == sourceMipLevels && DirectX::IsCompressed(sourceDxgiFormat) && !DirectX::IsSRGB(sourceDxgiFormat))
{
// Keep image in the current compressed format (artist choice) so we don't have to run the slow mipmap generation
keepAsIs = true;
targetDxgiFormat = sourceDxgiFormat;
targetFormat = ToPixelFormat(currentImage->GetMetadata().format);
}
// Decompress if texture is compressed (next steps need decompressed input data, for eg. mip maps generation or format changing) // Decompress if texture is compressed (next steps need decompressed input data, for eg. mip maps generation or format changing)
if (DirectX::IsCompressed(sourceDxgiFormat)) if (!keepAsIs && DirectX::IsCompressed(sourceDxgiFormat))
{ {
auto& tmpImg = GET_TMP_IMG(); auto& tmpImg = GET_TMP_IMG();
@@ -640,7 +649,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
} }
// Fix sRGB problem // Fix sRGB problem
if (DirectX::IsSRGB(sourceDxgiFormat)) if (!keepAsIs && DirectX::IsSRGB(sourceDxgiFormat))
{ {
sourceDxgiFormat = ToDxgiFormat(PixelFormatExtensions::ToNonsRGB(ToPixelFormat(sourceDxgiFormat))); sourceDxgiFormat = ToDxgiFormat(PixelFormatExtensions::ToNonsRGB(ToPixelFormat(sourceDxgiFormat)));
((DirectX::TexMetadata&)currentImage->GetMetadata()).format = sourceDxgiFormat; ((DirectX::TexMetadata&)currentImage->GetMetadata()).format = sourceDxgiFormat;
@@ -649,7 +658,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
} }
// Remove alpha if source texture has it but output should not, valid for compressed output only (DirectX seams to use alpha to pre-multiply colors because BC1 format has no place for alpha) // Remove alpha if source texture has it but output should not, valid for compressed output only (DirectX seams to use alpha to pre-multiply colors because BC1 format has no place for alpha)
if (DirectX::HasAlpha(sourceDxgiFormat) && options.Type == TextureFormatType::ColorRGB && options.Compress) if (!keepAsIs && DirectX::HasAlpha(sourceDxgiFormat) && options.Type == TextureFormatType::ColorRGB && options.Compress)
{ {
auto& tmpImg = GET_TMP_IMG(); auto& tmpImg = GET_TMP_IMG();
@@ -674,7 +683,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
} }
// Check flip/rotate source image // Check flip/rotate source image
if (options.FlipY) if (!keepAsIs && options.FlipY)
{ {
auto& tmpImg = GET_TMP_IMG(); auto& tmpImg = GET_TMP_IMG();
@@ -691,7 +700,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
} }
// Generate mip maps chain // Generate mip maps chain
if (useMipLevels && options.GenerateMipMaps) if (!keepAsIs && useMipLevels && options.GenerateMipMaps)
{ {
auto& tmpImg = GET_TMP_IMG(); auto& tmpImg = GET_TMP_IMG();
@@ -714,7 +723,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
} }
// Preserve mipmap alpha coverage (if requested) // Preserve mipmap alpha coverage (if requested)
if (DirectX::HasAlpha(currentImage->GetMetadata().format) && options.PreserveAlphaCoverage && useMipLevels) if (!keepAsIs && DirectX::HasAlpha(currentImage->GetMetadata().format) && options.PreserveAlphaCoverage && useMipLevels)
{ {
auto& tmpImg = GET_TMP_IMG(); auto& tmpImg = GET_TMP_IMG();
@@ -746,7 +755,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
ASSERT((int32)currentImage->GetMetadata().mipLevels >= mipLevels); ASSERT((int32)currentImage->GetMetadata().mipLevels >= mipLevels);
// Compress mip maps or convert image // Compress mip maps or convert image
if (targetDxgiFormat != sourceDxgiFormat) if (!keepAsIs && targetDxgiFormat != sourceDxgiFormat)
{ {
auto& tmpImg = GET_TMP_IMG(); auto& tmpImg = GET_TMP_IMG();
@@ -884,7 +893,7 @@ bool TextureTool::ConvertDirectXTex(TextureData& dst, const TextureData& src, co
return true; return true;
} }
} }
// Check if convert data // Check if convert data
else if (inImage->GetMetadata().format != dstFormatDxgi) else if (inImage->GetMetadata().format != dstFormatDxgi)
{ {
result = DirectX::Convert(inImage->GetImages(), inImage->GetImageCount(), inImage->GetMetadata(), dstFormatDxgi, DirectX::TEX_FILTER_DEFAULT, DirectX::TEX_THRESHOLD_DEFAULT, dstImage); result = DirectX::Convert(inImage->GetImages(), inImage->GetImageCount(), inImage->GetMetadata(), dstFormatDxgi, DirectX::TEX_FILTER_DEFAULT, DirectX::TEX_THRESHOLD_DEFAULT, dstImage);