Merge remote-tracking branch 'origin/master' into localization
# Conflicts: # Source/Platforms/DotNet/Newtonsoft.Json.dll # Source/Platforms/DotNet/Newtonsoft.Json.pdb # Source/Platforms/UWP/Binaries/Newtonsoft.Json.dll # Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.dll
This commit is contained in:
@@ -43,7 +43,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
const auto uwpDataPath = platformDataPath / (isXboxOne ? TEXT("XboxOne") : TEXT("UWP")) / TEXT("Binaries");
|
const auto uwpDataPath = platformDataPath / (isXboxOne ? TEXT("XboxOne") : TEXT("UWP")) / TEXT("Binaries");
|
||||||
const auto gameSettings = GameSettings::Get();
|
const auto gameSettings = GameSettings::Get();
|
||||||
const auto platformSettings = UWPPlatformSettings::Get();
|
const auto platformSettings = UWPPlatformSettings::Get();
|
||||||
Array<byte> fileTemplate;
|
StringAnsi fileTemplate;
|
||||||
|
|
||||||
// Copy binaries
|
// Copy binaries
|
||||||
const auto binPath = data.GetGameBinariesPath();
|
const auto binPath = data.GetGameBinariesPath();
|
||||||
@@ -149,12 +149,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (!FileSystem::FileExists(dstAssemblyInfoPath))
|
if (!FileSystem::FileExists(dstAssemblyInfoPath))
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
if (File::ReadAllBytes(srcAssemblyInfoPath, fileTemplate))
|
if (File::ReadAllText(srcAssemblyInfoPath, fileTemplate))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to load AssemblyInfo.cs template."));
|
data.Error(TEXT("Failed to load AssemblyInfo.cs template."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
|
||||||
|
|
||||||
// Write data to file
|
// Write data to file
|
||||||
auto file = FileWriteStream::Open(dstAssemblyInfoPath);
|
auto file = FileWriteStream::Open(dstAssemblyInfoPath);
|
||||||
@@ -163,7 +162,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
{
|
{
|
||||||
auto now = DateTime::Now();
|
auto now = DateTime::Now();
|
||||||
file->WriteTextFormatted(
|
file->WriteTextFormatted(
|
||||||
(char*)fileTemplate.Get()
|
fileTemplate.Get()
|
||||||
, gameSettings->ProductName.ToStringAnsi()
|
, gameSettings->ProductName.ToStringAnsi()
|
||||||
, gameSettings->CompanyName.ToStringAnsi()
|
, gameSettings->CompanyName.ToStringAnsi()
|
||||||
, now.GetYear()
|
, now.GetYear()
|
||||||
@@ -182,12 +181,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (!FileSystem::FileExists(dstAppPath))
|
if (!FileSystem::FileExists(dstAppPath))
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
if (File::ReadAllBytes(srcAppPath, fileTemplate))
|
if (File::ReadAllText(srcAppPath, fileTemplate))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to load App.cs template."));
|
data.Error(TEXT("Failed to load App.cs template."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
|
||||||
|
|
||||||
// Write data to file
|
// Write data to file
|
||||||
auto file = FileWriteStream::Open(dstAppPath);
|
auto file = FileWriteStream::Open(dstAppPath);
|
||||||
@@ -195,7 +193,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
file->WriteTextFormatted(
|
file->WriteTextFormatted(
|
||||||
(char*)fileTemplate.Get()
|
fileTemplate.Get()
|
||||||
, defaultNamespace.ToStringAnsi() // {0} Default Namespace
|
, defaultNamespace.ToStringAnsi() // {0} Default Namespace
|
||||||
);
|
);
|
||||||
hasError = file->HasError();
|
hasError = file->HasError();
|
||||||
@@ -211,12 +209,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
const auto srcFlaxGeneratedPath = uwpDataPath / TEXT("FlaxGenerated.cs");
|
const auto srcFlaxGeneratedPath = uwpDataPath / TEXT("FlaxGenerated.cs");
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
if (File::ReadAllBytes(srcFlaxGeneratedPath, fileTemplate))
|
if (File::ReadAllText(srcFlaxGeneratedPath, fileTemplate))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to load FlaxGenerated.cs template."));
|
data.Error(TEXT("Failed to load FlaxGenerated.cs template."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
StringAnsi autoRotationPreferences;
|
StringAnsi autoRotationPreferences;
|
||||||
@@ -252,7 +249,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
file->WriteTextFormatted(
|
file->WriteTextFormatted(
|
||||||
(char*)fileTemplate.Get()
|
fileTemplate.Get()
|
||||||
, autoRotationPreferences.Get()
|
, autoRotationPreferences.Get()
|
||||||
, preferredLaunchWindowingMode.Get()
|
, preferredLaunchWindowingMode.Get()
|
||||||
);
|
);
|
||||||
@@ -272,12 +269,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (!FileSystem::FileExists(dstSolutionPath))
|
if (!FileSystem::FileExists(dstSolutionPath))
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
if (File::ReadAllBytes(srcSolutionPath, fileTemplate))
|
if (File::ReadAllText(srcSolutionPath, fileTemplate))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to load Solution.sln template."));
|
data.Error(TEXT("Failed to load Solution.sln template."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
|
||||||
|
|
||||||
// Write data to file
|
// Write data to file
|
||||||
auto file = FileWriteStream::Open(dstSolutionPath);
|
auto file = FileWriteStream::Open(dstSolutionPath);
|
||||||
@@ -285,7 +281,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
file->WriteTextFormatted(
|
file->WriteTextFormatted(
|
||||||
(char*)fileTemplate.Get()
|
fileTemplate.Get()
|
||||||
, projectName.ToStringAnsi() // {0} Project Name
|
, projectName.ToStringAnsi() // {0} Project Name
|
||||||
, mode // {1} Platform Mode
|
, mode // {1} Platform Mode
|
||||||
, projectGuid.ToStringAnsi() // {2} Project ID
|
, projectGuid.ToStringAnsi() // {2} Project ID
|
||||||
@@ -305,12 +301,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
const auto srcProjectPath = uwpDataPath / TEXT("Project.csproj");
|
const auto srcProjectPath = uwpDataPath / TEXT("Project.csproj");
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
if (File::ReadAllBytes(srcProjectPath, fileTemplate))
|
if (File::ReadAllText(srcProjectPath, fileTemplate))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to load Project.csproj template."));
|
data.Error(TEXT("Failed to load Project.csproj template."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
|
||||||
|
|
||||||
// Build included files data
|
// Build included files data
|
||||||
StringBuilder filesInclude(2048);
|
StringBuilder filesInclude(2048);
|
||||||
@@ -334,7 +329,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
file->WriteTextFormatted(
|
file->WriteTextFormatted(
|
||||||
(char*)fileTemplate.Get()
|
fileTemplate.Get()
|
||||||
, projectName.ToStringAnsi() // {0} Project Name
|
, projectName.ToStringAnsi() // {0} Project Name
|
||||||
, mode // {1} Platform Mode
|
, mode // {1} Platform Mode
|
||||||
, projectGuid.Get() // {2} Project ID
|
, projectGuid.Get() // {2} Project ID
|
||||||
@@ -357,12 +352,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (!FileSystem::FileExists(dstManifestPath))
|
if (!FileSystem::FileExists(dstManifestPath))
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
if (File::ReadAllBytes(srcManifestPath, fileTemplate))
|
if (File::ReadAllText(srcManifestPath, fileTemplate))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to load Package.appxmanifest template."));
|
data.Error(TEXT("Failed to load Package.appxmanifest template."));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
fileTemplate[fileTemplate.Count() - 1] = 0;
|
|
||||||
|
|
||||||
// Build included files data
|
// Build included files data
|
||||||
StringBuilder filesInclude(2048);
|
StringBuilder filesInclude(2048);
|
||||||
@@ -385,7 +379,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
file->WriteTextFormatted(
|
file->WriteTextFormatted(
|
||||||
(char*)fileTemplate.Get()
|
fileTemplate.Get()
|
||||||
, projectName.ToStringAnsi() // {0} Display Name
|
, projectName.ToStringAnsi() // {0} Display Name
|
||||||
, gameSettings->CompanyName.ToStringAnsi() // {1} Company Name
|
, gameSettings->CompanyName.ToStringAnsi() // {1} Company Name
|
||||||
, productId.ToStringAnsi() // {2} Product ID
|
, productId.ToStringAnsi() // {2} Product ID
|
||||||
|
|||||||
@@ -46,10 +46,7 @@ namespace FlaxEditor.CustomEditors
|
|||||||
|
|
||||||
if (values.HasReferenceValue)
|
if (values.HasReferenceValue)
|
||||||
{
|
{
|
||||||
var v = (IList)values.ReferenceValue;
|
if (values.ReferenceValue is IList v && values.Count == v.Count && v.Count > index)
|
||||||
|
|
||||||
// Get the reference value if collections are the same size
|
|
||||||
if (v != null && values.Count == v.Count)
|
|
||||||
{
|
{
|
||||||
_referenceValue = v[index];
|
_referenceValue = v[index];
|
||||||
_hasReferenceValue = true;
|
_hasReferenceValue = true;
|
||||||
|
|||||||
@@ -150,7 +150,10 @@ namespace FlaxEditor.Options
|
|||||||
private void Save()
|
private void Save()
|
||||||
{
|
{
|
||||||
// Update file
|
// Update file
|
||||||
Editor.SaveJsonAsset(_optionsFilePath, Options);
|
if (Editor.SaveJsonAsset(_optionsFilePath, Options))
|
||||||
|
{
|
||||||
|
MessageBox.Show(string.Format("Failed to save editor option to '{0}'. Ensure that directory exists and program has access to it.", _optionsFilePath), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
|
||||||
// Special case for editor analytics
|
// Special case for editor analytics
|
||||||
var editorAnalyticsTrackingFile = Path.Combine(Editor.LocalCachePath, "noTracking");
|
var editorAnalyticsTrackingFile = Path.Combine(Editor.LocalCachePath, "noTracking");
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FlaxEditor.Viewport
|
|||||||
/// <seealso cref="IGizmoOwner" />
|
/// <seealso cref="IGizmoOwner" />
|
||||||
public class PrefabWindowViewport : PrefabPreview, IEditorPrimitivesOwner
|
public class PrefabWindowViewport : PrefabPreview, IEditorPrimitivesOwner
|
||||||
{
|
{
|
||||||
|
[HideInEditor]
|
||||||
private sealed class PrefabSpritesRenderer : MainEditorGizmoViewport.EditorSpritesRenderer
|
private sealed class PrefabSpritesRenderer : MainEditorGizmoViewport.EditorSpritesRenderer
|
||||||
{
|
{
|
||||||
public PrefabWindowViewport Viewport;
|
public PrefabWindowViewport Viewport;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ DECLARE_ENUM_OPERATORS(AssetsCacheFlags);
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flax Game Engine assets cache container
|
/// Flax Game Engine assets cache container
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class AssetsCache
|
class FLAXENGINE_API AssetsCache
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,18 @@ bool CreateJson::Create(const StringView& path, StringAnsiView& data, StringAnsi
|
|||||||
LOG(Warning, "Asset will have different type name {0} -> {1}", typeName, String(dataTypename.Get()));
|
LOG(Warning, "Asset will have different type name {0} -> {1}", typeName, String(dataTypename.Get()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const String directory = StringUtils::GetDirectoryName(path);
|
||||||
|
if (!FileSystem::DirectoryExists(directory))
|
||||||
|
{
|
||||||
|
if (FileSystem::CreateDirectory(directory))
|
||||||
|
{
|
||||||
|
LOG(Warning, "Failed to create directory");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rapidjson_flax::StringBuffer buffer;
|
rapidjson_flax::StringBuffer buffer;
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,18 @@ bool StringView::operator!=(const String& other) const
|
|||||||
return StringUtils::Compare(this->GetText(), *other) != 0;
|
return StringUtils::Compare(this->GetText(), *other) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String StringView::Left(int32 count) const
|
||||||
|
{
|
||||||
|
const int32 countClamped = count < 0 ? 0 : count < Length() ? count : Length();
|
||||||
|
return String(**this, countClamped);
|
||||||
|
}
|
||||||
|
|
||||||
|
String StringView::Right(int32 count) const
|
||||||
|
{
|
||||||
|
const int32 countClamped = count < 0 ? 0 : count < Length() ? count : Length();
|
||||||
|
return String(**this + Length() - countClamped);
|
||||||
|
}
|
||||||
|
|
||||||
String StringView::Substring(int32 startIndex) const
|
String StringView::Substring(int32 startIndex) const
|
||||||
{
|
{
|
||||||
ASSERT(startIndex >= 0 && startIndex < Length());
|
ASSERT(startIndex >= 0 && startIndex < Length());
|
||||||
|
|||||||
@@ -321,6 +321,20 @@ public:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the left most given number of characters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">The characters count.</param>
|
||||||
|
/// <returns>The substring.</returns>
|
||||||
|
String Left(int32 count) const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the string of characters from the right (end of the string).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="count">The characters count.</param>
|
||||||
|
/// <returns>The substring.</returns>
|
||||||
|
String Right(int32 count) const;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves substring created from characters starting from startIndex to the String end.
|
/// Retrieves substring created from characters starting from startIndex to the String end.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1040,7 +1040,7 @@ void StagingManagerVulkan::Dispose()
|
|||||||
ScopeLock lock(_locker);
|
ScopeLock lock(_locker);
|
||||||
|
|
||||||
#if !BUILD_RELEASE
|
#if !BUILD_RELEASE
|
||||||
LOG(Info, "Vulakn staging buffers peek memory usage: {0}, allocs: {1}, frees: {2}", Utilities::BytesToText(_allBuffersPeekSize), Utilities::BytesToText(_allBuffersAllocSize), Utilities::BytesToText(_allBuffersFreeSize));
|
LOG(Info, "Vulkan staging buffers peek memory usage: {0}, allocs: {1}, frees: {2}", Utilities::BytesToText(_allBuffersPeekSize), Utilities::BytesToText(_allBuffersAllocSize), Utilities::BytesToText(_allBuffersFreeSize));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Release buffers and clear memory
|
// Release buffers and clear memory
|
||||||
|
|||||||
@@ -347,6 +347,12 @@ void Actor::SetOrderInParent(int32 index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Actor* Actor::GetChild(int32 index) const
|
||||||
|
{
|
||||||
|
CHECK_RETURN(index >= 0 && index < Children.Count(), nullptr);
|
||||||
|
return Children[index];
|
||||||
|
}
|
||||||
|
|
||||||
Actor* Actor::GetChild(const StringView& name) const
|
Actor* Actor::GetChild(const StringView& name) const
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < Children.Count(); i++)
|
for (int32 i = 0; i < Children.Count(); i++)
|
||||||
@@ -354,7 +360,6 @@ Actor* Actor::GetChild(const StringView& name) const
|
|||||||
if (Children[i]->GetName() == name)
|
if (Children[i]->GetName() == name)
|
||||||
return Children[i];
|
return Children[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,6 +487,12 @@ void Actor::SetName(const StringView& value)
|
|||||||
Level::callActorEvent(Level::ActorEventType::OnActorNameChanged, this, nullptr);
|
Level::callActorEvent(Level::ActorEventType::OnActorNameChanged, this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Script* Actor::GetScript(int32 index) const
|
||||||
|
{
|
||||||
|
CHECK_RETURN(index >= 0 && index < Scripts.Count(), nullptr);
|
||||||
|
return Scripts[index];
|
||||||
|
}
|
||||||
|
|
||||||
Script* Actor::GetScript(const MClass* type) const
|
Script* Actor::GetScript(const MClass* type) const
|
||||||
{
|
{
|
||||||
CHECK_RETURN(type, nullptr);
|
CHECK_RETURN(type, nullptr);
|
||||||
|
|||||||
@@ -192,10 +192,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The child actor index.</param>
|
/// <param name="index">The child actor index.</param>
|
||||||
/// <returns>The child actor (always valid).</returns>
|
/// <returns>The child actor (always valid).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Actor* GetChild(int32 index) const
|
API_FUNCTION() Actor* GetChild(int32 index) const;
|
||||||
{
|
|
||||||
return Children[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the child actor with the given name.
|
/// Gets the child actor with the given name.
|
||||||
@@ -266,10 +263,7 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">The script index.</param>
|
/// <param name="index">The script index.</param>
|
||||||
/// <returns>The script (always valid).</returns>
|
/// <returns>The script (always valid).</returns>
|
||||||
API_FUNCTION() FORCE_INLINE Script* GetScript(int32 index) const
|
API_FUNCTION() Script* GetScript(int32 index) const;
|
||||||
{
|
|
||||||
return Scripts[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the script of the given type from this actor.
|
/// Gets the script of the given type from this actor.
|
||||||
|
|||||||
@@ -65,22 +65,6 @@ void Game::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs
|
|||||||
|
|
||||||
void Game::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
|
void Game::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
// Save app state asynchronously after requesting a deferral. Holding a deferral
|
|
||||||
// indicates that the application is busy performing suspending operations. Be
|
|
||||||
// aware that a deferral may not be held indefinitely. After about five seconds,
|
|
||||||
// the app will be forced to exit.
|
|
||||||
SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral();
|
|
||||||
|
|
||||||
create_task([this, deferral]()
|
|
||||||
{
|
|
||||||
m_deviceResources->Trim();
|
|
||||||
|
|
||||||
m_main->Suspend();
|
|
||||||
|
|
||||||
deferral->Complete();
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::OnResuming(Platform::Object^ sender, Platform::Object^ args)
|
void Game::OnResuming(Platform::Object^ sender, Platform::Object^ args)
|
||||||
@@ -396,9 +380,10 @@ int PlatformImpl::GetSpecialFolderPath(const SpecialFolder type, wchar_t* buffer
|
|||||||
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
|
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
|
||||||
break;
|
break;
|
||||||
case SpecialFolder::ProgramData:
|
case SpecialFolder::ProgramData:
|
||||||
|
path = Windows::Storage::ApplicationData::Current->RoamingFolder->Path;
|
||||||
break;
|
break;
|
||||||
//case SpecialFolder::Temporary: path = Windows::Storage::ApplicationData::Current->TemporaryFolder->Path; break;
|
|
||||||
case SpecialFolder::Temporary:
|
case SpecialFolder::Temporary:
|
||||||
|
//path = Windows::Storage::ApplicationData::Current->TemporaryFolder->Path;
|
||||||
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
|
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ CharacterController::CharacterController(const SpawnParams& params)
|
|||||||
, _radius(50.0f)
|
, _radius(50.0f)
|
||||||
, _height(150.0f)
|
, _height(150.0f)
|
||||||
, _minMoveDistance(0.0f)
|
, _minMoveDistance(0.0f)
|
||||||
, _upDirection(Vector3::Up)
|
|
||||||
, _isUpdatingTransform(false)
|
, _isUpdatingTransform(false)
|
||||||
, _nonWalkableMode(CharacterController::NonWalkableModes::PreventClimbing)
|
, _upDirection(Vector3::Up)
|
||||||
|
, _nonWalkableMode(NonWalkableModes::PreventClimbing)
|
||||||
, _lastFlags(CollisionFlags::None)
|
, _lastFlags(CollisionFlags::None)
|
||||||
{
|
{
|
||||||
static_assert(sizeof(_filterData) == sizeof(PxFilterData), "Invalid filter data size.");
|
static_assert(sizeof(_filterData) == sizeof(PxFilterData), "Invalid filter data size.");
|
||||||
@@ -61,7 +61,12 @@ void CharacterController::SetSlopeLimit(float value)
|
|||||||
_slopeLimit = value;
|
_slopeLimit = value;
|
||||||
|
|
||||||
if (_controller)
|
if (_controller)
|
||||||
_controller->setSlopeLimit(cosf(value * DegreesToRadians));
|
_controller->setSlopeLimit(Math::Cos(value * DegreesToRadians));
|
||||||
|
}
|
||||||
|
|
||||||
|
CharacterController::NonWalkableModes CharacterController::GetNonWalkableMode() const
|
||||||
|
{
|
||||||
|
return _nonWalkableMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CharacterController::SetNonWalkableMode(NonWalkableModes value)
|
void CharacterController::SetNonWalkableMode(NonWalkableModes value)
|
||||||
@@ -72,6 +77,11 @@ void CharacterController::SetNonWalkableMode(NonWalkableModes value)
|
|||||||
_controller->setNonWalkableMode(static_cast<PxControllerNonWalkableMode::Enum>(value));
|
_controller->setNonWalkableMode(static_cast<PxControllerNonWalkableMode::Enum>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float CharacterController::GetStepOffset() const
|
||||||
|
{
|
||||||
|
return _stepOffset;
|
||||||
|
}
|
||||||
|
|
||||||
void CharacterController::SetStepOffset(float value)
|
void CharacterController::SetStepOffset(float value)
|
||||||
{
|
{
|
||||||
if (Math::NearEqual(value, _stepOffset))
|
if (Math::NearEqual(value, _stepOffset))
|
||||||
|
|||||||
@@ -118,10 +118,7 @@ public:
|
|||||||
/// Gets the non-walkable mode for the character controller.
|
/// Gets the non-walkable mode for the character controller.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_PROPERTY(Attributes="EditorOrder(215), DefaultValue(NonWalkableModes.PreventClimbing), EditorDisplay(\"Character Controller\")")
|
API_PROPERTY(Attributes="EditorOrder(215), DefaultValue(NonWalkableModes.PreventClimbing), EditorDisplay(\"Character Controller\")")
|
||||||
FORCE_INLINE NonWalkableModes GetNonWalkableMode() const
|
NonWalkableModes GetNonWalkableMode() const;
|
||||||
{
|
|
||||||
return _nonWalkableMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the non-walkable mode for the character controller.
|
/// Sets the non-walkable mode for the character controller.
|
||||||
@@ -132,10 +129,7 @@ public:
|
|||||||
/// Gets the step height. The character will step up a stair only if it is closer to the ground than the indicated value. This should not be greater than the Character Controller’s height or it will generate an error.
|
/// Gets the step height. The character will step up a stair only if it is closer to the ground than the indicated value. This should not be greater than the Character Controller’s height or it will generate an error.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
API_PROPERTY(Attributes="EditorOrder(220), DefaultValue(30.0f), Limit(0), EditorDisplay(\"Character Controller\")")
|
API_PROPERTY(Attributes="EditorOrder(220), DefaultValue(30.0f), Limit(0), EditorDisplay(\"Character Controller\")")
|
||||||
FORCE_INLINE float GetStepOffset() const
|
float GetStepOffset() const;
|
||||||
{
|
|
||||||
return _stepOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the step height. The character will step up a stair only if it is closer to the ground than the indicated value. This should not be greater than the Character Controller’s height or it will generate an error.
|
/// Sets the step height. The character will step up a stair only if it is closer to the ground than the indicated value. This should not be greater than the Character Controller’s height or it will generate an error.
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ void RemoveLongPathPrefix(const String& path, String& result)
|
|||||||
result.Remove(2, 6);
|
result.Remove(2, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
String StringUtils::GetDirectoryName(const String& path)
|
String StringUtils::GetDirectoryName(const StringView& path)
|
||||||
{
|
{
|
||||||
const int32 lastFrontSlash = path.FindLast('\\');
|
const int32 lastFrontSlash = path.FindLast('\\');
|
||||||
const int32 lastBackSlash = path.FindLast('/');
|
const int32 lastBackSlash = path.FindLast('/');
|
||||||
@@ -297,24 +297,22 @@ String StringUtils::GetDirectoryName(const String& path)
|
|||||||
return splitIndex != INVALID_INDEX ? path.Left(splitIndex) : String::Empty;
|
return splitIndex != INVALID_INDEX ? path.Left(splitIndex) : String::Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
String StringUtils::GetFileName(const String& path)
|
String StringUtils::GetFileName(const StringView& path)
|
||||||
{
|
{
|
||||||
Char chr;
|
Char chr;
|
||||||
const int32 length = path.Length();
|
const int32 length = path.Length();
|
||||||
int32 num = length;
|
int32 num = length;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
num--;
|
num--;
|
||||||
if (num < 0)
|
if (num < 0)
|
||||||
return path;
|
return String(path);
|
||||||
chr = path[num];
|
chr = path[num];
|
||||||
} while (chr != DirectorySeparatorChar && chr != AltDirectorySeparatorChar && chr != VolumeSeparatorChar);
|
} while (chr != DirectorySeparatorChar && chr != AltDirectorySeparatorChar && chr != VolumeSeparatorChar);
|
||||||
|
|
||||||
return path.Substring(num + 1, length - num - 1);
|
return path.Substring(num + 1, length - num - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
String StringUtils::GetFileNameWithoutExtension(const String& path)
|
String StringUtils::GetFileNameWithoutExtension(const StringView& path)
|
||||||
{
|
{
|
||||||
String filename = GetFileName(path);
|
String filename = GetFileName(path);
|
||||||
const int32 num = filename.FindLast('.');
|
const int32 num = filename.FindLast('.');
|
||||||
@@ -325,14 +323,14 @@ String StringUtils::GetFileNameWithoutExtension(const String& path)
|
|||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
String StringUtils::GetPathWithoutExtension(const String& path)
|
String StringUtils::GetPathWithoutExtension(const StringView& path)
|
||||||
{
|
{
|
||||||
const int32 num = path.FindLast('.');
|
const int32 num = path.FindLast('.');
|
||||||
if (num != -1)
|
if (num != -1)
|
||||||
{
|
{
|
||||||
return path.Substring(0, num);
|
return path.Substring(0, num);
|
||||||
}
|
}
|
||||||
return path;
|
return String(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringUtils::PathRemoveRelativeParts(String& path)
|
void StringUtils::PathRemoveRelativeParts(String& path)
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "Engine/Platform/MessageBox.h"
|
#include "Engine/Platform/MessageBox.h"
|
||||||
#include "Engine/Platform/WindowsManager.h"
|
#include "Engine/Platform/WindowsManager.h"
|
||||||
#include "Engine/Platform/Clipboard.h"
|
#include "Engine/Platform/Clipboard.h"
|
||||||
|
#include "Engine/Platform/IGuiData.h"
|
||||||
#include "Engine/Utilities/StringConverter.h"
|
#include "Engine/Utilities/StringConverter.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
#include "Engine/Engine/Engine.h"
|
#include "Engine/Engine/Engine.h"
|
||||||
@@ -58,6 +59,15 @@ X11::Display* xDisplay = nullptr;
|
|||||||
X11::XIM IM = nullptr;
|
X11::XIM IM = nullptr;
|
||||||
X11::XIC IC = nullptr;
|
X11::XIC IC = nullptr;
|
||||||
X11::Atom xAtomDeleteWindow;
|
X11::Atom xAtomDeleteWindow;
|
||||||
|
X11::Atom xAtomXdndEnter;
|
||||||
|
X11::Atom xAtomXdndPosition;
|
||||||
|
X11::Atom xAtomXdndLeave;
|
||||||
|
X11::Atom xAtomXdndDrop;
|
||||||
|
X11::Atom xAtomXdndActionCopy;
|
||||||
|
X11::Atom xAtomXdndStatus;
|
||||||
|
X11::Atom xAtomXdndSelection;
|
||||||
|
X11::Atom xAtomXdndFinished;
|
||||||
|
X11::Atom xAtomXdndAware;
|
||||||
X11::Atom xAtomWmState;
|
X11::Atom xAtomWmState;
|
||||||
X11::Atom xAtomWmStateHidden;
|
X11::Atom xAtomWmStateHidden;
|
||||||
X11::Atom xAtomWmStateMaxVert;
|
X11::Atom xAtomWmStateMaxVert;
|
||||||
@@ -65,6 +75,11 @@ X11::Atom xAtomWmStateMaxHorz;
|
|||||||
X11::Atom xAtomWmWindowOpacity;
|
X11::Atom xAtomWmWindowOpacity;
|
||||||
X11::Atom xAtomWmName;
|
X11::Atom xAtomWmName;
|
||||||
X11::Atom xAtomClipboard;
|
X11::Atom xAtomClipboard;
|
||||||
|
X11::Atom xDnDRequested = 0;
|
||||||
|
X11::Window xDndSourceWindow = 0;
|
||||||
|
DragDropEffect xDndResult;
|
||||||
|
Vector2 xDndPos;
|
||||||
|
int32 xDnDVersion = 0;
|
||||||
int32 SystemDpi = 96;
|
int32 SystemDpi = 96;
|
||||||
X11::Cursor Cursors[(int32)CursorType::MAX];
|
X11::Cursor Cursors[(int32)CursorType::MAX];
|
||||||
X11::XcursorImage* CursorsImg[(int32)CursorType::MAX];
|
X11::XcursorImage* CursorsImg[(int32)CursorType::MAX];
|
||||||
@@ -1171,6 +1186,13 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Property
|
||||||
|
{
|
||||||
|
unsigned char* data;
|
||||||
|
int format, nitems;
|
||||||
|
X11::Atom type;
|
||||||
|
};
|
||||||
|
|
||||||
namespace Impl
|
namespace Impl
|
||||||
{
|
{
|
||||||
LinuxKeyboard Keyboard;
|
LinuxKeyboard Keyboard;
|
||||||
@@ -1222,6 +1244,371 @@ namespace Impl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Property ReadProperty(X11::Display* display, X11::Window window, X11::Atom property)
|
||||||
|
{
|
||||||
|
X11::Atom readType = 0;
|
||||||
|
int readFormat = 0;
|
||||||
|
unsigned long nitems = 0;
|
||||||
|
unsigned long readBytes = 0;
|
||||||
|
unsigned char* result = nullptr;
|
||||||
|
int bytesCount = 1024;
|
||||||
|
if (property != 0)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (result != nullptr)
|
||||||
|
X11::XFree(result);
|
||||||
|
XGetWindowProperty(display, window, property, 0, bytesCount, 0, AnyPropertyType, &readType, &readFormat, &nitems, &readBytes, &result);
|
||||||
|
bytesCount *= 2;
|
||||||
|
} while (readBytes != 0);
|
||||||
|
}
|
||||||
|
Property p = { result, readFormat, (int)nitems, readType };
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static X11::Atom SelectTargetFromList(X11::Display* display, const char* targetType, X11::Atom* list, int count)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
X11::Atom atom = list[i];
|
||||||
|
if (atom != 0 && StringAnsi(XGetAtomName(display, atom)) == targetType)
|
||||||
|
return atom;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static X11::Atom SelectTargetFromAtoms(X11::Display* display, const char* targetType, X11::Atom t1, X11::Atom t2, X11::Atom t3)
|
||||||
|
{
|
||||||
|
if (t1 != 0 && StringAnsi(XGetAtomName(display, t1)) == targetType)
|
||||||
|
return t1;
|
||||||
|
if (t2 != 0 && StringAnsi(XGetAtomName(display, t2)) == targetType)
|
||||||
|
return t2;
|
||||||
|
if (t3 != 0 && StringAnsi(XGetAtomName(display, t3)) == targetType)
|
||||||
|
return t3;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static X11::Window FindAppWindow(X11::Display* display, X11::Window w)
|
||||||
|
{
|
||||||
|
int nprops, i = 0;
|
||||||
|
X11::Atom* a;
|
||||||
|
if (w == 0)
|
||||||
|
return 0;
|
||||||
|
a = X11::XListProperties(display, w, &nprops);
|
||||||
|
for (i = 0; i < nprops; i++)
|
||||||
|
{
|
||||||
|
if (a[i] == xAtomXdndAware)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nprops)
|
||||||
|
X11::XFree(a);
|
||||||
|
if (i != nprops)
|
||||||
|
return w;
|
||||||
|
X11::Window child, wtmp;
|
||||||
|
int tmp;
|
||||||
|
unsigned int utmp;
|
||||||
|
X11::XQueryPointer(display, w, &wtmp, &child, &tmp, &tmp, &tmp, &tmp, &utmp);
|
||||||
|
return FindAppWindow(display, child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LinuxDropFilesData : public IGuiData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Array<String> Files;
|
||||||
|
|
||||||
|
Type GetType() const override
|
||||||
|
{
|
||||||
|
return Type::Files;
|
||||||
|
}
|
||||||
|
String GetAsText() const override
|
||||||
|
{
|
||||||
|
return String::Empty;
|
||||||
|
}
|
||||||
|
void GetAsFiles(Array<String>* files) const override
|
||||||
|
{
|
||||||
|
files->Add(Files);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LinuxDropTextData : public IGuiData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StringView Text;
|
||||||
|
|
||||||
|
Type GetType() const override
|
||||||
|
{
|
||||||
|
return Type::Text;
|
||||||
|
}
|
||||||
|
String GetAsText() const override
|
||||||
|
{
|
||||||
|
return String(Text);
|
||||||
|
}
|
||||||
|
void GetAsFiles(Array<String>* files) const override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
DragDropEffect LinuxWindow::DoDragDrop(const StringView& data)
|
||||||
|
{
|
||||||
|
auto cursorWrong = X11::XCreateFontCursor(xDisplay, 54);
|
||||||
|
auto cursorTransient = X11::XCreateFontCursor(xDisplay, 24);
|
||||||
|
auto cursorGood = X11::XCreateFontCursor(xDisplay, 4);
|
||||||
|
Array<X11::Atom, FixedAllocation<3>> formats;
|
||||||
|
formats.Add(X11::XInternAtom(xDisplay, "text/plain", 0));
|
||||||
|
formats.Add(X11::XInternAtom(xDisplay, "TEXT", 0));
|
||||||
|
formats.Add((X11::Atom)31);
|
||||||
|
StringAnsi dataAnsi(data);
|
||||||
|
LinuxDropTextData dropData;
|
||||||
|
dropData.Text = data;
|
||||||
|
|
||||||
|
// Begin dragging
|
||||||
|
auto screen = X11::XDefaultScreen(xDisplay);
|
||||||
|
auto rootWindow = X11::XRootWindow(xDisplay, screen);
|
||||||
|
if (X11::XGrabPointer(xDisplay, _window, 1, Button1MotionMask | ButtonReleaseMask, GrabModeAsync, GrabModeAsync, rootWindow, cursorWrong, CurrentTime) != GrabSuccess)
|
||||||
|
return DragDropEffect::None;
|
||||||
|
X11::XSetSelectionOwner(xDisplay, xAtomXdndSelection, _window, CurrentTime);
|
||||||
|
|
||||||
|
// Process events
|
||||||
|
X11::XEvent event;
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
Unaware,
|
||||||
|
Unreceptive,
|
||||||
|
CanDrop,
|
||||||
|
};
|
||||||
|
int status = Unaware, previousVersion = -1;
|
||||||
|
X11::Window previousWindow = 0;
|
||||||
|
DragDropEffect result = DragDropEffect::None;
|
||||||
|
float lastDraw = Platform::GetTimeSeconds();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
X11::XNextEvent(xDisplay, &event);
|
||||||
|
|
||||||
|
if (event.type == SelectionClear)
|
||||||
|
break;
|
||||||
|
if (event.type == SelectionRequest)
|
||||||
|
{
|
||||||
|
// Extract the relavent data
|
||||||
|
X11::Window owner = event.xselectionrequest.owner;
|
||||||
|
X11::Atom selection = event.xselectionrequest.selection;
|
||||||
|
X11::Atom target = event.xselectionrequest.target;
|
||||||
|
X11::Atom property = event.xselectionrequest.property;
|
||||||
|
X11::Window requestor = event.xselectionrequest.requestor;
|
||||||
|
X11::Time timestamp = event.xselectionrequest.time;
|
||||||
|
X11::Display* disp = event.xselection.display;
|
||||||
|
X11::XEvent s;
|
||||||
|
s.xselection.type = SelectionNotify;
|
||||||
|
s.xselection.requestor = requestor;
|
||||||
|
s.xselection.selection = selection;
|
||||||
|
s.xselection.target = target;
|
||||||
|
s.xselection.property = 0;
|
||||||
|
s.xselection.time = timestamp;
|
||||||
|
if (target == X11::XInternAtom(disp, "TARGETS", 0))
|
||||||
|
{
|
||||||
|
Array<X11::Atom> targets;
|
||||||
|
targets.Add(target);
|
||||||
|
targets.Add(X11::XInternAtom(disp, "MULTIPLE", 0));
|
||||||
|
targets.Add(formats.Get(), formats.Count());
|
||||||
|
X11::XChangeProperty(disp, requestor, property, (X11::Atom)4, 32, PropModeReplace, (unsigned char*)targets.Get(), targets.Count());
|
||||||
|
s.xselection.property = property;
|
||||||
|
}
|
||||||
|
else if (formats.Contains(target))
|
||||||
|
{
|
||||||
|
s.xselection.property = property;
|
||||||
|
X11::XChangeProperty(disp, requestor, property, target, 8, PropModeReplace, reinterpret_cast<const unsigned char*>(dataAnsi.Get()), dataAnsi.Length());
|
||||||
|
}
|
||||||
|
X11::XSendEvent(event.xselection.display, event.xselectionrequest.requestor, 1, 0, &s);
|
||||||
|
}
|
||||||
|
else if (event.type == MotionNotify)
|
||||||
|
{
|
||||||
|
// Find window under mouse
|
||||||
|
auto window = Impl::FindAppWindow(xDisplay, rootWindow);
|
||||||
|
int fmt, version = -1;
|
||||||
|
X11::Atom atmp;
|
||||||
|
unsigned long nitems, bytesLeft;
|
||||||
|
unsigned char* data = nullptr;
|
||||||
|
if (window == previousWindow)
|
||||||
|
version = previousVersion;
|
||||||
|
else if(window == 0)
|
||||||
|
;
|
||||||
|
else if (X11::XGetWindowProperty(xDisplay, window, xAtomXdndAware, 0, 2, 0, AnyPropertyType, &atmp, &fmt, &nitems, &bytesLeft, &data) != Success)
|
||||||
|
continue;
|
||||||
|
else if (data == 0)
|
||||||
|
continue;
|
||||||
|
else if (fmt != 32)
|
||||||
|
continue;
|
||||||
|
else if (nitems != 1)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
version = data[0];
|
||||||
|
if (status == Unaware && version != -1)
|
||||||
|
status = Unreceptive;
|
||||||
|
else if(version == -1)
|
||||||
|
status = Unaware;
|
||||||
|
xDndPos = Vector2((float)event.xmotion.x_root, (float)event.xmotion.y_root);
|
||||||
|
|
||||||
|
// Update mouse grab
|
||||||
|
if (status == Unaware)
|
||||||
|
X11::XChangeActivePointerGrab(xDisplay, Button1MotionMask | ButtonReleaseMask, cursorWrong, CurrentTime);
|
||||||
|
else if(status == Unreceptive)
|
||||||
|
X11::XChangeActivePointerGrab(xDisplay, Button1MotionMask | ButtonReleaseMask, cursorTransient, CurrentTime);
|
||||||
|
else
|
||||||
|
X11::XChangeActivePointerGrab(xDisplay, Button1MotionMask | ButtonReleaseMask, cursorGood, CurrentTime);
|
||||||
|
|
||||||
|
if (window != previousWindow && previousVersion != -1)
|
||||||
|
{
|
||||||
|
// Send drag left event
|
||||||
|
auto ww = WindowsManager::GetByNativePtr((void*)previousWindow);
|
||||||
|
if (ww)
|
||||||
|
{
|
||||||
|
ww->_dragOver = false;
|
||||||
|
ww->OnDragLeave();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X11::XClientMessageEvent m;
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.type = ClientMessage;
|
||||||
|
m.display = event.xclient.display;
|
||||||
|
m.window = previousWindow;
|
||||||
|
m.message_type = xAtomXdndLeave;
|
||||||
|
m.format = 32;
|
||||||
|
m.data.l[0] = _window;
|
||||||
|
m.data.l[1] = 0;
|
||||||
|
m.data.l[2] = 0;
|
||||||
|
m.data.l[3] = 0;
|
||||||
|
m.data.l[4] = 0;
|
||||||
|
X11::XSendEvent(xDisplay, previousWindow, 0, NoEventMask, (X11::XEvent*)&m);
|
||||||
|
X11::XFlush(xDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window != previousWindow && version != -1)
|
||||||
|
{
|
||||||
|
// Send drag enter event
|
||||||
|
auto ww = WindowsManager::GetByNativePtr((void*)window);
|
||||||
|
if (ww)
|
||||||
|
{
|
||||||
|
xDndPos = ww->ScreenToClient(Platform::GetMousePosition());
|
||||||
|
xDndResult = DragDropEffect::None;
|
||||||
|
ww->OnDragEnter(&dropData, xDndPos, xDndResult);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X11::XClientMessageEvent m;
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.type = ClientMessage;
|
||||||
|
m.display = event.xclient.display;
|
||||||
|
m.window = window;
|
||||||
|
m.message_type = xAtomXdndEnter;
|
||||||
|
m.format = 32;
|
||||||
|
m.data.l[0] = _window;
|
||||||
|
m.data.l[1] = Math::Min(5, version) << 24 | (formats.Count() > 3);
|
||||||
|
m.data.l[2] = formats.Count() > 0 ? formats[0] : 0;
|
||||||
|
m.data.l[3] = formats.Count() > 1 ? formats[1] : 0;
|
||||||
|
m.data.l[4] = formats.Count() > 2 ? formats[2] : 0;
|
||||||
|
X11::XSendEvent(xDisplay, window, 0, NoEventMask, (X11::XEvent*)&m);
|
||||||
|
X11::XFlush(xDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version != -1)
|
||||||
|
{
|
||||||
|
// Send position event
|
||||||
|
auto ww = WindowsManager::GetByNativePtr((void*)window);
|
||||||
|
if (ww)
|
||||||
|
{
|
||||||
|
xDndPos = ww->ScreenToClient(Platform::GetMousePosition());
|
||||||
|
ww->_dragOver = true;
|
||||||
|
xDndResult = DragDropEffect::None;
|
||||||
|
ww->OnDragOver(&dropData, xDndPos, xDndResult);
|
||||||
|
status = CanDrop;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int x, y, tmp;
|
||||||
|
unsigned int utmp;
|
||||||
|
X11::Window wtmp;
|
||||||
|
X11::XQueryPointer(xDisplay, window, &wtmp, &wtmp, &tmp, &tmp, &x, &y, &utmp);
|
||||||
|
X11::XClientMessageEvent m;
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.type = ClientMessage;
|
||||||
|
m.display = event.xclient.display;
|
||||||
|
m.window = window;
|
||||||
|
m.message_type = xAtomXdndPosition;
|
||||||
|
m.format = 32;
|
||||||
|
m.data.l[0] = _window;
|
||||||
|
m.data.l[1] = 0;
|
||||||
|
m.data.l[2] = (x << 16) | y;
|
||||||
|
m.data.l[3] = CurrentTime;
|
||||||
|
m.data.l[4] = xAtomXdndActionCopy;
|
||||||
|
X11::XSendEvent(xDisplay, window, 0, NoEventMask, (X11::XEvent*)&m);
|
||||||
|
X11::XFlush(xDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
previousWindow = window;
|
||||||
|
previousVersion = version;
|
||||||
|
}
|
||||||
|
else if (event.type == ClientMessage && event.xclient.message_type == xAtomXdndStatus)
|
||||||
|
{
|
||||||
|
if ((event.xclient.data.l[1]&1) && status != Unaware)
|
||||||
|
status = CanDrop;
|
||||||
|
if (!(event.xclient.data.l[1]&1) && status != Unaware)
|
||||||
|
status = Unreceptive;
|
||||||
|
}
|
||||||
|
else if (event.type == ButtonRelease && event.xbutton.button == 1)
|
||||||
|
{
|
||||||
|
if (status == CanDrop)
|
||||||
|
{
|
||||||
|
// Send drop event
|
||||||
|
auto ww = WindowsManager::GetByNativePtr((void*)previousWindow);
|
||||||
|
if (ww)
|
||||||
|
{
|
||||||
|
xDndPos = ww->ScreenToClient(Platform::GetMousePosition());
|
||||||
|
xDndResult = DragDropEffect::None;
|
||||||
|
ww->OnDragDrop(&dropData, xDndPos, xDndResult);
|
||||||
|
ww->Focus();
|
||||||
|
result = xDndResult;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X11::XClientMessageEvent m;
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.type = ClientMessage;
|
||||||
|
m.display = event.xclient.display;
|
||||||
|
m.window = previousWindow;
|
||||||
|
m.message_type = xAtomXdndDrop;
|
||||||
|
m.format = 32;
|
||||||
|
m.data.l[0] = _window;
|
||||||
|
m.data.l[1] = 0;
|
||||||
|
m.data.l[2] = CurrentTime;
|
||||||
|
m.data.l[3] = 0;
|
||||||
|
m.data.l[4] = 0;
|
||||||
|
X11::XSendEvent(xDisplay, previousWindow, 0, NoEventMask, (X11::XEvent*)&m);
|
||||||
|
X11::XFlush(xDisplay);
|
||||||
|
result = DragDropEffect::Copy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redraw
|
||||||
|
const float time = Platform::GetTimeSeconds();
|
||||||
|
if (time - lastDraw >= 1.0f / 60.0f)
|
||||||
|
{
|
||||||
|
lastDraw = time;
|
||||||
|
Engine::OnDraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End grabbing
|
||||||
|
X11::XChangeActivePointerGrab(xDisplay, Button1MotionMask | ButtonReleaseMask, 0, CurrentTime);
|
||||||
|
XUngrabPointer(xDisplay, CurrentTime);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LinuxClipboard::Clear()
|
void LinuxClipboard::Clear()
|
||||||
@@ -1653,7 +2040,15 @@ bool LinuxPlatform::Init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
xAtomDeleteWindow = X11::XInternAtom(xDisplay, "WM_DELETE_WINDOW", 0);
|
xAtomDeleteWindow = X11::XInternAtom(xDisplay, "WM_DELETE_WINDOW", 0);
|
||||||
xAtomWmState = X11::XInternAtom(xDisplay, "_NET_WM_STATE", 0);
|
xAtomXdndEnter = X11::XInternAtom(xDisplay, "XdndEnter", 0);
|
||||||
|
xAtomXdndPosition = X11::XInternAtom(xDisplay, "XdndPosition", 0);
|
||||||
|
xAtomXdndLeave = X11::XInternAtom(xDisplay, "XdndLeave", 0);
|
||||||
|
xAtomXdndDrop = X11::XInternAtom(xDisplay, "XdndDrop", 0);
|
||||||
|
xAtomXdndActionCopy = X11::XInternAtom(xDisplay, "XdndActionCopy", 0);
|
||||||
|
xAtomXdndStatus = X11::XInternAtom(xDisplay, "XdndStatus", 0);
|
||||||
|
xAtomXdndSelection = X11::XInternAtom(xDisplay, "XdndSelection", 0);
|
||||||
|
xAtomXdndFinished = X11::XInternAtom(xDisplay, "XdndFinished", 0);
|
||||||
|
xAtomXdndAware = X11::XInternAtom(xDisplay, "XdndAware", 0);
|
||||||
xAtomWmStateHidden = X11::XInternAtom(xDisplay, "_NET_WM_STATE_HIDDEN", 0);
|
xAtomWmStateHidden = X11::XInternAtom(xDisplay, "_NET_WM_STATE_HIDDEN", 0);
|
||||||
xAtomWmStateMaxHorz = X11::XInternAtom(xDisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
|
xAtomWmStateMaxHorz = X11::XInternAtom(xDisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
|
||||||
xAtomWmStateMaxVert = X11::XInternAtom(xDisplay, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
|
xAtomWmStateMaxVert = X11::XInternAtom(xDisplay, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
|
||||||
@@ -1801,6 +2196,93 @@ void LinuxPlatform::Tick()
|
|||||||
window->Close(ClosingReason::User);
|
window->Close(ClosingReason::User);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((uint32)event.xclient.message_type == (uint32)xAtomXdndEnter)
|
||||||
|
{
|
||||||
|
// Drag&drop enter
|
||||||
|
X11::Window source = event.xclient.data.l[0];
|
||||||
|
xDnDVersion = (int32)(event.xclient.data.l[1] >> 24);
|
||||||
|
const char* targetTypeFiles = "text/uri-list";
|
||||||
|
if (event.xclient.data.l[1] & 1)
|
||||||
|
{
|
||||||
|
Property p = Impl::ReadProperty(xDisplay, source, XInternAtom(xDisplay, "XdndTypeList", 0));
|
||||||
|
xDnDRequested = Impl::SelectTargetFromList(xDisplay, targetTypeFiles, (X11::Atom*)p.data, p.nitems);
|
||||||
|
X11::XFree(p.data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xDnDRequested = Impl::SelectTargetFromAtoms(xDisplay, targetTypeFiles, event.xclient.data.l[2], event.xclient.data.l[3], event.xclient.data.l[4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((uint32)event.xclient.message_type == (uint32)xAtomXdndPosition)
|
||||||
|
{
|
||||||
|
// Drag&drop move
|
||||||
|
X11::XClientMessageEvent m;
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.type = ClientMessage;
|
||||||
|
m.display = event.xclient.display;
|
||||||
|
m.window = event.xclient.data.l[0];
|
||||||
|
m.message_type = xAtomXdndStatus;
|
||||||
|
m.format = 32;
|
||||||
|
m.data.l[0] = event.xany.window;
|
||||||
|
m.data.l[1] = (xDnDRequested != 0);
|
||||||
|
m.data.l[2] = 0;
|
||||||
|
m.data.l[3] = 0;
|
||||||
|
m.data.l[4] = xAtomXdndActionCopy;
|
||||||
|
X11::XSendEvent(xDisplay, event.xclient.data.l[0], 0, NoEventMask, (X11::XEvent*)&m);
|
||||||
|
X11::XFlush(xDisplay);
|
||||||
|
xDndPos = Vector2((float)(event.xclient.data.l[2] >> 16), (float)(event.xclient.data.l[2] & 0xffff));
|
||||||
|
window = WindowsManager::GetByNativePtr((void*)event.xany.window);
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
LinuxDropFilesData dropData;
|
||||||
|
xDndResult = DragDropEffect::None;
|
||||||
|
if (window->_dragOver)
|
||||||
|
{
|
||||||
|
window->OnDragEnter(&dropData, xDndPos, xDndResult);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window->_dragOver = true;
|
||||||
|
window->OnDragOver(&dropData, xDndPos, xDndResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((uint32)event.xclient.message_type == (uint32)xAtomXdndLeave)
|
||||||
|
{
|
||||||
|
window = WindowsManager::GetByNativePtr((void*)event.xany.window);
|
||||||
|
if (window && window->_dragOver)
|
||||||
|
{
|
||||||
|
window->_dragOver = false;
|
||||||
|
window->OnDragLeave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((uint32)event.xclient.message_type == (uint32)xAtomXdndDrop)
|
||||||
|
{
|
||||||
|
auto w = event.xany.window;
|
||||||
|
if (xDnDRequested != 0)
|
||||||
|
{
|
||||||
|
xDndSourceWindow = event.xclient.data.l[0];
|
||||||
|
auto primary = XInternAtom(xDisplay, "PRIMARY", 0);
|
||||||
|
if (xDnDVersion >= 1)
|
||||||
|
XConvertSelection(xDisplay, xAtomXdndSelection, xDnDRequested, primary, w, event.xclient.data.l[2]);
|
||||||
|
else
|
||||||
|
XConvertSelection(xDisplay, xAtomXdndSelection, xDnDRequested, primary, w, CurrentTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
X11::XClientMessageEvent m;
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.type = ClientMessage;
|
||||||
|
m.display = event.xclient.display;
|
||||||
|
m.window = event.xclient.data.l[0];
|
||||||
|
m.message_type = xAtomXdndFinished;
|
||||||
|
m.format = 32;
|
||||||
|
m.data.l[0] = w;
|
||||||
|
m.data.l[1] = 0;
|
||||||
|
m.data.l[2] = 0;
|
||||||
|
X11::XSendEvent(xDisplay, event.xclient.data.l[0], 0, NoEventMask, (X11::XEvent*)&m);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MapNotify:
|
case MapNotify:
|
||||||
// Auto-focus shown windows
|
// Auto-focus shown windows
|
||||||
@@ -1982,6 +2464,41 @@ void LinuxPlatform::Tick()
|
|||||||
X11::XSendEvent(xDisplay, ev.requestor, 0, 0, (X11::XEvent*)&ev);
|
X11::XSendEvent(xDisplay, ev.requestor, 0, 0, (X11::XEvent*)&ev);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SelectionNotify:
|
||||||
|
if (event.xselection.target == xDnDRequested)
|
||||||
|
{
|
||||||
|
// Drag&drop
|
||||||
|
window = WindowsManager::GetByNativePtr((void*)event.xany.window);
|
||||||
|
if (window)
|
||||||
|
{
|
||||||
|
Property p = Impl::ReadProperty(xDisplay, event.xany.window, X11::XInternAtom(xDisplay, "PRIMARY", 0));
|
||||||
|
if (xDndResult != DragDropEffect::None)
|
||||||
|
{
|
||||||
|
LinuxDropFilesData dropData;
|
||||||
|
const String filesList((const char*)p.data);
|
||||||
|
filesList.Split('\n', dropData.Files);
|
||||||
|
for (auto& e : dropData.Files)
|
||||||
|
{
|
||||||
|
e.Replace(TEXT("file://"), TEXT(""));
|
||||||
|
e = e.TrimTrailing();
|
||||||
|
}
|
||||||
|
xDndResult = DragDropEffect::None;
|
||||||
|
window->OnDragDrop(&dropData, xDndPos, xDndResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
X11::XClientMessageEvent m;
|
||||||
|
memset(&m, 0, sizeof(m));
|
||||||
|
m.type = ClientMessage;
|
||||||
|
m.display = xDisplay;
|
||||||
|
m.window = xDndSourceWindow;
|
||||||
|
m.message_type = xAtomXdndFinished;
|
||||||
|
m.format = 32;
|
||||||
|
m.data.l[0] = event.xany.window;
|
||||||
|
m.data.l[1] = 1;
|
||||||
|
m.data.l[2] = xAtomXdndActionCopy;
|
||||||
|
XSendEvent(xDisplay, xDndSourceWindow, 0, NoEventMask, (X11::XEvent*)&m);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,7 +103,6 @@ LinuxWindow::LinuxWindow(const CreateWindowSettings& settings)
|
|||||||
bool Fullscreen;
|
bool Fullscreen;
|
||||||
bool AllowMinimize;
|
bool AllowMinimize;
|
||||||
bool AllowMaximize;
|
bool AllowMaximize;
|
||||||
bool AllowDragAndDrop;
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const X11::Window window = X11::XCreateWindow(
|
const X11::Window window = X11::XCreateWindow(
|
||||||
@@ -223,6 +222,15 @@ LinuxWindow::LinuxWindow(const CreateWindowSettings& settings)
|
|||||||
}
|
}
|
||||||
X11::XChangeProperty(display, window, wmState, (X11::Atom)4, 32, PropModeReplace, (unsigned char*)states, statesCount);
|
X11::XChangeProperty(display, window, wmState, (X11::Atom)4, 32, PropModeReplace, (unsigned char*)states, statesCount);
|
||||||
|
|
||||||
|
// Drag&drop support
|
||||||
|
if (settings.AllowDragAndDrop)
|
||||||
|
{
|
||||||
|
auto xdndVersion = 5;
|
||||||
|
auto xdndAware = XInternAtom(display, "XdndAware", 0);
|
||||||
|
if (xdndAware != 0)
|
||||||
|
X11::XChangeProperty(display, window, xdndAware, (X11::Atom)4, 32, PropModeReplace, (unsigned char*)&xdndVersion, 1);
|
||||||
|
}
|
||||||
|
|
||||||
// Sync
|
// Sync
|
||||||
X11::XFlush(display);
|
X11::XFlush(display);
|
||||||
X11::XSync(display, 0);
|
X11::XSync(display, 0);
|
||||||
@@ -725,12 +733,6 @@ void LinuxWindow::SetTitle(const StringView& title)
|
|||||||
_title = title;
|
_title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
DragDropEffect LinuxWindow::DoDragDrop(const StringView& data)
|
|
||||||
{
|
|
||||||
// TODO: impl drag and drop on Linux
|
|
||||||
return DragDropEffect::None;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LinuxWindow::StartTrackingMouse(bool useMouseScreenOffset)
|
void LinuxWindow::StartTrackingMouse(bool useMouseScreenOffset)
|
||||||
{
|
{
|
||||||
// TODO: impl this
|
// TODO: impl this
|
||||||
|
|||||||
@@ -13,14 +13,13 @@
|
|||||||
class LinuxWindow : public WindowBase
|
class LinuxWindow : public WindowBase
|
||||||
{
|
{
|
||||||
friend LinuxPlatform;
|
friend LinuxPlatform;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef unsigned long HandleType;
|
typedef unsigned long HandleType;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool _resizeDisabled, _focusOnMapped = false;
|
bool _resizeDisabled, _focusOnMapped = false, _dragOver = false;
|
||||||
float _opacity = 1.0f;
|
float _opacity = 1.0f;
|
||||||
HandleType _window;
|
HandleType _window;
|
||||||
|
|
||||||
|
|||||||
@@ -207,19 +207,19 @@ public:
|
|||||||
// Returns the directory name of the specified path string
|
// Returns the directory name of the specified path string
|
||||||
// @param path The path string from which to obtain the directory name
|
// @param path The path string from which to obtain the directory name
|
||||||
// @returns Directory name
|
// @returns Directory name
|
||||||
static String GetDirectoryName(const String& path);
|
static String GetDirectoryName(const StringView& path);
|
||||||
|
|
||||||
// Returns the file name and extension of the specified path string
|
// Returns the file name and extension of the specified path string
|
||||||
// @param path The path string from which to obtain the file name and extension
|
// @param path The path string from which to obtain the file name and extension
|
||||||
// @returns File name with extension
|
// @returns File name with extension
|
||||||
static String GetFileName(const String& path);
|
static String GetFileName(const StringView& path);
|
||||||
|
|
||||||
// Returns the file name without extension of the specified path string
|
// Returns the file name without extension of the specified path string
|
||||||
// @param path The path string from which to obtain the file name
|
// @param path The path string from which to obtain the file name
|
||||||
// @returns File name without extension
|
// @returns File name without extension
|
||||||
static String GetFileNameWithoutExtension(const String& path);
|
static String GetFileNameWithoutExtension(const StringView& path);
|
||||||
|
|
||||||
static String GetPathWithoutExtension(const String& path);
|
static String GetPathWithoutExtension(const StringView& path);
|
||||||
|
|
||||||
static void PathRemoveRelativeParts(String& path);
|
static void PathRemoveRelativeParts(String& path);
|
||||||
|
|
||||||
|
|||||||
@@ -318,14 +318,15 @@ void Win32Platform::Free(void* ptr)
|
|||||||
void* Win32Platform::AllocatePages(uint64 numPages, uint64 pageSize)
|
void* Win32Platform::AllocatePages(uint64 numPages, uint64 pageSize)
|
||||||
{
|
{
|
||||||
const uint64 numBytes = numPages * pageSize;
|
const uint64 numBytes = numPages * pageSize;
|
||||||
|
#if PLATFORM_UWP
|
||||||
// Use VirtualAlloc to allocate page-aligned memory
|
return VirtualAllocFromApp(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
#else
|
||||||
return VirtualAlloc(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
return VirtualAlloc(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Win32Platform::FreePages(void* ptr)
|
void Win32Platform::FreePages(void* ptr)
|
||||||
{
|
{
|
||||||
// Free page-aligned memory
|
|
||||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ bool DepthOfFieldPass::Init()
|
|||||||
_platformSupportsDoF = limits.HasCompute;
|
_platformSupportsDoF = limits.HasCompute;
|
||||||
_platformSupportsBokeh = _platformSupportsDoF && limits.HasGeometryShaders && limits.HasDrawIndirect && limits.HasAppendConsumeBuffers;
|
_platformSupportsBokeh = _platformSupportsDoF && limits.HasGeometryShaders && limits.HasDrawIndirect && limits.HasAppendConsumeBuffers;
|
||||||
|
|
||||||
|
_platformSupportsBokeh &= GPUDevice::Instance->GetRendererType() != RendererType::DirectX12; // TODO: fix bokeh crash on d3d12 (driver issue probably - started to happen recently)
|
||||||
|
|
||||||
// Create pipeline states
|
// Create pipeline states
|
||||||
if (_platformSupportsDoF)
|
if (_platformSupportsDoF)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -326,6 +326,24 @@ bool MAssembly::LoadWithImage(const String& assemblyPath)
|
|||||||
mono_debug_open_image_from_memory(assemblyImage, _debugData.Get(), _debugData.Count());
|
mono_debug_open_image_from_memory(assemblyImage, _debugData.Get(), _debugData.Count());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Hack to load debug information for Newtonsoft.Json (enable it to debug C# code of json lib)
|
||||||
|
if (assemblyPath.EndsWith(TEXT("FlaxEngine.CSharp.dll")))
|
||||||
|
{
|
||||||
|
static Array<byte> NewtonsoftJsonDebugData;
|
||||||
|
File::ReadAllBytes(StringUtils::GetDirectoryName(assemblyPath) / TEXT("Newtonsoft.Json.pdb"), NewtonsoftJsonDebugData);
|
||||||
|
if (NewtonsoftJsonDebugData.HasItems())
|
||||||
|
{
|
||||||
|
StringAnsi tmp(StringUtils::GetDirectoryName(assemblyPath) / TEXT("Newtonsoft.Json.dll"));
|
||||||
|
MonoAssembly* a = mono_assembly_open(tmp.Get(), &status);
|
||||||
|
if (a)
|
||||||
|
{
|
||||||
|
mono_debug_open_image_from_memory(mono_assembly_get_image(a), NewtonsoftJsonDebugData.Get(), NewtonsoftJsonDebugData.Count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Set state
|
// Set state
|
||||||
|
|||||||
@@ -178,13 +178,15 @@ void Script::SetupType()
|
|||||||
{
|
{
|
||||||
// Enable tick functions based on the method overriden in C# or Visual Script
|
// Enable tick functions based on the method overriden in C# or Visual Script
|
||||||
ScriptingTypeHandle typeHandle = GetTypeHandle();
|
ScriptingTypeHandle typeHandle = GetTypeHandle();
|
||||||
_tickUpdate = _tickLateUpdate = _tickFixedUpdate = 0;
|
|
||||||
while (typeHandle != Script::TypeInitializer)
|
while (typeHandle != Script::TypeInitializer)
|
||||||
{
|
{
|
||||||
auto& type = typeHandle.GetType();
|
auto& type = typeHandle.GetType();
|
||||||
|
if (type.Script.ScriptVTable)
|
||||||
|
{
|
||||||
_tickUpdate |= type.Script.ScriptVTable[8] != nullptr;
|
_tickUpdate |= type.Script.ScriptVTable[8] != nullptr;
|
||||||
_tickLateUpdate |= type.Script.ScriptVTable[9] != nullptr;
|
_tickLateUpdate |= type.Script.ScriptVTable[9] != nullptr;
|
||||||
_tickFixedUpdate |= type.Script.ScriptVTable[10] != nullptr;
|
_tickFixedUpdate |= type.Script.ScriptVTable[10] != nullptr;
|
||||||
|
}
|
||||||
typeHandle = type.GetBaseType();
|
typeHandle = type.GetBaseType();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Graphics/RenderTask.h"
|
#include "Engine/Graphics/RenderTask.h"
|
||||||
#include "Engine/Serialization/JsonTools.h"
|
#include "Engine/Serialization/JsonTools.h"
|
||||||
#include "Engine/Utilities/StringConverter.h"
|
|
||||||
#include <ThirdParty/mono-2.0/mono/metadata/mono-debug.h>
|
#include <ThirdParty/mono-2.0/mono/metadata/mono-debug.h>
|
||||||
#include <ThirdParty/mono-2.0/mono/metadata/object.h>
|
#include <ThirdParty/mono-2.0/mono/metadata/object.h>
|
||||||
|
|
||||||
|
|||||||
@@ -154,8 +154,7 @@ public:
|
|||||||
// @param length Text length
|
// @param length Text length
|
||||||
void WriteText(const char* text, int32 length)
|
void WriteText(const char* text, int32 length)
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < length; i++)
|
WriteBytes((const void*)text, sizeof(char) * length);
|
||||||
WriteChar(text[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Writes text to the stream
|
// Writes text to the stream
|
||||||
@@ -163,8 +162,7 @@ public:
|
|||||||
// @param length Text length
|
// @param length Text length
|
||||||
void WriteText(const Char* text, int32 length)
|
void WriteText(const Char* text, int32 length)
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < length; i++)
|
WriteBytes((const void*)text, sizeof(Char) * length);
|
||||||
WriteChar(text[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ namespace FlaxEngine.GUI
|
|||||||
public int GetChildIndexAt(Vector2 point)
|
public int GetChildIndexAt(Vector2 point)
|
||||||
{
|
{
|
||||||
int result = -1;
|
int result = -1;
|
||||||
for (int i = 0; i < _children.Count; i++)
|
for (int i = _children.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var child = _children[i];
|
var child = _children[i];
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ namespace FlaxEngine.GUI
|
|||||||
public Control GetChildAt(Vector2 point)
|
public Control GetChildAt(Vector2 point)
|
||||||
{
|
{
|
||||||
Control result = null;
|
Control result = null;
|
||||||
for (int i = 0; i < _children.Count; i++)
|
for (int i = _children.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var child = _children[i];
|
var child = _children[i];
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ namespace FlaxEngine.GUI
|
|||||||
throw new ArgumentNullException(nameof(isValid));
|
throw new ArgumentNullException(nameof(isValid));
|
||||||
|
|
||||||
Control result = null;
|
Control result = null;
|
||||||
for (int i = 0; i < _children.Count; i++)
|
for (int i = _children.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var child = _children[i];
|
var child = _children[i];
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ namespace FlaxEngine.GUI
|
|||||||
public Control GetChildAtRecursive(Vector2 point)
|
public Control GetChildAtRecursive(Vector2 point)
|
||||||
{
|
{
|
||||||
Control result = null;
|
Control result = null;
|
||||||
for (int i = 0; i < _children.Count; i++)
|
for (int i = _children.Count - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
var child = _children[i];
|
var child = _children[i];
|
||||||
|
|
||||||
|
|||||||
@@ -73,13 +73,18 @@ namespace FlaxEngine.GUI
|
|||||||
Vector2 locationWS = target.PointToWindow(location);
|
Vector2 locationWS = target.PointToWindow(location);
|
||||||
Vector2 locationSS = parentWin.PointToScreen(locationWS);
|
Vector2 locationSS = parentWin.PointToScreen(locationWS);
|
||||||
Vector2 screenSize = Platform.VirtualDesktopSize;
|
Vector2 screenSize = Platform.VirtualDesktopSize;
|
||||||
|
Vector2 parentWinLocationSS = parentWin.PointToScreen(Vector2.Zero);
|
||||||
|
float parentWinRightSS = parentWinLocationSS.Y + parentWin.Size.Y;
|
||||||
|
float parentWinBottomSS = parentWinLocationSS.X + parentWin.Size.X;
|
||||||
Vector2 rightBottomLocationSS = locationSS + dpiSize;
|
Vector2 rightBottomLocationSS = locationSS + dpiSize;
|
||||||
if (screenSize.Y < rightBottomLocationSS.Y)
|
|
||||||
|
// Prioritize tooltip placement within parent window, fall back to virtual desktop
|
||||||
|
if (parentWinRightSS < rightBottomLocationSS.Y || screenSize.Y < rightBottomLocationSS.Y)
|
||||||
{
|
{
|
||||||
// Direction: up
|
// Direction: up
|
||||||
locationSS.Y -= dpiSize.Y;
|
locationSS.Y -= dpiSize.Y;
|
||||||
}
|
}
|
||||||
if (screenSize.X < rightBottomLocationSS.X)
|
if (parentWinBottomSS < rightBottomLocationSS.X || screenSize.X < rightBottomLocationSS.X)
|
||||||
{
|
{
|
||||||
// Direction: left
|
// Direction: left
|
||||||
locationSS.X -= dpiSize.X;
|
locationSS.X -= dpiSize.X;
|
||||||
@@ -155,7 +160,7 @@ namespace FlaxEngine.GUI
|
|||||||
/// <param name="dt">The delta time.</param>
|
/// <param name="dt">The delta time.</param>
|
||||||
public void OnMouseOverControl(Control target, float dt)
|
public void OnMouseOverControl(Control target, float dt)
|
||||||
{
|
{
|
||||||
if (!Visible)
|
if (!Visible && _timeToPopupLeft > 0.0f)
|
||||||
{
|
{
|
||||||
_lastTarget = target;
|
_lastTarget = target;
|
||||||
_timeToPopupLeft -= dt;
|
_timeToPopupLeft -= dt;
|
||||||
|
|||||||
BIN
Source/Platforms/DotNet/Newtonsoft.Json.dll
(Stored with Git LFS)
BIN
Source/Platforms/DotNet/Newtonsoft.Json.dll
(Stored with Git LFS)
Binary file not shown.
BIN
Source/Platforms/DotNet/Newtonsoft.Json.pdb
(Stored with Git LFS)
BIN
Source/Platforms/DotNet/Newtonsoft.Json.pdb
(Stored with Git LFS)
Binary file not shown.
BIN
Source/Platforms/UWP/Binaries/Newtonsoft.Json.dll
(Stored with Git LFS)
BIN
Source/Platforms/UWP/Binaries/Newtonsoft.Json.dll
(Stored with Git LFS)
Binary file not shown.
@@ -54,6 +54,7 @@
|
|||||||
<AppxManifest Include="Package.appxmanifest">
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AppxManifest>
|
</AppxManifest>
|
||||||
|
<None Include="Game.Build.json" />
|
||||||
<None Include="WSACertificate.pfx" />
|
<None Include="WSACertificate.pfx" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>{3}
|
<ItemGroup>{3}
|
||||||
@@ -70,7 +71,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Content\**" />
|
<Content Include="Content\**" />
|
||||||
<MonoDataFiles Include="Mono\**" />
|
<MonoDataFiles Include="$(ProjectDir)Mono\**" />
|
||||||
<DataSecondary Include="DataSecondary\**" />
|
<DataSecondary Include="DataSecondary\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
BIN
Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.dll
(Stored with Git LFS)
BIN
Source/Platforms/XboxOne/Binaries/Newtonsoft.Json.dll
(Stored with Git LFS)
Binary file not shown.
@@ -54,6 +54,7 @@
|
|||||||
<AppxManifest Include="Package.appxmanifest">
|
<AppxManifest Include="Package.appxmanifest">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</AppxManifest>
|
</AppxManifest>
|
||||||
|
<None Include="Game.Build.json" />
|
||||||
<None Include="WSACertificate.pfx" />
|
<None Include="WSACertificate.pfx" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>{3}
|
<ItemGroup>{3}
|
||||||
@@ -70,7 +71,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Content\**" />
|
<Content Include="Content\**" />
|
||||||
<MonoDataFiles Include="Mono\**" />
|
<MonoDataFiles Include="$(ProjectDir)Mono\**" />
|
||||||
<DataSecondary Include="DataSecondary\**" />
|
<DataSecondary Include="DataSecondary\**" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -250,6 +250,8 @@ namespace Flax.Build.Bindings
|
|||||||
var path = GetCachePath(moduleInfo.Module, moduleOptions);
|
var path = GetCachePath(moduleInfo.Module, moduleOptions);
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
return false;
|
return false;
|
||||||
|
try
|
||||||
|
{
|
||||||
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
|
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
|
||||||
using (var reader = new BinaryReader(stream, Encoding.UTF8))
|
using (var reader = new BinaryReader(stream, Encoding.UTF8))
|
||||||
{
|
{
|
||||||
@@ -297,14 +299,13 @@ namespace Flax.Build.Bindings
|
|||||||
Namespace = moduleInfo.Namespace,
|
Namespace = moduleInfo.Namespace,
|
||||||
IsFromCache = true,
|
IsFromCache = true,
|
||||||
};
|
};
|
||||||
try
|
|
||||||
{
|
|
||||||
newModuleInfo.Read(reader);
|
newModuleInfo.Read(reader);
|
||||||
|
|
||||||
// Skip parsing and use data loaded from cache
|
// Skip parsing and use data loaded from cache
|
||||||
moduleInfo = newModuleInfo;
|
moduleInfo = newModuleInfo;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// Skip loading cache
|
// Skip loading cache
|
||||||
@@ -313,4 +314,3 @@ namespace Flax.Build.Bindings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|||||||
@@ -1225,6 +1225,7 @@ namespace Flax.Build.Bindings
|
|||||||
var paramsCount = eventInfo.Type.GenericArgs?.Count ?? 0;
|
var paramsCount = eventInfo.Type.GenericArgs?.Count ?? 0;
|
||||||
|
|
||||||
// C# event invoking wrapper (calls C# event from C++ delegate)
|
// C# event invoking wrapper (calls C# event from C++ delegate)
|
||||||
|
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
|
||||||
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MEvent.h");
|
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MEvent.h");
|
||||||
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
|
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
|
||||||
contents.Append(" ");
|
contents.Append(" ");
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ namespace Flax.Build.Platforms
|
|||||||
options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_UWP");
|
options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_UWP");
|
||||||
options.CompileEnv.PreprocessorDefinitions.Add("WINAPI_FAMILY=WINAPI_FAMILY_PC_APP");
|
options.CompileEnv.PreprocessorDefinitions.Add("WINAPI_FAMILY=WINAPI_FAMILY_PC_APP");
|
||||||
options.CompileEnv.PreprocessorDefinitions.Add("_WINRT_DLL");
|
options.CompileEnv.PreprocessorDefinitions.Add("_WINRT_DLL");
|
||||||
|
options.CompileEnv.PreprocessorDefinitions.Add("_WINDLL");
|
||||||
options.CompileEnv.PreprocessorDefinitions.Add("__WRL_NO_DEFAULT_LIB__");
|
options.CompileEnv.PreprocessorDefinitions.Add("__WRL_NO_DEFAULT_LIB__");
|
||||||
|
|
||||||
options.LinkEnv.InputLibraries.Add("WindowsApp.lib");
|
options.LinkEnv.InputLibraries.Add("WindowsApp.lib");
|
||||||
options.LinkEnv.InputLibraries.Add("dloadhelper.lib");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -680,6 +680,8 @@ namespace Flax.Build.Platforms
|
|||||||
args.Add("/WINMD");
|
args.Add("/WINMD");
|
||||||
args.Add(string.Format("/WINMDFILE:\"{0}\"", Path.ChangeExtension(outputFilePath, "winmd")));
|
args.Add(string.Format("/WINMDFILE:\"{0}\"", Path.ChangeExtension(outputFilePath, "winmd")));
|
||||||
args.Add("/APPCONTAINER");
|
args.Add("/APPCONTAINER");
|
||||||
|
if (linkEnvironment.Output == LinkerOutput.SharedLibrary)
|
||||||
|
args.Add("/DYNAMICBASE");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (linkEnvironment.LinkTimeCodeGeneration)
|
if (linkEnvironment.LinkTimeCodeGeneration)
|
||||||
@@ -937,7 +939,7 @@ namespace Flax.Build.Platforms
|
|||||||
xmlTextWriter.WriteStartElement("Properties");
|
xmlTextWriter.WriteStartElement("Properties");
|
||||||
|
|
||||||
// TODO: better logo handling
|
// TODO: better logo handling
|
||||||
var logoSrcPath = Path.Combine(Environment.CurrentDirectory, "Source", "Logo.png");
|
var logoSrcPath = Path.Combine(Globals.EngineRoot, "Source", "Logo.png");
|
||||||
var logoDstPath = Path.Combine(options.IntermediateFolder, "Logo.png");
|
var logoDstPath = Path.Combine(options.IntermediateFolder, "Logo.png");
|
||||||
if (!File.Exists(logoDstPath))
|
if (!File.Exists(logoDstPath))
|
||||||
Utilities.FileCopy(logoSrcPath, logoDstPath);
|
Utilities.FileCopy(logoSrcPath, logoDstPath);
|
||||||
|
|||||||
Reference in New Issue
Block a user