From f6ee5123d73cb221423f0d82b3df2a78b1a8a0ba Mon Sep 17 00:00:00 2001 From: Menotdan Date: Sun, 7 May 2023 23:10:07 -0400 Subject: [PATCH 01/45] Revert "Use shorter, relative path for displaying Asset Tooltips." This reverts commit 4c906f4040880b3a77686f27289800fb6c0cb55a. Revert changes I don't want anymore, after making a new branch for the changes I've done. --- Source/Editor/Content/Items/AssetItem.cs | 4 +- Source/Editor/Content/Items/ContentFolder.cs | 9 +-- Source/Editor/Content/Items/ContentItem.cs | 14 +--- Source/Editor/Options/InterfaceOptions.cs | 7 -- Source/Editor/Utilities/Utils.cs | 76 +------------------- 5 files changed, 8 insertions(+), 102 deletions(-) diff --git a/Source/Editor/Content/Items/AssetItem.cs b/Source/Editor/Content/Items/AssetItem.cs index 120d0e416..6697ed27c 100644 --- a/Source/Editor/Content/Items/AssetItem.cs +++ b/Source/Editor/Content/Items/AssetItem.cs @@ -80,9 +80,9 @@ namespace FlaxEditor.Content /// The String Builder. protected virtual void OnBuildTooltipText(StringBuilder sb) { - sb.Append("Type: ").Append(Utilities.Utils.TranslateTypeName(TypeName)).AppendLine(); + sb.Append("Type: ").Append(TypeName).AppendLine(); sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((int)new FileInfo(Path).Length)).AppendLine(); - sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine(); + sb.Append("Path: ").Append(Path).AppendLine(); } /// diff --git a/Source/Editor/Content/Items/ContentFolder.cs b/Source/Editor/Content/Items/ContentFolder.cs index 974b813ee..cbbc15f24 100644 --- a/Source/Editor/Content/Items/ContentFolder.cs +++ b/Source/Editor/Content/Items/ContentFolder.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Text; using FlaxEditor.GUI.Drag; using FlaxEngine; using FlaxEngine.GUI; @@ -138,13 +137,7 @@ namespace FlaxEditor.Content /// public override void UpdateTooltipText() { - string fileDescription = "Folder"; - StringBuilder sb = new StringBuilder(); - - sb.Append("Type: ").Append(fileDescription).AppendLine(); - sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine(); - - TooltipText = sb.ToString(); + TooltipText = Path; } /// diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs index b4a4caa9a..284f3f1b3 100644 --- a/Source/Editor/Content/Items/ContentItem.cs +++ b/Source/Editor/Content/Items/ContentItem.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Text; using FlaxEditor.Content.GUI; using FlaxEditor.GUI.Drag; using FlaxEngine; @@ -355,19 +353,11 @@ namespace FlaxEditor.Content } /// - /// Updates the tooltip text. + /// Updates the tooltip text text. /// public virtual void UpdateTooltipText() { - string fileExtension = System.IO.Path.GetExtension(Path); - string fileDescription = Utilities.Utils.TranslateFileExtension(fileExtension); - StringBuilder sb = new StringBuilder(); - - sb.Append("Type: ").Append(fileDescription).AppendLine(); - sb.Append("Size: ").Append(Utilities.Utils.FormatBytesCount((int)new FileInfo(Path).Length)).AppendLine(); - sb.Append("Path: ").Append(Utilities.Utils.GetAssetNamePathWithExt(Path)).AppendLine(); - - TooltipText = sb.ToString(); + TooltipText = "Path: " + Path; } /// diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index d8e30d62b..acfb7f5e8 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -134,13 +134,6 @@ namespace FlaxEditor.Options [EditorDisplay("Interface"), EditorOrder(280), Tooltip("Editor content window orientation.")] public FlaxEngine.GUI.Orientation ContentWindowOrientation { get; set; } = FlaxEngine.GUI.Orientation.Horizontal; - /// - /// Gets or sets the option to use type name translations. - /// - [DefaultValue(true)] - [EditorDisplay("Interface"), EditorOrder(290), Tooltip("Attempt to translate asset type names.")] - public bool TranslateTypeNames { get; set; } = true; - /// /// Gets or sets the timestamps prefix mode for output log messages. /// diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index 6ef5a8ea0..ade084431 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -20,8 +20,6 @@ using FlaxEditor.SceneGraph; using FlaxEditor.Scripting; using FlaxEngine; using FlaxEngine.GUI; -using FlaxEditor.Options; -using System.Linq; namespace FlaxEngine { @@ -1019,76 +1017,6 @@ namespace FlaxEditor.Utilities node.Visible = isThisVisible | isAnyChildVisible; } - /// - /// Gets the asset type, translating if possible, and if enabled in InterfaceOptions.TranslateTypes. - /// - /// The type name. - /// The translated type name. - public static string TranslateTypeName(string typeName) - { - // TODO: Surely there is a better way to get this value. - if (!Editor.Instance.Options.Options.Interface.TranslateTypeNames) - { - return typeName; - } - - string[] typeNamespaces = typeName.Split('.'); - string lastNamespace = typeNamespaces.Last(); - - // TODO: Add better handling for unconventional type names. - try - { - // Adds spaces between capital letters. - return string.Concat(lastNamespace.Select(x => Char.IsUpper(x) ? " " + x : x.ToString())).TrimStart(' '); - } catch { - return typeName; - } - } - - /// - /// Gets a description of a file from it's extension. - /// - /// The file's extension - /// The processed description. - public static string TranslateFileExtension(string fileExtension) - { - string fileDescription = ""; - switch (fileExtension) - { - case ".cs": - fileDescription = "C# Source Code"; - break; - case ".cpp": - fileDescription = "C++ Source Code"; - break; - case ".h": - fileDescription = "C++ Header File"; - break; - case ".json": - fileDescription = "JSON File"; - break; - default: - fileDescription = fileExtension; - break; - } - - return fileDescription; - } - - - /// - /// Gets the asset name relative to the project root folder (with asset file extension) - /// - /// The asset path. - /// The processed name path. - public static string GetAssetNamePathWithExt(string path) - { - var projectFolder = Globals.ProjectFolder; - if (path.StartsWith(projectFolder)) - path = path.Substring(projectFolder.Length + 1); - return path; - } - /// /// Gets the asset name relative to the project root folder (without asset file extension) /// @@ -1096,7 +1024,9 @@ namespace FlaxEditor.Utilities /// The processed name path. public static string GetAssetNamePath(string path) { - path = GetAssetNamePathWithExt(path); + var projectFolder = Globals.ProjectFolder; + if (path.StartsWith(projectFolder)) + path = path.Substring(projectFolder.Length + 1); return StringUtils.GetPathWithoutExtension(path); } From 74af2e53a8b0a16f4e1a8012ca52b62cbaf10ca9 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Mon, 8 May 2023 12:50:33 -0400 Subject: [PATCH 02/45] Add IconButton for this branch. --- Source/Engine/UI/GUI/Common/IconButton.cs | 74 +++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 Source/Engine/UI/GUI/Common/IconButton.cs diff --git a/Source/Engine/UI/GUI/Common/IconButton.cs b/Source/Engine/UI/GUI/Common/IconButton.cs new file mode 100644 index 000000000..e2652cd9f --- /dev/null +++ b/Source/Engine/UI/GUI/Common/IconButton.cs @@ -0,0 +1,74 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +using System; + +namespace FlaxEngine.GUI +{ + /// + /// Button with an icon. + /// + public class IconButton : Button + { + /// + /// The sprite rendered on the button. + /// + public SpriteHandle ButtonSprite { get; set; } + + /// + /// Whether or not to hide the border of the button. + /// + public bool HideBorder = true; + + /// + /// Initializes a new instance of the class. + /// + /// The sprite used by the button. + public IconButton(SpriteHandle buttonSprite) + : this(0, 0, buttonSprite) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Position X coordinate + /// Position Y coordinate + /// The sprite used by the button. + /// Width + /// Height + /// Whether or not to hide the border. + public IconButton(float x, float y, SpriteHandle buttonSprite, float width = 120, float height = DefaultHeight, bool hideBorder = true) + : base(x, y, width, height) + { + ButtonSprite = buttonSprite; + BackgroundBrush = new SpriteBrush(ButtonSprite); + HideBorder = hideBorder; + } + + /// + /// Initializes a new instance of the class. + /// + /// Position + /// Size + /// The sprite used by the button. + public IconButton(Float2 location, Float2 size, SpriteHandle buttonSprite) + : this(location.X, location.Y, buttonSprite, size.X, size.Y) + { + } + + /// + /// Sets the colors of the button, taking into account the field.> + /// + /// The color to use. + public override void SetColors(Color color) + { + BackgroundColor = color; + BackgroundColorSelected = color.RGBMultiplied(0.8f); + BackgroundColorHighlighted = color.RGBMultiplied(1.2f); + + BorderColor = HideBorder ? Color.Transparent : color.RGBMultiplied(0.5f); + BorderColorSelected = BorderColor; + BorderColorHighlighted = BorderColor; + } + } +} From 86d0ccb2103a140047702ff0c345062b7bde82bf Mon Sep 17 00:00:00 2001 From: Menotdan Date: Mon, 8 May 2023 12:51:34 -0400 Subject: [PATCH 03/45] Mark SetColors() virtual to override it in IconButton --- Source/Engine/UI/GUI/Common/Button.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/UI/GUI/Common/Button.cs b/Source/Engine/UI/GUI/Common/Button.cs index 0e0d29615..532523be7 100644 --- a/Source/Engine/UI/GUI/Common/Button.cs +++ b/Source/Engine/UI/GUI/Common/Button.cs @@ -195,7 +195,7 @@ namespace FlaxEngine.GUI /// Sets the button colors palette based on a given main color. /// /// The main color. - public void SetColors(Color color) + public virtual void SetColors(Color color) { BackgroundColor = color; BorderColor = color.RGBMultiplied(0.5f); From ec60c90963066254074c7c9a4eebe3298f38080c Mon Sep 17 00:00:00 2001 From: Menotdan Date: Mon, 8 May 2023 15:59:19 -0400 Subject: [PATCH 04/45] Implement basic design of the eyedropper button. --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index 8209b63cf..daf5cfa05 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -3,6 +3,7 @@ using FlaxEditor.GUI.Input; using FlaxEngine; using FlaxEngine.GUI; +using System; namespace FlaxEditor.GUI.Dialogs { @@ -25,6 +26,7 @@ namespace FlaxEditor.GUI.Dialogs { private const float ButtonsWidth = 60.0f; private const float PickerMargin = 6.0f; + private const float EyedropperMargin = 8.0f; private const float RGBAMargin = 12.0f; private const float HSVMargin = 0.0f; private const float ChannelsMargin = 4.0f; @@ -48,6 +50,7 @@ namespace FlaxEditor.GUI.Dialogs private TextBox _cHex; private Button _cCancel; private Button _cOK; + private IconButton _cEyedropper; /// /// Gets the selected color. @@ -192,10 +195,26 @@ namespace FlaxEditor.GUI.Dialogs }; _cOK.Clicked += OnSubmit; + // Eyedropper button + _cEyedropper = new IconButton(_cOK.X - EyedropperMargin, _cHex.Bottom + PickerMargin, Editor.Instance.Icons.Add64, hideBorder: false) + { + Parent = this, + }; + _cEyedropper.Clicked += OnEyedropColor; + _cEyedropper.Height = (_cValue.Bottom - _cEyedropper.Y) * 0.5f; + _cEyedropper.Width = _cEyedropper.Height; + _cEyedropper.X -= _cEyedropper.Width; + //_cEyedropper.SetColors(_cEyedropper.BackgroundColor); + // Set initial color SelectedColor = initialValue; } + private void OnEyedropColor() + { + throw new NotImplementedException(); + } + private void OnRGBAChanged() { if (_disableEvents) From c73ab05d70afd299a11f12cd52a5e4883eb780a6 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Tue, 9 May 2023 16:14:37 -0400 Subject: [PATCH 05/45] Rather odd attempt to screenshot the view --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 2 +- Source/Engine/Utilities/Screenshot.cpp | 76 +++++++++++++++++++ Source/Engine/Utilities/Screenshot.h | 8 ++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index daf5cfa05..ab3a3fa17 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -212,7 +212,7 @@ namespace FlaxEditor.GUI.Dialogs private void OnEyedropColor() { - throw new NotImplementedException(); + Editor.Log("Color: " + Screenshot.GetPixelAt(7, 6).ToString()); } private void OnRGBAChanged() diff --git a/Source/Engine/Utilities/Screenshot.cpp b/Source/Engine/Utilities/Screenshot.cpp index d67f8d123..553801e5b 100644 --- a/Source/Engine/Utilities/Screenshot.cpp +++ b/Source/Engine/Utilities/Screenshot.cpp @@ -3,6 +3,7 @@ #include "Screenshot.h" #include "Engine/Core/Log.h" #include "Engine/Core/Math/Math.h" +#include "Engine/Core/Math/Color32.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Platform/FileSystem.h" #include "Engine/Graphics/Textures/TextureData.h" @@ -129,6 +130,66 @@ void CaptureScreenshot::OnFail() ThreadPoolTask::OnFail(); } + + +/// +/// Capture screenshot helper +/// +/// +class GetPixelData : public ThreadPoolTask +{ + friend Screenshot; +private: + TextureData _data; + Color32 _color; + +public: + int32 x; + int32 y; + +public: + /// + /// Gets the texture data container. + /// + /// Texture data + FORCE_INLINE TextureData& GetData() + { + return _data; + } + + FORCE_INLINE Color32 GetColor() + { + return _color; + } + +protected: + // [ThreadPoolTask] + bool Run() override; + void OnFail() override; +}; + +bool GetPixelData::Run() +{ + LOG(Warning, "REAL"); + TextureMipData *mipData = _data.GetData(0, 0); + Array pixels; + mipData->GetPixels(pixels, _data.Width, _data.Height, _data.Format); + + _color = pixels[(y * _data.Width) + x]; + LOG(Warning, "really real"); + LOG(Warning, "Color: {0} {1} {2}", _color.R, _color.B, _color.G); + return false; +} + +void GetPixelData::OnFail() +{ + LOG(Warning, "Cannot get pixel data."); + + // Base + ThreadPoolTask::OnFail(); +} + + void Screenshot::Capture(GPUTexture* target, const StringView& path) { // Validate @@ -242,3 +303,18 @@ void Screenshot::Capture(const StringView& path) Capture(mainTask, path); } + +Color32 Screenshot::GetPixelAt(int32 x, int32 y) { + GPUSwapChain* swapChain = Engine::MainWindow->GetSwapChain(); + + auto getPixelTask = New(); + getPixelTask->x = x; + getPixelTask->y = y; + + Task* downloadTask = swapChain->DownloadDataAsync(getPixelTask->GetData()); + downloadTask->ContinueWith(getPixelTask); + downloadTask->Start(); + + //downloadTask->Wait(750); + return getPixelTask->GetColor(); +} diff --git a/Source/Engine/Utilities/Screenshot.h b/Source/Engine/Utilities/Screenshot.h index c51c34199..e2b95e748 100644 --- a/Source/Engine/Utilities/Screenshot.h +++ b/Source/Engine/Utilities/Screenshot.h @@ -39,4 +39,12 @@ API_CLASS(Static) class FLAXENGINE_API Screenshot /// /// The custom file location. Use null or empty to use default one. API_FUNCTION() static void Capture(const StringView& path = StringView::Empty); + + /// + /// Get the pixel at specified coordinates. + /// + /// The x coordinate to read. + /// The y coordinate to read. + /// The color + API_FUNCTION() static Color32 GetPixelAt(int32 x, int32 y); }; From 1ebf4d49e512b2075899cf5c8496c3849076a26a Mon Sep 17 00:00:00 2001 From: Menotdan Date: Tue, 9 May 2023 16:49:03 -0400 Subject: [PATCH 06/45] trying to get the correct window --- Source/Editor/GUI/Dialogs/ColorPickerDialog.cs | 11 ++++++++++- Source/Engine/Utilities/Screenshot.cpp | 9 +++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index ab3a3fa17..e30e9438d 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -1,6 +1,7 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using FlaxEditor.GUI.Input; +using FlaxEditor.Windows; using FlaxEngine; using FlaxEngine.GUI; using System; @@ -212,7 +213,15 @@ namespace FlaxEditor.GUI.Dialogs private void OnEyedropColor() { - Editor.Log("Color: " + Screenshot.GetPixelAt(7, 6).ToString()); + Float2 mousePosition = new Float2(0, 0); + foreach (EditorWindow window in Editor.Instance.Windows.Windows) + { + if (window.IsMouseOver) + { + mousePosition = window.RootWindow.MousePosition; + } + } + Editor.Log("Color: " + Screenshot.GetPixelAt(Mathf.FloorToInt(mousePosition.X), Mathf.FloorToInt(mousePosition.Y)).ToString()); } private void OnRGBAChanged() diff --git a/Source/Engine/Utilities/Screenshot.cpp b/Source/Engine/Utilities/Screenshot.cpp index 553801e5b..c946ef695 100644 --- a/Source/Engine/Utilities/Screenshot.cpp +++ b/Source/Engine/Utilities/Screenshot.cpp @@ -174,10 +174,11 @@ bool GetPixelData::Run() TextureMipData *mipData = _data.GetData(0, 0); Array pixels; mipData->GetPixels(pixels, _data.Width, _data.Height, _data.Format); - - _color = pixels[(y * _data.Width) + x]; - LOG(Warning, "really real"); - LOG(Warning, "Color: {0} {1} {2}", _color.R, _color.B, _color.G); + + LOG(Warning, "{0}, {1} ({2} at {3})", x, y, pixels.Count(), (y * _data.Width) + x); + //_color = pixels[(y * _data.Width) + x]; + //LOG(Warning, "really real"); + //LOG(Warning, "Color: {0} {1} {2}", _color.R, _color.B, _color.G); return false; } From 59c54db27595ab04acf2312cdf70d3e3c85dab81 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 10 May 2023 00:58:38 -0400 Subject: [PATCH 07/45] Implement C# callback for pixels finished reading --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 20 ++++++++++--------- Source/Engine/Utilities/Screenshot.cpp | 13 +++++++----- Source/Engine/Utilities/Screenshot.h | 2 ++ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index e30e9438d..53eabebb4 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -112,6 +112,9 @@ namespace FlaxEditor.GUI.Dialogs _onChanged = colorChanged; _onClosed = pickerClosed; + // Register the event for eyedropper pixels being read. + Screenshot.PixelReadDelegate += PixelDataRead; + // Selector _cSelector = new ColorSelectorWithSliders(180, 18) { @@ -211,17 +214,16 @@ namespace FlaxEditor.GUI.Dialogs SelectedColor = initialValue; } + private void PixelDataRead(Color32 pixel_color) + { + Color color = pixel_color; + Editor.Log(string.Format("Color: {0} {1} {2}", color.R, color.G, color.B)); + } + private void OnEyedropColor() { - Float2 mousePosition = new Float2(0, 0); - foreach (EditorWindow window in Editor.Instance.Windows.Windows) - { - if (window.IsMouseOver) - { - mousePosition = window.RootWindow.MousePosition; - } - } - Editor.Log("Color: " + Screenshot.GetPixelAt(Mathf.FloorToInt(mousePosition.X), Mathf.FloorToInt(mousePosition.Y)).ToString()); + Float2 mousePosition = FlaxEngine.Input.MouseScreenPosition; + Screenshot.GetPixelAt(Mathf.FloorToInt(mousePosition.X), Mathf.FloorToInt(mousePosition.Y)); } private void OnRGBAChanged() diff --git a/Source/Engine/Utilities/Screenshot.cpp b/Source/Engine/Utilities/Screenshot.cpp index c946ef695..0635180a8 100644 --- a/Source/Engine/Utilities/Screenshot.cpp +++ b/Source/Engine/Utilities/Screenshot.cpp @@ -130,7 +130,7 @@ void CaptureScreenshot::OnFail() ThreadPoolTask::OnFail(); } - +Delegate Screenshot::PixelReadDelegate; /// /// Capture screenshot helper @@ -176,9 +176,12 @@ bool GetPixelData::Run() mipData->GetPixels(pixels, _data.Width, _data.Height, _data.Format); LOG(Warning, "{0}, {1} ({2} at {3})", x, y, pixels.Count(), (y * _data.Width) + x); - //_color = pixels[(y * _data.Width) + x]; - //LOG(Warning, "really real"); - //LOG(Warning, "Color: {0} {1} {2}", _color.R, _color.B, _color.G); + _color = pixels[(y * _data.Width) + x]; + LOG(Warning, "really real"); + LOG(Warning, "Color: R: {0}, G: {1}, B: {2}", _color.R, _color.G, _color.B); + + LOG(Warning, "Bound functions: {0}", Screenshot::PixelReadDelegate.Count()); + Screenshot::PixelReadDelegate(_color); return false; } @@ -314,8 +317,8 @@ Color32 Screenshot::GetPixelAt(int32 x, int32 y) { Task* downloadTask = swapChain->DownloadDataAsync(getPixelTask->GetData()); downloadTask->ContinueWith(getPixelTask); + LOG(Warning, "Started download task. real"); downloadTask->Start(); - //downloadTask->Wait(750); return getPixelTask->GetColor(); } diff --git a/Source/Engine/Utilities/Screenshot.h b/Source/Engine/Utilities/Screenshot.h index e2b95e748..4fe497355 100644 --- a/Source/Engine/Utilities/Screenshot.h +++ b/Source/Engine/Utilities/Screenshot.h @@ -47,4 +47,6 @@ API_CLASS(Static) class FLAXENGINE_API Screenshot /// The y coordinate to read. /// The color API_FUNCTION() static Color32 GetPixelAt(int32 x, int32 y); + + API_EVENT() static Delegate PixelReadDelegate; }; From 27b6ba83a60a7a698f438ed71ea58698971a2cb6 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 10 May 2023 10:31:44 -0400 Subject: [PATCH 08/45] Added Windows Base Class for getting screen pixels and other screen-wide utilities --- Source/Engine/Platform/Windows/WindowsScreenUtils.cpp | 0 Source/Engine/Platform/Windows/WindowsScreenUtils.h | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.cpp create mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.h diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h new file mode 100644 index 000000000..4e8841525 --- /dev/null +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.h @@ -0,0 +1,5 @@ +#pragma once +class WindowsScreenUtils +{ +}; + From 873d42344bc623612f054f50a97dd422b7b7a836 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 10 May 2023 10:39:25 -0400 Subject: [PATCH 09/45] remove files as visual studio is bugging. --- Source/Engine/Platform/Windows/WindowsScreenUtils.cpp | 0 Source/Engine/Platform/Windows/WindowsScreenUtils.h | 5 ----- 2 files changed, 5 deletions(-) delete mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.cpp delete mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.h diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h deleted file mode 100644 index 4e8841525..000000000 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once -class WindowsScreenUtils -{ -}; - From 51004bbd9dd086f417a77972af79ba7bbe291055 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 10 May 2023 11:03:05 -0400 Subject: [PATCH 10/45] Learned about filter folders and now VS likes me :) --- Source/Engine/Platform/Windows/WindowsScreenUtils.cpp | 0 Source/Engine/Platform/Windows/WindowsScreenUtils.h | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.cpp create mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.h diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h new file mode 100644 index 000000000..4e8841525 --- /dev/null +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.h @@ -0,0 +1,5 @@ +#pragma once +class WindowsScreenUtils +{ +}; + From 1855ff133ec25ad68f8f482ae0eef6b19b0d7b7e Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 10 May 2023 12:46:54 -0400 Subject: [PATCH 11/45] Tweak a few classes, add the Base classes. --- .../Engine/Platform/Base/ScreenUtilsBase.cpp | 0 Source/Engine/Platform/Base/ScreenUtilsBase.h | 0 Source/Engine/Platform/ScreenUtils.cpp | 0 Source/Engine/Platform/ScreenUtils.h | 17 ++++ .../Platform/Windows/WindowsScreenUtils.cpp | 22 ++++++ .../Platform/Windows/WindowsScreenUtils.h | 8 +- Source/Engine/Utilities/Screenshot.cpp | 79 ------------------- Source/Engine/Utilities/Screenshot.h | 10 --- 8 files changed, 45 insertions(+), 91 deletions(-) create mode 100644 Source/Engine/Platform/Base/ScreenUtilsBase.cpp create mode 100644 Source/Engine/Platform/Base/ScreenUtilsBase.h create mode 100644 Source/Engine/Platform/ScreenUtils.cpp create mode 100644 Source/Engine/Platform/ScreenUtils.h diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.h b/Source/Engine/Platform/Base/ScreenUtilsBase.h new file mode 100644 index 000000000..e69de29bb diff --git a/Source/Engine/Platform/ScreenUtils.cpp b/Source/Engine/Platform/ScreenUtils.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Source/Engine/Platform/ScreenUtils.h b/Source/Engine/Platform/ScreenUtils.h new file mode 100644 index 000000000..91192dd41 --- /dev/null +++ b/Source/Engine/Platform/ScreenUtils.h @@ -0,0 +1,17 @@ +#if PLATFORM_WINDOWS +#include "Windows/WindowsScreenUtils.h" +#elif PLATFORM_LINUX +#include "Linux/LinuxScreenUtils.h" +#elif PLATFORM_MAC +#include "Mac/MacScreenUtils.h" +#else +#error No Screen Utils For This Platform! Please ensure you are not targetting an Editor build. +#endif + +#include "Types.h" +#include "Engine/Scripting/ScriptingType.h" + +API_CLASS(Static) class FLAXENGINE_API ScreenUtils +{ + DECLARE_SCRIPTING_TYPE_NO_SPAWN(ScreenUtils); +}; diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp index e69de29bb..8f9798184 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp @@ -0,0 +1,22 @@ +#include "WindowsScreenUtils.h" +#include "Engine/Core/Math/Color32.h" +#include "Engine/Core/Math/Vector2.h" + +#include + +Color32 PlatformScreenUtils::GetPixelAt(int32 x, int32 y) { + HDC deviceContext = GetDC(NULL); + COLORREF color = GetPixel(deviceContext, x, y); + ReleaseDC(NULL, deviceContext); + + Color32 returnColor = { GetRValue(color), GetGValue(color), GetBValue(color), 255 }; + return returnColor; +} + +Int2 PlatformScreenUtils::GetScreenCursorPosition() { + POINT cursorPos; + GetCursorPos(&cursorPos); + + Int2 returnCursorPos = { cursorPos.x, cursorPos.y }; + return returnCursorPos; +} diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h index 4e8841525..690be0b88 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.h +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.h @@ -1,5 +1,9 @@ #pragma once -class WindowsScreenUtils -{ +#include "Engine/Core/Math/Color32.h" + +class PlatformScreenUtils { +public: + static Color32 GetPixelAt(int32 x, int32 y); + static Int2 GetScreenCursorPosition(); }; diff --git a/Source/Engine/Utilities/Screenshot.cpp b/Source/Engine/Utilities/Screenshot.cpp index 0635180a8..fbde8043b 100644 --- a/Source/Engine/Utilities/Screenshot.cpp +++ b/Source/Engine/Utilities/Screenshot.cpp @@ -130,70 +130,6 @@ void CaptureScreenshot::OnFail() ThreadPoolTask::OnFail(); } -Delegate Screenshot::PixelReadDelegate; - -/// -/// Capture screenshot helper -/// -/// -class GetPixelData : public ThreadPoolTask -{ - friend Screenshot; -private: - TextureData _data; - Color32 _color; - -public: - int32 x; - int32 y; - -public: - /// - /// Gets the texture data container. - /// - /// Texture data - FORCE_INLINE TextureData& GetData() - { - return _data; - } - - FORCE_INLINE Color32 GetColor() - { - return _color; - } - -protected: - // [ThreadPoolTask] - bool Run() override; - void OnFail() override; -}; - -bool GetPixelData::Run() -{ - LOG(Warning, "REAL"); - TextureMipData *mipData = _data.GetData(0, 0); - Array pixels; - mipData->GetPixels(pixels, _data.Width, _data.Height, _data.Format); - - LOG(Warning, "{0}, {1} ({2} at {3})", x, y, pixels.Count(), (y * _data.Width) + x); - _color = pixels[(y * _data.Width) + x]; - LOG(Warning, "really real"); - LOG(Warning, "Color: R: {0}, G: {1}, B: {2}", _color.R, _color.G, _color.B); - - LOG(Warning, "Bound functions: {0}", Screenshot::PixelReadDelegate.Count()); - Screenshot::PixelReadDelegate(_color); - return false; -} - -void GetPixelData::OnFail() -{ - LOG(Warning, "Cannot get pixel data."); - - // Base - ThreadPoolTask::OnFail(); -} - - void Screenshot::Capture(GPUTexture* target, const StringView& path) { // Validate @@ -307,18 +243,3 @@ void Screenshot::Capture(const StringView& path) Capture(mainTask, path); } - -Color32 Screenshot::GetPixelAt(int32 x, int32 y) { - GPUSwapChain* swapChain = Engine::MainWindow->GetSwapChain(); - - auto getPixelTask = New(); - getPixelTask->x = x; - getPixelTask->y = y; - - Task* downloadTask = swapChain->DownloadDataAsync(getPixelTask->GetData()); - downloadTask->ContinueWith(getPixelTask); - LOG(Warning, "Started download task. real"); - downloadTask->Start(); - - return getPixelTask->GetColor(); -} diff --git a/Source/Engine/Utilities/Screenshot.h b/Source/Engine/Utilities/Screenshot.h index 4fe497355..c51c34199 100644 --- a/Source/Engine/Utilities/Screenshot.h +++ b/Source/Engine/Utilities/Screenshot.h @@ -39,14 +39,4 @@ API_CLASS(Static) class FLAXENGINE_API Screenshot /// /// The custom file location. Use null or empty to use default one. API_FUNCTION() static void Capture(const StringView& path = StringView::Empty); - - /// - /// Get the pixel at specified coordinates. - /// - /// The x coordinate to read. - /// The y coordinate to read. - /// The color - API_FUNCTION() static Color32 GetPixelAt(int32 x, int32 y); - - API_EVENT() static Delegate PixelReadDelegate; }; From 2ce727d994802d1fdb7716676648ea60caf1f170 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 10 May 2023 13:34:28 -0400 Subject: [PATCH 12/45] Correctly implement the ScreenUtils class --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 28 +++++++++++------- .../Engine/Platform/Base/ScreenUtilsBase.cpp | 11 +++++++ Source/Engine/Platform/Base/ScreenUtilsBase.h | 29 +++++++++++++++++++ Source/Engine/Platform/ScreenUtils.h | 6 ---- .../Platform/Windows/WindowsScreenUtils.cpp | 8 +++-- .../Platform/Windows/WindowsScreenUtils.h | 11 +++++-- 6 files changed, 73 insertions(+), 20 deletions(-) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index 53eabebb4..8df064581 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -112,9 +112,6 @@ namespace FlaxEditor.GUI.Dialogs _onChanged = colorChanged; _onClosed = pickerClosed; - // Register the event for eyedropper pixels being read. - Screenshot.PixelReadDelegate += PixelDataRead; - // Selector _cSelector = new ColorSelectorWithSliders(180, 18) { @@ -204,7 +201,7 @@ namespace FlaxEditor.GUI.Dialogs { Parent = this, }; - _cEyedropper.Clicked += OnEyedropColor; + _cEyedropper.Clicked += OnEyedropStart; _cEyedropper.Height = (_cValue.Bottom - _cEyedropper.Y) * 0.5f; _cEyedropper.Width = _cEyedropper.Height; _cEyedropper.X -= _cEyedropper.Width; @@ -214,18 +211,21 @@ namespace FlaxEditor.GUI.Dialogs SelectedColor = initialValue; } - private void PixelDataRead(Color32 pixel_color) + private Color32 GetEyedropColor() { - Color color = pixel_color; - Editor.Log(string.Format("Color: {0} {1} {2}", color.R, color.G, color.B)); + Int2 mousePosition = ScreenUtils.GetScreenCursorPosition(); + Color32 pixelColor = ScreenUtils.GetPixelAt(mousePosition.X, mousePosition.Y); + + return pixelColor; } - private void OnEyedropColor() + private void OnEyedropStart() { - Float2 mousePosition = FlaxEngine.Input.MouseScreenPosition; - Screenshot.GetPixelAt(Mathf.FloorToInt(mousePosition.X), Mathf.FloorToInt(mousePosition.Y)); + Color32 pixelColor = GetEyedropColor(); + Editor.Log(string.Format("Pixel Color: ({0}, {1}, {2})", pixelColor.R, pixelColor.G, pixelColor.B)); } + private void OnRGBAChanged() { if (_disableEvents) @@ -251,6 +251,14 @@ namespace FlaxEditor.GUI.Dialogs SelectedColor = color; } + + /// + public override void Update(float deltaTime) + { + base.Update(deltaTime); + + } + /// public override void Draw() { diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp index e69de29bb..081c65bf4 100644 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp +++ b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp @@ -0,0 +1,11 @@ +#include "ScreenUtilsBase.h" +#include "Engine/Core/Math/Color32.h" +#include "Engine/Core/Math/Vector2.h" + +Color32 ScreenUtilsBase::GetPixelAt(int32 x, int32 y) { + return Color32::Black; +} + +Int2 ScreenUtilsBase::GetScreenCursorPosition() { + return { 0, 0 }; +} diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.h b/Source/Engine/Platform/Base/ScreenUtilsBase.h index e69de29bb..ddfa4f329 100644 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.h +++ b/Source/Engine/Platform/Base/ScreenUtilsBase.h @@ -0,0 +1,29 @@ +#pragma once + +#include "Engine/Core/Types/BaseTypes.h" + +API_INJECT_CODE(cpp, "#include \"Engine/Platform/ScreenUtils.h\""); + +/// +/// Platform-dependent screen utilties. +/// +API_CLASS(Static, Name = "ScreenUtils", Tag = "NativeInvokeUseName") +class FLAXENGINE_API ScreenUtilsBase +{ +public: + static struct FLAXENGINE_API ScriptingTypeInitializer TypeInitializer; + + /// + /// Gets the pixel color at the specified coordinates. + /// + /// X Coordinate to read. + /// Y Coordinate to read. + /// Pixel color at the specified coordinates. + API_FUNCTION() static Color32 GetPixelAt(int32 x, int32 y); + + /// + /// Gets the cursor position, in screen cooridnates. + /// + /// Cursor position, in screen coordinates. + API_FUNCTION() static Int2 GetScreenCursorPosition(); +}; diff --git a/Source/Engine/Platform/ScreenUtils.h b/Source/Engine/Platform/ScreenUtils.h index 91192dd41..3033d2118 100644 --- a/Source/Engine/Platform/ScreenUtils.h +++ b/Source/Engine/Platform/ScreenUtils.h @@ -9,9 +9,3 @@ #endif #include "Types.h" -#include "Engine/Scripting/ScriptingType.h" - -API_CLASS(Static) class FLAXENGINE_API ScreenUtils -{ - DECLARE_SCRIPTING_TYPE_NO_SPAWN(ScreenUtils); -}; diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp index 8f9798184..a4c4127bd 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp @@ -4,7 +4,11 @@ #include -Color32 PlatformScreenUtils::GetPixelAt(int32 x, int32 y) { +#if PLATFORM_WINDOWS +#pragma comment(lib, "Gdi32.lib") +#endif + +Color32 ScreenUtils::GetPixelAt(int32 x, int32 y) { HDC deviceContext = GetDC(NULL); COLORREF color = GetPixel(deviceContext, x, y); ReleaseDC(NULL, deviceContext); @@ -13,7 +17,7 @@ Color32 PlatformScreenUtils::GetPixelAt(int32 x, int32 y) { return returnColor; } -Int2 PlatformScreenUtils::GetScreenCursorPosition() { +Int2 ScreenUtils::GetScreenCursorPosition() { POINT cursorPos; GetCursorPos(&cursorPos); diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h index 690be0b88..8f03e033f 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.h +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.h @@ -1,9 +1,16 @@ #pragma once -#include "Engine/Core/Math/Color32.h" -class PlatformScreenUtils { +#if PLATFORM_WINDOWS + +#include "Engine/Core/Math/Color32.h" +#include "Engine/Platform/Base/ScreenUtilsBase.h" + +class FLAXENGINE_API ScreenUtils : public ScreenUtilsBase { public: + + // [ScreenUtilsBase] static Color32 GetPixelAt(int32 x, int32 y); static Int2 GetScreenCursorPosition(); }; +#endif From 4144c22dc45c001ba9093b6f7d6fb795fd7c5cc4 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 10 May 2023 13:41:24 -0400 Subject: [PATCH 13/45] Working demo of colorpicker eyedropper --- Source/Editor/GUI/Dialogs/ColorPickerDialog.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index 8df064581..1b4b8e740 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -37,6 +37,7 @@ namespace FlaxEditor.GUI.Dialogs private Color _value; private bool _disableEvents; private bool _useDynamicEditing; + private bool _activeEyedropper; private ColorValueBox.ColorPickerEvent _onChanged; private ColorValueBox.ColorPickerClosedEvent _onClosed; @@ -108,6 +109,7 @@ namespace FlaxEditor.GUI.Dialogs { _initialValue = initialValue; _useDynamicEditing = useDynamicEditing; + _activeEyedropper = false; _value = Color.Transparent; _onChanged = colorChanged; _onClosed = pickerClosed; @@ -221,10 +223,16 @@ namespace FlaxEditor.GUI.Dialogs private void OnEyedropStart() { - Color32 pixelColor = GetEyedropColor(); - Editor.Log(string.Format("Pixel Color: ({0}, {1}, {2})", pixelColor.R, pixelColor.G, pixelColor.B)); + _activeEyedropper = true; } + private void UpdateEyedrop() + { + Color32 pixelColor = GetEyedropColor(); + Editor.Log(string.Format("Pixel Color: ({0}, {1}, {2})", pixelColor.R, pixelColor.G, pixelColor.B)); + + SelectedColor = new Color(pixelColor.R, pixelColor.G, pixelColor.B); + } private void OnRGBAChanged() { @@ -257,6 +265,10 @@ namespace FlaxEditor.GUI.Dialogs { base.Update(deltaTime); + if (_activeEyedropper) + { + UpdateEyedrop(); + } } /// From a2d4207504b65c4abaeec97950befb0d3519f429 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 10 May 2023 19:30:58 -0400 Subject: [PATCH 14/45] Fix compile errors. --- Source/Editor/Content/Items/ContentFolder.cs | 1 + Source/Editor/Content/Items/ContentItem.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Source/Editor/Content/Items/ContentFolder.cs b/Source/Editor/Content/Items/ContentFolder.cs index a654ea697..86c374fee 100644 --- a/Source/Editor/Content/Items/ContentFolder.cs +++ b/Source/Editor/Content/Items/ContentFolder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Text; using FlaxEditor.GUI.Drag; using FlaxEngine; using FlaxEngine.GUI; diff --git a/Source/Editor/Content/Items/ContentItem.cs b/Source/Editor/Content/Items/ContentItem.cs index 60adb1caa..2a0390b30 100644 --- a/Source/Editor/Content/Items/ContentItem.cs +++ b/Source/Editor/Content/Items/ContentItem.cs @@ -2,6 +2,8 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Text; using FlaxEditor.Content.GUI; using FlaxEditor.GUI.Drag; using FlaxEngine; From f94ae3f3fd7095767f48c3c7d14b6cafedd06616 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Thu, 11 May 2023 13:20:43 -0400 Subject: [PATCH 15/45] Add mouse hook to the color picker. --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 5 ++- .../Engine/Platform/Base/ScreenUtilsBase.cpp | 3 ++ Source/Engine/Platform/Base/ScreenUtilsBase.h | 5 +++ .../Platform/Windows/WindowsScreenUtils.cpp | 41 ++++++++++++++++++- .../Platform/Windows/WindowsScreenUtils.h | 1 + 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index 1b4b8e740..c5842a41f 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -224,14 +224,15 @@ namespace FlaxEditor.GUI.Dialogs private void OnEyedropStart() { _activeEyedropper = true; + ScreenUtils.BlockAndReadMouse(); } private void UpdateEyedrop() { Color32 pixelColor = GetEyedropColor(); - Editor.Log(string.Format("Pixel Color: ({0}, {1}, {2})", pixelColor.R, pixelColor.G, pixelColor.B)); - SelectedColor = new Color(pixelColor.R, pixelColor.G, pixelColor.B); + + } private void OnRGBAChanged() diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp index 081c65bf4..7445ee4ab 100644 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp +++ b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp @@ -9,3 +9,6 @@ Color32 ScreenUtilsBase::GetPixelAt(int32 x, int32 y) { Int2 ScreenUtilsBase::GetScreenCursorPosition() { return { 0, 0 }; } + +void ScreenUtilsBase::BlockAndReadMouse() { +} diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.h b/Source/Engine/Platform/Base/ScreenUtilsBase.h index ddfa4f329..86a776fc1 100644 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.h +++ b/Source/Engine/Platform/Base/ScreenUtilsBase.h @@ -26,4 +26,9 @@ public: /// /// Cursor position, in screen coordinates. API_FUNCTION() static Int2 GetScreenCursorPosition(); + + /// + /// Blocks mouse input and runs a callback + /// + API_FUNCTION() static void BlockAndReadMouse(); }; diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp index a4c4127bd..f0ec7acf0 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp @@ -7,8 +7,10 @@ #if PLATFORM_WINDOWS #pragma comment(lib, "Gdi32.lib") #endif +#include -Color32 ScreenUtils::GetPixelAt(int32 x, int32 y) { +Color32 ScreenUtils::GetPixelAt(int32 x, int32 y) +{ HDC deviceContext = GetDC(NULL); COLORREF color = GetPixel(deviceContext, x, y); ReleaseDC(NULL, deviceContext); @@ -17,10 +19,45 @@ Color32 ScreenUtils::GetPixelAt(int32 x, int32 y) { return returnColor; } -Int2 ScreenUtils::GetScreenCursorPosition() { +Int2 ScreenUtils::GetScreenCursorPosition() +{ POINT cursorPos; GetCursorPos(&cursorPos); Int2 returnCursorPos = { cursorPos.x, cursorPos.y }; return returnCursorPos; } + +static HHOOK _mouseCallbackHook; +LRESULT CALLBACK ScreenUtilsMouseCallback( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam +) +{ + LOG(Warning, "Hell lag. {0}", GetCurrentThreadId()); + if (wParam != WM_LBUTTONDOWN) { // Return as early as possible. + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + if (nCode < 0) { + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + + if (nCode >= 0 && wParam == WM_LBUTTONDOWN) { // Now try to run our code. + LOG(Warning, "Mouse callback hit. Skipping event. (hopefully)"); + UnhookWindowsHookEx(_mouseCallbackHook); + return 1; + } +} + +void ScreenUtils::BlockAndReadMouse() +{ + _mouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, ScreenUtilsMouseCallback, NULL, NULL); + if (_mouseCallbackHook == NULL) + { + LOG(Warning, "Failed to set mouse hook."); + LOG(Warning, "Error: {0}", GetLastError()); + } +} diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h index 8f03e033f..c10179eac 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.h +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.h @@ -11,6 +11,7 @@ public: // [ScreenUtilsBase] static Color32 GetPixelAt(int32 x, int32 y); static Int2 GetScreenCursorPosition(); + static void BlockAndReadMouse(); }; #endif From 2a7a07d2fc3a623b9bd7aeea259d0031a66889a4 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Mon, 15 May 2023 20:44:18 -0400 Subject: [PATCH 16/45] Add a delegate, unfortunately it doesn't work? --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 15 +++++++--- .../Engine/Platform/Base/ScreenUtilsBase.cpp | 5 ++++ Source/Engine/Platform/Base/ScreenUtilsBase.h | 11 ++++++++ .../Platform/Windows/WindowsScreenUtils.cpp | 28 +++++++++++++++++++ .../Platform/Windows/WindowsScreenUtils.h | 8 +++++- 5 files changed, 62 insertions(+), 5 deletions(-) diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index c5842a41f..bdef28db2 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -221,18 +221,25 @@ namespace FlaxEditor.GUI.Dialogs return pixelColor; } + private void ColorPicked(Color32 colorPicked) + { + Editor.LogWarning("Ok???"); + _activeEyedropper = false; + SelectedColor = colorPicked; + ScreenUtils.PickColorDone -= ColorPicked; + } + private void OnEyedropStart() { _activeEyedropper = true; - ScreenUtils.BlockAndReadMouse(); + ScreenUtils.PickColor(); + ScreenUtils.PickColorDone += ColorPicked; } private void UpdateEyedrop() { Color32 pixelColor = GetEyedropColor(); - SelectedColor = new Color(pixelColor.R, pixelColor.G, pixelColor.B); - - + SelectedColor = pixelColor; } private void OnRGBAChanged() diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp index 7445ee4ab..833588336 100644 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp +++ b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp @@ -12,3 +12,8 @@ Int2 ScreenUtilsBase::GetScreenCursorPosition() { void ScreenUtilsBase::BlockAndReadMouse() { } + +void ScreenUtilsBase::PickColor() { +} + +Delegate ScreenUtilsBase::PickColorDone; diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.h b/Source/Engine/Platform/Base/ScreenUtilsBase.h index 86a776fc1..9a4299ad6 100644 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.h +++ b/Source/Engine/Platform/Base/ScreenUtilsBase.h @@ -1,6 +1,7 @@ #pragma once #include "Engine/Core/Types/BaseTypes.h" +#include "Engine/Core/Delegate.h" API_INJECT_CODE(cpp, "#include \"Engine/Platform/ScreenUtils.h\""); @@ -27,8 +28,18 @@ public: /// Cursor position, in screen coordinates. API_FUNCTION() static Int2 GetScreenCursorPosition(); + /// + /// Starts async color picking. Will return a color through ColorReturnCallback. + /// /// Blocks mouse input and runs a callback /// API_FUNCTION() static void BlockAndReadMouse(); + + /// + /// Called when PickColor() is finished. + /// + API_EVENT() static Delegate PickColorDone; }; diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp index f0ec7acf0..17bcfa2a8 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp @@ -1,6 +1,7 @@ #include "WindowsScreenUtils.h" #include "Engine/Core/Math/Color32.h" #include "Engine/Core/Math/Vector2.h" +#include "Engine/Core/Delegate.h" #include @@ -8,6 +9,7 @@ #pragma comment(lib, "Gdi32.lib") #endif #include +#include Color32 ScreenUtils::GetPixelAt(int32 x, int32 y) { @@ -48,8 +50,12 @@ LRESULT CALLBACK ScreenUtilsMouseCallback( if (nCode >= 0 && wParam == WM_LBUTTONDOWN) { // Now try to run our code. LOG(Warning, "Mouse callback hit. Skipping event. (hopefully)"); UnhookWindowsHookEx(_mouseCallbackHook); + + ScreenUtils::PickSelected(); return 1; } + + return CallNextHookEx(NULL, nCode, wParam, lParam); } void ScreenUtils::BlockAndReadMouse() @@ -61,3 +67,25 @@ void ScreenUtils::BlockAndReadMouse() LOG(Warning, "Error: {0}", GetLastError()); } } + +Delegate ScreenUtils::PickColorDone; + +void ScreenUtils::Test(Color32 testVal) { + LOG(Warning, "GOT IT"); +} + +void ScreenUtils::PickSelected() { + // Push event with color. + Int2 cursorPos = ScreenUtils::GetScreenCursorPosition(); + Color32 colorPicked = ScreenUtils::GetPixelAt(cursorPos.X, cursorPos.Y); + + LOG(Warning, "REAL: {0}", PickColorDone.Count()); + PickColorDone(colorPicked); + LOG(Warning, "FAKE"); +} + +void ScreenUtils::PickColor() +{ + MCore::AttachThread(); + BlockAndReadMouse(); +} diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h index c10179eac..d8cd1c9f7 100644 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.h +++ b/Source/Engine/Platform/Windows/WindowsScreenUtils.h @@ -2,8 +2,8 @@ #if PLATFORM_WINDOWS -#include "Engine/Core/Math/Color32.h" #include "Engine/Platform/Base/ScreenUtilsBase.h" +#include "Engine/Core/Math/Color32.h" class FLAXENGINE_API ScreenUtils : public ScreenUtilsBase { public: @@ -12,6 +12,12 @@ public: static Color32 GetPixelAt(int32 x, int32 y); static Int2 GetScreenCursorPosition(); static void BlockAndReadMouse(); + static void PickColor(); + static Delegate PickColorDone; + +public: + static void PickSelected(); + static void Test(Color32 testVal); }; #endif From 5cf380386092175e0644f444283764132a9805b0 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Tue, 16 May 2023 10:50:53 -0400 Subject: [PATCH 17/45] Add ScreenUtilities class, to replace ScreenUtils in the Engine, so it is being moved to the Editor. --- .../ScreenUtilities/ScreenUtilities.h | 45 +++++++++++++++++++ .../ScreenUtilitiesWindows.cpp | 6 +++ 2 files changed, 51 insertions(+) create mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h create mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h new file mode 100644 index 000000000..468934b63 --- /dev/null +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h @@ -0,0 +1,45 @@ +#pragma once + +#include "Engine/Core/Types/BaseTypes.h" +#include "Engine/Core/Delegate.h" + +API_INJECT_CODE(cpp, "#include \"Editor/Utilities/ScreenUtilities/ScreenUtilities.h\""); + +/// +/// Platform-dependent screen utilties. +/// +API_CLASS(Static, Name = "ScreenUtils", Tag = "NativeInvokeUseName") +class FLAXENGINE_API ScreenUtilities +{ +public: + static struct FLAXENGINE_API ScriptingTypeInitializer TypeInitializer; + + /// + /// Gets the pixel color at the specified coordinates. + /// + /// X Coordinate to read. + /// Y Coordinate to read. + /// Pixel color at the specified coordinates. + API_FUNCTION() static Color32 GetPixelAt(int32 x, int32 y); + + /// + /// Gets the cursor position, in screen cooridnates. + /// + /// Cursor position, in screen coordinates. + API_FUNCTION() static Int2 GetScreenCursorPosition(); + + /// + /// Starts async color picking. Will return a color through ColorReturnCallback. + /// + /// Blocks mouse input and runs a callback + /// + API_FUNCTION() static void BlockAndReadMouse(); + + /// + /// Called when PickColor() is finished. + /// + API_EVENT() static Delegate PickColorDone; +}; diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp new file mode 100644 index 000000000..0ff177a70 --- /dev/null +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp @@ -0,0 +1,6 @@ +#if PLATFORM_WINDOWS + +#include "ScreenUtilities.h" + + +#endif From a8705130860b5d6314fb41c30c944238c7a6d565 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Tue, 16 May 2023 13:54:25 -0400 Subject: [PATCH 18/45] Color picker finally works, refactored the code. --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 10 +- .../ScreenUtilities/ScreenUtilities.h | 2 +- .../ScreenUtilitiesWindows.cpp | 92 +++++++++++++++++++ .../Engine/Platform/Base/ScreenUtilsBase.cpp | 19 ---- Source/Engine/Platform/Base/ScreenUtilsBase.h | 45 --------- Source/Engine/Platform/ScreenUtils.cpp | 0 Source/Engine/Platform/ScreenUtils.h | 11 --- .../Platform/Windows/WindowsScreenUtils.cpp | 91 ------------------ .../Platform/Windows/WindowsScreenUtils.h | 23 ----- 9 files changed, 98 insertions(+), 195 deletions(-) delete mode 100644 Source/Engine/Platform/Base/ScreenUtilsBase.cpp delete mode 100644 Source/Engine/Platform/Base/ScreenUtilsBase.h delete mode 100644 Source/Engine/Platform/ScreenUtils.cpp delete mode 100644 Source/Engine/Platform/ScreenUtils.h delete mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.cpp delete mode 100644 Source/Engine/Platform/Windows/WindowsScreenUtils.h diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index bdef28db2..7f24372e3 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -215,8 +215,8 @@ namespace FlaxEditor.GUI.Dialogs private Color32 GetEyedropColor() { - Int2 mousePosition = ScreenUtils.GetScreenCursorPosition(); - Color32 pixelColor = ScreenUtils.GetPixelAt(mousePosition.X, mousePosition.Y); + Int2 mousePosition = ScreenUtilities.GetScreenCursorPosition(); + Color32 pixelColor = ScreenUtilities.GetPixelAt(mousePosition.X, mousePosition.Y); return pixelColor; } @@ -226,14 +226,14 @@ namespace FlaxEditor.GUI.Dialogs Editor.LogWarning("Ok???"); _activeEyedropper = false; SelectedColor = colorPicked; - ScreenUtils.PickColorDone -= ColorPicked; + ScreenUtilities.PickColorDone -= ColorPicked; } private void OnEyedropStart() { _activeEyedropper = true; - ScreenUtils.PickColor(); - ScreenUtils.PickColorDone += ColorPicked; + ScreenUtilities.PickColor(); + ScreenUtilities.PickColorDone += ColorPicked; } private void UpdateEyedrop() diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h index 468934b63..34d6d49da 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h @@ -8,7 +8,7 @@ API_INJECT_CODE(cpp, "#include \"Editor/Utilities/ScreenUtilities/ScreenUtilitie /// /// Platform-dependent screen utilties. /// -API_CLASS(Static, Name = "ScreenUtils", Tag = "NativeInvokeUseName") +API_CLASS(Static, Name = "ScreenUtilities", Tag = "NativeInvokeUseName") class FLAXENGINE_API ScreenUtilities { public: diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp index 0ff177a70..5bc0b17cc 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp @@ -1,6 +1,98 @@ #if PLATFORM_WINDOWS #include "ScreenUtilities.h" +#include "Engine/Core/Math/Color32.h" +#include "Engine/Core/Math/Vector2.h" +#include "Engine/Core/Delegate.h" +#include "Engine/Core/Log.h" +#include "Engine/Scripting/ManagedCLR/MCore.h" + +#include + + +#pragma comment(lib, "Gdi32.lib") + + +Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) +{ + HDC deviceContext = GetDC(NULL); + COLORREF color = GetPixel(deviceContext, x, y); + ReleaseDC(NULL, deviceContext); + + Color32 returnColor = { GetRValue(color), GetGValue(color), GetBValue(color), 255 }; + return returnColor; +} + +Int2 ScreenUtilities::GetScreenCursorPosition() +{ + POINT cursorPos; + GetCursorPos(&cursorPos); + + Int2 returnCursorPos = { cursorPos.x, cursorPos.y }; + return returnCursorPos; +} + +class ScreenUtilitiesWindows +{ +public: + static void PickSelected(); +}; + +void ScreenUtilitiesWindows::PickSelected() { + // Push event with the picked color. + Int2 cursorPos = ScreenUtilities::GetScreenCursorPosition(); + Color32 colorPicked = ScreenUtilities::GetPixelAt(cursorPos.X, cursorPos.Y); + + LOG(Warning, "REAL: {0}", ScreenUtilities::PickColorDone.Count()); + ScreenUtilities::PickColorDone(colorPicked); + LOG(Warning, "FAKE"); +} + +static HHOOK _mouseCallbackHook; +LRESULT CALLBACK ScreenUtilsMouseCallback( + _In_ int nCode, + _In_ WPARAM wParam, + _In_ LPARAM lParam +) +{ + LOG(Warning, "Hell lag. {0}", GetCurrentThreadId()); + if (wParam != WM_LBUTTONDOWN) { // Return as early as possible. + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + if (nCode < 0) { + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + + if (nCode >= 0 && wParam == WM_LBUTTONDOWN) { // Now try to run our code. + LOG(Warning, "Mouse callback hit. Skipping event. (hopefully)"); + UnhookWindowsHookEx(_mouseCallbackHook); + + ScreenUtilitiesWindows::PickSelected(); + return 1; + } + + return CallNextHookEx(NULL, nCode, wParam, lParam); +} + +void ScreenUtilities::BlockAndReadMouse() +{ + _mouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, ScreenUtilsMouseCallback, NULL, NULL); + if (_mouseCallbackHook == NULL) + { + LOG(Warning, "Failed to set mouse hook."); + LOG(Warning, "Error: {0}", GetLastError()); + } +} + +Delegate ScreenUtilities::PickColorDone; + +void ScreenUtilities::PickColor() +{ +// MCore::AttachThread(); + BlockAndReadMouse(); +} #endif diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp b/Source/Engine/Platform/Base/ScreenUtilsBase.cpp deleted file mode 100644 index 833588336..000000000 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "ScreenUtilsBase.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" - -Color32 ScreenUtilsBase::GetPixelAt(int32 x, int32 y) { - return Color32::Black; -} - -Int2 ScreenUtilsBase::GetScreenCursorPosition() { - return { 0, 0 }; -} - -void ScreenUtilsBase::BlockAndReadMouse() { -} - -void ScreenUtilsBase::PickColor() { -} - -Delegate ScreenUtilsBase::PickColorDone; diff --git a/Source/Engine/Platform/Base/ScreenUtilsBase.h b/Source/Engine/Platform/Base/ScreenUtilsBase.h deleted file mode 100644 index 9a4299ad6..000000000 --- a/Source/Engine/Platform/Base/ScreenUtilsBase.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "Engine/Core/Types/BaseTypes.h" -#include "Engine/Core/Delegate.h" - -API_INJECT_CODE(cpp, "#include \"Engine/Platform/ScreenUtils.h\""); - -/// -/// Platform-dependent screen utilties. -/// -API_CLASS(Static, Name = "ScreenUtils", Tag = "NativeInvokeUseName") -class FLAXENGINE_API ScreenUtilsBase -{ -public: - static struct FLAXENGINE_API ScriptingTypeInitializer TypeInitializer; - - /// - /// Gets the pixel color at the specified coordinates. - /// - /// X Coordinate to read. - /// Y Coordinate to read. - /// Pixel color at the specified coordinates. - API_FUNCTION() static Color32 GetPixelAt(int32 x, int32 y); - - /// - /// Gets the cursor position, in screen cooridnates. - /// - /// Cursor position, in screen coordinates. - API_FUNCTION() static Int2 GetScreenCursorPosition(); - - /// - /// Starts async color picking. Will return a color through ColorReturnCallback. - /// - /// Blocks mouse input and runs a callback - /// - API_FUNCTION() static void BlockAndReadMouse(); - - /// - /// Called when PickColor() is finished. - /// - API_EVENT() static Delegate PickColorDone; -}; diff --git a/Source/Engine/Platform/ScreenUtils.cpp b/Source/Engine/Platform/ScreenUtils.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/Source/Engine/Platform/ScreenUtils.h b/Source/Engine/Platform/ScreenUtils.h deleted file mode 100644 index 3033d2118..000000000 --- a/Source/Engine/Platform/ScreenUtils.h +++ /dev/null @@ -1,11 +0,0 @@ -#if PLATFORM_WINDOWS -#include "Windows/WindowsScreenUtils.h" -#elif PLATFORM_LINUX -#include "Linux/LinuxScreenUtils.h" -#elif PLATFORM_MAC -#include "Mac/MacScreenUtils.h" -#else -#error No Screen Utils For This Platform! Please ensure you are not targetting an Editor build. -#endif - -#include "Types.h" diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp b/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp deleted file mode 100644 index 17bcfa2a8..000000000 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include "WindowsScreenUtils.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" - -#include - -#if PLATFORM_WINDOWS -#pragma comment(lib, "Gdi32.lib") -#endif -#include -#include - -Color32 ScreenUtils::GetPixelAt(int32 x, int32 y) -{ - HDC deviceContext = GetDC(NULL); - COLORREF color = GetPixel(deviceContext, x, y); - ReleaseDC(NULL, deviceContext); - - Color32 returnColor = { GetRValue(color), GetGValue(color), GetBValue(color), 255 }; - return returnColor; -} - -Int2 ScreenUtils::GetScreenCursorPosition() -{ - POINT cursorPos; - GetCursorPos(&cursorPos); - - Int2 returnCursorPos = { cursorPos.x, cursorPos.y }; - return returnCursorPos; -} - -static HHOOK _mouseCallbackHook; -LRESULT CALLBACK ScreenUtilsMouseCallback( - _In_ int nCode, - _In_ WPARAM wParam, - _In_ LPARAM lParam -) -{ - LOG(Warning, "Hell lag. {0}", GetCurrentThreadId()); - if (wParam != WM_LBUTTONDOWN) { // Return as early as possible. - return CallNextHookEx(NULL, nCode, wParam, lParam); - } - - if (nCode < 0) { - return CallNextHookEx(NULL, nCode, wParam, lParam); - } - - - if (nCode >= 0 && wParam == WM_LBUTTONDOWN) { // Now try to run our code. - LOG(Warning, "Mouse callback hit. Skipping event. (hopefully)"); - UnhookWindowsHookEx(_mouseCallbackHook); - - ScreenUtils::PickSelected(); - return 1; - } - - return CallNextHookEx(NULL, nCode, wParam, lParam); -} - -void ScreenUtils::BlockAndReadMouse() -{ - _mouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, ScreenUtilsMouseCallback, NULL, NULL); - if (_mouseCallbackHook == NULL) - { - LOG(Warning, "Failed to set mouse hook."); - LOG(Warning, "Error: {0}", GetLastError()); - } -} - -Delegate ScreenUtils::PickColorDone; - -void ScreenUtils::Test(Color32 testVal) { - LOG(Warning, "GOT IT"); -} - -void ScreenUtils::PickSelected() { - // Push event with color. - Int2 cursorPos = ScreenUtils::GetScreenCursorPosition(); - Color32 colorPicked = ScreenUtils::GetPixelAt(cursorPos.X, cursorPos.Y); - - LOG(Warning, "REAL: {0}", PickColorDone.Count()); - PickColorDone(colorPicked); - LOG(Warning, "FAKE"); -} - -void ScreenUtils::PickColor() -{ - MCore::AttachThread(); - BlockAndReadMouse(); -} diff --git a/Source/Engine/Platform/Windows/WindowsScreenUtils.h b/Source/Engine/Platform/Windows/WindowsScreenUtils.h deleted file mode 100644 index d8cd1c9f7..000000000 --- a/Source/Engine/Platform/Windows/WindowsScreenUtils.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#if PLATFORM_WINDOWS - -#include "Engine/Platform/Base/ScreenUtilsBase.h" -#include "Engine/Core/Math/Color32.h" - -class FLAXENGINE_API ScreenUtils : public ScreenUtilsBase { -public: - - // [ScreenUtilsBase] - static Color32 GetPixelAt(int32 x, int32 y); - static Int2 GetScreenCursorPosition(); - static void BlockAndReadMouse(); - static void PickColor(); - static Delegate PickColorDone; - -public: - static void PickSelected(); - static void Test(Color32 testVal); -}; - -#endif From 7a6c1b8b86a2095d72a1ca718daca21433077dc0 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 17 May 2023 20:59:42 -0400 Subject: [PATCH 19/45] Add linux implementation definitions. --- .../ScreenUtilities/ScreenUtilitiesLinux.cpp | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp new file mode 100644 index 000000000..531255df0 --- /dev/null +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp @@ -0,0 +1,32 @@ +#if PLATFORM_LINUX + +#include "ScreenUtilities.h" +#include "Engine/Core/Math/Color32.h" +#include "Engine/Core/Math/Vector2.h" +#include "Engine/Core/Delegate.h" +#include "Engine/Core/Log.h" + +Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) +{ +} + +Int2 ScreenUtilities::GetScreenCursorPosition() +{ +} + +class ScreenUtilitiesLinux +{ +public: +}; + +void ScreenUtilities::BlockAndReadMouse() +{ +} + +Delegate ScreenUtilities::PickColorDone; + +void ScreenUtilities::PickColor() +{ +} + +#endif \ No newline at end of file From 6e6a4274889da76f45a0e78914f3a542c6301b93 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 17 May 2023 21:44:26 -0400 Subject: [PATCH 20/45] refactor the code to not include BlockAndReadMouse() as a public API_FUNCTION() --- Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h | 5 ----- .../Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp | 3 ++- .../Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h index 34d6d49da..01380e25b 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h @@ -33,11 +33,6 @@ public: /// - /// Blocks mouse input and runs a callback - /// - API_FUNCTION() static void BlockAndReadMouse(); - /// /// Called when PickColor() is finished. /// diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp index 531255df0..5e0efb2f2 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp @@ -17,9 +17,10 @@ Int2 ScreenUtilities::GetScreenCursorPosition() class ScreenUtilitiesLinux { public: + static void BlockAndReadMouse(); }; -void ScreenUtilities::BlockAndReadMouse() +void ScreenUtilitiesLinux::BlockAndReadMouse() { } diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp index 5bc0b17cc..e04d3fb77 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp @@ -36,6 +36,7 @@ class ScreenUtilitiesWindows { public: static void PickSelected(); + static void BlockAndReadMouse(); }; void ScreenUtilitiesWindows::PickSelected() { @@ -76,7 +77,7 @@ LRESULT CALLBACK ScreenUtilsMouseCallback( return CallNextHookEx(NULL, nCode, wParam, lParam); } -void ScreenUtilities::BlockAndReadMouse() +void ScreenUtilitiesWindows::BlockAndReadMouse() { _mouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, ScreenUtilsMouseCallback, NULL, NULL); if (_mouseCallbackHook == NULL) @@ -90,8 +91,7 @@ Delegate ScreenUtilities::PickColorDone; void ScreenUtilities::PickColor() { -// MCore::AttachThread(); - BlockAndReadMouse(); + ScreenUtilitiesWindows::BlockAndReadMouse(); } From d0f5d3270fcceb9cd5ca1e6d435eff2bb9ec065d Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 17 May 2023 23:16:44 -0400 Subject: [PATCH 21/45] Implement GetPixelAt and GetCursorPosition. --- .../ScreenUtilities/ScreenUtilitiesLinux.cpp | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp index 5e0efb2f2..4e81f3018 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp @@ -6,12 +6,53 @@ #include "Engine/Core/Delegate.h" #include "Engine/Core/Log.h" +#include "Engine/Platform/Linux/IncludeX11.h" + Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) { + X11::XColor color; + Color32 outputColor; + + X11::Display* display = X11::XOpenDisplay((char *) NULL); + int defaultScreen = X11::XDefaultScreen(display); + + X11::XImage* image; + image = X11::XGetImage(display, X11::XRootWindow(display, defaultScreen), x, y, 1, 1, AllPlanes, XYPixmap); + color.pixel = XGetPixel(image, 0, 0); + X11::XFree(image); + + X11::XQueryColor(display, X11::XDefaultColormap(display, defaultScreen), &color); + outputColor.R = color.red / 256; + outputColor.G = color.green / 256; + outputColor.B = color.blue / 256; + + X11::XCloseDisplay(display); + return outputColor; } Int2 ScreenUtilities::GetScreenCursorPosition() { + Int2 cursorPosition = { 0, 0 }; + X11::Display* display = X11::XOpenDisplay(NULL); + X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); + + // Buffers (Some useful, some not.) + X11::Window rootWindowBuffer; + int rootX, rootY; + int winXBuffer, winYBuffer; + uint maskBuffer; + + int gotPointer = X11::XQueryPointer(display, rootWindow, &rootWindowBuffer, &rootWindowBuffer, &rootX, &rootY, &winXBuffer, &winYBuffer, &maskBuffer); + if (!gotPointer) { + LOG(Error, "Failed to read mouse pointer (Are you using multiple displays?)"); + return cursorPosition; + } + + cursorPosition.X = rootX; + cursorPosition.Y = rootY; + + X11::XCloseDisplay(display); + return cursorPosition; } class ScreenUtilitiesLinux @@ -22,12 +63,14 @@ public: void ScreenUtilitiesLinux::BlockAndReadMouse() { + return; } Delegate ScreenUtilities::PickColorDone; void ScreenUtilities::PickColor() { + return; } #endif \ No newline at end of file From b6395cf6f1ad673cefd75ab8759e7c076bee86f2 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Wed, 17 May 2023 23:51:24 -0400 Subject: [PATCH 22/45] Trying to implement XGrabPointer... --- .../Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp index 4e81f3018..537038396 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp @@ -63,6 +63,16 @@ public: void ScreenUtilitiesLinux::BlockAndReadMouse() { + X11::Display* display = X11::XOpenDisplay(NULL); + X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); + + int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, Button1Mask, GrabModeAsync, GrabModeAsync, rootWindow, NULL, CurrentTime); + if (grabbedPointer != GrabSuccess) { + LOG(Error, "Failed to grab cursor for events."); + } + + // No idea how to proceed from here for events. + return; } From 1d079842f660adec794f2c7e1e75626fddac6b76 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Wed, 17 May 2023 23:57:23 -0400 Subject: [PATCH 23/45] Add Mac screen utilities, and removed an unneeded log. --- Source/Editor/GUI/Dialogs/ColorPickerDialog.cs | 1 - .../Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index 7f24372e3..0c81ecc51 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -223,7 +223,6 @@ namespace FlaxEditor.GUI.Dialogs private void ColorPicked(Color32 colorPicked) { - Editor.LogWarning("Ok???"); _activeEyedropper = false; SelectedColor = colorPicked; ScreenUtilities.PickColorDone -= ColorPicked; diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp new file mode 100644 index 000000000..8b816608b --- /dev/null +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp @@ -0,0 +1,7 @@ +#if PLATFORM_MAC +#include +#include + + + +#endif From 408d620b17a028df2377bafb9d85e3cb563fa563 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Thu, 18 May 2023 00:00:06 -0400 Subject: [PATCH 24/45] Removed more unneeded logs. --- .../Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp index e04d3fb77..5af695c4d 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp @@ -40,13 +40,11 @@ public: }; void ScreenUtilitiesWindows::PickSelected() { - // Push event with the picked color. Int2 cursorPos = ScreenUtilities::GetScreenCursorPosition(); Color32 colorPicked = ScreenUtilities::GetPixelAt(cursorPos.X, cursorPos.Y); - LOG(Warning, "REAL: {0}", ScreenUtilities::PickColorDone.Count()); + // Push event with the picked color. ScreenUtilities::PickColorDone(colorPicked); - LOG(Warning, "FAKE"); } static HHOOK _mouseCallbackHook; @@ -56,7 +54,6 @@ LRESULT CALLBACK ScreenUtilsMouseCallback( _In_ LPARAM lParam ) { - LOG(Warning, "Hell lag. {0}", GetCurrentThreadId()); if (wParam != WM_LBUTTONDOWN) { // Return as early as possible. return CallNextHookEx(NULL, nCode, wParam, lParam); } @@ -67,7 +64,6 @@ LRESULT CALLBACK ScreenUtilsMouseCallback( if (nCode >= 0 && wParam == WM_LBUTTONDOWN) { // Now try to run our code. - LOG(Warning, "Mouse callback hit. Skipping event. (hopefully)"); UnhookWindowsHookEx(_mouseCallbackHook); ScreenUtilitiesWindows::PickSelected(); From f5d3e30972b0b4edd3249aa5e5bbcbfecf1cdef7 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Thu, 18 May 2023 15:42:04 -0400 Subject: [PATCH 25/45] XGrabPointer doesn't seem to be doing what I want. --- .../ScreenUtilities/ScreenUtilitiesLinux.cpp | 28 +++++++++++++++---- .../Engine/Platform/Linux/LinuxPlatform.cpp | 7 +++-- Source/Engine/Platform/Linux/LinuxPlatform.h | 5 ++++ 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp index 537038396..15077f4f2 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp @@ -5,6 +5,7 @@ #include "Engine/Core/Math/Vector2.h" #include "Engine/Core/Delegate.h" #include "Engine/Core/Log.h" +#include "Engine/Platform/Linux/LinuxPlatform.h" #include "Engine/Platform/Linux/IncludeX11.h" @@ -40,7 +41,7 @@ Int2 ScreenUtilities::GetScreenCursorPosition() X11::Window rootWindowBuffer; int rootX, rootY; int winXBuffer, winYBuffer; - uint maskBuffer; + unsigned int maskBuffer; int gotPointer = X11::XQueryPointer(display, rootWindow, &rootWindowBuffer, &rootWindowBuffer, &rootX, &rootY, &winXBuffer, &winYBuffer, &maskBuffer); if (!gotPointer) { @@ -59,28 +60,43 @@ class ScreenUtilitiesLinux { public: static void BlockAndReadMouse(); + static void xEventHandler(void* event); }; +void ScreenUtilitiesLinux::xEventHandler(void* eventPtr) { + X11::XEvent* event = (X11::XEvent*) eventPtr; + + LOG(Warning, "Got event. {0}", event->type); + + if (0) { + LOG(Warning, "Got MOUSE CLICK event."); + X11::Display* display = X11::XOpenDisplay(NULL); + LOG(Warning, "Tried to ungrab pointer. {0}", X11::XUngrabPointer(display, CurrentTime)); + X11::XCloseDisplay(display); + + LinuxPlatform::xEventRecieved.Unbind(xEventHandler); // Unbind the event, we only want to handle one click event. + } +} + void ScreenUtilitiesLinux::BlockAndReadMouse() { X11::Display* display = X11::XOpenDisplay(NULL); X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); - int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, Button1Mask, GrabModeAsync, GrabModeAsync, rootWindow, NULL, CurrentTime); + int grabbedPointer = X11::XGrabPointer(display, rootWindow, 1, Button1Mask, GrabModeAsync, GrabModeAsync, rootWindow, NULL, CurrentTime); if (grabbedPointer != GrabSuccess) { LOG(Error, "Failed to grab cursor for events."); + return; } - // No idea how to proceed from here for events. - - return; + LinuxPlatform::xEventRecieved.Bind(xEventHandler); } Delegate ScreenUtilities::PickColorDone; void ScreenUtilities::PickColor() { - return; + ScreenUtilitiesLinux::BlockAndReadMouse(); } #endif \ No newline at end of file diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index 8015162ec..6de848180 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -5,6 +5,7 @@ #include "LinuxPlatform.h" #include "LinuxWindow.h" #include "LinuxInput.h" +#include "IncludeX11.h" #include "Engine/Core/Log.h" #include "Engine/Core/Types/Guid.h" #include "Engine/Core/Types/String.h" @@ -30,7 +31,6 @@ #include "Engine/Input/Input.h" #include "Engine/Input/Mouse.h" #include "Engine/Input/Keyboard.h" -#include "IncludeX11.h" #include #include #include @@ -2217,6 +2217,8 @@ void LinuxPlatform::BeforeRun() { } +Delegate LinuxPlatform::xEventRecieved; + void LinuxPlatform::Tick() { UnixPlatform::Tick(); @@ -2234,7 +2236,8 @@ void LinuxPlatform::Tick() if (X11::XFilterEvent(&event, 0)) continue; - + + xEventRecieved(&event); // Fire the event, since we recieved an event. LinuxWindow* window; switch (event.type) { diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.h b/Source/Engine/Platform/Linux/LinuxPlatform.h index 89afe9292..486674652 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.h +++ b/Source/Engine/Platform/Linux/LinuxPlatform.h @@ -33,6 +33,11 @@ public: /// The user home directory. static const String& GetHomeDirectory(); + /// + /// An event that is fired when an XEvent is recieved by Flax. + /// + static Delegate xEventRecieved; + public: // [UnixPlatform] From 8f6ceece10dd548fae88793b43b25b535d221e51 Mon Sep 17 00:00:00 2001 From: Menotdan Date: Thu, 18 May 2023 19:40:39 -0400 Subject: [PATCH 26/45] Change XGrabPointer call a bit. --- .../ScreenUtilities/ScreenUtilitiesLinux.cpp | 17 +++++++++++------ Source/Engine/Platform/Linux/LinuxPlatform.cpp | 3 ++- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp index 15077f4f2..d4734b12d 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp @@ -67,14 +67,18 @@ void ScreenUtilitiesLinux::xEventHandler(void* eventPtr) { X11::XEvent* event = (X11::XEvent*) eventPtr; LOG(Warning, "Got event. {0}", event->type); + X11::Display* display = X11::XOpenDisplay(NULL); - if (0) { + if (event->type == ButtonPress) { LOG(Warning, "Got MOUSE CLICK event."); - X11::Display* display = X11::XOpenDisplay(NULL); - LOG(Warning, "Tried to ungrab pointer. {0}", X11::XUngrabPointer(display, CurrentTime)); - X11::XCloseDisplay(display); - LinuxPlatform::xEventRecieved.Unbind(xEventHandler); // Unbind the event, we only want to handle one click event. + + X11::XUngrabPointer(display, CurrentTime); + X11::XCloseDisplay(display); + } else + { + LOG(Warning, "Got a different event.."); + X11::XCloseDisplay(display); } } @@ -83,7 +87,8 @@ void ScreenUtilitiesLinux::BlockAndReadMouse() X11::Display* display = X11::XOpenDisplay(NULL); X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); - int grabbedPointer = X11::XGrabPointer(display, rootWindow, 1, Button1Mask, GrabModeAsync, GrabModeAsync, rootWindow, NULL, CurrentTime); + X11::Cursor cursor = XCreateFontCursor(display, 130); + int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, ButtonPressMask, GrabModeAsync, GrabModeAsync, rootWindow, cursor, CurrentTime); if (grabbedPointer != GrabSuccess) { LOG(Error, "Failed to grab cursor for events."); return; diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index 6de848180..631b8d017 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -2237,7 +2237,8 @@ void LinuxPlatform::Tick() if (X11::XFilterEvent(&event, 0)) continue; - xEventRecieved(&event); // Fire the event, since we recieved an event. + xEventRecieved(&event); // Fire this event, since we recieved an event. + LinuxWindow* window; switch (event.type) { From cdee91f2580b4fe9d10fe9037a524a8c62ff30fa Mon Sep 17 00:00:00 2001 From: Menotdan Date: Thu, 18 May 2023 21:48:47 -0400 Subject: [PATCH 27/45] Color Picker FINALLY works --- .../ScreenUtilities/ScreenUtilitiesLinux.cpp | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp index d4734b12d..6dc2103d9 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp @@ -14,7 +14,7 @@ Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) X11::XColor color; Color32 outputColor; - X11::Display* display = X11::XOpenDisplay((char *) NULL); + X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); int defaultScreen = X11::XDefaultScreen(display); X11::XImage* image; @@ -27,14 +27,13 @@ Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) outputColor.G = color.green / 256; outputColor.B = color.blue / 256; - X11::XCloseDisplay(display); return outputColor; } Int2 ScreenUtilities::GetScreenCursorPosition() { Int2 cursorPosition = { 0, 0 }; - X11::Display* display = X11::XOpenDisplay(NULL); + X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); // Buffers (Some useful, some not.) @@ -45,14 +44,13 @@ Int2 ScreenUtilities::GetScreenCursorPosition() int gotPointer = X11::XQueryPointer(display, rootWindow, &rootWindowBuffer, &rootWindowBuffer, &rootX, &rootY, &winXBuffer, &winYBuffer, &maskBuffer); if (!gotPointer) { - LOG(Error, "Failed to read mouse pointer (Are you using multiple displays?)"); + LOG(Error, "Failed to find the mouse pointer (Are you using multiple displays?)"); return cursorPosition; } cursorPosition.X = rootX; cursorPosition.Y = rootY; - X11::XCloseDisplay(display); return cursorPosition; } @@ -66,34 +64,33 @@ public: void ScreenUtilitiesLinux::xEventHandler(void* eventPtr) { X11::XEvent* event = (X11::XEvent*) eventPtr; - LOG(Warning, "Got event. {0}", event->type); - X11::Display* display = X11::XOpenDisplay(NULL); + X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); if (event->type == ButtonPress) { - LOG(Warning, "Got MOUSE CLICK event."); - LinuxPlatform::xEventRecieved.Unbind(xEventHandler); // Unbind the event, we only want to handle one click event. + Int2 cursorPosition = ScreenUtilities::GetScreenCursorPosition(); + Color32 colorPicked = ScreenUtilities::GetPixelAt(cursorPosition.X, cursorPosition.Y); + ScreenUtilities::PickColorDone(colorPicked); // Run the callback for picking colors being complete. + LinuxPlatform::xEventRecieved.Unbind(xEventHandler); // Unbind the event, we only want to handle one click event X11::XUngrabPointer(display, CurrentTime); - X11::XCloseDisplay(display); - } else - { - LOG(Warning, "Got a different event.."); - X11::XCloseDisplay(display); } } void ScreenUtilitiesLinux::BlockAndReadMouse() { - X11::Display* display = X11::XOpenDisplay(NULL); + X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); X11::Cursor cursor = XCreateFontCursor(display, 130); int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, ButtonPressMask, GrabModeAsync, GrabModeAsync, rootWindow, cursor, CurrentTime); if (grabbedPointer != GrabSuccess) { LOG(Error, "Failed to grab cursor for events."); + + X11::XFreeCursor(display, cursor); return; } + X11::XFreeCursor(display, cursor); LinuxPlatform::xEventRecieved.Bind(xEventHandler); } From 8c20ba83de53338ada8fed81eb40811eb97547aa Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Thu, 18 May 2023 22:10:35 -0400 Subject: [PATCH 28/45] Lay out what needs to be implemented for Mac --- .../ScreenUtilities/ScreenUtilitiesMac.cpp | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp index 8b816608b..2a81ab301 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp @@ -2,6 +2,39 @@ #include #include +Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) +{ + // Called from C# for live updates to the color. + return { 0, 0, 0, 255 }; +} + +Int2 ScreenUtilities::GetScreenCursorPosition() +{ + // Called from C# for live updates to the color. + + return { 0, 0 }; +} + +class ScreenUtilitiesMac +{ +public: + static void BlockAndReadMouse(); +}; + +void ScreenUtilitiesMac::BlockAndReadMouse() +{ + // Maybe you don't need this if you go with NSColorSampler +} + +Delegate ScreenUtilities::PickColorDone; + +void ScreenUtilities::PickColor() +{ + // This is what C# calls to start the color picking sequence + // This should stop mouse clicks from working for one click, and that click is on the selected color + // There is a class called NSColorSample that might implement that for you, but maybe not. + // It also might just work to copy the Linux Impl since Mac uses X as well, right? +} #endif From 66f66c548182826837c1a5c768db7c7209e64415 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Fri, 19 May 2023 00:11:29 -0400 Subject: [PATCH 29/45] Whoops forgot includes. Hopefully this builds, but I don't have a mac to test so... --- Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp index 2a81ab301..ae48112ea 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp @@ -1,6 +1,9 @@ #if PLATFORM_MAC #include #include +#include "ScreenUtilities.h" +#include "Engine/Core/Types/BaseTypes.h" +#include "Engine/Core/Delegate.h" Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) { From 306cedeb3958cb2e05c22db95cf7fa1fad137569 Mon Sep 17 00:00:00 2001 From: Menotdan <32620310+Menotdan@users.noreply.github.com> Date: Fri, 19 May 2023 00:54:49 -0400 Subject: [PATCH 30/45] stopped being stupid and just copied dependencies from the other implementations. --- .../Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp index ae48112ea..f774242ce 100644 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp +++ b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp @@ -1,9 +1,12 @@ #if PLATFORM_MAC #include #include + #include "ScreenUtilities.h" -#include "Engine/Core/Types/BaseTypes.h" +#include "Engine/Core/Math/Color32.h" +#include "Engine/Core/Math/Vector2.h" #include "Engine/Core/Delegate.h" +#include "Engine/Core/Log.h" Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) { From 9572073eda3c28852c17b44710d54e92560a926a Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 26 May 2023 13:43:20 +0200 Subject: [PATCH 31/45] Add `CustomArgs` to compile and link environment in build tool for customization --- .../Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs | 6 ++++++ Source/Tools/Flax.Build/Build/NativeCpp/LinkEnvironment.cs | 6 ++++++ Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs | 2 ++ Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs | 2 ++ .../Flax.Build/Platforms/Windows/WindowsToolchainBase.cs | 2 ++ 5 files changed, 18 insertions(+) diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs b/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs index 9ca96f4fe..72d0380e4 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs @@ -157,6 +157,11 @@ namespace Flax.Build.NativeCpp /// public readonly List IncludePaths = new List(); + /// + /// The collection of custom arguments to pass to the compilator. + /// + public readonly HashSet CustomArgs = new HashSet(); + /// public object Clone() { @@ -183,6 +188,7 @@ namespace Flax.Build.NativeCpp }; clone.PreprocessorDefinitions.AddRange(PreprocessorDefinitions); clone.IncludePaths.AddRange(IncludePaths); + clone.CustomArgs.AddRange(CustomArgs); return clone; } } diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/LinkEnvironment.cs b/Source/Tools/Flax.Build/Build/NativeCpp/LinkEnvironment.cs index 34b7df03f..92f08d71f 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/LinkEnvironment.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/LinkEnvironment.cs @@ -106,6 +106,11 @@ namespace Flax.Build.NativeCpp /// public readonly List LibraryPaths = new List(); + /// + /// The collection of custom arguments to pass to the linker. + /// + public readonly HashSet CustomArgs = new HashSet(); + /// public object Clone() { @@ -127,6 +132,7 @@ namespace Flax.Build.NativeCpp clone.DocumentationFiles.AddRange(DocumentationFiles); clone.InputLibraries.AddRange(InputLibraries); clone.LibraryPaths.AddRange(LibraryPaths); + clone.CustomArgs.AddRange(CustomArgs); return clone; } } diff --git a/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs b/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs index bc6482fff..8c82d2058 100644 --- a/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs @@ -125,6 +125,7 @@ namespace Flax.Build.Platforms // Setup arguments shared by all source files var commonArgs = new List(); + commonArgs.AddRange(options.CompileEnv.CustomArgs); { commonArgs.Add("-c"); commonArgs.Add("-fmessage-length=0"); @@ -252,6 +253,7 @@ namespace Flax.Build.Platforms // Setup arguments var args = new List(); + args.AddRange(options.LinkEnv.CustomArgs); { args.Add(string.Format("-o \"{0}\"", outputFilePath)); AddArgsCommon(options, args); diff --git a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs index 16e4b62f0..17e97c274 100644 --- a/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Unix/UnixToolchain.cs @@ -315,6 +315,7 @@ namespace Flax.Build.Platforms // Setup arguments shared by all source files var commonArgs = new List(); + commonArgs.AddRange(options.CompileEnv.CustomArgs); SetupCompileCppFilesArgs(graph, options, commonArgs, outputPath); { commonArgs.Add("-c"); @@ -501,6 +502,7 @@ namespace Flax.Build.Platforms // Setup arguments var args = new List(); + args.AddRange(options.LinkEnv.CustomArgs); { args.Add(string.Format("-o \"{0}\"", outputFilePath)); diff --git a/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs b/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs index 0190050fb..9cde9ae13 100644 --- a/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs +++ b/Source/Tools/Flax.Build/Platforms/Windows/WindowsToolchainBase.cs @@ -428,6 +428,7 @@ namespace Flax.Build.Platforms // Setup arguments shared by all source files var commonArgs = new List(); + commonArgs.AddRange(options.CompileEnv.CustomArgs); SetupCompileCppFilesArgs(graph, options, commonArgs); { // Suppress Startup Banner @@ -669,6 +670,7 @@ namespace Flax.Build.Platforms // Setup arguments var args = new List(); + args.AddRange(options.LinkEnv.CustomArgs); SetupLinkFilesArgs(graph, options, args); { // Suppress startup banner From 91fdd60b072bd7d9e8c7d0d81e15c135f5c10ec2 Mon Sep 17 00:00:00 2001 From: Wiktor Kocielski Date: Fri, 26 May 2023 08:35:55 +0300 Subject: [PATCH 32/45] BytesToText -> UnitsToText --- Source/Engine/Core/Utilities.h | 39 +++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/Source/Engine/Core/Utilities.h b/Source/Engine/Core/Utilities.h index c65200077..0c7de9323 100644 --- a/Source/Engine/Core/Utilities.h +++ b/Source/Engine/Core/Utilities.h @@ -31,20 +31,43 @@ namespace Utilities return (T)round((double)value * 1000.0) / (T)1000; } + // Converts units to the best fitting human-readable denominator + // @param units Units count + // @param divider Amount of units required for the next size + // @param sizes Array with human-readable sizes to convert from + // @return The best fitting string of the units + template + String UnitsToText(T units, int32 divider, const Array& sizes) + { + if(sizes.Count() == 0) + return String::Format(TEXT("{0}"), units); + int32 i = 0; + double dblSUnits = static_cast(units); + for (; static_cast(units / static_cast(divider)) > 0; i++, units /= divider) + dblSUnits = units / static_cast(divider); + if (i >= sizes.Count()) + return String::Format(TEXT("{0}{1}"), units, sizes[0]); + return String::Format(TEXT("{0}{1}"), RoundTo2DecimalPlaces(dblSUnits), sizes[i]); + } + // Converts size of the file (in bytes) to the best fitting string // @param bytes Size of the file in bytes // @return The best fitting string of the file size template String BytesToText(T bytes) { - static const Char* sizes[] = { TEXT("B"), TEXT("KB"), TEXT("MB"), TEXT("GB"), TEXT("TB") }; - uint64 i = 0; - double dblSByte = static_cast(bytes); - for (; static_cast(bytes / 1024.0) > 0; i++, bytes /= 1024) - dblSByte = bytes / 1024.0; - if (i >= ARRAY_COUNT(sizes)) - return String::Empty; - return String::Format(TEXT("{0} {1}"), RoundTo2DecimalPlaces(dblSByte), sizes[i]); + static Array sizes = { TEXT("b"), TEXT("Kb"), TEXT("Mb"), TEXT("Gb"), TEXT("Tb"), TEXT("Pb"), TEXT("Eb"), TEXT("Zb"), TEXT("Yb") }; + return UnitsToText(bytes, 1024, sizes); + } + + // Converts hertz to the best fitting string + // @param hertz Hertz for convertion + // @return The best fitting string + template + String HertzToText(T hertz) + { + static Array sizes = { TEXT("Hz"), TEXT("KHz"), TEXT("MHz"), TEXT("GHz"), TEXT("THz"), TEXT("PHz"), TEXT("EHz"), TEXT("ZHz"), TEXT("YHz") }; + return UnitsToText(hertz, 1000, sizes); } // Returns the amount of set bits in 32-bit integer. From bdf6a114911cb7102a60d30bfb525ba362cb4f27 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Fri, 26 May 2023 19:55:11 +0300 Subject: [PATCH 33/45] Prefer high-performance discrete GPUs when enumerating adapters --- .../DirectX/DX11/GPUDeviceDX11.cpp | 64 +++++++++++++++++-- .../DirectX/DX12/GPUDeviceDX12.cpp | 44 ++++++++++++- .../DirectX/IncludeDirectXHeaders.h | 2 + .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 18 ++++-- 4 files changed, 115 insertions(+), 13 deletions(-) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index ede8ad404..1f833933a 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -114,7 +114,15 @@ GPUDevice* GPUDeviceDX11::Create() // Create DXGI factory #if PLATFORM_WINDOWS IDXGIFactory1* dxgiFactory; - HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)); + IDXGIFactory6* dxgiFactory6; + HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory6)); + if (hr == S_OK) + dxgiFactory = dxgiFactory6; + else + { + dxgiFactory6 = nullptr; + hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)); + } #else IDXGIFactory2* dxgiFactory; HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)); @@ -126,16 +134,17 @@ GPUDevice* GPUDeviceDX11::Create() } // Enumerate the DXGIFactory's adapters + int32 selectedAdapterIndex = -1; Array adapters; - IDXGIAdapter* tmpAdapter; - for (uint32 index = 0; dxgiFactory->EnumAdapters(index, &tmpAdapter) != DXGI_ERROR_NOT_FOUND; index++) + IDXGIAdapter* tempAdapter; + for (uint32 index = 0; dxgiFactory->EnumAdapters(index, &tempAdapter) != DXGI_ERROR_NOT_FOUND; index++) { GPUAdapterDX adapter; - if (tmpAdapter && TryCreateDevice(tmpAdapter, maxAllowedFeatureLevel, &adapter.MaxFeatureLevel)) + if (tempAdapter && TryCreateDevice(tempAdapter, maxAllowedFeatureLevel, &adapter.MaxFeatureLevel)) { adapter.Index = index; - VALIDATE_DIRECTX_RESULT(tmpAdapter->GetDesc(&adapter.Description)); - uint32 outputs = RenderToolsDX::CountAdapterOutputs(tmpAdapter); + VALIDATE_DIRECTX_RESULT(tempAdapter->GetDesc(&adapter.Description)); + uint32 outputs = RenderToolsDX::CountAdapterOutputs(tempAdapter); LOG(Info, "Adapter {1}: '{0}', DirectX {2}", adapter.Description.Description, index, RenderToolsDX::GetFeatureLevelString(adapter.MaxFeatureLevel)); LOG(Info, " Dedicated Video Memory: {0}, Dedicated System Memory: {1}, Shared System Memory: {2}, Output(s): {3}", Utilities::BytesToText(adapter.Description.DedicatedVideoMemory), Utilities::BytesToText(adapter.Description.DedicatedSystemMemory), Utilities::BytesToText(adapter.Description.SharedSystemMemory), outputs); @@ -143,9 +152,41 @@ GPUDevice* GPUDeviceDX11::Create() adapters.Add(adapter); } } +#if PLATFORM_WINDOWS + // Find the best performing adapter and prefer using it instead of the first device + const auto gpuPreference = DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE; + if (dxgiFactory6 != nullptr && selectedAdapterIndex == -1) + { + if (dxgiFactory6->EnumAdapterByGpuPreference(0, gpuPreference, IID_PPV_ARGS(&tempAdapter)) != DXGI_ERROR_NOT_FOUND) + { + GPUAdapterDX adapter; + if (tempAdapter && TryCreateDevice(tempAdapter, maxAllowedFeatureLevel, &adapter.MaxFeatureLevel)) + { + DXGI_ADAPTER_DESC desc; + VALIDATE_DIRECTX_RESULT(tempAdapter->GetDesc(&desc)); + for (int i = 0; i < adapters.Count(); i++) + { + if (adapters[i].Description.AdapterLuid.LowPart == desc.AdapterLuid.LowPart && + adapters[i].Description.AdapterLuid.HighPart == desc.AdapterLuid.HighPart) + { + selectedAdapterIndex = i; + break; + } + } + } + } + } +#endif // Select the adapter to use - GPUAdapterDX selectedAdapter = adapters[0]; + if (selectedAdapterIndex < 0) + selectedAdapterIndex = 0; + if (adapters.Count() == 0 || selectedAdapterIndex >= adapters.Count()) + { + LOG(Error, "Failed to find valid DirectX adapter!"); + return nullptr; + } + GPUAdapterDX selectedAdapter = adapters[selectedAdapterIndex]; uint32 vendorId = 0; if (CommandLine::Options.NVIDIA) vendorId = GPU_VENDOR_ID_NVIDIA; @@ -180,6 +221,15 @@ GPUDevice* GPUDeviceDX11::Create() Delete(device); return nullptr; } + +#if PLATFORM_WINDOWS + if (dxgiFactory6 != nullptr) + dxgiFactory6->Release(); + else +#endif + { + dxgiFactory->Release(); + } return device; } diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index f12efeafc..456a793f1 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -89,7 +89,15 @@ GPUDevice* GPUDeviceDX12::Create() // Create DXGI factory (CreateDXGIFactory2 is supported on Windows 8.1 or newer) IDXGIFactory4* dxgiFactory; - HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)); + IDXGIFactory6* dxgiFactory6; + HRESULT hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory6)); + if (hr == S_OK) + dxgiFactory = dxgiFactory6; + else + { + dxgiFactory6 = nullptr; + hr = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory)); + } if (hr != S_OK) { LOG(Error, "Cannot create DXGI adapter. Error code: {0:x}.", hr); @@ -97,6 +105,7 @@ GPUDevice* GPUDeviceDX12::Create() } // Enumerate the DXGIFactory's adapters + int32 selectedAdapterIndex = -1; Array adapters; IDXGIAdapter* tempAdapter; for (uint32 index = 0; dxgiFactory->EnumAdapters(index, &tempAdapter) != DXGI_ERROR_NOT_FOUND; index++) @@ -118,8 +127,39 @@ GPUDevice* GPUDeviceDX12::Create() } } + // Find the best performing adapter and prefer using it instead of the first device + const auto gpuPreference = DXGI_GPU_PREFERENCE_HIGH_PERFORMANCE; + if (dxgiFactory6 != nullptr && selectedAdapterIndex == -1) + { + if (dxgiFactory6->EnumAdapterByGpuPreference(0, gpuPreference, IID_PPV_ARGS(&tempAdapter)) != DXGI_ERROR_NOT_FOUND) + { + GPUAdapterDX adapter; + if (tempAdapter && CheckDX12Support(tempAdapter)) + { + DXGI_ADAPTER_DESC desc; + VALIDATE_DIRECTX_RESULT(tempAdapter->GetDesc(&desc)); + for (int i = 0; i < adapters.Count(); i++) + { + if (adapters[i].Description.AdapterLuid.LowPart == desc.AdapterLuid.LowPart && + adapters[i].Description.AdapterLuid.HighPart == desc.AdapterLuid.HighPart) + { + selectedAdapterIndex = i; + break; + } + } + } + } + } + // Select the adapter to use - GPUAdapterDX selectedAdapter = adapters[0]; + if (selectedAdapterIndex < 0) + selectedAdapterIndex = 0; + if (adapters.Count() == 0 || selectedAdapterIndex >= adapters.Count()) + { + LOG(Error, "Failed to find valid DirectX adapter!"); + return nullptr; + } + GPUAdapterDX selectedAdapter = adapters[selectedAdapterIndex]; uint32 vendorId = 0; if (CommandLine::Options.NVIDIA) vendorId = GPU_VENDOR_ID_NVIDIA; diff --git a/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h b/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h index 79e8fb7bd..deb0168fb 100644 --- a/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h +++ b/Source/Engine/GraphicsDevice/DirectX/IncludeDirectXHeaders.h @@ -40,9 +40,11 @@ typedef IGraphicsUnknown IDXGISwapChain3; #include #include #include +#include #endif #if GRAPHICS_API_DIRECTX12 #include +#include #endif #pragma comment(lib, "DXGI.lib") diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index d78155fc8..9c6d158ce 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -1155,6 +1155,7 @@ GPUDevice* GPUDeviceVulkan::Create() #endif // Enumerate all GPU devices and pick one + int32 selectedAdapterIndex = -1; uint32 gpuCount = 0; VALIDATE_VULKAN_RESULT(vkEnumeratePhysicalDevices(Instance, &gpuCount, nullptr)); if (gpuCount <= 0) @@ -1187,6 +1188,9 @@ GPUDevice* GPUDeviceVulkan::Create() break; case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: type = TEXT("Discrete GPU"); + // Select the first discrete GPU device + if (selectedAdapterIndex == -1) + selectedAdapterIndex = gpuIndex; break; case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: type = TEXT("Virtual GPU"); @@ -1203,7 +1207,13 @@ GPUDevice* GPUDeviceVulkan::Create() } // Select the adapter to use - int32 selectedAdapter = 0; + if (selectedAdapterIndex < 0) + selectedAdapterIndex = 0; + if (adapters.Count() == 0 || selectedAdapterIndex >= adapters.Count()) + { + LOG(Error, "Failed to find valid Vulkan adapter!"); + return nullptr; + } uint32 vendorId = 0; if (CommandLine::Options.NVIDIA) vendorId = GPU_VENDOR_ID_NVIDIA; @@ -1217,15 +1227,15 @@ GPUDevice* GPUDeviceVulkan::Create() { if (adapters[i].GetVendorId() == vendorId) { - selectedAdapter = i; + selectedAdapterIndex = i; break; } } } - ASSERT(selectedAdapter != -1 && adapters[selectedAdapter].IsValid()); + ASSERT(adapters[selectedAdapterIndex].IsValid()); // Create device - auto device = New(ShaderProfile::Vulkan_SM5, New(adapters[selectedAdapter])); + auto device = New(ShaderProfile::Vulkan_SM5, New(adapters[selectedAdapterIndex])); if (device->Init()) { LOG(Warning, "Graphics Device init failed"); From 4e683dcc1577429e7c4332c7614e44b5642c396c Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Fri, 26 May 2023 20:17:14 +0300 Subject: [PATCH 34/45] Clean up DXGIFactory after use on D3D12 --- .../Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index 456a793f1..257593a9d 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -202,6 +202,15 @@ GPUDevice* GPUDeviceDX12::Create() return nullptr; } +#if !(PLATFORM_XBOX_SCARLETT || PLATFORM_XBOX_ONE) + if (dxgiFactory6 != nullptr) + dxgiFactory6->Release(); + else +#endif + { + dxgiFactory->Release(); + } + return device; } From bca5e908f1b85da6ec41fb3e2d5bf283ff126326 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sat, 27 May 2023 00:40:52 +0300 Subject: [PATCH 35/45] Copy content files using Content Database instead of Content Importing Fixes an issue where copying asset files does not change the asset ID, causing the copied assets to remain linked to the original files. --- Source/Editor/Windows/ContentWindow.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index c9c1a8d21..c2b56466d 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -611,7 +611,20 @@ namespace FlaxEditor.Windows /// The files paths to import. public void Paste(string[] files) { - Editor.ContentImporting.Import(files, CurrentViewFolder); + List importFiles = new List(); + foreach (var sourcePath in files) + { + var item = Editor.ContentDatabase.Find(sourcePath); + if (item != null) + { + string targetPath = Path.Combine(CurrentViewFolder.Path, item.FileName); + Editor.ContentDatabase.Copy(item, targetPath); + } + else + importFiles.Add(sourcePath); + } + + Editor.ContentImporting.Import(importFiles, CurrentViewFolder); } /// From a21abaac8495b31c927ce94cc0ffa0e309a4e4aa Mon Sep 17 00:00:00 2001 From: Wiktor Kocielski Date: Fri, 26 May 2023 08:19:32 +0300 Subject: [PATCH 36/45] Implement INetworkObject::OnNetworkSync and make INetworkObject just virtual --- Source/Engine/Networking/INetworkObject.h | 19 ++++++++++++------- .../Engine/Networking/NetworkReplicator.cpp | 8 ++++++++ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Source/Engine/Networking/INetworkObject.h b/Source/Engine/Networking/INetworkObject.h index 457811557..932c3aa0d 100644 --- a/Source/Engine/Networking/INetworkObject.h +++ b/Source/Engine/Networking/INetworkObject.h @@ -13,22 +13,27 @@ API_INTERFACE(Namespace = "FlaxEngine.Networking") class FLAXENGINE_API INetwork DECLARE_SCRIPTING_TYPE_MINIMAL(INetworkObject); public: /// - /// Event called when network objects gets spawned. + /// Event called when network object gets spawned. /// - API_FUNCTION() virtual void OnNetworkSpawn() = 0; + API_FUNCTION() virtual void OnNetworkSpawn() {}; /// - /// Event called when network objects gets despawned. + /// Event called when network object gets despawned. /// - API_FUNCTION() virtual void OnNetworkDespawn() = 0; + API_FUNCTION() virtual void OnNetworkDespawn() {}; /// /// Event called before network object gets replicated (before reading data). /// - API_FUNCTION() virtual void OnNetworkSerialize() = 0; + API_FUNCTION() virtual void OnNetworkSerialize() {}; /// - /// Event called when network objects gets replicated (after reading data). + /// Event called when network object gets replicated (after reading data). /// - API_FUNCTION() virtual void OnNetworkDeserialize() = 0; + API_FUNCTION() virtual void OnNetworkDeserialize() {}; + + /// + /// Event called when network object gets synced (called only once upon initial sync). + /// + API_FUNCTION() virtual void OnNetworkSync() {}; }; diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 8d0ba3c0e..0a0319196 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -111,6 +111,7 @@ struct NetworkReplicatedObject uint8 Spawned : 1; DataContainer TargetClientIds; INetworkObject* AsNetworkObject; + bool NetworkObjectSync = false; NetworkReplicatedObject() { @@ -637,7 +638,14 @@ void InvokeObjectReplication(NetworkReplicatedObject& item, uint32 ownerFrame, b } if (item.AsNetworkObject) + { item.AsNetworkObject->OnNetworkDeserialize(); + if (!item.NetworkObjectSync) + { + item.AsNetworkObject->OnNetworkSync(); + item.NetworkObjectSync = true; + } + } // Speed up replication of client-owned objects to other clients from server to reduce lag (data has to go from client to server and then to other clients) if (NetworkManager::IsServer()) From c9d48d00e72703ed475939532206a36231d908a6 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sat, 27 May 2023 11:15:54 -0500 Subject: [PATCH 37/45] Change default script name to MyScript and make the name invalid if it is called Script. --- Source/Editor/Content/Proxy/ScriptProxy.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Content/Proxy/ScriptProxy.cs b/Source/Editor/Content/Proxy/ScriptProxy.cs index 3196ea833..f688f37df 100644 --- a/Source/Editor/Content/Proxy/ScriptProxy.cs +++ b/Source/Editor/Content/Proxy/ScriptProxy.cs @@ -45,7 +45,7 @@ namespace FlaxEditor.Content } /// - public override string NewItemName => "Script"; + public override string NewItemName => "MyScript"; /// public override bool CanCreate(ContentFolder targetLocation) @@ -72,6 +72,8 @@ namespace FlaxEditor.Content // Scripts cannot start with digit. if (Char.IsDigit(filename[0])) return false; + if (filename.Equals("Script")) + return false; return true; } From bb567cafdedfa060fcc483f687540b46e0c1ef7f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 11:46:48 +0200 Subject: [PATCH 38/45] Improve #1120 to use shared lookup table export from engine source and reduce memory alloc from Array via Span --- Source/Engine/Core/ObjectsRemovalService.cpp | 6 +++++ Source/Engine/Core/Utilities.h | 23 ++++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Source/Engine/Core/ObjectsRemovalService.cpp b/Source/Engine/Core/ObjectsRemovalService.cpp index 77ce686e0..35458595e 100644 --- a/Source/Engine/Core/ObjectsRemovalService.cpp +++ b/Source/Engine/Core/ObjectsRemovalService.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #include "ObjectsRemovalService.h" +#include "Utilities.h" #include "Collections/Dictionary.h" #include "Engine/Engine/Time.h" #include "Engine/Engine/EngineService.h" @@ -8,6 +9,11 @@ #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Scripting/ScriptingObject.h" +const Char* BytesSizesData[] = { TEXT("b"), TEXT("Kb"), TEXT("Mb"), TEXT("Gb"), TEXT("Tb"), TEXT("Pb"), TEXT("Eb"), TEXT("Zb"), TEXT("Yb") }; +const Char* HertzSizesData[] = { TEXT("Hz"), TEXT("KHz"), TEXT("MHz"), TEXT("GHz"), TEXT("THz"), TEXT("PHz"), TEXT("EHz"), TEXT("ZHz"), TEXT("YHz") }; +Span Utilities::Private::BytesSizes(BytesSizesData, ARRAY_COUNT(BytesSizesData)); +Span Utilities::Private::HertzSizes(HertzSizesData, ARRAY_COUNT(HertzSizesData)); + namespace ObjectsRemovalServiceImpl { CriticalSection PoolLocker; diff --git a/Source/Engine/Core/Utilities.h b/Source/Engine/Core/Utilities.h index 0c7de9323..36339baf5 100644 --- a/Source/Engine/Core/Utilities.h +++ b/Source/Engine/Core/Utilities.h @@ -4,12 +4,19 @@ #include "Types/BaseTypes.h" #include "Types/String.h" +#include "Types/Span.h" #if _MSC_VER && PLATFORM_SIMD_SSE4_2 #include #endif namespace Utilities { + struct Private + { + static FLAXENGINE_API Span BytesSizes; + static FLAXENGINE_API Span HertzSizes; + }; + // Round floating point value up to 1 decimal place template FORCE_INLINE T RoundTo1DecimalPlace(T value) @@ -37,17 +44,17 @@ namespace Utilities // @param sizes Array with human-readable sizes to convert from // @return The best fitting string of the units template - String UnitsToText(T units, int32 divider, const Array& sizes) + String UnitsToText(T units, int32 divider, const Span sizes) { - if(sizes.Count() == 0) + if (sizes.Length() == 0) return String::Format(TEXT("{0}"), units); int32 i = 0; double dblSUnits = static_cast(units); for (; static_cast(units / static_cast(divider)) > 0; i++, units /= divider) dblSUnits = units / static_cast(divider); - if (i >= sizes.Count()) - return String::Format(TEXT("{0}{1}"), units, sizes[0]); - return String::Format(TEXT("{0}{1}"), RoundTo2DecimalPlaces(dblSUnits), sizes[i]); + if (i >= sizes.Length()) + i = 0; + return String::Format(TEXT("{0} {1}"), RoundTo2DecimalPlaces(dblSUnits), sizes[i]); } // Converts size of the file (in bytes) to the best fitting string @@ -56,8 +63,7 @@ namespace Utilities template String BytesToText(T bytes) { - static Array sizes = { TEXT("b"), TEXT("Kb"), TEXT("Mb"), TEXT("Gb"), TEXT("Tb"), TEXT("Pb"), TEXT("Eb"), TEXT("Zb"), TEXT("Yb") }; - return UnitsToText(bytes, 1024, sizes); + return UnitsToText(bytes, 1024, Private::BytesSizes); } // Converts hertz to the best fitting string @@ -66,8 +72,7 @@ namespace Utilities template String HertzToText(T hertz) { - static Array sizes = { TEXT("Hz"), TEXT("KHz"), TEXT("MHz"), TEXT("GHz"), TEXT("THz"), TEXT("PHz"), TEXT("EHz"), TEXT("ZHz"), TEXT("YHz") }; - return UnitsToText(hertz, 1000, sizes); + return UnitsToText(hertz, 1000, Private::HertzSizes); } // Returns the amount of set bits in 32-bit integer. From ecc6f83130b78a19d667cd478566bb4146ed1068 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 12:03:22 +0200 Subject: [PATCH 39/45] Use `Utilities::HertzToText` from #1120 to log cpu clock speed --- Source/Engine/Platform/Base/PlatformBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Platform/Base/PlatformBase.cpp b/Source/Engine/Platform/Base/PlatformBase.cpp index 353e2b8f9..eb02c1ce9 100644 --- a/Source/Engine/Platform/Base/PlatformBase.cpp +++ b/Source/Engine/Platform/Base/PlatformBase.cpp @@ -157,7 +157,7 @@ void PlatformBase::LogInfo() LOG(Info, "CPU package count: {0}, Core count: {1}, Logical processors: {2}", cpuInfo.ProcessorPackageCount, cpuInfo.ProcessorCoreCount, cpuInfo.LogicalProcessorCount); LOG(Info, "CPU Page size: {0}, cache line size: {1} bytes", Utilities::BytesToText(cpuInfo.PageSize), cpuInfo.CacheLineSize); LOG(Info, "L1 cache: {0}, L2 cache: {1}, L3 cache: {2}", Utilities::BytesToText(cpuInfo.L1CacheSize), Utilities::BytesToText(cpuInfo.L2CacheSize), Utilities::BytesToText(cpuInfo.L3CacheSize)); - LOG(Info, "Clock speed: {0} GHz", Utilities::RoundTo2DecimalPlaces(cpuInfo.ClockSpeed * 1e-9f)); + LOG(Info, "Clock speed: {0}", Utilities::HertzToText(cpuInfo.ClockSpeed)); const MemoryStats memStats = Platform::GetMemoryStats(); LOG(Info, "Physical Memory: {0} total, {1} used ({2}%)", Utilities::BytesToText(memStats.TotalPhysicalMemory), Utilities::BytesToText(memStats.UsedPhysicalMemory), Utilities::RoundTo2DecimalPlaces((float)memStats.UsedPhysicalMemory * 100.0f / (float)memStats.TotalPhysicalMemory)); From 95d89382c9f58a1f085e62e66ffd21feccda9aa7 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 12:35:14 +0200 Subject: [PATCH 40/45] Update Flax `.gitignore` to skip generated code module header files --- .gitignore | 1 + Source/FlaxEngine.Gen.cpp | 12 ------------ Source/FlaxEngine.Gen.cs | 17 ----------------- Source/FlaxEngine.Gen.h | 15 --------------- 4 files changed, 1 insertion(+), 44 deletions(-) delete mode 100644 Source/FlaxEngine.Gen.cpp delete mode 100644 Source/FlaxEngine.Gen.cs delete mode 100644 Source/FlaxEngine.Gen.h diff --git a/.gitignore b/.gitignore index 8ee95cf27..1e9aef426 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ Cache/ Binaries/ Output/ Logs/ +Source/*.Gen.* Source/*.csproj /Package_*/ !Source/Engine/Debug diff --git a/Source/FlaxEngine.Gen.cpp b/Source/FlaxEngine.Gen.cpp deleted file mode 100644 index d175cbc6a..000000000 --- a/Source/FlaxEngine.Gen.cpp +++ /dev/null @@ -1,12 +0,0 @@ -// This code was auto-generated. Do not modify it. - -#include "Engine/Scripting/BinaryModule.h" -#include "FlaxEngine.Gen.h" - -StaticallyLinkedBinaryModuleInitializer StaticallyLinkedBinaryModuleFlaxEngine(GetBinaryModuleFlaxEngine); - -extern "C" BinaryModule* GetBinaryModuleFlaxEngine() -{ - static NativeBinaryModule module("FlaxEngine", MAssemblyOptions()); - return &module; -} diff --git a/Source/FlaxEngine.Gen.cs b/Source/FlaxEngine.Gen.cs deleted file mode 100644 index f6090396e..000000000 --- a/Source/FlaxEngine.Gen.cs +++ /dev/null @@ -1,17 +0,0 @@ -// This code was auto-generated. Do not modify it. - -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("FlaxEngine")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Flax")] -[assembly: AssemblyProduct("FlaxEngine")] -[assembly: AssemblyCopyright("Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: ComVisible(false)] -[assembly: Guid("b8442186-4a70-7c85-704a-857c68060f38")] -[assembly: AssemblyVersion("1.5.6339")] -[assembly: AssemblyFileVersion("1.5.6339")] diff --git a/Source/FlaxEngine.Gen.h b/Source/FlaxEngine.Gen.h deleted file mode 100644 index 81aab8d55..000000000 --- a/Source/FlaxEngine.Gen.h +++ /dev/null @@ -1,15 +0,0 @@ -// This code was auto-generated. Do not modify it. - -#pragma once - -#define FLAXENGINE_NAME "FlaxEngine" -#define FLAXENGINE_VERSION Version(1, 5, 6339) -#define FLAXENGINE_VERSION_TEXT "1.5.6339" -#define FLAXENGINE_VERSION_MAJOR 1 -#define FLAXENGINE_VERSION_MINOR 5 -#define FLAXENGINE_VERSION_BUILD 6339 -#define FLAXENGINE_COMPANY "Flax" -#define FLAXENGINE_COPYRIGHT "Copyright (c) 2012-2023 Wojciech Figat. All rights reserved." - -class BinaryModule; -extern "C" FLAXENGINE_API BinaryModule* GetBinaryModuleFlaxEngine(); From 583a5d9223a2e5f5ca2a6a05a5f4010a3a193f5b Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 13:17:43 +0200 Subject: [PATCH 41/45] Minor fixes to content window navigation --- Source/Editor/Content/GUI/ContentView.cs | 7 +++++-- Source/Editor/Windows/ContentWindow.cs | 8 ++------ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Source/Editor/Content/GUI/ContentView.cs b/Source/Editor/Content/GUI/ContentView.cs index 7eb2e0950..6065ca9f8 100644 --- a/Source/Editor/Content/GUI/ContentView.cs +++ b/Source/Editor/Content/GUI/ContentView.cs @@ -692,10 +692,13 @@ namespace FlaxEditor.Content.GUI c = char.ToLowerInvariant(c); for (int i = 0; i < _items.Count; i++) { - var name = _items[i].ShortName; + var item = _items[i]; + var name = item.ShortName; if (!string.IsNullOrEmpty(name) && char.ToLowerInvariant(name[0]) == c) { - Select(_items[i]); + Select(item); + if (Parent is Panel panel) + panel.ScrollViewTo(item, true); break; } } diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index c2b56466d..207abb84f 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -611,19 +611,15 @@ namespace FlaxEditor.Windows /// The files paths to import. public void Paste(string[] files) { - List importFiles = new List(); + var importFiles = new List(); foreach (var sourcePath in files) { var item = Editor.ContentDatabase.Find(sourcePath); if (item != null) - { - string targetPath = Path.Combine(CurrentViewFolder.Path, item.FileName); - Editor.ContentDatabase.Copy(item, targetPath); - } + Editor.ContentDatabase.Copy(item, Path.Combine(CurrentViewFolder.Path, item.FileName)); else importFiles.Add(sourcePath); } - Editor.ContentImporting.Import(importFiles, CurrentViewFolder); } From 3e906686db005d9ea7f1e187644d663700fdbae1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 13:30:14 +0200 Subject: [PATCH 42/45] Improve #1119 to use a bit flag for object sync --- Source/Engine/Networking/NetworkReplicator.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 0a0319196..6f6211b74 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -109,13 +109,14 @@ struct NetworkReplicatedObject uint32 LastOwnerFrame = 0; NetworkObjectRole Role; uint8 Spawned : 1; + uint8 Synced : 1; DataContainer TargetClientIds; INetworkObject* AsNetworkObject; - bool NetworkObjectSync = false; NetworkReplicatedObject() { Spawned = 0; + Synced = 0; } bool operator==(const NetworkReplicatedObject& other) const @@ -640,10 +641,10 @@ void InvokeObjectReplication(NetworkReplicatedObject& item, uint32 ownerFrame, b if (item.AsNetworkObject) { item.AsNetworkObject->OnNetworkDeserialize(); - if (!item.NetworkObjectSync) + if (!item.Synced) { + item.Synced = true; item.AsNetworkObject->OnNetworkSync(); - item.NetworkObjectSync = true; } } From 9cdd1cbc45a14cd0b5df8f974b37fa1f960cf9db Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 15:30:16 +0200 Subject: [PATCH 43/45] Add `Platform::GetMousePosition`/`WindowsPlatform::SetMousePosition` for unified access to screen-space mouse position on all platforms #1109 --- Source/Engine/Input/Keyboard.h | 3 +-- Source/Engine/Input/Mouse.h | 3 --- Source/Engine/Platform/Base/PlatformBase.cpp | 16 ++++++++++++++ Source/Engine/Platform/Base/PlatformBase.h | 12 +++++++++++ .../Engine/Platform/Linux/LinuxPlatform.cpp | 5 +---- Source/Engine/Platform/UWP/UWPPlatform.cpp | 21 ------------------- Source/Engine/Platform/UWP/UWPPlatform.h | 2 -- Source/Engine/Platform/Win32/Win32Platform.h | 2 +- .../Platform/Windows/WindowsPlatform.cpp | 12 +++++++++++ .../Engine/Platform/Windows/WindowsPlatform.h | 2 ++ 10 files changed, 45 insertions(+), 33 deletions(-) diff --git a/Source/Engine/Input/Keyboard.h b/Source/Engine/Input/Keyboard.h index 45f8e295e..7e238bcf5 100644 --- a/Source/Engine/Input/Keyboard.h +++ b/Source/Engine/Input/Keyboard.h @@ -26,9 +26,8 @@ protected: public: /// - /// Gets the text entered during the current frame. + /// Gets the text entered during the current frame (Unicode format). /// - /// The input text (Unicode). API_PROPERTY() StringView GetInputText() const { return StringView(_state.InputText, _state.InputTextLength); diff --git a/Source/Engine/Input/Mouse.h b/Source/Engine/Input/Mouse.h index 7fc2be75a..0acd31238 100644 --- a/Source/Engine/Input/Mouse.h +++ b/Source/Engine/Input/Mouse.h @@ -58,7 +58,6 @@ public: /// /// Gets the position of the mouse in the screen-space coordinates. /// - /// The mouse position API_PROPERTY() FORCE_INLINE Float2 GetPosition() const { return _state.MousePosition; @@ -72,7 +71,6 @@ public: /// /// Gets the delta position of the mouse in the screen-space coordinates. /// - /// The mouse position delta API_PROPERTY() FORCE_INLINE Float2 GetPositionDelta() const { return _state.MousePosition - _prevState.MousePosition; @@ -81,7 +79,6 @@ public: /// /// Gets the mouse wheel change during the last frame. /// - /// Mouse wheel value delta API_PROPERTY() FORCE_INLINE float GetScrollDelta() const { return _state.MouseWheelDelta; diff --git a/Source/Engine/Platform/Base/PlatformBase.cpp b/Source/Engine/Platform/Base/PlatformBase.cpp index eb02c1ce9..89fcc1011 100644 --- a/Source/Engine/Platform/Base/PlatformBase.cpp +++ b/Source/Engine/Platform/Base/PlatformBase.cpp @@ -5,6 +5,7 @@ #include "Engine/Platform/MemoryStats.h" #include "Engine/Platform/MessageBox.h" #include "Engine/Platform/FileSystem.h" +#include "Engine/Platform/Window.h" #include "Engine/Platform/User.h" #include "Engine/Core/Log.h" #include "Engine/Core/Types/DateTime.h" @@ -520,6 +521,21 @@ void PlatformBase::CreateGuid(Guid& result) result = Guid(dateThingHigh, randomThing | (sequentialThing << 16), cyclesThing, dateThingLow); } +Float2 PlatformBase::GetMousePosition() +{ + const Window* win = Engine::MainWindow; + if (win) + return win->ClientToScreen(win->GetMousePosition()); + return Float2::Minimum; +} + +void PlatformBase::SetMousePosition(const Float2& position) +{ + const Window* win = Engine::MainWindow; + if (win) + win->SetMousePosition(win->ScreenToClient(position)); +} + Float2 PlatformBase::GetVirtualDesktopSize() { return Platform::GetVirtualDesktopBounds().Size; diff --git a/Source/Engine/Platform/Base/PlatformBase.h b/Source/Engine/Platform/Base/PlatformBase.h index e7800c94d..7b06fa3d0 100644 --- a/Source/Engine/Platform/Base/PlatformBase.h +++ b/Source/Engine/Platform/Base/PlatformBase.h @@ -660,6 +660,18 @@ public: public: + /// + /// Gets the mouse cursor position in screen-space coordinates. + /// + /// Mouse cursor coordinates. + API_PROPERTY() static Float2 GetMousePosition(); + + /// + /// Sets the mouse cursor position in screen-space coordinates. + /// + /// Cursor position to set. + API_PROPERTY() static void SetMousePosition(const Float2& position); + /// /// Gets the origin position and size of the monitor at the given screen-space location. /// diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index 631b8d017..e954dd784 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -2643,10 +2643,8 @@ Float2 LinuxPlatform::GetMousePosition() { if (!xDisplay) return Float2::Zero; - - int32 x, y; + int32 x = 0, y = 0; uint32 screenCount = (uint32)X11::XScreenCount(xDisplay); - for (uint32 i = 0; i < screenCount; i++) { X11::Window outRoot, outChild; @@ -2655,7 +2653,6 @@ Float2 LinuxPlatform::GetMousePosition() if (X11::XQueryPointer(xDisplay, X11::XRootWindow(xDisplay, i), &outRoot, &outChild, &x, &y, &childX, &childY, &mask)) break; } - return Float2((float)x, (float)y); } diff --git a/Source/Engine/Platform/UWP/UWPPlatform.cpp b/Source/Engine/Platform/UWP/UWPPlatform.cpp index f7c883878..06a0d964d 100644 --- a/Source/Engine/Platform/UWP/UWPPlatform.cpp +++ b/Source/Engine/Platform/UWP/UWPPlatform.cpp @@ -158,27 +158,6 @@ void UWPPlatform::OpenUrl(const StringView& url) // TODO: add support for OpenUrl on UWP } -Float2 UWPPlatform::GetMousePosition() -{ - // Use the main window - auto win = Engine::MainWindow; - if (win) - { - return win->ClientToScreen(win->GetMousePosition()); - } - return Float2::Minimum; -} - -void UWPPlatform::SetMousePosition(const Float2& pos) -{ - // Use the main window - auto win = Engine::MainWindow; - if (win) - { - win->SetMousePosition(win->ScreenToClient(pos)); - } -} - Float2 UWPPlatform::GetDesktopSize() { Float2 result; diff --git a/Source/Engine/Platform/UWP/UWPPlatform.h b/Source/Engine/Platform/UWP/UWPPlatform.h index be114f419..9bc0d7afd 100644 --- a/Source/Engine/Platform/UWP/UWPPlatform.h +++ b/Source/Engine/Platform/UWP/UWPPlatform.h @@ -37,8 +37,6 @@ public: static bool GetHasFocus(); static bool CanOpenUrl(const StringView& url); static void OpenUrl(const StringView& url); - static Float2 GetMousePosition(); - static void SetMousePosition(const Float2& pos); static Rectangle GetMonitorBounds(const Float2& screenPos); static Float2 GetDesktopSize(); static Rectangle GetVirtualDesktopBounds(); diff --git a/Source/Engine/Platform/Win32/Win32Platform.h b/Source/Engine/Platform/Win32/Win32Platform.h index b50d31616..d3f9a5cdc 100644 --- a/Source/Engine/Platform/Win32/Win32Platform.h +++ b/Source/Engine/Platform/Win32/Win32Platform.h @@ -109,7 +109,7 @@ public: static void CreateGuid(Guid& result); static String GetMainDirectory(); static String GetExecutableFilePath(); - static struct Guid GetUniqueDeviceId(); + static Guid GetUniqueDeviceId(); static String GetWorkingDirectory(); static bool SetWorkingDirectory(const String& path); static void FreeLibrary(void* handle); diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index e215cbaf0..7c8a5b060 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -825,6 +825,18 @@ void WindowsPlatform::OpenUrl(const StringView& url) ::ShellExecuteW(nullptr, TEXT("open"), *url, nullptr, nullptr, SW_SHOWNORMAL); } +Float2 WindowsPlatform::GetMousePosition() +{ + POINT cursorPos; + GetCursorPos(&cursorPos); + return Float2((float)cursorPos.x, (float)cursorPos.y); +} + +void WindowsPlatform::SetMousePosition(const Float2& pos) +{ + ::SetCursorPos((int)pos.X, (int)pos.Y); +} + struct GetMonitorBoundsData { Float2 Pos; diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.h b/Source/Engine/Platform/Windows/WindowsPlatform.h index 7441d0812..a144e09e5 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.h +++ b/Source/Engine/Platform/Windows/WindowsPlatform.h @@ -71,6 +71,8 @@ public: static bool GetHasFocus(); static bool CanOpenUrl(const StringView& url); static void OpenUrl(const StringView& url); + static Float2 GetMousePosition(); + static void SetMousePosition(const Float2& pos); static Rectangle GetMonitorBounds(const Float2& screenPos); static Float2 GetDesktopSize(); static Rectangle GetVirtualDesktopBounds(); From 62946f63598ae501bd3c217dc7b602a280a44d35 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 16:12:32 +0200 Subject: [PATCH 44/45] Cleanup and improve code from #1109 --- .../Editor/GUI/Dialogs/ColorPickerDialog.cs | 61 ++++---- Source/Editor/GUI/Input/ColorValueBox.cs | 7 +- Source/Editor/Surface/Elements/ColorValue.cs | 2 +- Source/Editor/Utilities/ScreenUtilities.cpp | 130 ++++++++++++++++++ Source/Editor/Utilities/ScreenUtilities.h | 33 +++++ .../ScreenUtilities/ScreenUtilities.h | 40 ------ .../ScreenUtilities/ScreenUtilitiesLinux.cpp | 104 -------------- .../ScreenUtilities/ScreenUtilitiesMac.cpp | 46 ------- .../ScreenUtilitiesWindows.cpp | 94 ------------- Source/Editor/Utilities/Utils.cs | 4 +- .../Engine/Platform/Linux/LinuxPlatform.cpp | 13 +- Source/Engine/Platform/Linux/LinuxPlatform.h | 2 +- Source/Engine/UI/GUI/Common/IconButton.cs | 74 ---------- Source/Engine/Utilities/Screenshot.cpp | 2 - 14 files changed, 212 insertions(+), 400 deletions(-) create mode 100644 Source/Editor/Utilities/ScreenUtilities.cpp create mode 100644 Source/Editor/Utilities/ScreenUtilities.h delete mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h delete mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp delete mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp delete mode 100644 Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp delete mode 100644 Source/Engine/UI/GUI/Common/IconButton.cs diff --git a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs index 0c81ecc51..161b3f4ae 100644 --- a/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs +++ b/Source/Editor/GUI/Dialogs/ColorPickerDialog.cs @@ -1,10 +1,8 @@ // Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. using FlaxEditor.GUI.Input; -using FlaxEditor.Windows; using FlaxEngine; using FlaxEngine.GUI; -using System; namespace FlaxEditor.GUI.Dialogs { @@ -52,7 +50,7 @@ namespace FlaxEditor.GUI.Dialogs private TextBox _cHex; private Button _cCancel; private Button _cOK; - private IconButton _cEyedropper; + private Button _cEyedropper; /// /// Gets the selected color. @@ -109,7 +107,6 @@ namespace FlaxEditor.GUI.Dialogs { _initialValue = initialValue; _useDynamicEditing = useDynamicEditing; - _activeEyedropper = false; _value = Color.Transparent; _onChanged = colorChanged; _onClosed = pickerClosed; @@ -199,46 +196,41 @@ namespace FlaxEditor.GUI.Dialogs _cOK.Clicked += OnSubmit; // Eyedropper button - _cEyedropper = new IconButton(_cOK.X - EyedropperMargin, _cHex.Bottom + PickerMargin, Editor.Instance.Icons.Add64, hideBorder: false) + var style = Style.Current; + _cEyedropper = new Button(_cOK.X - EyedropperMargin, _cHex.Bottom + PickerMargin) { + TooltipText = "Eyedropper tool to pick a color directly from the screen", + BackgroundBrush = new SpriteBrush(Editor.Instance.Icons.Search32), + BackgroundColor = style.Foreground, + BackgroundColorHighlighted = style.Foreground.RGBMultiplied(0.9f), + BorderColor = Color.Transparent, + BorderColorHighlighted = style.BorderSelected, Parent = this, }; _cEyedropper.Clicked += OnEyedropStart; _cEyedropper.Height = (_cValue.Bottom - _cEyedropper.Y) * 0.5f; _cEyedropper.Width = _cEyedropper.Height; _cEyedropper.X -= _cEyedropper.Width; - //_cEyedropper.SetColors(_cEyedropper.BackgroundColor); // Set initial color SelectedColor = initialValue; } - private Color32 GetEyedropColor() + private void OnColorPicked(Color32 colorPicked) { - Int2 mousePosition = ScreenUtilities.GetScreenCursorPosition(); - Color32 pixelColor = ScreenUtilities.GetPixelAt(mousePosition.X, mousePosition.Y); - - return pixelColor; - } - - private void ColorPicked(Color32 colorPicked) - { - _activeEyedropper = false; - SelectedColor = colorPicked; - ScreenUtilities.PickColorDone -= ColorPicked; + if (_activeEyedropper) + { + _activeEyedropper = false; + SelectedColor = colorPicked; + ScreenUtilities.PickColorDone -= OnColorPicked; + } } private void OnEyedropStart() { _activeEyedropper = true; ScreenUtilities.PickColor(); - ScreenUtilities.PickColorDone += ColorPicked; - } - - private void UpdateEyedrop() - { - Color32 pixelColor = GetEyedropColor(); - SelectedColor = pixelColor; + ScreenUtilities.PickColorDone += OnColorPicked; } private void OnRGBAChanged() @@ -266,15 +258,16 @@ namespace FlaxEditor.GUI.Dialogs SelectedColor = color; } - /// public override void Update(float deltaTime) { base.Update(deltaTime); + // Update eye dropper tool if (_activeEyedropper) { - UpdateEyedrop(); + Float2 mousePosition = Platform.MousePosition; + SelectedColor = ScreenUtilities.GetColorAt(mousePosition); } } @@ -331,6 +324,20 @@ namespace FlaxEditor.GUI.Dialogs base.OnShow(); } + /// + public override bool OnKeyDown(KeyboardKeys key) + { + if (_activeEyedropper && key == KeyboardKeys.Escape) + { + // Cancel eye dropping + _activeEyedropper = false; + ScreenUtilities.PickColorDone -= OnColorPicked; + return true; + } + + return base.OnKeyDown(key); + } + /// public override void OnSubmit() { diff --git a/Source/Editor/GUI/Input/ColorValueBox.cs b/Source/Editor/GUI/Input/ColorValueBox.cs index bafa27c87..167cc65bb 100644 --- a/Source/Editor/GUI/Input/ColorValueBox.cs +++ b/Source/Editor/GUI/Input/ColorValueBox.cs @@ -57,6 +57,11 @@ namespace FlaxEditor.GUI.Input /// protected Color _value; + /// + /// Enables live preview of the selected value from the picker. Otherwise will update the value only when user confirms it on dialog closing. + /// + public bool UseDynamicEditing = true; + /// /// Occurs when value gets changed. /// @@ -143,7 +148,7 @@ namespace FlaxEditor.GUI.Input base.OnSubmit(); // Show color picker dialog - _currentDialog = ShowPickColorDialog?.Invoke(this, _value, OnColorChanged, OnPickerClosed); + _currentDialog = ShowPickColorDialog?.Invoke(this, _value, OnColorChanged, OnPickerClosed, UseDynamicEditing); } private void OnColorChanged(Color color, bool sliding) diff --git a/Source/Editor/Surface/Elements/ColorValue.cs b/Source/Editor/Surface/Elements/ColorValue.cs index 96069cfeb..19934581d 100644 --- a/Source/Editor/Surface/Elements/ColorValue.cs +++ b/Source/Editor/Surface/Elements/ColorValue.cs @@ -30,7 +30,7 @@ namespace FlaxEditor.Surface.Elements { ParentNode = parentNode; Archetype = archetype; - + UseDynamicEditing = false; ParentNode.ValuesChanged += OnNodeValuesChanged; } diff --git a/Source/Editor/Utilities/ScreenUtilities.cpp b/Source/Editor/Utilities/ScreenUtilities.cpp new file mode 100644 index 000000000..cff41f7bf --- /dev/null +++ b/Source/Editor/Utilities/ScreenUtilities.cpp @@ -0,0 +1,130 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +#include "ScreenUtilities.h" +#include "Engine/Core/Math/Vector2.h" +#include "Engine/Core/Delegate.h" +#include "Engine/Core/Log.h" +#include "Engine/Profiler/ProfilerCPU.h" + +Delegate ScreenUtilities::PickColorDone; + +#if PLATFORM_WINDOWS + +#include + +#pragma comment(lib, "Gdi32.lib") + +static HHOOK MouseCallbackHook; + +LRESULT CALLBACK OnScreenUtilsMouseCallback(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam) +{ + if (nCode >= 0 && wParam == WM_LBUTTONDOWN) + { + UnhookWindowsHookEx(MouseCallbackHook); + + // Push event with the picked color + const Float2 cursorPos = Platform::GetMousePosition(); + const Color32 colorPicked = ScreenUtilities::GetColorAt(cursorPos); + ScreenUtilities::PickColorDone(colorPicked); + return 1; + } + return CallNextHookEx(NULL, nCode, wParam, lParam); +} + +Color32 ScreenUtilities::GetColorAt(const Float2& pos) +{ + PROFILE_CPU(); + HDC deviceContext = GetDC(NULL); + COLORREF color = GetPixel(deviceContext, (int)pos.X, (int)pos.Y); + ReleaseDC(NULL, deviceContext); + return Color32(GetRValue(color), GetGValue(color), GetBValue(color), 255); +} + +void ScreenUtilities::PickColor() +{ + MouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, OnScreenUtilsMouseCallback, NULL, NULL); + if (MouseCallbackHook == NULL) + { + LOG(Warning, "Failed to set mouse hook."); + LOG(Warning, "Error: {0}", GetLastError()); + } +} + +#elif PLATFORM_LINUX + +#include "Engine/Platform/Linux/LinuxPlatform.h" +#include "Engine/Platform/Linux/IncludeX11.h" + +Color32 ScreenUtilities::GetColorAt(const Float2& pos) +{ + X11::XColor color; + + X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); + int defaultScreen = X11::XDefaultScreen(display); + + X11::XImage* image; + image = X11::XGetImage(display, X11::XRootWindow(display, defaultScreen), x, y, 1, 1, AllPlanes, XYPixmap); + color.pixel = XGetPixel(image, 0, 0); + X11::XFree(image); + + X11::XQueryColor(display, X11::XDefaultColormap(display, defaultScreen), &color); + + Color32 outputColor; + outputColor.R = color.red / 256; + outputColor.G = color.green / 256; + outputColor.B = color.blue / 256; + return outputColor; +} + +void OnScreenUtilsXEventCallback(void* eventPtr) +{ + X11::XEvent* event = (X11::XEvent*) eventPtr; + X11::Display* display = (X11::Display*)LinuxPlatform::GetXDisplay(); + if (event->type == ButtonPress) + { + const Float2 cursorPos = Platform::GetMousePosition(); + const Color32 colorPicked = ScreenUtilities::GetColorAt(cursorPos); + X11::XUngrabPointer(display, CurrentTime); + ScreenUtilities::PickColorDone(colorPicked); + LinuxPlatform::xEventRecieved.Unbind(OnScreenUtilsXEventCallback); + } +} + +void ScreenUtilities::PickColor() +{ + PROFILE_CPU(); + X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); + X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); + + X11::Cursor cursor = XCreateFontCursor(display, 130); + int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, ButtonPressMask, GrabModeAsync, GrabModeAsync, rootWindow, cursor, CurrentTime); + if (grabbedPointer != GrabSuccess) + { + LOG(Error, "Failed to grab cursor for events."); + X11::XFreeCursor(display, cursor); + return; + } + + X11::XFreeCursor(display, cursor); + LinuxPlatform::xEventRecieved.Bind(OnScreenUtilsXEventCallback); +} + +#elif PLATFORM_MAC + +#include +#include + +Color32 ScreenUtilities::GetColorAt(const Float2& pos) +{ + // TODO: implement ScreenUtilities for macOS + return { 0, 0, 0, 255 }; +} + +void ScreenUtilities::PickColor() +{ + // This is what C# calls to start the color picking sequence + // This should stop mouse clicks from working for one click, and that click is on the selected color + // There is a class called NSColorSample that might implement that for you, but maybe not. +} + +#endif diff --git a/Source/Editor/Utilities/ScreenUtilities.h b/Source/Editor/Utilities/ScreenUtilities.h new file mode 100644 index 000000000..506dc8634 --- /dev/null +++ b/Source/Editor/Utilities/ScreenUtilities.h @@ -0,0 +1,33 @@ +// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Engine/Core/Types/BaseTypes.h" +#include "Engine/Core/Math/Color32.h" +#include "Engine/Core/Math/Vector2.h" +#include "Engine/Core/Delegate.h" + +/// +/// Platform-dependent screen utilities. +/// +API_CLASS(Static) class FLAXENGINE_API ScreenUtilities +{ + DECLARE_SCRIPTING_TYPE_MINIMAL(ScreenUtilities); + + /// + /// Gets the pixel color at the specified coordinates. + /// + /// Screen-space coordinate to read. + /// Pixel color at the specified coordinates. + API_FUNCTION() static Color32 GetColorAt(const Float2& pos); + + /// + /// Starts async color picking. Color will be returned through PickColorDone event when the actions ends (user selected the final color with a mouse). When action is active, GetColorAt can be used to read the current value. + /// + API_FUNCTION() static void PickColor(); + + /// + /// Called when PickColor action is finished. + /// + API_EVENT() static Delegate PickColorDone; +}; diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h deleted file mode 100644 index 01380e25b..000000000 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilities.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "Engine/Core/Types/BaseTypes.h" -#include "Engine/Core/Delegate.h" - -API_INJECT_CODE(cpp, "#include \"Editor/Utilities/ScreenUtilities/ScreenUtilities.h\""); - -/// -/// Platform-dependent screen utilties. -/// -API_CLASS(Static, Name = "ScreenUtilities", Tag = "NativeInvokeUseName") -class FLAXENGINE_API ScreenUtilities -{ -public: - static struct FLAXENGINE_API ScriptingTypeInitializer TypeInitializer; - - /// - /// Gets the pixel color at the specified coordinates. - /// - /// X Coordinate to read. - /// Y Coordinate to read. - /// Pixel color at the specified coordinates. - API_FUNCTION() static Color32 GetPixelAt(int32 x, int32 y); - - /// - /// Gets the cursor position, in screen cooridnates. - /// - /// Cursor position, in screen coordinates. - API_FUNCTION() static Int2 GetScreenCursorPosition(); - - /// - /// Starts async color picking. Will return a color through ColorReturnCallback. - /// - /// Called when PickColor() is finished. - /// - API_EVENT() static Delegate PickColorDone; -}; diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp deleted file mode 100644 index 6dc2103d9..000000000 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesLinux.cpp +++ /dev/null @@ -1,104 +0,0 @@ -#if PLATFORM_LINUX - -#include "ScreenUtilities.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" -#include "Engine/Core/Log.h" -#include "Engine/Platform/Linux/LinuxPlatform.h" - -#include "Engine/Platform/Linux/IncludeX11.h" - -Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) -{ - X11::XColor color; - Color32 outputColor; - - X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); - int defaultScreen = X11::XDefaultScreen(display); - - X11::XImage* image; - image = X11::XGetImage(display, X11::XRootWindow(display, defaultScreen), x, y, 1, 1, AllPlanes, XYPixmap); - color.pixel = XGetPixel(image, 0, 0); - X11::XFree(image); - - X11::XQueryColor(display, X11::XDefaultColormap(display, defaultScreen), &color); - outputColor.R = color.red / 256; - outputColor.G = color.green / 256; - outputColor.B = color.blue / 256; - - return outputColor; -} - -Int2 ScreenUtilities::GetScreenCursorPosition() -{ - Int2 cursorPosition = { 0, 0 }; - X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); - X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); - - // Buffers (Some useful, some not.) - X11::Window rootWindowBuffer; - int rootX, rootY; - int winXBuffer, winYBuffer; - unsigned int maskBuffer; - - int gotPointer = X11::XQueryPointer(display, rootWindow, &rootWindowBuffer, &rootWindowBuffer, &rootX, &rootY, &winXBuffer, &winYBuffer, &maskBuffer); - if (!gotPointer) { - LOG(Error, "Failed to find the mouse pointer (Are you using multiple displays?)"); - return cursorPosition; - } - - cursorPosition.X = rootX; - cursorPosition.Y = rootY; - - return cursorPosition; -} - -class ScreenUtilitiesLinux -{ -public: - static void BlockAndReadMouse(); - static void xEventHandler(void* event); -}; - -void ScreenUtilitiesLinux::xEventHandler(void* eventPtr) { - X11::XEvent* event = (X11::XEvent*) eventPtr; - - X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); - - if (event->type == ButtonPress) { - Int2 cursorPosition = ScreenUtilities::GetScreenCursorPosition(); - Color32 colorPicked = ScreenUtilities::GetPixelAt(cursorPosition.X, cursorPosition.Y); - - ScreenUtilities::PickColorDone(colorPicked); // Run the callback for picking colors being complete. - LinuxPlatform::xEventRecieved.Unbind(xEventHandler); // Unbind the event, we only want to handle one click event - X11::XUngrabPointer(display, CurrentTime); - } -} - -void ScreenUtilitiesLinux::BlockAndReadMouse() -{ - X11::Display* display = (X11::Display*) LinuxPlatform::GetXDisplay(); - X11::Window rootWindow = X11::XRootWindow(display, X11::XDefaultScreen(display)); - - X11::Cursor cursor = XCreateFontCursor(display, 130); - int grabbedPointer = X11::XGrabPointer(display, rootWindow, 0, ButtonPressMask, GrabModeAsync, GrabModeAsync, rootWindow, cursor, CurrentTime); - if (grabbedPointer != GrabSuccess) { - LOG(Error, "Failed to grab cursor for events."); - - X11::XFreeCursor(display, cursor); - return; - } - - X11::XFreeCursor(display, cursor); - LinuxPlatform::xEventRecieved.Bind(xEventHandler); -} - -Delegate ScreenUtilities::PickColorDone; - -void ScreenUtilities::PickColor() -{ - ScreenUtilitiesLinux::BlockAndReadMouse(); -} - -#endif \ No newline at end of file diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp deleted file mode 100644 index f774242ce..000000000 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesMac.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#if PLATFORM_MAC -#include -#include - -#include "ScreenUtilities.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" -#include "Engine/Core/Log.h" - -Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) -{ - // Called from C# for live updates to the color. - - return { 0, 0, 0, 255 }; -} - -Int2 ScreenUtilities::GetScreenCursorPosition() -{ - // Called from C# for live updates to the color. - - return { 0, 0 }; -} - -class ScreenUtilitiesMac -{ -public: - static void BlockAndReadMouse(); -}; - -void ScreenUtilitiesMac::BlockAndReadMouse() -{ - // Maybe you don't need this if you go with NSColorSampler -} - -Delegate ScreenUtilities::PickColorDone; - -void ScreenUtilities::PickColor() -{ - // This is what C# calls to start the color picking sequence - // This should stop mouse clicks from working for one click, and that click is on the selected color - // There is a class called NSColorSample that might implement that for you, but maybe not. - // It also might just work to copy the Linux Impl since Mac uses X as well, right? -} - -#endif diff --git a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp b/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp deleted file mode 100644 index 5af695c4d..000000000 --- a/Source/Editor/Utilities/ScreenUtilities/ScreenUtilitiesWindows.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#if PLATFORM_WINDOWS - -#include "ScreenUtilities.h" -#include "Engine/Core/Math/Color32.h" -#include "Engine/Core/Math/Vector2.h" -#include "Engine/Core/Delegate.h" -#include "Engine/Core/Log.h" -#include "Engine/Scripting/ManagedCLR/MCore.h" - -#include - - -#pragma comment(lib, "Gdi32.lib") - - -Color32 ScreenUtilities::GetPixelAt(int32 x, int32 y) -{ - HDC deviceContext = GetDC(NULL); - COLORREF color = GetPixel(deviceContext, x, y); - ReleaseDC(NULL, deviceContext); - - Color32 returnColor = { GetRValue(color), GetGValue(color), GetBValue(color), 255 }; - return returnColor; -} - -Int2 ScreenUtilities::GetScreenCursorPosition() -{ - POINT cursorPos; - GetCursorPos(&cursorPos); - - Int2 returnCursorPos = { cursorPos.x, cursorPos.y }; - return returnCursorPos; -} - -class ScreenUtilitiesWindows -{ -public: - static void PickSelected(); - static void BlockAndReadMouse(); -}; - -void ScreenUtilitiesWindows::PickSelected() { - Int2 cursorPos = ScreenUtilities::GetScreenCursorPosition(); - Color32 colorPicked = ScreenUtilities::GetPixelAt(cursorPos.X, cursorPos.Y); - - // Push event with the picked color. - ScreenUtilities::PickColorDone(colorPicked); -} - -static HHOOK _mouseCallbackHook; -LRESULT CALLBACK ScreenUtilsMouseCallback( - _In_ int nCode, - _In_ WPARAM wParam, - _In_ LPARAM lParam -) -{ - if (wParam != WM_LBUTTONDOWN) { // Return as early as possible. - return CallNextHookEx(NULL, nCode, wParam, lParam); - } - - if (nCode < 0) { - return CallNextHookEx(NULL, nCode, wParam, lParam); - } - - - if (nCode >= 0 && wParam == WM_LBUTTONDOWN) { // Now try to run our code. - UnhookWindowsHookEx(_mouseCallbackHook); - - ScreenUtilitiesWindows::PickSelected(); - return 1; - } - - return CallNextHookEx(NULL, nCode, wParam, lParam); -} - -void ScreenUtilitiesWindows::BlockAndReadMouse() -{ - _mouseCallbackHook = SetWindowsHookEx(WH_MOUSE_LL, ScreenUtilsMouseCallback, NULL, NULL); - if (_mouseCallbackHook == NULL) - { - LOG(Warning, "Failed to set mouse hook."); - LOG(Warning, "Error: {0}", GetLastError()); - } -} - -Delegate ScreenUtilities::PickColorDone; - -void ScreenUtilities::PickColor() -{ - ScreenUtilitiesWindows::BlockAndReadMouse(); -} - - -#endif diff --git a/Source/Editor/Utilities/Utils.cs b/Source/Editor/Utilities/Utils.cs index acc0cf605..5f836e069 100644 --- a/Source/Editor/Utilities/Utils.cs +++ b/Source/Editor/Utilities/Utils.cs @@ -1037,9 +1037,7 @@ namespace FlaxEditor.Utilities /// The processed name path. public static string GetAssetNamePath(string path) { - var projectFolder = Globals.ProjectFolder; - if (path.StartsWith(projectFolder)) - path = path.Substring(projectFolder.Length + 1); + path = GetAssetNamePathWithExt(path); return StringUtils.GetPathWithoutExtension(path); } diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.cpp b/Source/Engine/Platform/Linux/LinuxPlatform.cpp index e954dd784..92a26032d 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.cpp +++ b/Source/Engine/Platform/Linux/LinuxPlatform.cpp @@ -5,7 +5,6 @@ #include "LinuxPlatform.h" #include "LinuxWindow.h" #include "LinuxInput.h" -#include "IncludeX11.h" #include "Engine/Core/Log.h" #include "Engine/Core/Types/Guid.h" #include "Engine/Core/Types/String.h" @@ -31,6 +30,7 @@ #include "Engine/Input/Input.h" #include "Engine/Input/Mouse.h" #include "Engine/Input/Keyboard.h" +#include "IncludeX11.h" #include #include #include @@ -88,6 +88,7 @@ X11::Cursor Cursors[(int32)CursorType::MAX]; X11::XcursorImage* CursorsImg[(int32)CursorType::MAX]; Dictionary KeyNameMap; Array KeyCodeMap; +Delegate LinuxPlatform::xEventRecieved; // Message boxes configuration #define LINUX_DIALOG_MIN_BUTTON_WIDTH 64 @@ -2217,8 +2218,6 @@ void LinuxPlatform::BeforeRun() { } -Delegate LinuxPlatform::xEventRecieved; - void LinuxPlatform::Tick() { UnixPlatform::Tick(); @@ -2233,12 +2232,12 @@ void LinuxPlatform::Tick() { X11::XEvent event; X11::XNextEvent(xDisplay, &event); - if (X11::XFilterEvent(&event, 0)) continue; - - xEventRecieved(&event); // Fire this event, since we recieved an event. - + + // External event handling + xEventRecieved(&event); + LinuxWindow* window; switch (event.type) { diff --git a/Source/Engine/Platform/Linux/LinuxPlatform.h b/Source/Engine/Platform/Linux/LinuxPlatform.h index 486674652..e995ab42d 100644 --- a/Source/Engine/Platform/Linux/LinuxPlatform.h +++ b/Source/Engine/Platform/Linux/LinuxPlatform.h @@ -34,7 +34,7 @@ public: static const String& GetHomeDirectory(); /// - /// An event that is fired when an XEvent is recieved by Flax. + /// An event that is fired when an XEvent is received during platform tick. /// static Delegate xEventRecieved; diff --git a/Source/Engine/UI/GUI/Common/IconButton.cs b/Source/Engine/UI/GUI/Common/IconButton.cs deleted file mode 100644 index e2652cd9f..000000000 --- a/Source/Engine/UI/GUI/Common/IconButton.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. - -using System; - -namespace FlaxEngine.GUI -{ - /// - /// Button with an icon. - /// - public class IconButton : Button - { - /// - /// The sprite rendered on the button. - /// - public SpriteHandle ButtonSprite { get; set; } - - /// - /// Whether or not to hide the border of the button. - /// - public bool HideBorder = true; - - /// - /// Initializes a new instance of the class. - /// - /// The sprite used by the button. - public IconButton(SpriteHandle buttonSprite) - : this(0, 0, buttonSprite) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// Position X coordinate - /// Position Y coordinate - /// The sprite used by the button. - /// Width - /// Height - /// Whether or not to hide the border. - public IconButton(float x, float y, SpriteHandle buttonSprite, float width = 120, float height = DefaultHeight, bool hideBorder = true) - : base(x, y, width, height) - { - ButtonSprite = buttonSprite; - BackgroundBrush = new SpriteBrush(ButtonSprite); - HideBorder = hideBorder; - } - - /// - /// Initializes a new instance of the class. - /// - /// Position - /// Size - /// The sprite used by the button. - public IconButton(Float2 location, Float2 size, SpriteHandle buttonSprite) - : this(location.X, location.Y, buttonSprite, size.X, size.Y) - { - } - - /// - /// Sets the colors of the button, taking into account the field.> - /// - /// The color to use. - public override void SetColors(Color color) - { - BackgroundColor = color; - BackgroundColorSelected = color.RGBMultiplied(0.8f); - BackgroundColorHighlighted = color.RGBMultiplied(1.2f); - - BorderColor = HideBorder ? Color.Transparent : color.RGBMultiplied(0.5f); - BorderColorSelected = BorderColor; - BorderColorHighlighted = BorderColor; - } - } -} diff --git a/Source/Engine/Utilities/Screenshot.cpp b/Source/Engine/Utilities/Screenshot.cpp index fbde8043b..7e1d3d902 100644 --- a/Source/Engine/Utilities/Screenshot.cpp +++ b/Source/Engine/Utilities/Screenshot.cpp @@ -3,7 +3,6 @@ #include "Screenshot.h" #include "Engine/Core/Log.h" #include "Engine/Core/Math/Math.h" -#include "Engine/Core/Math/Color32.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Platform/FileSystem.h" #include "Engine/Graphics/Textures/TextureData.h" @@ -11,7 +10,6 @@ #include "Engine/Graphics/GPUResourceProperty.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUSwapChain.h" -#include "Engine/Engine/Engine.h" #include "Engine/Threading/ThreadPoolTask.h" #include "Engine/Engine/Globals.h" #if COMPILE_WITH_TEXTURE_TOOL From 311637616b4825a2dd1c20c14677da314d6fbbd1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 28 May 2023 16:22:34 +0200 Subject: [PATCH 45/45] Fix Android Debug compilation error after recent Tracy update #948 --- Source/ThirdParty/tracy/client/TracyProfiler.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Source/ThirdParty/tracy/client/TracyProfiler.cpp b/Source/ThirdParty/tracy/client/TracyProfiler.cpp index 46a9d36e4..dfbb22a83 100644 --- a/Source/ThirdParty/tracy/client/TracyProfiler.cpp +++ b/Source/ThirdParty/tracy/client/TracyProfiler.cpp @@ -368,7 +368,6 @@ static int64_t SetupHwTimer() InitFailure( "CPU doesn't support invariant TSC.\nDefine TRACY_NO_INVARIANT_CHECK=1 to ignore this error, *if you know what you are doing*.\nAlternatively you may rebuild the application with the TRACY_TIMER_FALLBACK define to use lower resolution timer." ); #endif } -#endif #endif return Profiler::GetTime(); @@ -4784,4 +4783,4 @@ TRACY_API void ___tracy_shutdown_profiler( void ) #endif #endif - +#endif