Merge remote-tracking branch 'origin/master' into 1.10
# Conflicts: # Content/Editor/Gizmo/Material.flax # Content/Engine/DefaultTerrainMaterial.flax # Source/Editor/Windows/Assets/ModelWindow.cs # Source/Editor/Windows/Assets/SkinnedModelWindow.cs # Source/Engine/Core/Types/Variant.cpp
This commit is contained in:
2
.github/actions/vulkan/action.yml
vendored
2
.github/actions/vulkan/action.yml
vendored
@@ -3,7 +3,7 @@ description: Downloads and installs Vulkan SDK.
|
||||
inputs:
|
||||
vulkan-version:
|
||||
description: 'Vulkan SDK release version (e.g. 1.2.198.1).'
|
||||
default: '1.2.198.1'
|
||||
default: '1.3.290.0'
|
||||
required: false
|
||||
runs:
|
||||
using: "composite"
|
||||
|
||||
14
.github/workflows/cd.yml
vendored
14
.github/workflows/cd.yml
vendored
@@ -35,12 +35,12 @@ jobs:
|
||||
run: |
|
||||
.\PackageEditor.bat -arch=x64 -platform=Windows -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows-Editor
|
||||
path: Output/Editor.zip
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows-EditorDebugSymbols
|
||||
path: Output/EditorDebugSymbols.zip
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
run: |
|
||||
.\PackagePlatforms.bat -arch=x64 -platform=Windows -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Windows-Game
|
||||
path: Output/Windows.zip
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
run: |
|
||||
./PackageEditor.sh -arch=x64 -platform=Linux -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Linux-Editor
|
||||
path: Output/FlaxEditorLinux.zip
|
||||
@@ -132,7 +132,7 @@ jobs:
|
||||
run: |
|
||||
./PackagePlatforms.sh -arch=x64 -platform=Linux -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Linux-Game
|
||||
path: Output/Linux.zip
|
||||
@@ -162,7 +162,7 @@ jobs:
|
||||
run: |
|
||||
./PackageEditor.command -arch=ARM64 -platform=Mac -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Mac-Editor
|
||||
path: Output/FlaxEditorMac.zip
|
||||
@@ -190,7 +190,7 @@ jobs:
|
||||
run: |
|
||||
./PackagePlatforms.command -arch=ARM64 -platform=Mac -deployOutput=Output
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Mac-Game
|
||||
path: Output/Mac.zip
|
||||
|
||||
BIN
Content/Editor/Gizmo/MaterialAxisFocus.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialAxisFocus.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialAxisLocked.flax
(Stored with Git LFS)
Normal file
BIN
Content/Editor/Gizmo/MaterialAxisLocked.flax
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialAxisX.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialAxisX.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialAxisY.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialAxisY.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialAxisZ.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialAxisZ.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Editor/Gizmo/MaterialSphere.flax
(Stored with Git LFS)
BIN
Content/Editor/Gizmo/MaterialSphere.flax
(Stored with Git LFS)
Binary file not shown.
19
Content/Editor/Scripting/ActorTemplate.cpp
Normal file
19
Content/Editor/Scripting/ActorTemplate.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
%copyright%#include "%filename%.h"
|
||||
|
||||
%class%::%class%(const SpawnParams& params)
|
||||
: Actor(params)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void %class%::OnEnable()
|
||||
{
|
||||
Actor::OnEnable();
|
||||
// Here you can add code that needs to be called when script is enabled (eg. register for events)
|
||||
}
|
||||
|
||||
void %class%::OnDisable()
|
||||
{
|
||||
Actor::OnDisable();
|
||||
// Here you can add code that needs to be called when script is disabled (eg. unregister from events)
|
||||
}
|
||||
39
Content/Editor/Scripting/ActorTemplate.cs
Normal file
39
Content/Editor/Scripting/ActorTemplate.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
%copyright%using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace %namespace%;
|
||||
|
||||
/// <summary>
|
||||
/// %class% Actor.
|
||||
/// </summary>
|
||||
public class %class% : Actor
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override void OnBeginPlay()
|
||||
{
|
||||
base.OnBeginPlay();
|
||||
// Here you can add code that needs to be called when Actor added to the game. This is called during edit time as well.
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnEndPlay()
|
||||
{
|
||||
base.OnEndPlay();
|
||||
// Here you can add code that needs to be called when Actor removed to the game. This is called during edit time as well.
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnEnable()
|
||||
{
|
||||
base.OnEnable();
|
||||
// Here you can add code that needs to be called when Actor is enabled (eg. register for events). This is called during edit time as well.
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void OnDisable()
|
||||
{
|
||||
base.OnDisable();
|
||||
// Here you can add code that needs to be called when Actor is disabled (eg. unregister from events). This is called during edit time as well.
|
||||
}
|
||||
}
|
||||
13
Content/Editor/Scripting/ActorTemplate.h
Normal file
13
Content/Editor/Scripting/ActorTemplate.h
Normal file
@@ -0,0 +1,13 @@
|
||||
%copyright%#pragma once
|
||||
|
||||
#include "Engine/Level/Actor.h"
|
||||
|
||||
API_CLASS() class %module%%class% : public Actor
|
||||
{
|
||||
API_AUTO_SERIALIZATION();
|
||||
DECLARE_SCENE_OBJECT(%class%);
|
||||
|
||||
// [Actor]
|
||||
void OnEnable() override;
|
||||
void OnDisable() override;
|
||||
};
|
||||
13
Content/Editor/Scripting/EmptyClassTemplate.cs
Normal file
13
Content/Editor/Scripting/EmptyClassTemplate.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
%copyright%using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace %namespace%;
|
||||
|
||||
/// <summary>
|
||||
/// %class% class.
|
||||
/// </summary>
|
||||
public class %class%
|
||||
{
|
||||
|
||||
}
|
||||
13
Content/Editor/Scripting/EmptyInterfaceTemplate.cs
Normal file
13
Content/Editor/Scripting/EmptyInterfaceTemplate.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
%copyright%using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace %namespace%;
|
||||
|
||||
/// <summary>
|
||||
/// %class% interface.
|
||||
/// </summary>
|
||||
public interface %class%
|
||||
{
|
||||
|
||||
}
|
||||
13
Content/Editor/Scripting/EmptyStructTemplate.cs
Normal file
13
Content/Editor/Scripting/EmptyStructTemplate.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
%copyright%using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace %namespace%;
|
||||
|
||||
/// <summary>
|
||||
/// %class% struct.
|
||||
/// </summary>
|
||||
public struct %class%
|
||||
{
|
||||
|
||||
}
|
||||
25
Content/Editor/Scripting/GamePluginTemplate.cs
Normal file
25
Content/Editor/Scripting/GamePluginTemplate.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
%copyright%using System;
|
||||
using System.Collections.Generic;
|
||||
using FlaxEngine;
|
||||
|
||||
namespace %namespace%;
|
||||
|
||||
/// <summary>
|
||||
/// %class% GamePlugin.
|
||||
/// </summary>
|
||||
public class %class% : GamePlugin
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Deinitialize()
|
||||
{
|
||||
base.Deinitialize();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.Utilities;
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace FlaxEditor.Content
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for C# script files.
|
||||
/// Context proxy object for C# Script files.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.CSharpProxy" />
|
||||
[ContentContextMenu("New/C#/C# Script")]
|
||||
@@ -89,6 +89,40 @@ namespace FlaxEditor.Content
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for C# Actor files.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.CSharpProxy" />
|
||||
[ContentContextMenu("New/C#/C# Actor")]
|
||||
public class CSharpActorProxy : CSharpProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "C# Actor";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void GetTemplatePath(out string path)
|
||||
{
|
||||
path = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ActorTemplate.cs");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for C# GamePlugin files.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.CSharpProxy" />
|
||||
[ContentContextMenu("New/C#/C# GamePlugin")]
|
||||
public class CSharpGamePluginProxy : CSharpProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "C# GamePlugin";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void GetTemplatePath(out string path)
|
||||
{
|
||||
path = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/GamePluginTemplate.cs");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for empty C# files.
|
||||
/// </summary>
|
||||
@@ -105,4 +139,55 @@ namespace FlaxEditor.Content
|
||||
path = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/CSharpEmptyTemplate.cs");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for empty C# class files.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.CSharpProxy" />
|
||||
[ContentContextMenu("New/C#/C# Class")]
|
||||
public class CSharpEmptyClassProxy : CSharpProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "C# Class";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void GetTemplatePath(out string path)
|
||||
{
|
||||
path = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/EmptyClassTemplate.cs");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for empty C# struct files.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.CSharpProxy" />
|
||||
[ContentContextMenu("New/C#/C# Struct")]
|
||||
public class CSharpEmptyStructProxy : CSharpProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "C# Struct";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void GetTemplatePath(out string path)
|
||||
{
|
||||
path = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/EmptyStructTemplate.cs");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for empty C# interface files.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.CSharpProxy" />
|
||||
[ContentContextMenu("New/C#/C# Interface")]
|
||||
public class CSharpEmptyInterfaceProxy : CSharpProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "C# Interface";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void GetTemplatePath(out string path)
|
||||
{
|
||||
path = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/EmptyInterfaceTemplate.cs");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,24 @@ namespace FlaxEditor.Content
|
||||
sourceTemplate = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ScriptTemplate.cpp");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for C++ Actor files.
|
||||
/// </summary>
|
||||
/// <seealso cref="FlaxEditor.Content.CppProxy" />
|
||||
[ContentContextMenu("New/C++/C++ Actor")]
|
||||
public class CppActorProxy : CppProxy
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string Name => "C++ Actor";
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void GetTemplatePaths(out string headerTemplate, out string sourceTemplate)
|
||||
{
|
||||
headerTemplate = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ActorTemplate.h");
|
||||
sourceTemplate = StringUtils.CombinePaths(Globals.EngineContentFolder, "Editor/Scripting/ActorTemplate.cpp");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Context proxy object for C++ Json Asset files.
|
||||
|
||||
@@ -671,11 +671,14 @@ bool GameCookerImpl::Build()
|
||||
MCore::Thread::Attach();
|
||||
|
||||
// Build Started
|
||||
CallEvent(GameCooker::EventType::BuildStarted);
|
||||
data.Tools->OnBuildStarted(data);
|
||||
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
||||
Steps[stepIndex]->OnBuildStarted(data);
|
||||
data.InitProgress(Steps.Count());
|
||||
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
|
||||
{
|
||||
CallEvent(GameCooker::EventType::BuildStarted);
|
||||
data.Tools->OnBuildStarted(data);
|
||||
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
||||
Steps[stepIndex]->OnBuildStarted(data);
|
||||
data.InitProgress(Steps.Count());
|
||||
}
|
||||
|
||||
// Execute all steps in a sequence
|
||||
bool failed = false;
|
||||
@@ -741,10 +744,13 @@ bool GameCookerImpl::Build()
|
||||
}
|
||||
IsRunning = false;
|
||||
CancelFlag = 0;
|
||||
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
||||
Steps[stepIndex]->OnBuildEnded(data, failed);
|
||||
data.Tools->OnBuildEnded(data, failed);
|
||||
CallEvent(failed ? GameCooker::EventType::BuildFailed : GameCooker::EventType::BuildDone);
|
||||
if (!EnumHasAnyFlags(data.Options, BuildOptions::NoCook))
|
||||
{
|
||||
for (int32 stepIndex = 0; stepIndex < Steps.Count(); stepIndex++)
|
||||
Steps[stepIndex]->OnBuildEnded(data, failed);
|
||||
data.Tools->OnBuildEnded(data, failed);
|
||||
CallEvent(failed ? GameCooker::EventType::BuildFailed : GameCooker::EventType::BuildDone);
|
||||
}
|
||||
Delete(Data);
|
||||
Data = nullptr;
|
||||
|
||||
|
||||
@@ -364,6 +364,33 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
}
|
||||
#endif
|
||||
const bool distributionPackage = buildSettings->ForDistribution || data.Configuration == BuildConfiguration::Release;
|
||||
|
||||
if (platformSettings->BuildAAB)
|
||||
{
|
||||
// .aab
|
||||
{
|
||||
CreateProcessSettings procSettings;
|
||||
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT(":app:bundle") : TEXT(":app:bundleDebug"));
|
||||
procSettings.WorkingDirectory = data.OriginalOutputPath;
|
||||
const int32 result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to build Gradle project into .aab package (result code: {0}). See log for more info."), result));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Copy result package
|
||||
const String aab = data.OriginalOutputPath / (distributionPackage ? TEXT("app/build/outputs/bundle/release/app-release.aab") : TEXT("app/build/outputs/bundle/debug/app-debug.aab"));
|
||||
const String outputAab = data.OriginalOutputPath / EditorUtilities::GetOutputName() + TEXT(".aab");
|
||||
if (FileSystem::CopyFile(outputAab, aab))
|
||||
{
|
||||
LOG(Error, "Failed to copy .aab package from {0} to {1}", aab, outputAab);
|
||||
return true;
|
||||
}
|
||||
LOG(Info, "Output Android AAB application package: {0} (size: {1} MB)", outputAab, FileSystem::GetFileSize(outputAab) / 1024 / 1024);
|
||||
}
|
||||
|
||||
// .apk
|
||||
{
|
||||
CreateProcessSettings procSettings;
|
||||
procSettings.FileName = String::Format(TEXT("\"{0}\" {1}"), data.OriginalOutputPath / gradlew, distributionPackage ? TEXT("assemble") : TEXT("assembleDebug"));
|
||||
@@ -371,20 +398,20 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
||||
const int32 result = Platform::CreateProcess(procSettings);
|
||||
if (result != 0)
|
||||
{
|
||||
data.Error(String::Format(TEXT("Failed to build Gradle project into package (result code: {0}). See log for more info."), result));
|
||||
data.Error(String::Format(TEXT("Failed to build Gradle project into .apk package (result code: {0}). See log for more info."), result));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy result package
|
||||
const String apk = data.OriginalOutputPath / (distributionPackage ? TEXT("app/build/outputs/apk/release/app-release-unsigned.apk") : TEXT("app/build/outputs/apk/debug/app-debug.apk"));
|
||||
const String outputApk = data.OriginalOutputPath / EditorUtilities::GetOutputName() + TEXT(".apk");
|
||||
if (FileSystem::CopyFile(outputApk, apk))
|
||||
{
|
||||
LOG(Error, "Failed to copy package from {0} to {1}", apk, outputApk);
|
||||
LOG(Error, "Failed to copy .apk package from {0} to {1}", apk, outputApk);
|
||||
return true;
|
||||
}
|
||||
LOG(Info, "Output Android application package: {0} (size: {1} MB)", outputApk, FileSystem::GetFileSize(outputApk) / 1024 / 1024);
|
||||
LOG(Info, "Output Android APK application package: {0} (size: {1} MB)", outputApk, FileSystem::GetFileSize(outputApk) / 1024 / 1024);
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -214,6 +214,33 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
FileSystem::NormalizePath(srcDotnet);
|
||||
LOG(Info, "Using .NET Runtime {} at {}", TEXT("Host"), srcDotnet);
|
||||
|
||||
// Get major Version
|
||||
Array<String> pathParts;
|
||||
srcDotnet.Split('/', pathParts);
|
||||
String version;
|
||||
for (int i = 0; i < pathParts.Count(); i++)
|
||||
{
|
||||
if (pathParts[i] == TEXT("runtimes"))
|
||||
{
|
||||
Array<String> versionParts;
|
||||
pathParts[i - 1].Split('.', versionParts);
|
||||
if (!versionParts.IsEmpty())
|
||||
{
|
||||
const String majorVersion = versionParts[0].TrimTrailing();
|
||||
int32 versionNum;
|
||||
StringUtils::Parse(*majorVersion, majorVersion.Length(), &versionNum);
|
||||
if (Math::IsInRange(versionNum, GAME_BUILD_DOTNET_RUNTIME_MIN_VER, GAME_BUILD_DOTNET_RUNTIME_MAX_VER)) // Check for major part
|
||||
version = majorVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (version.IsEmpty())
|
||||
{
|
||||
data.Error(TEXT("Failed to find supported .NET version for the current host platform."));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Deploy runtime files
|
||||
const Char* corlibPrivateName = TEXT("System.Private.CoreLib.dll");
|
||||
const bool srcDotnetFromEngine = srcDotnet.Contains(TEXT("Source/Platforms"));
|
||||
@@ -226,14 +253,14 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
{
|
||||
// AOT runtime files inside Engine Platform folder
|
||||
packFolder /= TEXT("Dotnet");
|
||||
dstDotnetLibs /= TEXT("lib/net8.0");
|
||||
srcDotnetLibs = packFolder / TEXT("lib/net8.0");
|
||||
dstDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
|
||||
srcDotnetLibs = packFolder / String::Format(TEXT("lib/net{}.0"), version);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Runtime files inside Dotnet SDK folder but placed for AOT
|
||||
dstDotnetLibs /= TEXT("lib/net8.0");
|
||||
srcDotnetLibs /= TEXT("../lib/net8.0");
|
||||
dstDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
|
||||
srcDotnetLibs /= String::Format(TEXT("../lib/net{}.0"), version);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -241,14 +268,14 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
if (srcDotnetFromEngine)
|
||||
{
|
||||
// Runtime files inside Engine Platform folder
|
||||
dstDotnetLibs /= TEXT("lib/net8.0");
|
||||
srcDotnetLibs /= TEXT("lib/net8.0");
|
||||
dstDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
|
||||
srcDotnetLibs /= String::Format(TEXT("lib/net{}.0"), version);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Runtime files inside Dotnet SDK folder
|
||||
dstDotnetLibs /= TEXT("shared/Microsoft.NETCore.App");
|
||||
srcDotnetLibs /= TEXT("../lib/net8.0");
|
||||
srcDotnetLibs /= String::Format(TEXT("../lib/net{}.0"), version);
|
||||
}
|
||||
}
|
||||
LOG(Info, "Copying .NET files from {} to {}", packFolder, dstDotnet);
|
||||
@@ -273,6 +300,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
||||
DEPLOY_NATIVE_FILE("libmonosgen-2.0.so");
|
||||
DEPLOY_NATIVE_FILE("libSystem.IO.Compression.Native.so");
|
||||
DEPLOY_NATIVE_FILE("libSystem.Native.so");
|
||||
DEPLOY_NATIVE_FILE("libSystem.Globalization.Native.so");
|
||||
DEPLOY_NATIVE_FILE("libSystem.Security.Cryptography.Native.Android.so");
|
||||
break;
|
||||
case BuildPlatform::iOSARM64:
|
||||
|
||||
@@ -301,7 +301,7 @@ namespace FlaxEditor.CustomEditors
|
||||
_valueToSet = null;
|
||||
|
||||
// Assign value
|
||||
if (val is IList l && l.Count == _values.Count)
|
||||
if (val is IList l && l.Count == _values.Count && _values.Count > 1)
|
||||
{
|
||||
for (int i = 0; i < _values.Count; i++)
|
||||
_values[i] = l[i];
|
||||
|
||||
@@ -9,6 +9,7 @@ using FlaxEditor.CustomEditors.Elements;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.GUI.ContextMenu;
|
||||
using FlaxEditor.GUI.Tree;
|
||||
using FlaxEditor.Modules;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEditor.Windows;
|
||||
using FlaxEditor.Windows.Assets;
|
||||
@@ -85,12 +86,7 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
|
||||
// Edit selected prefab asset
|
||||
var editPrefab = panel.Button("Edit Prefab");
|
||||
editPrefab.Button.Clicked += () =>
|
||||
{
|
||||
Editor.Instance.Windows.ContentWin.ClearItemsSearch();
|
||||
Editor.Instance.Windows.ContentWin.Select(prefab);
|
||||
Editor.Instance.Windows.ContentWin.Open(Editor.Instance.Windows.ContentWin.View.Selection[0]);
|
||||
};
|
||||
editPrefab.Button.Clicked += () => Editor.Instance.Windows.ContentWin.Open(Editor.Instance.ContentDatabase.FindAsset(prefab.ID));
|
||||
|
||||
// Viewing changes applied to this actor
|
||||
var viewChanges = panel.Button("View Changes");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FlaxEditor.CustomEditors.Elements;
|
||||
using FlaxEditor.Surface;
|
||||
using FlaxEngine;
|
||||
@@ -35,6 +36,8 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
(instance, parameter, tag) => ((AnimatedModel)instance).GetParameterValue(parameter.Identifier),
|
||||
(instance, value, parameter, tag) => ((AnimatedModel)instance).SetParameterValue(parameter.Identifier, value),
|
||||
Values);
|
||||
if (!parameters.Any())
|
||||
group.Label("No parameters", TextAlignment.Center);
|
||||
_parametersAdded = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,9 @@ public class ModelPrefabEditor : GenericEditor
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the import path UI
|
||||
Utilities.Utils.CreateImportPathUI(layout, modelPrefab.ImportPath, false);
|
||||
|
||||
var button = layout.Button("Reimport", "Reimports the source asset as prefab.");
|
||||
_reimportButton = button.Button;
|
||||
_reimportButton.Clicked += OnReimport;
|
||||
|
||||
@@ -117,6 +117,9 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
var data = SurfaceUtils.InitGraphParameters(parametersGroup);
|
||||
SurfaceUtils.DisplayGraphParameters(group, data, ParameterGet, ParameterSet, Values, ParameterDefaultValue);
|
||||
}
|
||||
|
||||
if (!parameters.Any())
|
||||
groups.Label("No parameters", TextAlignment.Center);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -424,6 +424,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
{
|
||||
presenter.Undo.AddAction(multiAction);
|
||||
presenter.Control.Focus();
|
||||
|
||||
// Scroll to bottom of script control where a new script is added.
|
||||
if (presenter.Panel.Parent is Panel p && Editor.Instance.Options.Options.Interface.ScrollToScriptOnAdd)
|
||||
{
|
||||
var loc = ScriptsEditor.Layout.Control.BottomLeft;
|
||||
p.ScrollViewTo(loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,10 +723,13 @@ namespace FlaxEditor.CustomEditors.Dedicated
|
||||
}
|
||||
|
||||
// Refresh anchors
|
||||
GetAnchorEquality(out bool xEq, out bool yEq, ValuesTypes);
|
||||
if (xEq != _cachedXEq || yEq != _cachedYEq)
|
||||
if (Values != null && Values[0] != null)
|
||||
{
|
||||
RebuildLayout();
|
||||
GetAnchorEquality(out bool xEq, out bool yEq, ValuesTypes);
|
||||
if (xEq != _cachedXEq || yEq != _cachedYEq)
|
||||
{
|
||||
RebuildLayout();
|
||||
}
|
||||
}
|
||||
|
||||
base.Refresh();
|
||||
|
||||
@@ -292,5 +292,17 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
_isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Deinitialize()
|
||||
{
|
||||
if (_validator != null)
|
||||
{
|
||||
_validator.OnDestroy();
|
||||
_validator = null;
|
||||
}
|
||||
|
||||
base.Deinitialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -898,9 +898,13 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
base.Draw();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void OnDestroy()
|
||||
{
|
||||
_pickerValidator.OnDestroy();
|
||||
_pickerValidator = null;
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
private bool ValidateActors(ActorNode node)
|
||||
|
||||
@@ -7,6 +7,7 @@ using FlaxEditor.CustomEditors.Elements;
|
||||
using FlaxEditor.GUI;
|
||||
using FlaxEditor.GUI.Drag;
|
||||
using FlaxEditor.SceneGraph;
|
||||
using FlaxEditor.SceneGraph.GUI;
|
||||
using FlaxEditor.Scripting;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
@@ -23,6 +24,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
public class FlaxObjectRefPickerControl : Control
|
||||
{
|
||||
private ScriptType _type;
|
||||
private ActorTreeNode _linkedTreeNode;
|
||||
private Object _value;
|
||||
private string _valueName;
|
||||
private bool _supportsPickDropDown;
|
||||
@@ -300,7 +302,43 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
|
||||
// Picker dropdown menu
|
||||
if (_supportsPickDropDown && (isSelected ? button2Rect : button1Rect).Contains(ref location))
|
||||
{
|
||||
ShowDropDownMenu();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (button == MouseButton.Left)
|
||||
{
|
||||
_isMouseDown = false;
|
||||
|
||||
// Highlight actor or script reference
|
||||
if (!_hasValidDragOver && !IsDragOver)
|
||||
{
|
||||
Actor actor = _value as Actor;
|
||||
if (actor == null && _value is Script script)
|
||||
actor = script.Actor;
|
||||
if (actor != null)
|
||||
{
|
||||
if (_linkedTreeNode != null && _linkedTreeNode.Actor == actor)
|
||||
{
|
||||
_linkedTreeNode.ExpandAllParents();
|
||||
_linkedTreeNode.StartHighlight();
|
||||
}
|
||||
else
|
||||
{
|
||||
_linkedTreeNode = Editor.Instance.Scene.GetActorNode(actor).TreeNode;
|
||||
_linkedTreeNode.ExpandAllParents();
|
||||
Editor.Instance.Windows.SceneWin.SceneTreePanel.ScrollViewTo(_linkedTreeNode, true);
|
||||
_linkedTreeNode.StartHighlight();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Reset valid drag over if still true at this point
|
||||
if (_hasValidDragOver)
|
||||
_hasValidDragOver = false;
|
||||
}
|
||||
|
||||
return base.OnMouseUp(location, button);
|
||||
}
|
||||
@@ -326,6 +364,12 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
// Check if has object selected
|
||||
if (_value != null)
|
||||
{
|
||||
if (_linkedTreeNode != null)
|
||||
{
|
||||
_linkedTreeNode.StopHighlight();
|
||||
_linkedTreeNode = null;
|
||||
}
|
||||
|
||||
// Select object
|
||||
if (_value is Actor actor)
|
||||
Select(actor);
|
||||
@@ -491,6 +535,7 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
_value = null;
|
||||
_type = ScriptType.Null;
|
||||
_valueName = null;
|
||||
_linkedTreeNode = null;
|
||||
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
@@ -228,7 +228,6 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
// Handle Sliding
|
||||
if (AllowSlidingForDifferentValues && (isSliding || _slidingEnded))
|
||||
{
|
||||
// TODO: handle linked values
|
||||
Float3 average = Float3.Zero;
|
||||
for (int i = 0; i < Values.Count; i++)
|
||||
{
|
||||
@@ -251,12 +250,24 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
for (int i = 0; i < Values.Count; i++)
|
||||
{
|
||||
var v = Values[i];
|
||||
if (v is Vector3 asVector3)
|
||||
v = asVector3 + new Vector3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
|
||||
else if (v is Float3 asFloat3)
|
||||
v = asFloat3 + new Float3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
|
||||
else if (v is Double3 asDouble3)
|
||||
v = asDouble3 + new Double3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
|
||||
if (LinkValues)
|
||||
{
|
||||
if (v is Vector3 asVector3)
|
||||
v = asVector3 + new Vector3(newValue.X, newValue.Y, newValue.Z);
|
||||
else if (v is Float3 asFloat3)
|
||||
v = asFloat3 + new Float3(newValue.X, newValue.Y, newValue.Z);
|
||||
else if (v is Double3 asDouble3)
|
||||
v = asDouble3 + new Double3(newValue.X, newValue.Y, newValue.Z);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v is Vector3 asVector3)
|
||||
v = asVector3 + new Vector3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
|
||||
else if (v is Float3 asFloat3)
|
||||
v = asFloat3 + new Float3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
|
||||
else if (v is Double3 asDouble3)
|
||||
v = asDouble3 + new Double3(_valueChanged == ValueChanged.X ? newValue.X : 0, _valueChanged == ValueChanged.Y ? newValue.Y : 0, _valueChanged == ValueChanged.Z ? newValue.Z : 0);
|
||||
}
|
||||
|
||||
newObjects[i] = v;
|
||||
}
|
||||
@@ -267,16 +278,27 @@ namespace FlaxEditor.CustomEditors.Editors
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: handle linked values
|
||||
for (int i = 0; i < Values.Count; i++)
|
||||
{
|
||||
object v = Values[i];
|
||||
if (v is Vector3 asVector3)
|
||||
v = new Vector3(_valueChanged == ValueChanged.X ? xValue : asVector3.X, _valueChanged == ValueChanged.Y ? yValue : asVector3.Y, _valueChanged == ValueChanged.Z ? zValue : asVector3.Z);
|
||||
else if (v is Float3 asFloat3)
|
||||
v = new Float3(_valueChanged == ValueChanged.X ? xValue : asFloat3.X, _valueChanged == ValueChanged.Y ? yValue : asFloat3.Y, _valueChanged == ValueChanged.Z ? zValue : asFloat3.Z);
|
||||
else if (v is Double3 asDouble3)
|
||||
v = new Double3(_valueChanged == ValueChanged.X ? xValue : asDouble3.X, _valueChanged == ValueChanged.Y ? yValue : asDouble3.Y, _valueChanged == ValueChanged.Z ? zValue : asDouble3.Z);
|
||||
if (LinkValues)
|
||||
{
|
||||
if (v is Vector3 asVector3)
|
||||
v = asVector3 + new Vector3(xValue, yValue, zValue);
|
||||
else if (v is Float3 asFloat3)
|
||||
v = asFloat3 + new Float3(xValue, yValue, zValue);
|
||||
else if (v is Double3 asDouble3)
|
||||
v = asDouble3 + new Double3(xValue, yValue, zValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v is Vector3 asVector3)
|
||||
v = new Vector3(_valueChanged == ValueChanged.X ? xValue : asVector3.X, _valueChanged == ValueChanged.Y ? yValue : asVector3.Y, _valueChanged == ValueChanged.Z ? zValue : asVector3.Z);
|
||||
else if (v is Float3 asFloat3)
|
||||
v = new Float3(_valueChanged == ValueChanged.X ? xValue : asFloat3.X, _valueChanged == ValueChanged.Y ? yValue : asFloat3.Y, _valueChanged == ValueChanged.Z ? zValue : asFloat3.Z);
|
||||
else if (v is Double3 asDouble3)
|
||||
v = new Double3(_valueChanged == ValueChanged.X ? xValue : asDouble3.X, _valueChanged == ValueChanged.Y ? yValue : asDouble3.Y, _valueChanged == ValueChanged.Z ? zValue : asDouble3.Z);
|
||||
}
|
||||
|
||||
newObjects[i] = v;
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ namespace FlaxEditor.CustomEditors
|
||||
if (instanceValues.Count != Count)
|
||||
throw new ArgumentException();
|
||||
|
||||
if (value is IList l && l.Count == Count)
|
||||
if (value is IList l && l.Count == Count && Count > 1)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
|
||||
@@ -550,7 +550,7 @@ int32 Editor::LoadProduct()
|
||||
}
|
||||
if (!FileSystem::FileExists(files[0]))
|
||||
{
|
||||
Platform::Fatal(TEXT("Cannot opoen selected project file because it doesn't exist."));
|
||||
Platform::Fatal(TEXT("Cannot open selected project file because it doesn't exist."));
|
||||
return -1;
|
||||
}
|
||||
projectPath = StringUtils::GetDirectoryName(files[0]);
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace FlaxEditor.GUI
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetPicker"/> class.
|
||||
/// </summary>
|
||||
/// <param name="assetType">The assets types that this picker accepts.</param>
|
||||
/// <param name="assetType">The asset types that this picker accepts.</param>
|
||||
/// <param name="location">The control location.</param>
|
||||
public AssetPicker(ScriptType assetType, Float2 location)
|
||||
: base(location, new Float2(DefaultIconSize + ButtonsOffset + ButtonsSize, DefaultIconSize))
|
||||
|
||||
@@ -23,10 +23,19 @@ namespace FlaxEditor.GUI.Tree
|
||||
/// </summary>
|
||||
public const float DefaultNodeOffsetY = 0;
|
||||
|
||||
private const float _targetHighlightScale = 1.25f;
|
||||
private const float _highlightScaleAnimDuration = 0.85f;
|
||||
|
||||
private Tree _tree;
|
||||
|
||||
private bool _opened, _canChangeOrder;
|
||||
private float _animationProgress, _cachedHeight;
|
||||
private bool _isHightlighted;
|
||||
private float _targetHighlightTimeSec;
|
||||
private float _currentHighlightTimeSec;
|
||||
// Used to prevent showing highlight on double mouse click
|
||||
private float _debounceHighlightTime;
|
||||
private float _highlightScale;
|
||||
private bool _mouseOverArrow, _mouseOverHeader;
|
||||
private float _xOffset, _textWidth;
|
||||
private float _headerHeight = 16.0f;
|
||||
@@ -605,9 +614,47 @@ namespace FlaxEditor.GUI.Tree
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a box around the text to highlight the node.
|
||||
/// </summary>
|
||||
/// <param name="durationSec">The duration of the highlight in seconds.</param>
|
||||
public void StartHighlight(float durationSec = 3)
|
||||
{
|
||||
_isHightlighted = true;
|
||||
_targetHighlightTimeSec = durationSec;
|
||||
_currentHighlightTimeSec = 0;
|
||||
_debounceHighlightTime = 0;
|
||||
_highlightScale = 2f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops any current highlight.
|
||||
/// </summary>
|
||||
public void StopHighlight()
|
||||
{
|
||||
_isHightlighted = false;
|
||||
_targetHighlightTimeSec = 0;
|
||||
_currentHighlightTimeSec = 0;
|
||||
_debounceHighlightTime = 0;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
// Highlight animations
|
||||
if (_isHightlighted)
|
||||
{
|
||||
_debounceHighlightTime += deltaTime;
|
||||
_currentHighlightTimeSec += deltaTime;
|
||||
|
||||
// In the first second, animate the highlight to shrink into it's resting position
|
||||
if (_currentHighlightTimeSec < _highlightScaleAnimDuration)
|
||||
_highlightScale = Mathf.Lerp(_highlightScale, _targetHighlightScale, _currentHighlightTimeSec);
|
||||
|
||||
if (_currentHighlightTimeSec >= _targetHighlightTimeSec)
|
||||
_isHightlighted = false;
|
||||
}
|
||||
|
||||
// Drop/down animation
|
||||
if (_animationProgress < 1.0f)
|
||||
{
|
||||
@@ -676,6 +723,18 @@ namespace FlaxEditor.GUI.Tree
|
||||
textRect.Width -= 18.0f;
|
||||
}
|
||||
|
||||
float textWidth = TextFont.GetFont().MeasureText(_text).X;
|
||||
Rectangle trueTextRect = textRect;
|
||||
trueTextRect.Width = textWidth;
|
||||
trueTextRect.Scale(_highlightScale);
|
||||
|
||||
if (_isHightlighted && _debounceHighlightTime > 0.1f)
|
||||
{
|
||||
Color highlightBackgroundColor = Editor.Instance.Options.Options.Visual.HighlightColor;
|
||||
highlightBackgroundColor = highlightBackgroundColor.AlphaMultiplied(0.3f);
|
||||
Render2D.FillRectangle(trueTextRect, highlightBackgroundColor);
|
||||
}
|
||||
|
||||
// Draw text
|
||||
Color textColor = CacheTextColor();
|
||||
Render2D.DrawText(TextFont.GetFont(), _text, textRect, textColor, TextAlignment.Near, TextAlignment.Center);
|
||||
@@ -730,6 +789,12 @@ namespace FlaxEditor.GUI.Tree
|
||||
}
|
||||
}
|
||||
|
||||
if (_isHightlighted && _debounceHighlightTime > 0.1f)
|
||||
{
|
||||
// Draw highlights
|
||||
Render2D.DrawRectangle(trueTextRect, Editor.Instance.Options.Options.Visual.HighlightColor, 3);
|
||||
}
|
||||
|
||||
// Base
|
||||
if (_opened)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using FlaxEditor.Options;
|
||||
using FlaxEditor.SceneGraph;
|
||||
using FlaxEngine;
|
||||
using System;
|
||||
|
||||
namespace FlaxEditor.Gizmo
|
||||
{
|
||||
@@ -18,8 +21,13 @@ namespace FlaxEditor.Gizmo
|
||||
private MaterialInstance _materialAxisY;
|
||||
private MaterialInstance _materialAxisZ;
|
||||
private MaterialInstance _materialAxisFocus;
|
||||
private MaterialInstance _materialAxisLocked;
|
||||
private MaterialBase _materialSphere;
|
||||
|
||||
// Material Parameter Names
|
||||
const String _brightnessParamName = "Brightness";
|
||||
const String _opacityParamName = "Opacity";
|
||||
|
||||
private void InitDrawing()
|
||||
{
|
||||
// Axis Models
|
||||
@@ -34,6 +42,7 @@ namespace FlaxEditor.Gizmo
|
||||
_materialAxisY = FlaxEngine.Content.LoadAsyncInternal<MaterialInstance>("Editor/Gizmo/MaterialAxisY");
|
||||
_materialAxisZ = FlaxEngine.Content.LoadAsyncInternal<MaterialInstance>("Editor/Gizmo/MaterialAxisZ");
|
||||
_materialAxisFocus = FlaxEngine.Content.LoadAsyncInternal<MaterialInstance>("Editor/Gizmo/MaterialAxisFocus");
|
||||
_materialAxisLocked = FlaxEngine.Content.LoadAsyncInternal<MaterialInstance>("Editor/Gizmo/MaterialAxisLocked");
|
||||
_materialSphere = FlaxEngine.Content.LoadAsyncInternal<MaterialInstance>("Editor/Gizmo/MaterialSphere");
|
||||
|
||||
// Ensure that every asset was loaded
|
||||
@@ -50,6 +59,25 @@ namespace FlaxEditor.Gizmo
|
||||
{
|
||||
Platform.Fatal("Failed to load transform gizmo resources.");
|
||||
}
|
||||
|
||||
// Setup editor options
|
||||
OnEditorOptionsChanged(Editor.Instance.Options.Options);
|
||||
Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged;
|
||||
}
|
||||
|
||||
private void OnEditorOptionsChanged(EditorOptions options)
|
||||
{
|
||||
float brightness = options.Visual.TransformGizmoBrightness;
|
||||
_materialAxisX.SetParameterValue(_brightnessParamName, brightness);
|
||||
_materialAxisY.SetParameterValue(_brightnessParamName, brightness);
|
||||
_materialAxisZ.SetParameterValue(_brightnessParamName, brightness);
|
||||
_materialAxisLocked.SetParameterValue(_brightnessParamName, brightness);
|
||||
|
||||
float opacity = options.Visual.TransformGizmoOpacity;
|
||||
_materialAxisX.SetParameterValue(_opacityParamName, opacity);
|
||||
_materialAxisY.SetParameterValue(_opacityParamName, opacity);
|
||||
_materialAxisZ.SetParameterValue(_opacityParamName, opacity);
|
||||
_materialAxisLocked.SetParameterValue(_opacityParamName, opacity);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -60,6 +88,21 @@ namespace FlaxEditor.Gizmo
|
||||
if (!_modelCube || !_modelCube.IsLoaded)
|
||||
return;
|
||||
|
||||
// Find out if any of the selected objects can not be moved
|
||||
bool gizmoLocked = false;
|
||||
if (Editor.Instance.StateMachine.IsPlayMode)
|
||||
{
|
||||
for (int i = 0; i < SelectionCount; i++)
|
||||
{
|
||||
var obj = GetSelectedObject(i);
|
||||
if (obj.CanTransform == false)
|
||||
{
|
||||
gizmoLocked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// As all axisMesh have the same pivot, add a little offset to the x axisMesh, this way SortDrawCalls is able to sort the draw order
|
||||
// https://github.com/FlaxEngine/FlaxEngine/issues/680
|
||||
|
||||
@@ -92,32 +135,38 @@ namespace FlaxEditor.Gizmo
|
||||
// X axis
|
||||
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
transAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||
MaterialInstance xAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX);
|
||||
transAxisMesh.Draw(ref renderContext, xAxisMaterialTransform, ref m3);
|
||||
|
||||
// Y axis
|
||||
Matrix.RotationX(Mathf.PiOverTwo, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
transAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||
MaterialInstance yAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY);
|
||||
transAxisMesh.Draw(ref renderContext, yAxisMaterialTransform, ref m3);
|
||||
|
||||
// Z axis
|
||||
Matrix.RotationX(Mathf.Pi, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
transAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||
MaterialInstance zAxisMaterialTransform = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ);
|
||||
transAxisMesh.Draw(ref renderContext, zAxisMaterialTransform, ref m3);
|
||||
|
||||
// XY plane
|
||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||
MaterialInstance xyPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX);
|
||||
cubeMesh.Draw(ref renderContext, xyPlaneMaterialTransform, ref m3);
|
||||
|
||||
// ZX plane
|
||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||
MaterialInstance zxPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisY);
|
||||
cubeMesh.Draw(ref renderContext, zxPlaneMaterialTransform, ref m3);
|
||||
|
||||
// YZ plane
|
||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||
MaterialInstance yzPlaneMaterialTransform = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisZ);
|
||||
cubeMesh.Draw(ref renderContext, yzPlaneMaterialTransform, ref m3);
|
||||
|
||||
// Center sphere
|
||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
||||
@@ -136,15 +185,18 @@ namespace FlaxEditor.Gizmo
|
||||
// X axis
|
||||
Matrix.RotationZ(Mathf.PiOverTwo, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
rotationAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||
MaterialInstance xAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX);
|
||||
rotationAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3);
|
||||
|
||||
// Y axis
|
||||
rotationAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m1);
|
||||
MaterialInstance yAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY);
|
||||
rotationAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m1);
|
||||
|
||||
// Z axis
|
||||
Matrix.RotationX(-Mathf.PiOverTwo, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
rotationAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||
MaterialInstance zAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ);
|
||||
rotationAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3);
|
||||
|
||||
// Center box
|
||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
||||
@@ -163,32 +215,38 @@ namespace FlaxEditor.Gizmo
|
||||
// X axis
|
||||
Matrix.RotationY(-Mathf.PiOverTwo, out m2);
|
||||
Matrix.Multiply(ref m2, ref mx1, out m3);
|
||||
scaleAxisMesh.Draw(ref renderContext, isXAxis ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||
MaterialInstance xAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isXAxis ? _materialAxisFocus : _materialAxisX);
|
||||
scaleAxisMesh.Draw(ref renderContext, xAxisMaterialRotate, ref m3);
|
||||
|
||||
// Y axis
|
||||
Matrix.RotationX(Mathf.PiOverTwo, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
scaleAxisMesh.Draw(ref renderContext, isYAxis ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||
MaterialInstance yAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isYAxis ? _materialAxisFocus : _materialAxisY);
|
||||
scaleAxisMesh.Draw(ref renderContext, yAxisMaterialRotate, ref m3);
|
||||
|
||||
// Z axis
|
||||
Matrix.RotationX(Mathf.Pi, out m2);
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
scaleAxisMesh.Draw(ref renderContext, isZAxis ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||
MaterialInstance zAxisMaterialRotate = gizmoLocked ? _materialAxisLocked : (isZAxis ? _materialAxisFocus : _materialAxisZ);
|
||||
scaleAxisMesh.Draw(ref renderContext, zAxisMaterialRotate, ref m3);
|
||||
|
||||
// XY plane
|
||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationX(Mathf.PiOverTwo), new Vector3(boxSize * boxScale, boxSize * boxScale, 0.0f));
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX, ref m3);
|
||||
MaterialInstance xyPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.XY ? _materialAxisFocus : _materialAxisX);
|
||||
cubeMesh.Draw(ref renderContext, xyPlaneMaterialScale, ref m3);
|
||||
|
||||
// ZX plane
|
||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.Identity, new Vector3(boxSize * boxScale, 0.0f, boxSize * boxScale));
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ, ref m3);
|
||||
MaterialInstance zxPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.ZX ? _materialAxisFocus : _materialAxisZ);
|
||||
cubeMesh.Draw(ref renderContext, zxPlaneMaterialScale, ref m3);
|
||||
|
||||
// YZ plane
|
||||
m2 = Matrix.Transformation(new Vector3(boxSize, boxSize * 0.1f, boxSize), Quaternion.RotationZ(Mathf.PiOverTwo), new Vector3(0.0f, boxSize * boxScale, boxSize * boxScale));
|
||||
Matrix.Multiply(ref m2, ref m1, out m3);
|
||||
cubeMesh.Draw(ref renderContext, _activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY, ref m3);
|
||||
MaterialInstance yzPlaneMaterialScale = gizmoLocked ? _materialAxisLocked : (_activeAxis == Axis.YZ ? _materialAxisFocus : _materialAxisY);
|
||||
cubeMesh.Draw(ref renderContext, yzPlaneMaterialScale, ref m3);
|
||||
|
||||
// Center box
|
||||
Matrix.Scaling(gizmoModelsScale2RealGizmoSize, out m2);
|
||||
|
||||
@@ -169,12 +169,12 @@ namespace FlaxEditor.Gizmo
|
||||
closestIntersection = intersection;
|
||||
}
|
||||
|
||||
/*// Center
|
||||
if (CenterBoxRaw.Intersects(ref localRay, out intersection) && intersection < closestIntersection)
|
||||
// Center
|
||||
if (CenterBoxRaw.Intersects(ref localRay, out intersection) && intersection > closestIntersection)
|
||||
{
|
||||
_activeAxis = Axis.Center;
|
||||
closestIntersection = intersection;
|
||||
}*/
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace FlaxEditor.Gizmo
|
||||
/// <summary>
|
||||
/// Offset to move axis away from center
|
||||
/// </summary>
|
||||
private const float AxisOffset = 0.8f;
|
||||
private const float AxisOffset = 1.2f;
|
||||
|
||||
/// <summary>
|
||||
/// How thick the axis should be
|
||||
|
||||
@@ -501,7 +501,7 @@ namespace FlaxEditor.Gizmo
|
||||
_scaleDelta = Vector3.Zero;
|
||||
|
||||
if (ActiveAxis == Axis.Center)
|
||||
scaleDelta = new Vector3(scaleDelta.AvgValue);
|
||||
scaleDelta = new Vector3(scaleDelta.ValuesSum);
|
||||
}
|
||||
|
||||
// Apply transformation (but to the parents, not whole selection pool)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FlaxEditor.Gizmo;
|
||||
@@ -647,7 +648,36 @@ namespace FlaxEditor
|
||||
private void DrawControlWidget(UIControl uiControl, ref Float2 pos, ref Float2 mousePos, ref Float2 size, float scale, Float2 resizeAxis, CursorType cursor)
|
||||
{
|
||||
var style = Style.Current;
|
||||
var rect = new Rectangle((pos + resizeAxis * 10 * scale) - size * 0.5f, size);
|
||||
var control = uiControl.Control;
|
||||
var rotation = control.Rotation;
|
||||
var rotationInRadians = rotation * Mathf.DegreesToRadians;
|
||||
var rect = new Rectangle(
|
||||
(pos +
|
||||
new Float2(resizeAxis.X * Mathf.Cos(rotationInRadians) - resizeAxis.Y * Mathf.Sin(rotationInRadians),
|
||||
resizeAxis.Y * Mathf.Cos(rotationInRadians) + resizeAxis.X * Mathf.Sin(rotationInRadians)) * 10 * scale) - size * 0.5f,
|
||||
size);
|
||||
|
||||
// Find more correct cursor at different angles
|
||||
var unwindRotation = Mathf.UnwindDegrees(rotation);
|
||||
if (unwindRotation is (>= 45 and < 135) or (> -135 and <= -45) )
|
||||
{
|
||||
switch (cursor)
|
||||
{
|
||||
case CursorType.SizeNESW:
|
||||
cursor = CursorType.SizeNWSE;
|
||||
break;
|
||||
case CursorType.SizeNS:
|
||||
cursor = CursorType.SizeWE;
|
||||
break;
|
||||
case CursorType.SizeNWSE:
|
||||
cursor = CursorType.SizeNESW;
|
||||
break;
|
||||
case CursorType.SizeWE:
|
||||
cursor = CursorType.SizeNS;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (rect.Contains(ref mousePos))
|
||||
{
|
||||
Render2D.FillRectangle(rect, style.Foreground);
|
||||
|
||||
@@ -1136,9 +1136,15 @@ namespace FlaxEditor.Modules
|
||||
Proxy.Add(new SceneAnimationProxy());
|
||||
Proxy.Add(new CSharpScriptProxy());
|
||||
Proxy.Add(new CSharpEmptyProxy());
|
||||
Proxy.Add(new CSharpEmptyClassProxy());
|
||||
Proxy.Add(new CSharpEmptyStructProxy());
|
||||
Proxy.Add(new CSharpEmptyInterfaceProxy());
|
||||
Proxy.Add(new CSharpActorProxy());
|
||||
Proxy.Add(new CSharpGamePluginProxy());
|
||||
Proxy.Add(new CppAssetProxy());
|
||||
Proxy.Add(new CppStaticClassProxy());
|
||||
Proxy.Add(new CppScriptProxy());
|
||||
Proxy.Add(new CppActorProxy());
|
||||
Proxy.Add(new SceneProxy());
|
||||
Proxy.Add(new PrefabProxy());
|
||||
Proxy.Add(new IESProfileProxy());
|
||||
|
||||
@@ -99,6 +99,10 @@ namespace FlaxEditor.Modules
|
||||
{
|
||||
if (Editor.StateMachine.IsEditMode)
|
||||
{
|
||||
// Show Game window if hidden
|
||||
if (Editor.Windows.GameWin.IsHidden)
|
||||
Editor.Windows.GameWin.Show();
|
||||
|
||||
Editor.Log("[PlayMode] Start");
|
||||
|
||||
if (Editor.Options.Options.General.AutoReloadScriptsOnMainWindowFocus)
|
||||
@@ -131,6 +135,10 @@ namespace FlaxEditor.Modules
|
||||
if (!Editor.StateMachine.IsEditMode)
|
||||
return;
|
||||
|
||||
// Show Game window if hidden
|
||||
if (Editor.Windows.GameWin.IsHidden)
|
||||
Editor.Windows.GameWin.Show();
|
||||
|
||||
var firstScene = Content.Settings.GameSettings.Load().FirstScene;
|
||||
if (firstScene == Guid.Empty)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.Text;
|
||||
using FlaxEditor.CustomEditors;
|
||||
using FlaxEditor.CustomEditors.Editors;
|
||||
using FlaxEngine;
|
||||
using FlaxEngine.GUI;
|
||||
using FlaxEngine.Json;
|
||||
|
||||
@@ -31,11 +33,33 @@ namespace FlaxEditor.Options
|
||||
|
||||
private void OnResetButtonClicked()
|
||||
{
|
||||
var obj = new T();
|
||||
var str = JsonSerializer.Serialize(obj);
|
||||
JsonSerializer.Deserialize(Values[0], str);
|
||||
SetValue(Values[0]);
|
||||
Refresh();
|
||||
var editorClassName = typeof(T).Name;
|
||||
|
||||
var editorName = new StringBuilder();
|
||||
editorName.Append(editorClassName[0]);
|
||||
for (var i = 1; i < editorClassName.Length; i++)
|
||||
{
|
||||
// Whenever there is an uppercase letter, add a space to make it more pretty for the end user
|
||||
if (char.IsUpper(editorClassName[i]))
|
||||
{
|
||||
editorName.Append(' ');
|
||||
}
|
||||
editorName.Append(editorClassName[i]);
|
||||
}
|
||||
|
||||
var result = MessageBox.Show($"Are you sure you want to reset \"{editorName}\" to default values?",
|
||||
"Reset values?",
|
||||
MessageBoxButtons.YesNo
|
||||
);
|
||||
|
||||
if (result == DialogResult.Yes || result == DialogResult.OK)
|
||||
{
|
||||
var obj = new T();
|
||||
var str = JsonSerializer.Serialize(obj);
|
||||
JsonSerializer.Deserialize(Values[0], str);
|
||||
SetValue(Values[0]);
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +258,13 @@ namespace FlaxEditor.Options
|
||||
|
||||
private TextAlignment _tooltipTextAlignment = TextAlignment.Center;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to scroll to the script when a script is added to an actor.
|
||||
/// </summary>
|
||||
[DefaultValue(true)]
|
||||
[EditorDisplay("Interface"), EditorOrder(322)]
|
||||
public bool ScrollToScriptOnAdd { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamps prefix mode for output log messages.
|
||||
/// </summary>
|
||||
|
||||
@@ -22,37 +22,51 @@ namespace FlaxEditor.Options
|
||||
/// Gets or sets the first outline color.
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(Color), "0.039,0.827,0.156")]
|
||||
[EditorDisplay("Gizmo"), EditorOrder(100), Tooltip("The first color of the selection outline gradient.")]
|
||||
[EditorDisplay("Transform Gizmo"), EditorOrder(100), Tooltip("The first color of the selection outline gradient.")]
|
||||
public Color SelectionOutlineColor0 { get; set; } = new Color(0.039f, 0.827f, 0.156f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the second outline color.
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(Color), "0.019,0.615,0.101")]
|
||||
[EditorDisplay("Gizmo"), EditorOrder(101), Tooltip("The second color of the selection outline gradient.")]
|
||||
[EditorDisplay("Transform Gizmo"), EditorOrder(101), Tooltip("The second color of the selection outline gradient.")]
|
||||
public Color SelectionOutlineColor1 { get; set; } = new Color(0.019f, 0.615f, 0.101f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the selection outline size for UI controls.
|
||||
/// </summary>
|
||||
[DefaultValue(2.0f)]
|
||||
[EditorDisplay("Gizmo", "UI Control Outline Size"), EditorOrder(100), Tooltip("The size of the selection outline for UI controls.")]
|
||||
[EditorDisplay("UI Gizmo", "UI Control Outline Size"), EditorOrder(103), Tooltip("The size of the selection outline for UI controls.")]
|
||||
public float UISelectionOutlineSize { get; set; } = 2.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the transform gizmo size.
|
||||
/// </summary>
|
||||
[DefaultValue(1.0f), Limit(0.01f, 100.0f, 0.01f)]
|
||||
[EditorDisplay("Gizmo"), EditorOrder(110), Tooltip("The transform gizmo size.")]
|
||||
[EditorDisplay("Transform Gizmo"), EditorOrder(110), Tooltip("The transform gizmo size.")]
|
||||
public float GizmoSize { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color used to highlight selected meshes and CSG surfaces.
|
||||
/// </summary>
|
||||
[DefaultValue(typeof(Color), "0.0,0.533,1.0,1.0")]
|
||||
[EditorDisplay("Gizmo"), EditorOrder(200), Tooltip("The color used to highlight selected meshes and CSG surfaces.")]
|
||||
[EditorDisplay("Transform Gizmo"), EditorOrder(200), Tooltip("The color used to highlight selected meshes and CSG surfaces.")]
|
||||
public Color HighlightColor { get; set; } = new Color(0.0f, 0.533f, 1.0f, 1.0f);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set a value indicating how bright the transform gizmo is. Value over 1 will result in the gizmo emitting light.
|
||||
/// </summary>
|
||||
[DefaultValue(1f), Range(0f, 5f)]
|
||||
[EditorDisplay("Transform Gizmo", "Gizmo Brightness"), EditorOrder(210)]
|
||||
public float TransformGizmoBrightness { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set a value indicating the opacity of the transform gizmo.
|
||||
/// </summary>
|
||||
[DefaultValue(1f), Range(0f, 1f)]
|
||||
[EditorDisplay("Transform Gizmo", "Gizmo Opacity"), EditorOrder(211)]
|
||||
public float TransformGizmoOpacity { get; set; } = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether enable MSAA for DebugDraw primitives rendering. Helps with pixel aliasing but reduces performance.
|
||||
/// </summary>
|
||||
|
||||
@@ -596,11 +596,17 @@ namespace FlaxEditor.SceneGraph.GUI
|
||||
{
|
||||
bool worldPositionsStays = Root.GetKey(KeyboardKeys.Control) == false;
|
||||
var objects = new SceneObject[_dragActors.Objects.Count];
|
||||
var treeNodes = new TreeNode[_dragActors.Objects.Count];
|
||||
for (int i = 0; i < objects.Length; i++)
|
||||
{
|
||||
objects[i] = _dragActors.Objects[i].Actor;
|
||||
treeNodes[i] = _dragActors.Objects[i].TreeNode;
|
||||
}
|
||||
var action = new ParentActorsAction(objects, newParent, newOrder, worldPositionsStays);
|
||||
ActorNode.Root.Undo?.AddAction(action);
|
||||
action.Do();
|
||||
ParentTree.Focus();
|
||||
ParentTree.Select(treeNodes.ToList());
|
||||
result = DragDropEffect.Move;
|
||||
}
|
||||
// Drag scripts
|
||||
|
||||
@@ -1216,13 +1216,16 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
// Highlight selected blend point
|
||||
var style = Style.Current;
|
||||
var selectedIndex = _selectedAnimation.SelectedIndex;
|
||||
if (selectedIndex != -1 && (ContainsFocus || IsMouseOver))
|
||||
if (selectedIndex != -1 && selectedIndex < _editor.BlendPoints.Count && (ContainsFocus || IsMouseOver))
|
||||
{
|
||||
var point = _editor.BlendPoints[selectedIndex];
|
||||
var highlightColor = point.IsMouseDown ? style.SelectionBorder : style.BackgroundSelected;
|
||||
Render2D.PushTint(ref highlightColor);
|
||||
Render2D.DrawTriangles(_selectedTriangles, _selectedColors);
|
||||
Render2D.PopTint();
|
||||
if (point != null)
|
||||
{
|
||||
var highlightColor = point.IsMouseDown ? style.SelectionBorder : style.BackgroundSelected;
|
||||
Render2D.PushTint(ref highlightColor);
|
||||
Render2D.DrawTriangles(_selectedTriangles, _selectedColors);
|
||||
Render2D.PopTint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1502,9 +1502,10 @@ namespace FlaxEditor.Surface.Archetypes
|
||||
{
|
||||
data = new object[]
|
||||
{
|
||||
filterText.Substring(2),
|
||||
new Color(1.0f, 1.0f, 1.0f, 0.2f),
|
||||
new Float2(400.0f, 400.0f),
|
||||
filterText.Substring(2), // Title
|
||||
new Color(1.0f, 1.0f, 1.0f, 0.2f), // Color
|
||||
new Float2(400.0f, 400.0f), // Size
|
||||
-1, // Order
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -172,10 +172,22 @@ namespace FlaxEditor.Surface
|
||||
/// <inheritdoc />
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (_isRenaming && (!_renameTextBox.IsFocused || !RootWindow.IsFocused))
|
||||
if (_isRenaming)
|
||||
{
|
||||
Rename(_renameTextBox.Text);
|
||||
StopRenaming();
|
||||
// Stop renaming when clicking anywhere else
|
||||
if (!_renameTextBox.IsFocused || !RootWindow.IsFocused)
|
||||
{
|
||||
Rename(_renameTextBox.Text);
|
||||
StopRenaming();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rename on F2
|
||||
if (IsSelected && Editor.Instance.Options.Options.Input.Rename.Process(this))
|
||||
{
|
||||
StartRenaming();
|
||||
}
|
||||
}
|
||||
|
||||
base.Update(deltaTime);
|
||||
@@ -417,6 +429,7 @@ namespace FlaxEditor.Surface
|
||||
base.OnShowSecondaryContextMenu(menu, location);
|
||||
|
||||
menu.AddSeparator();
|
||||
menu.AddButton("Rename", StartRenaming);
|
||||
ContextMenuChildMenu cmOrder = menu.AddChildMenu("Order");
|
||||
{
|
||||
cmOrder.ContextMenu.AddButton("Bring Forward", () =>
|
||||
|
||||
@@ -383,6 +383,40 @@ namespace FlaxEditor.Utilities
|
||||
File.Delete(file);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an Import path ui that show the asset import path and adds a button to show the folder in the file system.
|
||||
/// </summary>
|
||||
/// <param name="parentLayout">The parent layout container.</param>
|
||||
/// <param name="assetItem">The asset item to get the import path of.</param>
|
||||
public static void CreateImportPathUI(CustomEditors.LayoutElementsContainer parentLayout, Content.BinaryAssetItem assetItem)
|
||||
{
|
||||
assetItem.GetImportPath(out var path);
|
||||
CreateImportPathUI(parentLayout, path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an Import path ui that show the import path and adds a button to show the folder in the file system.
|
||||
/// </summary>
|
||||
/// <param name="parentLayout">The parent layout container.</param>
|
||||
/// <param name="path">The import path.</param>
|
||||
/// <param name="useInitialSpacing">Whether to use an initial layout space of 5 for separation.</param>
|
||||
public static void CreateImportPathUI(CustomEditors.LayoutElementsContainer parentLayout, string path, bool useInitialSpacing = true)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
{
|
||||
if (useInitialSpacing)
|
||||
parentLayout.Space(5);
|
||||
parentLayout.Label("Import Path:").Label.TooltipText = "Source asset path (can be relative or absolute to the project)";
|
||||
var textBox = parentLayout.TextBox().TextBox;
|
||||
textBox.TooltipText = "Path is not editable here.";
|
||||
textBox.IsReadOnly = true;
|
||||
textBox.Text = path;
|
||||
parentLayout.Space(2);
|
||||
var button = parentLayout.Button(Constants.ShowInExplorer).Button;
|
||||
button.Clicked += () => FileSystem.ShowFileExplorer(Path.GetDirectoryName(path));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the directory. Supports subdirectories copy with files override option.
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using FlaxEditor.Content;
|
||||
@@ -207,8 +208,11 @@ namespace FlaxEditor.Windows.Assets
|
||||
var importSettingsValues = new ValueContainer(new ScriptMemberInfo(importSettingsField)) { proxy.ImportSettings };
|
||||
group.Object(importSettingsValues);
|
||||
|
||||
// Creates the import path UI
|
||||
Utilities.Utils.CreateImportPathUI(layout, proxy.Window.Item as BinaryAssetItem);
|
||||
|
||||
layout.Space(5);
|
||||
var reimportButton = group.Button("Reimport");
|
||||
var reimportButton = layout.Button("Reimport");
|
||||
reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.Content.Import;
|
||||
@@ -100,7 +101,10 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
base.Initialize(layout);
|
||||
|
||||
layout.Space(10);
|
||||
// Creates the import path UI
|
||||
Utilities.Utils.CreateImportPathUI(layout, window.Item as BinaryAssetItem);
|
||||
|
||||
layout.Space(5);
|
||||
var reimportButton = layout.Button("Reimport");
|
||||
reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.Content.Import;
|
||||
@@ -53,7 +54,10 @@ namespace FlaxEditor.Windows.Assets
|
||||
|
||||
base.Initialize(layout);
|
||||
|
||||
layout.Space(10);
|
||||
// Creates the import path UI
|
||||
Utilities.Utils.CreateImportPathUI(layout, window.Item as BinaryAssetItem);
|
||||
|
||||
layout.Space(5);
|
||||
var reimportButton = layout.Button("Reimport");
|
||||
reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport();
|
||||
}
|
||||
|
||||
@@ -751,18 +751,18 @@ namespace FlaxEditor.Windows.Assets
|
||||
if (Utilities.Utils.OnAssetProperties(layout, proxy.Asset))
|
||||
return;
|
||||
|
||||
// Import Settings
|
||||
{
|
||||
var group = layout.Group("Import Settings");
|
||||
var group = layout.Group("Import Settings");
|
||||
|
||||
var importSettingsField = typeof(ImportPropertiesProxyBase).GetField(nameof(ImportSettings), BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var importSettingsValues = new ValueContainer(new ScriptMemberInfo(importSettingsField)) { proxy.ImportSettings };
|
||||
group.Object(importSettingsValues);
|
||||
var importSettingsField = typeof(ImportPropertiesProxyBase).GetField(nameof(ImportSettings), BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
var importSettingsValues = new ValueContainer(new ScriptMemberInfo(importSettingsField)) { proxy.ImportSettings };
|
||||
group.Object(importSettingsValues);
|
||||
|
||||
layout.Space(5);
|
||||
var reimportButton = group.Button("Reimport");
|
||||
reimportButton.Button.Clicked += () => ((ImportPropertiesProxyBase)Values[0]).Reimport();
|
||||
}
|
||||
// Creates the import path UI
|
||||
Utilities.Utils.CreateImportPathUI(layout, proxy.Window.Item as BinaryAssetItem);
|
||||
|
||||
layout.Space(5);
|
||||
var reimportButton = group.Button("Reimport");
|
||||
reimportButton.Button.Clicked += () => ((ImportPropertiesProxyBase)Values[0]).Reimport();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml;
|
||||
using FlaxEditor.Content;
|
||||
@@ -110,9 +111,19 @@ namespace FlaxEditor.Windows.Assets
|
||||
{
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
var proxy = (PropertiesProxy)Values[0];
|
||||
if (proxy._window == null)
|
||||
{
|
||||
layout.Label("Loading...", TextAlignment.Center);
|
||||
return;
|
||||
}
|
||||
|
||||
base.Initialize(layout);
|
||||
|
||||
// Creates the import path UI
|
||||
Utilities.Utils.CreateImportPathUI(layout, proxy._window.Item as BinaryAssetItem);
|
||||
|
||||
layout.Space(10);
|
||||
layout.Space(5);
|
||||
var reimportButton = layout.Button("Reimport");
|
||||
reimportButton.Button.Clicked += () => ((PropertiesProxy)Values[0]).Reimport();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using FlaxEditor.Content;
|
||||
using FlaxEditor.Content.Import;
|
||||
@@ -131,11 +132,21 @@ namespace FlaxEditor.Windows.Assets
|
||||
{
|
||||
public override void Initialize(LayoutElementsContainer layout)
|
||||
{
|
||||
var proxy = (ImportPropertiesProxy)Values[0];
|
||||
if (proxy._window == null)
|
||||
{
|
||||
layout.Label("Loading...", TextAlignment.Center);
|
||||
return;
|
||||
}
|
||||
|
||||
// Import settings
|
||||
base.Initialize(layout);
|
||||
|
||||
// Creates the import path UI
|
||||
Utilities.Utils.CreateImportPathUI(layout, proxy._window.Item as BinaryAssetItem);
|
||||
|
||||
// Reimport
|
||||
layout.Space(10);
|
||||
layout.Space(5);
|
||||
var reimportButton = layout.Button("Reimport");
|
||||
reimportButton.Button.Clicked += () => ((ImportPropertiesProxy)Values[0]).Reimport();
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ namespace FlaxEditor.Windows.Profiler
|
||||
|
||||
private string FormatCellBytes(object x)
|
||||
{
|
||||
return Utilities.Utils.FormatBytesCount((ulong)x);
|
||||
return Utilities.Utils.FormatBytesCount(Convert.ToUInt64(x));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -35,7 +35,7 @@ void MaterialBase::SetParameterValue(const StringView& name, const Variant& valu
|
||||
}
|
||||
else if (warnIfMissing)
|
||||
{
|
||||
LOG(Warning, "Missing material parameter '{0}' in material {1}", String(name), ToString());
|
||||
LOG(Warning, "Missing material parameter '{0}' in material {1}", name, ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="name">The parameter name.</param>
|
||||
/// <param name="value">The value to set.</param>
|
||||
/// <param name="warnIfMissing">True if warn if parameter is missing, otherwise will do nothing.</param>
|
||||
/// <param name="warnIfMissing">True to warn if parameter is missing, otherwise will do nothing.</param>
|
||||
API_FUNCTION() void SetParameterValue(const StringView& name, const Variant& value, bool warnIfMissing = true);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace
|
||||
bool IsWindowsSingleNewLineChar = false;
|
||||
#endif
|
||||
int LogTotalErrorsCnt = 0;
|
||||
int32 LogTotalWriteSize = 0;
|
||||
FileWriteStream* LogFile = nullptr;
|
||||
CriticalSection LogLocker;
|
||||
DateTime LogStartTime;
|
||||
@@ -149,10 +150,17 @@ void Log::Logger::Write(const StringView& msg)
|
||||
Platform::Log(msg);
|
||||
|
||||
// Write message to log file
|
||||
if (LogAfterInit)
|
||||
constexpr int32 LogMaxWriteSize = 1 * 1024 * 1024; // 1GB
|
||||
if (LogAfterInit && LogTotalWriteSize < LogMaxWriteSize)
|
||||
{
|
||||
LogTotalWriteSize += length;
|
||||
LogFile->WriteBytes(ptr, length * sizeof(Char));
|
||||
LogFile->WriteBytes(TEXT(PLATFORM_LINE_TERMINATOR), (ARRAY_COUNT(PLATFORM_LINE_TERMINATOR) - 1) * sizeof(Char));
|
||||
if (LogTotalWriteSize >= LogMaxWriteSize)
|
||||
{
|
||||
StringView endMessage(TEXT("Trimming log file.\n\n"));
|
||||
LogFile->WriteBytes(endMessage.Get(), endMessage.Length() * sizeof(Char));
|
||||
}
|
||||
#if LOG_ENABLE_AUTO_FLUSH
|
||||
LogFile->Flush();
|
||||
#endif
|
||||
|
||||
@@ -3453,6 +3453,16 @@ bool Variant::CanCast(const Variant& v, const VariantType& to)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
case VariantType::Null:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Asset:
|
||||
case VariantType::ManagedObject:
|
||||
case VariantType::Object:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -3963,6 +3973,23 @@ Variant Variant::Cast(const Variant& v, const VariantType& to)
|
||||
return Variant((double)v.AsEnum);
|
||||
}
|
||||
break;
|
||||
case VariantType::Null:
|
||||
switch (to.Type)
|
||||
{
|
||||
case VariantType::Asset:
|
||||
return Variant((Asset*)nullptr);
|
||||
case VariantType::Object:
|
||||
return Variant((ScriptingObject*)nullptr);
|
||||
case VariantType::ManagedObject:
|
||||
{
|
||||
Variant result;
|
||||
result.SetType(VariantType(VariantType::ManagedObject));
|
||||
result.MANAGED_GC_HANDLE = 0;
|
||||
return result;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default: ;
|
||||
}
|
||||
LOG(Error, "Cannot cast Variant from {0} to {1}", v.Type, to);
|
||||
|
||||
@@ -214,9 +214,11 @@ void MaterialParameter::SetValue(const Variant& value)
|
||||
break;
|
||||
case VariantType::Object:
|
||||
_asAsset = Cast<TextureBase>(value.AsObject);
|
||||
invalidType = _asAsset == nullptr && value.AsObject != nullptr;
|
||||
break;
|
||||
case VariantType::Asset:
|
||||
_asAsset = Cast<TextureBase>(value.AsAsset);
|
||||
invalidType = _asAsset == nullptr && value.AsAsset != nullptr;
|
||||
break;
|
||||
default:
|
||||
invalidType = true;
|
||||
@@ -239,6 +241,7 @@ void MaterialParameter::SetValue(const Variant& value)
|
||||
break;
|
||||
case VariantType::Object:
|
||||
_asGPUTexture = Cast<GPUTexture>(value.AsObject);
|
||||
invalidType = _asGPUTexture == nullptr && value.AsObject != nullptr;
|
||||
break;
|
||||
default:
|
||||
invalidType = true;
|
||||
@@ -258,9 +261,11 @@ void MaterialParameter::SetValue(const Variant& value)
|
||||
break;
|
||||
case VariantType::Object:
|
||||
_asAsset = Cast<GameplayGlobals>(value.AsObject);
|
||||
invalidType = _asAsset == nullptr && value.AsObject != nullptr;
|
||||
break;
|
||||
case VariantType::Asset:
|
||||
_asAsset = Cast<GameplayGlobals>(value.AsAsset);
|
||||
invalidType = _asAsset == nullptr && value.AsAsset != nullptr;
|
||||
break;
|
||||
default:
|
||||
invalidType = true;
|
||||
@@ -273,7 +278,7 @@ void MaterialParameter::SetValue(const Variant& value)
|
||||
}
|
||||
if (invalidType)
|
||||
{
|
||||
LOG(Error, "Invalid material parameter value type {0} to set (param type: {1})", value.Type, ScriptingEnum::ToString(_type));
|
||||
LOG(Error, "Invalid material parameter value '{}' of type '{}' to set (expected type: {})", value.ToString(), value.Type, ScriptingEnum::ToString(_type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +293,12 @@ void AnimatedModel::SetParameterValue(const StringView& name, const Variant& val
|
||||
{
|
||||
if (param.Name == name)
|
||||
{
|
||||
param.Value = value;
|
||||
if (param.Value.Type == value.Type)
|
||||
param.Value = value;
|
||||
else if (Variant::CanCast(value, param.Value.Type))
|
||||
param.Value = Variant::Cast(value, param.Value.Type);
|
||||
else
|
||||
LOG(Warning, "Animation Graph parameter '{0}' in AnimatedModel {1} is type '{2}' and not type '{3}'.", name, ToString(), param.Value.Type, value.Type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ API_CLASS(Attributes="HideInEditor") class FLAXENGINE_API ModelPrefab : public S
|
||||
/// <summary>
|
||||
/// Source model file path (absolute or relative to the project).
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="ReadOnly") String ImportPath;
|
||||
API_FIELD(Attributes="ReadOnly, HideInEditor") String ImportPath;
|
||||
|
||||
/// <summary>
|
||||
/// Model file import settings.
|
||||
|
||||
@@ -108,6 +108,12 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
API_FIELD(Attributes="EditorOrder(500), EditorDisplay(\"General\")")
|
||||
TextureQuality TexturesQuality = TextureQuality::ASTC_Medium;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to build Android App Bundle (aab) side by side with apk.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(500), EditorDisplay(\"General\", \"Build .aab\")")
|
||||
bool BuildAAB = true;
|
||||
|
||||
/// <summary>
|
||||
/// Custom icon texture to use for the application (overrides the default one).
|
||||
/// </summary>
|
||||
|
||||
@@ -1386,22 +1386,26 @@ void Render2D::DrawText(Font* font, const StringView& text, const TextRange& tex
|
||||
|
||||
FORCE_INLINE bool NeedAlphaWithTint(const Color& color)
|
||||
{
|
||||
return (color.A * TintLayersStack.Peek().A) < 1.0f;
|
||||
const float tint = TintLayersStack.Peek().A;
|
||||
return color.A * tint < 1.0f;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool NeedAlphaWithTint(const Color& color1, const Color& color2)
|
||||
{
|
||||
return (color1.A * TintLayersStack.Peek().A) < 1.0f || (color2.A * TintLayersStack.Peek().A) < 1.0f;
|
||||
const float tint = TintLayersStack.Peek().A;
|
||||
return color1.A * tint < 1.0f || color2.A * tint < 1.0f;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool NeedAlphaWithTint(const Color& color1, const Color& color2, const Color& color3)
|
||||
{
|
||||
return (color1.A * TintLayersStack.Peek().A) < 1.0f || (color2.A * TintLayersStack.Peek().A) < 1.0f || (color3.A * TintLayersStack.Peek().A) < 1.0f;
|
||||
const float tint = TintLayersStack.Peek().A;
|
||||
return color1.A * tint < 1.0f || color2.A * tint < 1.0f || color3.A * tint < 1.0f;
|
||||
}
|
||||
|
||||
FORCE_INLINE bool NeedAlphaWithTint(const Color& color1, const Color& color2, const Color& color3, const Color& color4)
|
||||
{
|
||||
return (color1.A * TintLayersStack.Peek().A) < 1.0f || (color2.A * TintLayersStack.Peek().A) < 1.0f || (color3.A * TintLayersStack.Peek().A) < 1.0f || (color4.A * TintLayersStack.Peek().A) < 1.0f;
|
||||
const float tint = TintLayersStack.Peek().A;
|
||||
return color1.A * tint < 1.0f || color2.A * tint < 1.0f || color3.A * tint < 1.0f || color4.A * tint < 1.0f;
|
||||
}
|
||||
|
||||
void Render2D::FillRectangle(const Rectangle& rect, const Color& color)
|
||||
|
||||
@@ -623,10 +623,6 @@ void ShadowsPass::SetupRenderContext(RenderContext& renderContext, RenderContext
|
||||
|
||||
void ShadowsPass::SetupLight(ShadowsCustomBuffer& shadows, RenderContext& renderContext, RenderContextBatch& renderContextBatch, RenderLightData& light, ShadowAtlasLight& atlasLight)
|
||||
{
|
||||
// Initialize frame-data
|
||||
atlasLight.ContextIndex = 0;
|
||||
atlasLight.ContextCount = 0;
|
||||
|
||||
// Copy light properties
|
||||
atlasLight.Sharpness = light.ShadowsSharpness;
|
||||
atlasLight.Fade = light.ShadowsStrength;
|
||||
@@ -1299,6 +1295,11 @@ RETRY_ATLAS_SETUP:
|
||||
for (RenderLightData* light : shadowedLights)
|
||||
{
|
||||
auto& atlasLight = shadows.Lights[light->ID];
|
||||
|
||||
// Reset frame-data
|
||||
atlasLight.ContextIndex = 0;
|
||||
atlasLight.ContextCount = 0;
|
||||
|
||||
if (atlasLight.Tiles[0].RectTile && atlasLight.Tiles[0].RectTile->Width == atlasLight.Resolution)
|
||||
{
|
||||
// Invalidate cache when whole atlas will be cleared
|
||||
|
||||
@@ -66,10 +66,6 @@ void ShaderProcessing::Parser::init()
|
||||
bool ShaderProcessing::Parser::process()
|
||||
{
|
||||
const Token defineToken("#define");
|
||||
const Separator singleLineCommentSeparator('/', '/');
|
||||
const Separator multiLineCommentSeparator('/', '*');
|
||||
|
||||
// TODO: split parsing into two phrases: comments preprocessing and parsing
|
||||
|
||||
// Read whole source code
|
||||
Token token;
|
||||
@@ -77,36 +73,8 @@ bool ShaderProcessing::Parser::process()
|
||||
{
|
||||
text.ReadToken(&token);
|
||||
|
||||
// Single line comment
|
||||
if (token.Separator == singleLineCommentSeparator)
|
||||
{
|
||||
// Read whole line
|
||||
text.ReadLine();
|
||||
}
|
||||
// Multi line comment
|
||||
else if (token.Separator == multiLineCommentSeparator)
|
||||
{
|
||||
// Read tokens until end sequence
|
||||
char prev = ' ';
|
||||
char c;
|
||||
while (text.CanRead())
|
||||
{
|
||||
c = text.ReadChar();
|
||||
if (prev == '*' && c == '/')
|
||||
{
|
||||
break;
|
||||
}
|
||||
prev = c;
|
||||
}
|
||||
|
||||
// Check if comment is valid (has end before file end)
|
||||
if (!text.CanRead())
|
||||
{
|
||||
OnWarning(TEXT("Missing multiline comment ending"));
|
||||
}
|
||||
}
|
||||
// Preprocessor definition
|
||||
else if (token == defineToken)
|
||||
// Preprocessor definition
|
||||
if (token == defineToken)
|
||||
{
|
||||
// Skip
|
||||
text.ReadLine();
|
||||
|
||||
@@ -717,6 +717,8 @@ bool ModelTool::ImportDataAssimp(const String& path, ModelData& data, Options& o
|
||||
flags |= aiProcess_FixInfacingNormals | aiProcess_GenSmoothNormals;
|
||||
if (options.CalculateTangents)
|
||||
flags |= aiProcess_CalcTangentSpace;
|
||||
if (options.ReverseWindingOrder)
|
||||
flags &= ~aiProcess_FlipWindingOrder;
|
||||
if (options.OptimizeMeshes)
|
||||
flags |= aiProcess_OptimizeMeshes | aiProcess_SplitLargeMeshes | aiProcess_ImproveCacheLocality;
|
||||
if (options.MergeMeshes)
|
||||
|
||||
@@ -385,6 +385,19 @@ bool ProcessMesh(ImporterData& data, FbxMesh* fbxMesh, MeshData& mesh, String& e
|
||||
mesh.Indices[i] = fbxIndices[i];
|
||||
}
|
||||
|
||||
if (data.Options.ReverseWindingOrder)
|
||||
{
|
||||
for (int32 i = 0; i < vertexCount; i += 3)
|
||||
{
|
||||
Swap(meshIndices[i + 1], meshIndices[i + 2]);
|
||||
Swap(meshPositions[i + 1], meshPositions[i + 2]);
|
||||
if (meshNormals)
|
||||
Swap(meshNormals[i + 1], meshNormals[i + 2]);
|
||||
if (meshTangents)
|
||||
Swap(meshTangents[i + 1], meshTangents[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
// Texture coordinates
|
||||
for (int32 channelIndex = 0; channelIndex < MODEL_MAX_UV && fbxMesh->GetElementUV(channelIndex); channelIndex++)
|
||||
{
|
||||
|
||||
@@ -777,6 +777,24 @@ bool ProcessMesh(ModelData& result, OpenFbxImporterData& data, const ofbx::Mesh*
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse winding order
|
||||
if (data.Options.ReverseWindingOrder)
|
||||
{
|
||||
uint32* meshIndices = mesh.Indices.Get();
|
||||
Float3* meshPositions = mesh.Positions.Get();
|
||||
Float3* meshNormals = mesh.Normals.HasItems() ? mesh.Normals.Get() : nullptr;
|
||||
Float3* meshTangents = mesh.Tangents.HasItems() ? mesh.Tangents.Get() : nullptr;
|
||||
|
||||
for (int i = 0; i < vertexCount; i += 3) {
|
||||
Swap(meshIndices[i + 1], meshIndices[i + 2]);
|
||||
Swap(meshPositions[i + 1], meshPositions[i + 2]);
|
||||
if (meshNormals)
|
||||
Swap(meshNormals[i + 1], meshNormals[i + 2]);
|
||||
if (meshTangents)
|
||||
Swap(meshTangents[i + 1], meshTangents[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
// Lightmap UVs
|
||||
mesh.SetLightmapUVsSource(data.Options.LightmapUVsSource);
|
||||
|
||||
|
||||
@@ -667,6 +667,7 @@ void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj
|
||||
SERIALIZE(FlipNormals);
|
||||
SERIALIZE(CalculateTangents);
|
||||
SERIALIZE(SmoothingTangentsAngle);
|
||||
SERIALIZE(ReverseWindingOrder);
|
||||
SERIALIZE(OptimizeMeshes);
|
||||
SERIALIZE(MergeMeshes);
|
||||
SERIALIZE(ImportLODs);
|
||||
@@ -717,6 +718,7 @@ void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifi
|
||||
DESERIALIZE(FlipNormals);
|
||||
DESERIALIZE(CalculateTangents);
|
||||
DESERIALIZE(SmoothingTangentsAngle);
|
||||
DESERIALIZE(ReverseWindingOrder);
|
||||
DESERIALIZE(OptimizeMeshes);
|
||||
DESERIALIZE(MergeMeshes);
|
||||
DESERIALIZE(ImportLODs);
|
||||
|
||||
@@ -170,6 +170,9 @@ public:
|
||||
// Specifies the maximum angle (in degrees) that may be between two vertex tangents before their tangents and bi-tangents are smoothed. The default value is 45.
|
||||
API_FIELD(Attributes="EditorOrder(45), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowSmoothingTangentsAngle)), Limit(0, 45, 0.1f)")
|
||||
float SmoothingTangentsAngle = 45.0f;
|
||||
// If checked, the winding order of the vertices will be reversed.
|
||||
API_FIELD(Attributes="EditorOrder(47), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
|
||||
bool ReverseWindingOrder = false;
|
||||
// Enable/disable meshes geometry optimization.
|
||||
API_FIELD(Attributes="EditorOrder(50), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
|
||||
bool OptimizeMeshes = true;
|
||||
|
||||
@@ -730,6 +730,9 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
|
||||
if (!options.FlipY &&
|
||||
!options.FlipX &&
|
||||
!options.InvertGreenChannel &&
|
||||
!options.InvertRedChannel &&
|
||||
!options.InvertAlphaChannel &&
|
||||
!options.InvertBlueChannel &&
|
||||
!options.ReconstructZChannel &&
|
||||
options.Compress &&
|
||||
type == ImageType::DDS &&
|
||||
@@ -824,16 +827,12 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
|
||||
result = TransformImage(currentImage->GetImages(), currentImage->GetImageCount(), currentImage->GetMetadata(),
|
||||
[&](DirectX::XMVECTOR* outPixels, const DirectX::XMVECTOR* inPixels, size_t w, size_t y)
|
||||
{
|
||||
static const DirectX::XMVECTORU32 s_selecty = { { { DirectX::XM_SELECT_0, DirectX::XM_SELECT_1, DirectX::XM_SELECT_0, DirectX::XM_SELECT_0 } } };
|
||||
|
||||
const DirectX::XMVECTORU32 s_selecty = { { { DirectX::XM_SELECT_0, DirectX::XM_SELECT_1, DirectX::XM_SELECT_0, DirectX::XM_SELECT_0 } } };
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
const DirectX::XMVECTOR value = inPixels[j];
|
||||
|
||||
const DirectX::XMVECTOR inverty = DirectX::XMVectorSubtract(DirectX::g_XMOne, value);
|
||||
|
||||
outPixels[j] = DirectX::XMVectorSelect(value, inverty, s_selecty);
|
||||
}
|
||||
}, timage);
|
||||
@@ -844,6 +843,78 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
|
||||
}
|
||||
SET_CURRENT_IMG(timage);
|
||||
}
|
||||
|
||||
// Check if invert red channel
|
||||
if (!keepAsIs && options.InvertRedChannel)
|
||||
{
|
||||
auto& timage = GET_TMP_IMG();
|
||||
result = TransformImage(currentImage->GetImages(), currentImage->GetImageCount(), currentImage->GetMetadata(),
|
||||
[&](DirectX::XMVECTOR* outPixels, const DirectX::XMVECTOR* inPixels, size_t w, size_t y)
|
||||
{
|
||||
const DirectX::XMVECTORU32 s_selectx = { { { DirectX::XM_SELECT_1, DirectX::XM_SELECT_0, DirectX::XM_SELECT_0, DirectX::XM_SELECT_0 } } };
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
const DirectX::XMVECTOR value = inPixels[j];
|
||||
const DirectX::XMVECTOR inverty = DirectX::XMVectorSubtract(DirectX::g_XMOne, value);
|
||||
outPixels[j] = DirectX::XMVectorSelect(value, inverty, s_selectx);
|
||||
}
|
||||
}, timage);
|
||||
if (FAILED(result))
|
||||
{
|
||||
errorMsg = String::Format(TEXT("Cannot invert red channel in texture, error: {0:x}"), static_cast<uint32>(result));
|
||||
return true;
|
||||
}
|
||||
SET_CURRENT_IMG(timage);
|
||||
}
|
||||
|
||||
// Check if invert blue channel
|
||||
if (!keepAsIs && options.InvertBlueChannel)
|
||||
{
|
||||
auto& timage = GET_TMP_IMG();
|
||||
result = TransformImage(currentImage->GetImages(), currentImage->GetImageCount(), currentImage->GetMetadata(),
|
||||
[&](DirectX::XMVECTOR* outPixels, const DirectX::XMVECTOR* inPixels, size_t w, size_t y)
|
||||
{
|
||||
const DirectX::XMVECTORU32 s_selectz = { { { DirectX::XM_SELECT_0, DirectX::XM_SELECT_0, DirectX::XM_SELECT_1, DirectX::XM_SELECT_0 } } };
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
const DirectX::XMVECTOR value = inPixels[j];
|
||||
const DirectX::XMVECTOR inverty = DirectX::XMVectorSubtract(DirectX::g_XMOne, value);
|
||||
outPixels[j] = DirectX::XMVectorSelect(value, inverty, s_selectz);
|
||||
}
|
||||
}, timage);
|
||||
if (FAILED(result))
|
||||
{
|
||||
errorMsg = String::Format(TEXT("Cannot invert blue channel in texture, error: {0:x}"), static_cast<uint32>(result));
|
||||
return true;
|
||||
}
|
||||
SET_CURRENT_IMG(timage);
|
||||
}
|
||||
|
||||
// Check if invert alpha channel
|
||||
if (!keepAsIs && options.InvertAlphaChannel)
|
||||
{
|
||||
auto& timage = GET_TMP_IMG();
|
||||
result = TransformImage(currentImage->GetImages(), currentImage->GetImageCount(), currentImage->GetMetadata(),
|
||||
[&](DirectX::XMVECTOR* outPixels, const DirectX::XMVECTOR* inPixels, size_t w, size_t y)
|
||||
{
|
||||
const DirectX::XMVECTORU32 s_selectw = { { { DirectX::XM_SELECT_0, DirectX::XM_SELECT_0, DirectX::XM_SELECT_0, DirectX::XM_SELECT_1 } } };
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
const DirectX::XMVECTOR value = inPixels[j];
|
||||
const DirectX::XMVECTOR inverty = DirectX::XMVectorSubtract(DirectX::g_XMOne, value);
|
||||
outPixels[j] = DirectX::XMVectorSelect(value, inverty, s_selectw);
|
||||
}
|
||||
}, timage);
|
||||
if (FAILED(result))
|
||||
{
|
||||
errorMsg = String::Format(TEXT("Cannot invert alpha channel in texture, error: {0:x}"), static_cast<uint32>(result));
|
||||
return true;
|
||||
}
|
||||
SET_CURRENT_IMG(timage);
|
||||
}
|
||||
|
||||
// Reconstruct Z Channel
|
||||
if (!keepAsIs & options.ReconstructZChannel)
|
||||
@@ -853,10 +924,8 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path
|
||||
result = TransformImage(currentImage->GetImages(), currentImage->GetImageCount(), currentImage->GetMetadata(),
|
||||
[&](DirectX::XMVECTOR* outPixels, const DirectX::XMVECTOR* inPixels, size_t w, size_t y)
|
||||
{
|
||||
static const DirectX::XMVECTORU32 s_selectz = { { { DirectX::XM_SELECT_0, DirectX::XM_SELECT_0, DirectX::XM_SELECT_1, DirectX::XM_SELECT_0 } } };
|
||||
|
||||
const DirectX::XMVECTORU32 s_selectz = { { { DirectX::XM_SELECT_0, DirectX::XM_SELECT_0, DirectX::XM_SELECT_1, DirectX::XM_SELECT_0 } } };
|
||||
UNREFERENCED_PARAMETER(y);
|
||||
|
||||
for (size_t j = 0; j < w; ++j)
|
||||
{
|
||||
const DirectX::XMVECTOR value = inPixels[j];
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace
|
||||
|
||||
String TextureTool::Options::ToString() const
|
||||
{
|
||||
return String::Format(TEXT("Type: {}, IsAtlas: {}, NeverStream: {}, IndependentChannels: {}, sRGB: {}, GenerateMipMaps: {}, FlipY: {}, InvertGreen: {} Scale: {}, MaxSize: {}, Resize: {}, PreserveAlphaCoverage: {}, PreserveAlphaCoverageReference: {}, SizeX: {}, SizeY: {}"),
|
||||
return String::Format(TEXT("Type: {}, IsAtlas: {}, NeverStream: {}, IndependentChannels: {}, sRGB: {}, GenerateMipMaps: {}, FlipY: {}, InvertRed: {}, InvertGreen: {}, InvertBlue {}, Invert Alpha {}, Scale: {}, MaxSize: {}, Resize: {}, PreserveAlphaCoverage: {}, PreserveAlphaCoverageReference: {}, SizeX: {}, SizeY: {}"),
|
||||
ScriptingEnum::ToString(Type),
|
||||
IsAtlas,
|
||||
NeverStream,
|
||||
@@ -33,7 +33,10 @@ String TextureTool::Options::ToString() const
|
||||
sRGB,
|
||||
GenerateMipMaps,
|
||||
FlipY,
|
||||
InvertRedChannel,
|
||||
InvertGreenChannel,
|
||||
InvertBlueChannel,
|
||||
InvertAlphaChannel,
|
||||
Scale,
|
||||
MaxSize,
|
||||
MaxSize,
|
||||
@@ -74,9 +77,18 @@ void TextureTool::Options::Serialize(SerializeStream& stream, const void* otherO
|
||||
stream.JKEY("FlipX");
|
||||
stream.Bool(FlipX);
|
||||
|
||||
stream.JKEY("InvertRedChannel");
|
||||
stream.Bool(InvertRedChannel);
|
||||
|
||||
stream.JKEY("InvertGreenChannel");
|
||||
stream.Bool(InvertGreenChannel);
|
||||
|
||||
stream.JKEY("InvertBlueChannel");
|
||||
stream.Bool(InvertBlueChannel);
|
||||
|
||||
stream.JKEY("InvertAlphaChannel");
|
||||
stream.Bool(InvertAlphaChannel);
|
||||
|
||||
stream.JKEY("ReconstructZChannel");
|
||||
stream.Bool(ReconstructZChannel);
|
||||
|
||||
@@ -141,7 +153,10 @@ void TextureTool::Options::Deserialize(DeserializeStream& stream, ISerializeModi
|
||||
GenerateMipMaps = JsonTools::GetBool(stream, "GenerateMipMaps", GenerateMipMaps);
|
||||
FlipY = JsonTools::GetBool(stream, "FlipY", FlipY);
|
||||
FlipX = JsonTools::GetBool(stream, "FlipX", FlipX);
|
||||
InvertRedChannel = JsonTools::GetBool(stream, "InvertRedChannel", InvertRedChannel);
|
||||
InvertGreenChannel = JsonTools::GetBool(stream, "InvertGreenChannel", InvertGreenChannel);
|
||||
InvertBlueChannel = JsonTools::GetBool(stream, "InvertBlueChannel", InvertBlueChannel);
|
||||
InvertAlphaChannel = JsonTools::GetBool(stream, "InvertAlphaChannel", InvertAlphaChannel);
|
||||
ReconstructZChannel = JsonTools::GetBool(stream, "ReconstructZChannel", ReconstructZChannel);
|
||||
Resize = JsonTools::GetBool(stream, "Resize", Resize);
|
||||
KeepAspectRatio = JsonTools::GetBool(stream, "KeepAspectRatio", KeepAspectRatio);
|
||||
|
||||
@@ -61,12 +61,24 @@ API_CLASS(Namespace="FlaxEngine.Tools", Static) class FLAXENGINE_API TextureTool
|
||||
API_FIELD(Attributes="EditorOrder(71)")
|
||||
bool FlipX = false;
|
||||
|
||||
// True if to invert the green channel on a normal map. Good for OpenGL to DirectX conversion.
|
||||
API_FIELD(Attributes = "EditorOrder(72)")
|
||||
// Invert the red channel.
|
||||
API_FIELD(Attributes = "EditorOrder(72), EditorDisplay(\"Invert Channels\"), ExpandGroups")
|
||||
bool InvertRedChannel = false;
|
||||
|
||||
// Invert the green channel. Good for OpenGL to DirectX conversion.
|
||||
API_FIELD(Attributes = "EditorOrder(73), EditorDisplay(\"Invert Channels\")")
|
||||
bool InvertGreenChannel = false;
|
||||
|
||||
// Invert the blue channel.
|
||||
API_FIELD(Attributes = "EditorOrder(74), EditorDisplay(\"Invert Channels\")")
|
||||
bool InvertBlueChannel = false;
|
||||
|
||||
// Invert the alpha channel.
|
||||
API_FIELD(Attributes = "EditorOrder(75), EditorDisplay(\"Invert Channels\")")
|
||||
bool InvertAlphaChannel = false;
|
||||
|
||||
// Rebuild Z (blue) channel assuming X/Y are normals.
|
||||
API_FIELD(Attributes = "EditorOrder(73)")
|
||||
API_FIELD(Attributes = "EditorOrder(76)")
|
||||
bool ReconstructZChannel = false;
|
||||
|
||||
// Texture size scale. Allows increasing or decreasing the imported texture resolution. Default is 1.
|
||||
|
||||
@@ -542,10 +542,10 @@ bool TextureTool::ImportTextureStb(ImageType type, const StringView& path, Textu
|
||||
// TODO: impl this
|
||||
LOG(Warning, "Option 'Flip X' is not supported");
|
||||
}
|
||||
if (options.InvertGreenChannel)
|
||||
if (options.InvertRedChannel || options.InvertGreenChannel || options.InvertBlueChannel || options.InvertAlphaChannel)
|
||||
{
|
||||
// TODO: impl this
|
||||
LOG(Warning, "Option 'Invert Green Channel' is not supported");
|
||||
LOG(Warning, "Option to invert channels is not supported");
|
||||
}
|
||||
if (options.ReconstructZChannel)
|
||||
{
|
||||
|
||||
@@ -249,7 +249,7 @@ namespace FlaxEngine.GUI
|
||||
var text = ConvertedText();
|
||||
|
||||
// Check if sth is selected to draw selection
|
||||
if (HasSelection)
|
||||
if (HasSelection && IsFocused)
|
||||
{
|
||||
var leftEdge = font.GetCharPosition(text, SelectionLeft, ref _layout);
|
||||
var rightEdge = font.GetCharPosition(text, SelectionRight, ref _layout);
|
||||
@@ -294,6 +294,8 @@ namespace FlaxEngine.GUI
|
||||
var color = TextColor;
|
||||
if (!enabled)
|
||||
color *= 0.6f;
|
||||
else if (_isReadOnly)
|
||||
color *= 0.85f;
|
||||
Render2D.DrawText(font, text, color, ref _layout, TextMaterial);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(_watermarkText))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
#include "TextProcessing.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
|
||||
TextProcessing::TextProcessing(const char* input, int32 length)
|
||||
: _buffer(input)
|
||||
@@ -54,6 +55,8 @@ void TextProcessing::Setup_HLSL()
|
||||
32,
|
||||
};
|
||||
Whitespaces.Set(whitespaces, ARRAY_COUNT(whitespaces));
|
||||
SingleLineComment = SeparatorData('/', '/');
|
||||
MultiLineCommentSeparator = SeparatorData('/', '*');
|
||||
}
|
||||
|
||||
char TextProcessing::ReadChar()
|
||||
@@ -123,6 +126,38 @@ void TextProcessing::ReadToken(Token* token)
|
||||
|
||||
token->Separator = Separators[s];
|
||||
ReadChar();
|
||||
|
||||
// Check for comments
|
||||
if (token->Separator == SingleLineComment)
|
||||
{
|
||||
// Read whole line
|
||||
ReadLine();
|
||||
|
||||
// Read another token
|
||||
ReadToken(token);
|
||||
}
|
||||
else if (token->Separator == MultiLineCommentSeparator)
|
||||
{
|
||||
// Read tokens until end sequence
|
||||
char prev = ' ';
|
||||
while (CanRead())
|
||||
{
|
||||
c = ReadChar();
|
||||
if (prev == '*' && c == '/')
|
||||
break;
|
||||
prev = c;
|
||||
}
|
||||
|
||||
// Check if comment is valid (has end before file end)
|
||||
if (!CanRead())
|
||||
{
|
||||
LOG(Warning, "Missing multiline comment ending");
|
||||
}
|
||||
|
||||
// Read another token
|
||||
ReadToken(token);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
#include "Engine/Platform/StringUtils.h"
|
||||
|
||||
/// <summary>
|
||||
/// Helper class to fast ANSI text processing (tokenization, reading, streaming etc.)
|
||||
/// Helper class to fast ANSI text processing (tokenization, reading, streaming etc.).
|
||||
/// </summary>
|
||||
class FLAXENGINE_API TextProcessing : public NonCopyable
|
||||
{
|
||||
public:
|
||||
/// <summary>
|
||||
/// Separator structure
|
||||
/// Separator structure.
|
||||
/// </summary>
|
||||
struct SeparatorData
|
||||
{
|
||||
@@ -200,18 +200,21 @@ public:
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Array with all token separators
|
||||
/// Array with all token separators.
|
||||
/// </summary>
|
||||
Array<SeparatorData> Separators;
|
||||
|
||||
/// /// <summary>
|
||||
/// Array with all white characters
|
||||
/// Array with all white characters.
|
||||
/// </summary>
|
||||
Array<char> Whitespaces;
|
||||
|
||||
SeparatorData SingleLineComment;
|
||||
SeparatorData MultiLineCommentSeparator;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Set separators and white chars for HLSL language
|
||||
/// Sets up separators and white chars for HLSL language.
|
||||
/// </summary>
|
||||
void Setup_HLSL();
|
||||
|
||||
@@ -219,25 +222,22 @@ public:
|
||||
/// <summary>
|
||||
/// Returns true if there are still characters in the buffer and can read data from it
|
||||
/// </summary>
|
||||
/// <returns>True if can read data, otherwise false</returns>
|
||||
FORCE_INLINE bool CanRead() const
|
||||
{
|
||||
return _position < _length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peeks single character without moving forward in the buffer
|
||||
/// Peeks a single character without moving forward in the buffer.
|
||||
/// </summary>
|
||||
/// <returns>First character</returns>
|
||||
FORCE_INLINE char PeekChar() const
|
||||
{
|
||||
return *_cursor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets current line number
|
||||
/// Gets the current line number.
|
||||
/// </summary>
|
||||
/// <returns>Current line number</returns>
|
||||
FORCE_INLINE int32 GetLine() const
|
||||
{
|
||||
return _line;
|
||||
|
||||
@@ -256,6 +256,13 @@ namespace Flax.Build
|
||||
#endif
|
||||
if (buildOptions.ScriptingAPI.IgnoreMissingDocumentationWarnings)
|
||||
args.Add("-nowarn:1591");
|
||||
if (buildOptions.ScriptingAPI.IgnoreSpecificWarnings.Any())
|
||||
{
|
||||
foreach (var warningString in buildOptions.ScriptingAPI.IgnoreSpecificWarnings)
|
||||
{
|
||||
args.Add($"-nowarn:{warningString}");
|
||||
}
|
||||
}
|
||||
|
||||
// Optimizations prevent debugging, only enable in release builds by default
|
||||
var optimize = optimizeAssembly.HasValue ? optimizeAssembly.Value : buildData.Configuration == TargetConfiguration.Release;
|
||||
|
||||
@@ -235,6 +235,11 @@ namespace Flax.Build.NativeCpp
|
||||
/// </summary>
|
||||
public HashSet<string> Analyzers;
|
||||
|
||||
/// <summary>
|
||||
/// The specific warnings to ignore.
|
||||
/// </summary>
|
||||
public HashSet<string> IgnoreSpecificWarnings;
|
||||
|
||||
/// <summary>
|
||||
/// True if ignore compilation warnings due to missing code documentation comments.
|
||||
/// </summary>
|
||||
@@ -265,6 +270,7 @@ namespace Flax.Build.NativeCpp
|
||||
FileReferences.AddRange(other.FileReferences);
|
||||
Analyzers.AddRange(other.Analyzers);
|
||||
IgnoreMissingDocumentationWarnings |= other.IgnoreMissingDocumentationWarnings;
|
||||
IgnoreSpecificWarnings.AddRange(other.IgnoreSpecificWarnings);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,6 +344,7 @@ namespace Flax.Build.NativeCpp
|
||||
},
|
||||
FileReferences = new HashSet<string>(),
|
||||
Analyzers = new HashSet<string>(),
|
||||
IgnoreSpecificWarnings = new HashSet<string>(),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) 2012-2024 Flax Engine. All rights reserved.
|
||||
|
||||
#define USE_STD
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
@@ -99,6 +101,9 @@ namespace Flax.Deploy
|
||||
Log.Info("Compressing game debug symbols files...");
|
||||
var gamePackageZipPath = Path.Combine(Deployer.PackageOutputPath, "GameDebugSymbols.zip");
|
||||
Utilities.FileDelete(gamePackageZipPath);
|
||||
#if USE_STD
|
||||
System.IO.Compression.ZipFile.CreateFromDirectory(Path.Combine(Deployer.PackageOutputPath, "GameDebugSymbols"), gamePackageZipPath, System.IO.Compression.CompressionLevel.Optimal, false);
|
||||
#else
|
||||
using (var zip = new Ionic.Zip.ZipFile())
|
||||
{
|
||||
zip.AddDirectory(Path.Combine(Deployer.PackageOutputPath, "GameDebugSymbols"));
|
||||
@@ -106,6 +111,7 @@ namespace Flax.Deploy
|
||||
zip.Comment = string.Format("Flax Game {0}.{1}.{2}\nDate: {3}", Deployer.VersionMajor, Deployer.VersionMinor, Deployer.VersionBuild, DateTime.UtcNow);
|
||||
zip.Save(gamePackageZipPath);
|
||||
}
|
||||
#endif
|
||||
Log.Info("Compressed game debug symbols package size: " + Utilities.GetFileSize(gamePackageZipPath));
|
||||
}
|
||||
Utilities.DirectoryDelete(Path.Combine(Deployer.PackageOutputPath, "GameDebugSymbols"));
|
||||
|
||||
@@ -32,16 +32,32 @@ namespace Flax.Build.Platforms
|
||||
return;
|
||||
try
|
||||
{
|
||||
// Get path
|
||||
RootPath = Utilities.ReadProcessOutput("xcode-select", "--print-path");
|
||||
if (string.IsNullOrEmpty(RootPath) || !Directory.Exists(RootPath))
|
||||
return;
|
||||
IsValid = true;
|
||||
Version = new Version(1, 0);
|
||||
Log.Verbose(string.Format("Found XCode at {0}", RootPath));
|
||||
|
||||
// Get version (optional)
|
||||
var versionText = Utilities.ReadProcessOutput("xcodebuild", "-version");
|
||||
var versionLines = versionText?.Split('\n') ?? null;
|
||||
if (versionLines != null && versionLines.Length != 0)
|
||||
{
|
||||
versionText = versionLines[0].Trim();
|
||||
var versionParts = versionText.Split(' ');
|
||||
if (versionParts != null && versionParts.Length > 1)
|
||||
{
|
||||
versionText = versionParts[1].Trim();
|
||||
if (Version.TryParse(versionText, out var v))
|
||||
Version = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
Log.Verbose(string.Format("Found XCode {1} at {0}", RootPath, Version));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,13 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
csProjectFileContent.AppendLine(" <AllowUnsafeBlocks>true</AllowUnsafeBlocks>");
|
||||
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreMissingDocumentationWarnings)
|
||||
csProjectFileContent.AppendLine(" <NoWarn>1591</NoWarn>");
|
||||
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreSpecificWarnings.Any())
|
||||
{
|
||||
foreach (var warningString in configuration.TargetBuildOptions.ScriptingAPI.IgnoreSpecificWarnings)
|
||||
{
|
||||
csProjectFileContent.AppendLine($" <NoWarn>{warningString}</NoWarn>");
|
||||
}
|
||||
}
|
||||
csProjectFileContent.AppendLine(string.Format(" <DocumentationFile>{0}\\{1}.CSharp.xml</DocumentationFile>", outputPath, project.BaseName));
|
||||
csProjectFileContent.AppendLine(" <UseVSHostingProcess>true</UseVSHostingProcess>");
|
||||
csProjectFileContent.AppendLine(" </PropertyGroup>");
|
||||
@@ -156,6 +163,13 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
csProjectFileContent.AppendLine(" <AllowUnsafeBlocks>true</AllowUnsafeBlocks>");
|
||||
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreMissingDocumentationWarnings)
|
||||
csProjectFileContent.AppendLine(" <NoWarn>1591</NoWarn>");
|
||||
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreSpecificWarnings.Any())
|
||||
{
|
||||
foreach (var warningString in configuration.TargetBuildOptions.ScriptingAPI.IgnoreSpecificWarnings)
|
||||
{
|
||||
csProjectFileContent.AppendLine($" <NoWarn>{warningString}</NoWarn>");
|
||||
}
|
||||
}
|
||||
csProjectFileContent.AppendLine(string.Format(" <DocumentationFile>{0}\\{1}.CSharp.xml</DocumentationFile>", outputPath, project.BaseName));
|
||||
csProjectFileContent.AppendLine(" <UseVSHostingProcess>true</UseVSHostingProcess>");
|
||||
csProjectFileContent.AppendLine(" </PropertyGroup>");
|
||||
|
||||
@@ -284,6 +284,13 @@ namespace Flax.Build.Projects.VisualStudio
|
||||
csProjectFileContent.AppendLine(" <AllowUnsafeBlocks>true</AllowUnsafeBlocks>");
|
||||
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreMissingDocumentationWarnings)
|
||||
csProjectFileContent.AppendLine(" <NoWarn>1591</NoWarn>");
|
||||
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreSpecificWarnings.Any())
|
||||
{
|
||||
foreach (var warningString in configuration.TargetBuildOptions.ScriptingAPI.IgnoreSpecificWarnings)
|
||||
{
|
||||
csProjectFileContent.AppendLine($" <NoWarn>{warningString}</NoWarn>");
|
||||
}
|
||||
}
|
||||
csProjectFileContent.AppendLine(string.Format(" <DocumentationFile>{0}\\{1}.CSharp.xml</DocumentationFile>", outputPath, project.BaseName));
|
||||
csProjectFileContent.AppendLine(" <UseVSHostingProcess>true</UseVSHostingProcess>");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user