Merge branch '1.1' into 1.2

# 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:
2021-04-24 12:32:17 +02:00
43 changed files with 820 additions and 245 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
"Version": {
"Major": 1,
"Minor": 1,
"Build": 6217
"Build": 6218
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.",
@@ -43,7 +43,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
const auto uwpDataPath = platformDataPath / (isXboxOne ? TEXT("XboxOne") : TEXT("UWP")) / TEXT("Binaries");
const auto gameSettings = GameSettings::Get();
const auto platformSettings = UWPPlatformSettings::Get();
Array<byte> fileTemplate;
StringAnsi fileTemplate;
// Copy binaries
const auto binPath = data.GetGameBinariesPath();
@@ -149,12 +149,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (!FileSystem::FileExists(dstAssemblyInfoPath))
{
// Get template
if (File::ReadAllBytes(srcAssemblyInfoPath, fileTemplate))
if (File::ReadAllText(srcAssemblyInfoPath, fileTemplate))
{
data.Error(TEXT("Failed to load AssemblyInfo.cs template."));
return true;
}
fileTemplate[fileTemplate.Count() - 1] = 0;
// Write data to file
auto file = FileWriteStream::Open(dstAssemblyInfoPath);
@@ -163,7 +162,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
{
auto now = DateTime::Now();
file->WriteTextFormatted(
(char*)fileTemplate.Get()
fileTemplate.Get()
, gameSettings->ProductName.ToStringAnsi()
, gameSettings->CompanyName.ToStringAnsi()
, now.GetYear()
@@ -182,12 +181,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (!FileSystem::FileExists(dstAppPath))
{
// Get template
if (File::ReadAllBytes(srcAppPath, fileTemplate))
if (File::ReadAllText(srcAppPath, fileTemplate))
{
data.Error(TEXT("Failed to load App.cs template."));
return true;
}
fileTemplate[fileTemplate.Count() - 1] = 0;
// Write data to file
auto file = FileWriteStream::Open(dstAppPath);
@@ -195,7 +193,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (file)
{
file->WriteTextFormatted(
(char*)fileTemplate.Get()
fileTemplate.Get()
, defaultNamespace.ToStringAnsi() // {0} Default Namespace
);
hasError = file->HasError();
@@ -211,12 +209,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
const auto srcFlaxGeneratedPath = uwpDataPath / TEXT("FlaxGenerated.cs");
{
// Get template
if (File::ReadAllBytes(srcFlaxGeneratedPath, fileTemplate))
if (File::ReadAllText(srcFlaxGeneratedPath, fileTemplate))
{
data.Error(TEXT("Failed to load FlaxGenerated.cs template."));
return true;
}
fileTemplate[fileTemplate.Count() - 1] = 0;
// Prepare
StringAnsi autoRotationPreferences;
@@ -252,7 +249,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (file)
{
file->WriteTextFormatted(
(char*)fileTemplate.Get()
fileTemplate.Get()
, autoRotationPreferences.Get()
, preferredLaunchWindowingMode.Get()
);
@@ -272,12 +269,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (!FileSystem::FileExists(dstSolutionPath))
{
// Get template
if (File::ReadAllBytes(srcSolutionPath, fileTemplate))
if (File::ReadAllText(srcSolutionPath, fileTemplate))
{
data.Error(TEXT("Failed to load Solution.sln template."));
return true;
}
fileTemplate[fileTemplate.Count() - 1] = 0;
// Write data to file
auto file = FileWriteStream::Open(dstSolutionPath);
@@ -285,7 +281,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (file)
{
file->WriteTextFormatted(
(char*)fileTemplate.Get()
fileTemplate.Get()
, projectName.ToStringAnsi() // {0} Project Name
, mode // {1} Platform Mode
, projectGuid.ToStringAnsi() // {2} Project ID
@@ -305,12 +301,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
const auto srcProjectPath = uwpDataPath / TEXT("Project.csproj");
{
// Get template
if (File::ReadAllBytes(srcProjectPath, fileTemplate))
if (File::ReadAllText(srcProjectPath, fileTemplate))
{
data.Error(TEXT("Failed to load Project.csproj template."));
return true;
}
fileTemplate[fileTemplate.Count() - 1] = 0;
// Build included files data
StringBuilder filesInclude(2048);
@@ -334,7 +329,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (file)
{
file->WriteTextFormatted(
(char*)fileTemplate.Get()
fileTemplate.Get()
, projectName.ToStringAnsi() // {0} Project Name
, mode // {1} Platform Mode
, projectGuid.Get() // {2} Project ID
@@ -357,12 +352,11 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (!FileSystem::FileExists(dstManifestPath))
{
// Get template
if (File::ReadAllBytes(srcManifestPath, fileTemplate))
if (File::ReadAllText(srcManifestPath, fileTemplate))
{
data.Error(TEXT("Failed to load Package.appxmanifest template."));
return true;
}
fileTemplate[fileTemplate.Count() - 1] = 0;
// Build included files data
StringBuilder filesInclude(2048);
@@ -385,7 +379,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
if (file)
{
file->WriteTextFormatted(
(char*)fileTemplate.Get()
fileTemplate.Get()
, projectName.ToStringAnsi() // {0} Display Name
, gameSettings->CompanyName.ToStringAnsi() // {1} Company Name
, productId.ToStringAnsi() // {2} Product ID
@@ -46,10 +46,7 @@ namespace FlaxEditor.CustomEditors
if (values.HasReferenceValue)
{
var v = (IList)values.ReferenceValue;
// Get the reference value if collections are the same size
if (v != null && values.Count == v.Count)
if (values.ReferenceValue is IList v && values.Count == v.Count && v.Count > index)
{
_referenceValue = v[index];
_hasReferenceValue = true;
+4 -1
View File
@@ -150,7 +150,10 @@ namespace FlaxEditor.Options
private void Save()
{
// 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
var editorAnalyticsTrackingFile = Path.Combine(Editor.LocalCachePath, "noTracking");
@@ -26,6 +26,7 @@ namespace FlaxEditor.Viewport
/// <seealso cref="IGizmoOwner" />
public class PrefabWindowViewport : PrefabPreview, IEditorPrimitivesOwner
{
[HideInEditor]
private sealed class PrefabSpritesRenderer : MainEditorGizmoViewport.EditorSpritesRenderer
{
public PrefabWindowViewport Viewport;
+1 -1
View File
@@ -31,7 +31,7 @@ DECLARE_ENUM_OPERATORS(AssetsCacheFlags);
/// <summary>
/// Flax Game Engine assets cache container
/// </summary>
class AssetsCache
class FLAXENGINE_API AssetsCache
{
public:
@@ -41,6 +41,18 @@ bool CreateJson::Create(const StringView& path, StringAnsiView& data, StringAnsi
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;
+12
View File
@@ -27,6 +27,18 @@ bool StringView::operator!=(const String& other) const
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
{
ASSERT(startIndex >= 0 && startIndex < Length());
+14
View File
@@ -321,6 +321,20 @@ 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>
/// Retrieves substring created from characters starting from startIndex to the String end.
/// </summary>
@@ -1040,7 +1040,7 @@ void StagingManagerVulkan::Dispose()
ScopeLock lock(_locker);
#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
// Release buffers and clear memory
+12 -1
View File
@@ -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
{
for (int32 i = 0; i < Children.Count(); i++)
@@ -354,7 +360,6 @@ Actor* Actor::GetChild(const StringView& name) const
if (Children[i]->GetName() == name)
return Children[i];
}
return nullptr;
}
@@ -482,6 +487,12 @@ void Actor::SetName(const StringView& value)
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
{
CHECK_RETURN(type, nullptr);
+2 -8
View File
@@ -192,10 +192,7 @@ public:
/// </summary>
/// <param name="index">The child actor index.</param>
/// <returns>The child actor (always valid).</returns>
API_FUNCTION() FORCE_INLINE Actor* GetChild(int32 index) const
{
return Children[index];
}
API_FUNCTION() Actor* GetChild(int32 index) const;
/// <summary>
/// Gets the child actor with the given name.
@@ -266,10 +263,7 @@ public:
/// </summary>
/// <param name="index">The script index.</param>
/// <returns>The script (always valid).</returns>
API_FUNCTION() FORCE_INLINE Script* GetScript(int32 index) const
{
return Scripts[index];
}
API_FUNCTION() Script* GetScript(int32 index) const;
/// <summary>
/// Gets the script of the given type from this actor.
+3 -18
View File
@@ -65,22 +65,6 @@ void Game::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs
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)
@@ -396,9 +380,10 @@ int PlatformImpl::GetSpecialFolderPath(const SpecialFolder type, wchar_t* buffer
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
break;
case SpecialFolder::ProgramData:
path = Windows::Storage::ApplicationData::Current->RoamingFolder->Path;
break;
//case SpecialFolder::Temporary: path = Windows::Storage::ApplicationData::Current->TemporaryFolder->Path; break;
case SpecialFolder::Temporary:
//path = Windows::Storage::ApplicationData::Current->TemporaryFolder->Path;
path = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
break;
}
@@ -409,7 +394,7 @@ int PlatformImpl::GetSpecialFolderPath(const SpecialFolder type, wchar_t* buffer
if (length >= bufferLength)
length = bufferLength - 1;
const wchar_t* data = path->Data();
for (int i = 0; i<length; i++)
for (int i = 0; i < length; i++)
buffer[i] = data[i];
buffer[length] = 0;
return length;
@@ -22,9 +22,9 @@ CharacterController::CharacterController(const SpawnParams& params)
, _radius(50.0f)
, _height(150.0f)
, _minMoveDistance(0.0f)
, _upDirection(Vector3::Up)
, _isUpdatingTransform(false)
, _nonWalkableMode(CharacterController::NonWalkableModes::PreventClimbing)
, _upDirection(Vector3::Up)
, _nonWalkableMode(NonWalkableModes::PreventClimbing)
, _lastFlags(CollisionFlags::None)
{
static_assert(sizeof(_filterData) == sizeof(PxFilterData), "Invalid filter data size.");
@@ -61,7 +61,12 @@ void CharacterController::SetSlopeLimit(float value)
_slopeLimit = value;
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)
@@ -72,6 +77,11 @@ void CharacterController::SetNonWalkableMode(NonWalkableModes value)
_controller->setNonWalkableMode(static_cast<PxControllerNonWalkableMode::Enum>(value));
}
float CharacterController::GetStepOffset() const
{
return _stepOffset;
}
void CharacterController::SetStepOffset(float value)
{
if (Math::NearEqual(value, _stepOffset))
@@ -118,10 +118,7 @@ public:
/// Gets the non-walkable mode for the character controller.
/// </summary>
API_PROPERTY(Attributes="EditorOrder(215), DefaultValue(NonWalkableModes.PreventClimbing), EditorDisplay(\"Character Controller\")")
FORCE_INLINE NonWalkableModes GetNonWalkableMode() const
{
return _nonWalkableMode;
}
NonWalkableModes GetNonWalkableMode() const;
/// <summary>
/// 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 Controllers height or it will generate an error.
/// </summary>
API_PROPERTY(Attributes="EditorOrder(220), DefaultValue(30.0f), Limit(0), EditorDisplay(\"Character Controller\")")
FORCE_INLINE float GetStepOffset() const
{
return _stepOffset;
}
float GetStepOffset() const;
/// <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 Controllers height or it will generate an error.
@@ -289,7 +289,7 @@ void RemoveLongPathPrefix(const String& path, String& result)
result.Remove(2, 6);
}
String StringUtils::GetDirectoryName(const String& path)
String StringUtils::GetDirectoryName(const StringView& path)
{
const int32 lastFrontSlash = 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;
}
String StringUtils::GetFileName(const String& path)
String StringUtils::GetFileName(const StringView& path)
{
Char chr;
const int32 length = path.Length();
int32 num = length;
do
{
num--;
if (num < 0)
return path;
return String(path);
chr = path[num];
} while (chr != DirectorySeparatorChar && chr != AltDirectorySeparatorChar && chr != VolumeSeparatorChar);
return path.Substring(num + 1, length - num - 1);
}
String StringUtils::GetFileNameWithoutExtension(const String& path)
String StringUtils::GetFileNameWithoutExtension(const StringView& path)
{
String filename = GetFileName(path);
const int32 num = filename.FindLast('.');
@@ -325,14 +323,14 @@ String StringUtils::GetFileNameWithoutExtension(const String& path)
return filename;
}
String StringUtils::GetPathWithoutExtension(const String& path)
String StringUtils::GetPathWithoutExtension(const StringView& path)
{
const int32 num = path.FindLast('.');
if (num != -1)
{
return path.Substring(0, num);
}
return path;
return String(path);
}
void StringUtils::PathRemoveRelativeParts(String& path)
+554 -1
View File
@@ -20,6 +20,7 @@
#include "Engine/Platform/MessageBox.h"
#include "Engine/Platform/WindowsManager.h"
#include "Engine/Platform/Clipboard.h"
#include "Engine/Platform/IGuiData.h"
#include "Engine/Utilities/StringConverter.h"
#include "Engine/Threading/Threading.h"
#include "Engine/Engine/Engine.h"
@@ -58,6 +59,15 @@ X11::Display* xDisplay = nullptr;
X11::XIM IM = nullptr;
X11::XIC IC = nullptr;
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 xAtomWmStateHidden;
X11::Atom xAtomWmStateMaxVert;
@@ -65,6 +75,11 @@ X11::Atom xAtomWmStateMaxHorz;
X11::Atom xAtomWmWindowOpacity;
X11::Atom xAtomWmName;
X11::Atom xAtomClipboard;
X11::Atom xDnDRequested = 0;
X11::Window xDndSourceWindow = 0;
DragDropEffect xDndResult;
Vector2 xDndPos;
int32 xDnDVersion = 0;
int32 SystemDpi = 96;
X11::Cursor Cursors[(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
{
LinuxKeyboard Keyboard;
@@ -1222,6 +1244,407 @@ 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();
float startTime = lastDraw;
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 == Button1)
{
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 / 20.0f)
{
lastDraw = time;
Engine::OnDraw();
}
// Prevent dead-loop
if (time - startTime >= 10.0f)
{
break;
}
}
// Drag end
if (previousWindow != 0 && 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);
}
}
// End grabbing
X11::XChangeActivePointerGrab(xDisplay, Button1MotionMask | ButtonReleaseMask, 0, CurrentTime);
XUngrabPointer(xDisplay, CurrentTime);
return result;
}
void LinuxClipboard::Clear()
@@ -1651,7 +2074,15 @@ bool LinuxPlatform::Init()
}
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);
xAtomWmStateMaxHorz = X11::XInternAtom(xDisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", 0);
xAtomWmStateMaxVert = X11::XInternAtom(xDisplay, "_NET_WM_STATE_MAXIMIZED_VERT", 0);
@@ -1799,6 +2230,93 @@ void LinuxPlatform::Tick()
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;
case MapNotify:
// Auto-focus shown windows
@@ -1980,6 +2498,41 @@ void LinuxPlatform::Tick()
X11::XSendEvent(xDisplay, ev.requestor, 0, 0, (X11::XEvent*)&ev);
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:
break;
}
+9 -7
View File
@@ -103,7 +103,6 @@ LinuxWindow::LinuxWindow(const CreateWindowSettings& settings)
bool Fullscreen;
bool AllowMinimize;
bool AllowMaximize;
bool AllowDragAndDrop;
*/
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);
// 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
X11::XFlush(display);
X11::XSync(display, 0);
@@ -725,12 +733,6 @@ void LinuxWindow::SetTitle(const StringView& title)
_title = title;
}
DragDropEffect LinuxWindow::DoDragDrop(const StringView& data)
{
// TODO: impl drag and drop on Linux
return DragDropEffect::None;
}
void LinuxWindow::StartTrackingMouse(bool useMouseScreenOffset)
{
// TODO: impl this
+1 -2
View File
@@ -13,14 +13,13 @@
class LinuxWindow : public WindowBase
{
friend LinuxPlatform;
public:
typedef unsigned long HandleType;
private:
bool _resizeDisabled, _focusOnMapped = false;
bool _resizeDisabled, _focusOnMapped = false, _dragOver = false;
float _opacity = 1.0f;
HandleType _window;
+4 -4
View File
@@ -207,19 +207,19 @@ public:
// Returns the directory name of the specified path string
// @param path The path string from which to obtain the 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
// @param path The path string from which to obtain the file name and 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
// @param path The path string from which to obtain the file name
// @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);
@@ -318,14 +318,15 @@ void Win32Platform::Free(void* ptr)
void* Win32Platform::AllocatePages(uint64 numPages, uint64 pageSize)
{
const uint64 numBytes = numPages * pageSize;
// Use VirtualAlloc to allocate page-aligned memory
#if PLATFORM_UWP
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);
#endif
}
void Win32Platform::FreePages(void* ptr)
{
// Free page-aligned memory
VirtualFree(ptr, 0, MEM_RELEASE);
}
@@ -38,7 +38,7 @@ namespace
CriticalSection SymLocker;
bool SymInitialized = false;
bool SymModulesDirty = true;
char* SymPath = nullptr;
Array<String> SymbolsPath;
#endif
}
@@ -617,9 +617,8 @@ void WindowsPlatform::Exit()
{
SymInitialized = false;
SymCleanup(GetCurrentProcess());
free(SymPath);
SymPath = nullptr;
}
SymbolsPath.Resize(0);
SymLocker.Unlock();
#endif
@@ -1116,7 +1115,13 @@ void* WindowsPlatform::LoadLibrary(const Char* filename)
#if CRASH_LOG_ENABLE
// Refresh modules info during next stack trace collecting to have valid debug symbols information
SymLocker.Lock();
SymModulesDirty = true;
const auto folder = StringUtils::GetDirectoryName(filename);
if (!SymbolsPath.Contains(folder))
SymbolsPath.Add(folder);
if (SymInitialized)
{
SymModulesDirty = true;
}
SymLocker.Unlock();
#endif
@@ -1137,80 +1142,43 @@ Array<PlatformBase::StackFrame> WindowsPlatform::GetStackFrames(int32 skipCount,
SymInitialized = true;
// Build search path
const size_t nSymPathLen = 4096;
SymPath = (char*)malloc(nSymPathLen);
SymPath[0] = 0;
strcat_s(SymPath, nSymPathLen, ".;");
const size_t nTempLen = 1024;
char szTemp[nTempLen];
// Current directory path
if (GetCurrentDirectoryA(nTempLen, szTemp) > 0)
String symbolSearchPath;
TCHAR ModulePath[MAX_PATH] = { 0 };
if (::GetModuleFileName(::GetModuleHandle(nullptr), ModulePath, MAX_PATH))
{
szTemp[nTempLen - 1] = 0;
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
symbolSearchPath += StringUtils::GetDirectoryName(ModulePath);
symbolSearchPath += ";";
}
// Main module path
if (GetModuleFileNameA(nullptr, szTemp, nTempLen) > 0)
for (auto& path : SymbolsPath)
{
szTemp[nTempLen - 1] = 0;
for (char* p = (szTemp + strlen(szTemp) - 1); p >= szTemp; --p)
{
// Locate the rightmost path separator
if ((*p == '\\') || (*p == '/') || (*p == ':'))
{
*p = 0;
break;
}
}
if (strlen(szTemp) > 0)
{
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
}
symbolSearchPath += path;
symbolSearchPath += ";";
}
// System symbols paths
if (GetEnvironmentVariableA("_NT_SYMBOL_PATH", szTemp, nTempLen) > 0)
String _NT_SYMBOL_PATH;
if (!Platform::GetEnvironmentVariable(TEXT("_NT_SYMBOL_PATH"), _NT_SYMBOL_PATH))
{
szTemp[nTempLen - 1] = 0;
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
symbolSearchPath += _NT_SYMBOL_PATH;
symbolSearchPath += ";";
}
if (GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", szTemp, nTempLen) > 0)
{
szTemp[nTempLen - 1] = 0;
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
}
if (GetEnvironmentVariableA("SYSTEMROOT", szTemp, nTempLen) > 0)
{
szTemp[nTempLen - 1] = 0;
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
strcat_s(szTemp, nTempLen, "\\system32");
strcat_s(SymPath, nSymPathLen, szTemp);
strcat_s(SymPath, nSymPathLen, ";");
}
SymInitialize(process, SymPath, FALSE);
symbolSearchPath += Platform::GetWorkingDirectory();
symbolSearchPath += ";";
DWORD options = SymGetOptions();
options |= SYMOPT_LOAD_LINES;
options |= SYMOPT_FAIL_CRITICAL_ERRORS;
options |= SYMOPT_DEFERRED_LOADS;
options |= SYMOPT_EXACT_SYMBOLS;
SymSetOptions(options);
SymInitializeW(process, *symbolSearchPath, TRUE);
}
// Load modules
// Refresh modules if needed
if (SymModulesDirty)
{
SymModulesDirty = false;
GetModuleListPSAPI(process);
SymRefreshModuleList(process);
}
SymRefreshModuleList(process);
// Capture the context if missing
/*EXCEPTION_POINTERS exceptionPointers;
@@ -34,6 +34,8 @@ bool DepthOfFieldPass::Init()
_platformSupportsDoF = limits.HasCompute;
_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
if (_platformSupportsDoF)
{
@@ -326,6 +326,24 @@ bool MAssembly::LoadWithImage(const String& assemblyPath)
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
// Set state
+6 -4
View File
@@ -178,13 +178,15 @@ void Script::SetupType()
{
// Enable tick functions based on the method overriden in C# or Visual Script
ScriptingTypeHandle typeHandle = GetTypeHandle();
_tickUpdate = _tickLateUpdate = _tickFixedUpdate = 0;
while (typeHandle != Script::TypeInitializer)
{
auto& type = typeHandle.GetType();
_tickUpdate |= type.Script.ScriptVTable[8] != nullptr;
_tickLateUpdate |= type.Script.ScriptVTable[9] != nullptr;
_tickFixedUpdate |= type.Script.ScriptVTable[10] != nullptr;
if (type.Script.ScriptVTable)
{
_tickUpdate |= type.Script.ScriptVTable[8] != nullptr;
_tickLateUpdate |= type.Script.ScriptVTable[9] != nullptr;
_tickFixedUpdate |= type.Script.ScriptVTable[10] != nullptr;
}
typeHandle = type.GetBaseType();
}
}
-1
View File
@@ -27,7 +27,6 @@
#include "Engine/Engine/EngineService.h"
#include "Engine/Graphics/RenderTask.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/object.h>
+2 -4
View File
@@ -154,8 +154,7 @@ public:
// @param length Text length
void WriteText(const char* text, int32 length)
{
for (int32 i = 0; i < length; i++)
WriteChar(text[i]);
WriteBytes((const void*)text, sizeof(char) * length);
}
// Writes text to the stream
@@ -163,8 +162,7 @@ public:
// @param length Text length
void WriteText(const Char* text, int32 length)
{
for (int32 i = 0; i < length; i++)
WriteChar(text[i]);
WriteBytes((const void*)text, sizeof(Char) * length);
}
template<typename... Args>
+6 -11
View File
@@ -39,9 +39,6 @@ namespace FlaxEngine.GUI
/// <summary>
/// Gets a value indicating whether use progress value smoothing.
/// </summary>
/// <value>
/// <c>true</c> if use progress value smoothing; otherwise, <c>false</c>.
/// </value>
public bool UseSmoothing => !Mathf.IsZero(SmoothingScale);
/// <summary>
@@ -91,8 +88,6 @@ namespace FlaxEngine.GUI
if (!Mathf.NearEqual(value, _value))
{
_value = value;
// Check if skip smoothing
if (!UseSmoothing)
{
_current = _value;
@@ -138,22 +133,22 @@ namespace FlaxEngine.GUI
/// <inheritdoc />
public override void Update(float deltaTime)
{
bool isDeltaSlow = deltaTime > (1 / 20.0f);
// Ensure progress bar is visible
if (Visible)
{
// Value smoothing
var value = _value;
if (Mathf.Abs(_current - _value) > 0.01f)
{
// Lerp or not if running slow
float value;
bool isDeltaSlow = deltaTime > (1 / 20.0f);
if (!isDeltaSlow && UseSmoothing)
value = Mathf.Lerp(_current, _value, Mathf.Saturate(deltaTime * 5.0f * SmoothingScale));
else
value = _value;
_current = value;
}
else
{
_current = _value;
}
}
base.Update(deltaTime);
+4 -4
View File
@@ -274,7 +274,7 @@ namespace FlaxEngine.GUI
public int GetChildIndexAt(Vector2 point)
{
int result = -1;
for (int i = 0; i < _children.Count; i++)
for (int i = _children.Count - 1; i >= 0; i--)
{
var child = _children[i];
@@ -296,7 +296,7 @@ namespace FlaxEngine.GUI
public Control GetChildAt(Vector2 point)
{
Control result = null;
for (int i = 0; i < _children.Count; i++)
for (int i = _children.Count - 1; i >= 0; i--)
{
var child = _children[i];
@@ -322,7 +322,7 @@ namespace FlaxEngine.GUI
throw new ArgumentNullException(nameof(isValid));
Control result = null;
for (int i = 0; i < _children.Count; i++)
for (int i = _children.Count - 1; i >= 0; i--)
{
var child = _children[i];
@@ -344,7 +344,7 @@ namespace FlaxEngine.GUI
public Control GetChildAtRecursive(Vector2 point)
{
Control result = null;
for (int i = 0; i < _children.Count; i++)
for (int i = _children.Count - 1; i >= 0; i--)
{
var child = _children[i];
+8 -3
View File
@@ -73,13 +73,18 @@ namespace FlaxEngine.GUI
Vector2 locationWS = target.PointToWindow(location);
Vector2 locationSS = parentWin.PointToScreen(locationWS);
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;
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
locationSS.Y -= dpiSize.Y;
}
if (screenSize.X < rightBottomLocationSS.X)
if (parentWinBottomSS < rightBottomLocationSS.X || screenSize.X < rightBottomLocationSS.X)
{
// Direction: left
locationSS.X -= dpiSize.X;
@@ -155,7 +160,7 @@ namespace FlaxEngine.GUI
/// <param name="dt">The delta time.</param>
public void OnMouseOverControl(Control target, float dt)
{
if (!Visible)
if (!Visible && _timeToPopupLeft > 0.0f)
{
_lastTarget = target;
_timeToPopupLeft -= dt;
+2 -2
View File
@@ -13,5 +13,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("b8442186-4a70-7c85-704a-857c262d00f6")]
[assembly: AssemblyVersion("1.1.6217")]
[assembly: AssemblyFileVersion("1.1.6217")]
[assembly: AssemblyVersion("1.1.6218")]
[assembly: AssemblyFileVersion("1.1.6218")]
+3 -3
View File
@@ -3,11 +3,11 @@
#pragma once
#define FLAXENGINE_NAME "FlaxEngine"
#define FLAXENGINE_VERSION Version(1, 1, 6217)
#define FLAXENGINE_VERSION_TEXT "1.1.6217"
#define FLAXENGINE_VERSION Version(1, 1, 6218)
#define FLAXENGINE_VERSION_TEXT "1.1.6218"
#define FLAXENGINE_VERSION_MAJOR 1
#define FLAXENGINE_VERSION_MINOR 1
#define FLAXENGINE_VERSION_BUILD 6217
#define FLAXENGINE_VERSION_BUILD 6218
#define FLAXENGINE_COMPANY "Flax"
#define FLAXENGINE_COPYRIGHT "Copyright (c) 2012-2021 Wojciech Figat. All rights reserved."
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -54,6 +54,7 @@
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<None Include="Game.Build.json" />
<None Include="WSACertificate.pfx" />
</ItemGroup>
<ItemGroup>{3}
@@ -70,7 +71,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Content\**" />
<MonoDataFiles Include="Mono\**" />
<MonoDataFiles Include="$(ProjectDir)Mono\**" />
<DataSecondary Include="DataSecondary\**" />
</ItemGroup>
<ItemGroup>
Binary file not shown.
@@ -54,6 +54,7 @@
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<None Include="Game.Build.json" />
<None Include="WSACertificate.pfx" />
</ItemGroup>
<ItemGroup>{3}
@@ -70,7 +71,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Content\**" />
<MonoDataFiles Include="Mono\**" />
<MonoDataFiles Include="$(ProjectDir)Mono\**" />
<DataSecondary Include="DataSecondary\**" />
</ItemGroup>
<ItemGroup>
@@ -250,66 +250,66 @@ namespace Flax.Build.Bindings
var path = GetCachePath(moduleInfo.Module, moduleOptions);
if (!File.Exists(path))
return false;
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var reader = new BinaryReader(stream, Encoding.UTF8))
try
{
// Version
var version = reader.ReadInt32();
if (version != CacheVersion)
return false;
if (File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location).Ticks != reader.ReadInt64())
return false;
// Build options
if (reader.ReadString() != moduleOptions.IntermediateFolder ||
reader.ReadInt32() != (int)moduleOptions.Platform.Target ||
reader.ReadInt32() != (int)moduleOptions.Architecture ||
reader.ReadInt32() != (int)moduleOptions.Configuration)
return false;
var publicDefinitions = Read(reader, Utilities.GetEmptyArray<string>());
if (publicDefinitions.Length != moduleOptions.PublicDefinitions.Count || publicDefinitions.Any(x => !moduleOptions.PublicDefinitions.Contains(x)))
return false;
var privateDefinitions = Read(reader, Utilities.GetEmptyArray<string>());
if (privateDefinitions.Length != moduleOptions.PrivateDefinitions.Count || privateDefinitions.Any(x => !moduleOptions.PrivateDefinitions.Contains(x)))
return false;
var preprocessorDefinitions = Read(reader, Utilities.GetEmptyArray<string>());
if (preprocessorDefinitions.Length != moduleOptions.CompileEnv.PreprocessorDefinitions.Count || preprocessorDefinitions.Any(x => !moduleOptions.CompileEnv.PreprocessorDefinitions.Contains(x)))
return false;
// Header files
var headerFilesCount = reader.ReadInt32();
if (headerFilesCount != headerFiles.Count)
return false;
for (int i = 0; i < headerFilesCount; i++)
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
using (var reader = new BinaryReader(stream, Encoding.UTF8))
{
var headerFile = headerFiles[i];
if (headerFile != reader.ReadString())
// Version
var version = reader.ReadInt32();
if (version != CacheVersion)
return false;
if (File.GetLastWriteTime(headerFile).Ticks > reader.ReadInt64())
if (File.GetLastWriteTime(Assembly.GetExecutingAssembly().Location).Ticks != reader.ReadInt64())
return false;
}
// Info
var newModuleInfo = new ModuleInfo
{
Module = moduleInfo.Module,
Name = moduleInfo.Name,
Namespace = moduleInfo.Namespace,
IsFromCache = true,
};
try
{
// Build options
if (reader.ReadString() != moduleOptions.IntermediateFolder ||
reader.ReadInt32() != (int)moduleOptions.Platform.Target ||
reader.ReadInt32() != (int)moduleOptions.Architecture ||
reader.ReadInt32() != (int)moduleOptions.Configuration)
return false;
var publicDefinitions = Read(reader, Utilities.GetEmptyArray<string>());
if (publicDefinitions.Length != moduleOptions.PublicDefinitions.Count || publicDefinitions.Any(x => !moduleOptions.PublicDefinitions.Contains(x)))
return false;
var privateDefinitions = Read(reader, Utilities.GetEmptyArray<string>());
if (privateDefinitions.Length != moduleOptions.PrivateDefinitions.Count || privateDefinitions.Any(x => !moduleOptions.PrivateDefinitions.Contains(x)))
return false;
var preprocessorDefinitions = Read(reader, Utilities.GetEmptyArray<string>());
if (preprocessorDefinitions.Length != moduleOptions.CompileEnv.PreprocessorDefinitions.Count || preprocessorDefinitions.Any(x => !moduleOptions.CompileEnv.PreprocessorDefinitions.Contains(x)))
return false;
// Header files
var headerFilesCount = reader.ReadInt32();
if (headerFilesCount != headerFiles.Count)
return false;
for (int i = 0; i < headerFilesCount; i++)
{
var headerFile = headerFiles[i];
if (headerFile != reader.ReadString())
return false;
if (File.GetLastWriteTime(headerFile).Ticks > reader.ReadInt64())
return false;
}
// Info
var newModuleInfo = new ModuleInfo
{
Module = moduleInfo.Module,
Name = moduleInfo.Name,
Namespace = moduleInfo.Namespace,
IsFromCache = true,
};
newModuleInfo.Read(reader);
// Skip parsing and use data loaded from cache
moduleInfo = newModuleInfo;
return true;
}
catch
{
// Skip loading cache
return false;
}
}
catch
{
// Skip loading cache
return false;
}
}
}
@@ -1129,6 +1129,7 @@ namespace Flax.Build.Bindings
var paramsCount = eventInfo.Type.GenericArgs?.Count ?? 0;
// C# event invoking wrapper (calls C# event from C++ delegate)
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MClass.h");
CppIncludeFiles.Add("Engine/Scripting/ManagedCLR/MEvent.h");
contents.Append(" ");
if (eventInfo.IsStatic)
@@ -1251,7 +1252,13 @@ namespace Flax.Build.Bindings
if (fieldInfo.Getter != null)
GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Getter, "{0}");
if (fieldInfo.Setter != null)
GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Setter, "{0} = {1}");
{
var callFormat = "{0} = {1}";
var type = fieldInfo.Setter.Parameters[0].Type;
if (type.IsArray)
callFormat = $"auto __tmp = {{1}}; for (int32 i = 0; i < {type.ArraySize}; i++) {{0}}[i] = __tmp[i]";
GenerateCppWrapperFunction(buildData, contents, classInfo, fieldInfo.Setter, callFormat);
}
}
// Properties
@@ -623,9 +623,6 @@ namespace Flax.Build.Bindings
if (!fieldInfo.IsReadOnly)
{
if (fieldInfo.Type.IsArray)
throw new NotImplementedException("Use ReadOnly on field. TODO: add support for setter for fixed-array fields.");
fieldInfo.Setter = new FunctionInfo
{
Name = "Set" + fieldInfo.Name,
@@ -67,10 +67,10 @@ namespace Flax.Build.Platforms
options.CompileEnv.PreprocessorDefinitions.Add("PLATFORM_UWP");
options.CompileEnv.PreprocessorDefinitions.Add("WINAPI_FAMILY=WINAPI_FAMILY_PC_APP");
options.CompileEnv.PreprocessorDefinitions.Add("_WINRT_DLL");
options.CompileEnv.PreprocessorDefinitions.Add("_WINDLL");
options.CompileEnv.PreprocessorDefinitions.Add("__WRL_NO_DEFAULT_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(string.Format("/WINMDFILE:\"{0}\"", Path.ChangeExtension(outputFilePath, "winmd")));
args.Add("/APPCONTAINER");
if (linkEnvironment.Output == LinkerOutput.SharedLibrary)
args.Add("/DYNAMICBASE");
}
if (linkEnvironment.LinkTimeCodeGeneration)
@@ -937,7 +939,7 @@ namespace Flax.Build.Platforms
xmlTextWriter.WriteStartElement("Properties");
// 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");
if (!File.Exists(logoDstPath))
Utilities.FileCopy(logoSrcPath, logoDstPath);