mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Basic drag & drop
This commit is contained in:
@@ -5,6 +5,8 @@ using GlitchyEditor.Assets;
|
||||
using GlitchyEditor.Assets.Importers;
|
||||
using GlitchyEditor.Assets.Processors;
|
||||
using GlitchyEditor.Assets.Exporters;
|
||||
using DirectX.Common;
|
||||
using GlitchyEditor.Platform.Windows;
|
||||
|
||||
namespace GlitchyEditor
|
||||
{
|
||||
@@ -16,8 +18,18 @@ namespace GlitchyEditor
|
||||
{
|
||||
Log.ClientLogger = new EditorLogger();
|
||||
Log.EngineLogger = new EditorLogger() { IsEngineLogger = true };
|
||||
|
||||
// TODO: Windows only
|
||||
HResult result = OleInitialize(null);
|
||||
Log.EngineLogger.Assert(result case .S_OK);
|
||||
|
||||
PushLayer(new EditorLayer(args, _contentManager));
|
||||
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
OleUninitialize();
|
||||
}
|
||||
|
||||
protected override IContentManager InitContentManager()
|
||||
|
||||
@@ -15,6 +15,7 @@ using System.IO;
|
||||
using GlitchyEngine.Core;
|
||||
using GlitchyEditor.Assets;
|
||||
using GlitchyEngine.Scripting;
|
||||
using GlitchyEditor.Platform.Windows;
|
||||
|
||||
namespace GlitchyEditor
|
||||
{
|
||||
@@ -115,13 +116,50 @@ namespace GlitchyEditor
|
||||
private bool _showImguiDemoWindow;
|
||||
#endif
|
||||
|
||||
/// Registers a drag'n'drop target that will fire corresponding DragDropEvent using the engine's event system.
|
||||
class GlobalDragDropTarget : IDropTargetImplBase
|
||||
{
|
||||
public override Result<DropEffect> OnDragEnter(int2 cursorPosition)
|
||||
{
|
||||
DragDropEvent event = scope DragDropEvent(.Enter, cursorPosition);
|
||||
Application.Instance.OnEvent(event);
|
||||
return event.OutDropEffect;
|
||||
}
|
||||
|
||||
public override Result<DropEffect> OnDragOver(int2 cursorPosition)
|
||||
{
|
||||
DragDropEvent event = scope DragDropEvent(.Over, cursorPosition);
|
||||
Application.Instance.OnEvent(event);
|
||||
return event.OutDropEffect;
|
||||
}
|
||||
|
||||
public override Result<void> OnDragLeave()
|
||||
{
|
||||
DragDropEvent event = scope DragDropEvent(.Over, .(-1, -1));
|
||||
Application.Instance.OnEvent(event);
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public override Result<DropEffect> OnDrop(int2 cursorPosition)
|
||||
{
|
||||
DragDropEvent event = scope DragDropEvent(.Drop, cursorPosition);
|
||||
Application.Instance.OnEvent(event);
|
||||
return event.OutDropEffect;
|
||||
}
|
||||
}
|
||||
|
||||
private GlobalDragDropTarget _dragDropTarget ~ _?.ReleaseRef();
|
||||
|
||||
[AllowAppend]
|
||||
public this(String[] args, EditorContentManager contentManager) : base("Editor")
|
||||
{
|
||||
Application.Get().Window.IsVSync = true;
|
||||
Application.Instance.Window.IsVSync = true;
|
||||
|
||||
ScriptEngine.ApplicationInfo.IsEditor = true;
|
||||
|
||||
_dragDropTarget = new .();
|
||||
_dragDropTarget.Register();
|
||||
|
||||
_contentManager = contentManager;
|
||||
|
||||
InitGraphics();
|
||||
@@ -675,6 +713,13 @@ namespace GlitchyEditor
|
||||
{
|
||||
ImGui.TextUnformatted("Project Name:");
|
||||
ImGui.InputText("##projectName", &projectNameBuffer, projectNameBuffer.Count - 1);
|
||||
|
||||
StringView projectName = StringView(&projectNameBuffer);
|
||||
|
||||
if (projectName.IsWhiteSpace)
|
||||
{
|
||||
ImGui.TextColored(.(1, 0, 0, 1), "Project Name required!");
|
||||
}
|
||||
|
||||
ImGui.NewLine();
|
||||
|
||||
@@ -693,7 +738,6 @@ namespace GlitchyEditor
|
||||
}
|
||||
}
|
||||
|
||||
StringView projectName = StringView(&projectNameBuffer);
|
||||
StringView directory = StringView(&projectDirectoryBuffer);
|
||||
|
||||
String target = scope String();
|
||||
@@ -703,9 +747,9 @@ namespace GlitchyEditor
|
||||
|
||||
ImGui.Text($"The Project will be in:\n{target}");
|
||||
|
||||
if (Directory.Exists(target))
|
||||
if (Directory.Exists(target) && !Directory.IsEmpty(target))
|
||||
{
|
||||
ImGui.TextColored(.(1, 0, 0, 1), "The directory is not empty!");
|
||||
ImGui.TextColored(.(1, 1, 0, 1), "The directory is not empty!");
|
||||
}
|
||||
|
||||
ImGui.NewLine();
|
||||
@@ -1521,6 +1565,7 @@ namespace GlitchyEditor
|
||||
dispatcher.Dispatch<WindowResizeEvent>(scope (e) => OnWindowResize(e));
|
||||
dispatcher.Dispatch<KeyPressedEvent>(scope (e) => OnKeyPressed(e));
|
||||
dispatcher.Dispatch<MouseScrolledEvent>(scope (e) => OnMouseScrolled(e));
|
||||
dispatcher.Dispatch<DragDropEvent>(scope (e) => OnDragDrop(e));
|
||||
}
|
||||
|
||||
private bool OnWindowResize(WindowResizeEvent e)
|
||||
@@ -1611,6 +1656,31 @@ namespace GlitchyEditor
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool _isDraggingFromOutside;
|
||||
private bool _droppedFromOutside;
|
||||
private DropEffect _effectWhenDropping = .None;
|
||||
|
||||
private bool OnDragDrop(DragDropEvent e)
|
||||
{
|
||||
Log.EngineLogger.Info($"D'n'D: {e.DragDropType} {e.CursorPosition.X} {e.CursorPosition.Y}");
|
||||
|
||||
switch (e.DragDropType)
|
||||
{
|
||||
case .Enter:
|
||||
_isDraggingFromOutside = true;
|
||||
_droppedFromOutside = false;
|
||||
case .Over:
|
||||
case .Leave:
|
||||
_isDraggingFromOutside = false;
|
||||
case .Drop:
|
||||
_droppedFromOutside = true;
|
||||
}
|
||||
|
||||
e.OutDropEffect = _effectWhenDropping;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
using System;
|
||||
using DirectX.Common;
|
||||
using DirectX.Math;
|
||||
using GlitchyEngine;
|
||||
using GlitchyEngine.Events;
|
||||
using static System.Windows;
|
||||
using GlitchyEngine.Math;
|
||||
|
||||
namespace GlitchyEditor.Platform.Windows;
|
||||
|
||||
// This entire thing is so platform dependent, that it really doesn't make sense to abstract while we are windows only.
|
||||
|
||||
static
|
||||
{
|
||||
[Import("Ole32.lib"), CLink]
|
||||
public static extern HResult OleInitialize(void* reserved);
|
||||
[Import("Ole32.lib"), CLink]
|
||||
public static extern void OleUninitialize();
|
||||
[Import("Ole32.lib"), CLink]
|
||||
public static extern HResult RegisterDragDrop(HWnd windowHandle, IDropTarget* dropTarget);
|
||||
}
|
||||
|
||||
[CRepr]
|
||||
struct IDropTarget : IUnknown
|
||||
{
|
||||
public static new Guid IID => .("00000122-0000-0000-C000-000000000046");
|
||||
|
||||
[CRepr]
|
||||
public struct VTable : IUnknown.VTable
|
||||
{
|
||||
public function [CallingConvention(.Stdcall)] HResult(IDropTarget* self, /*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect) DragEnter;
|
||||
public function [CallingConvention(.Stdcall)] HResult(IDropTarget* self, uint32 grfKeyState, int2 point, ref DropEffect effect) DragOver;
|
||||
public function [CallingConvention(.Stdcall)] HResult(IDropTarget* self) DragLeave;
|
||||
public function [CallingConvention(.Stdcall)] HResult(IDropTarget* self, /*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect) Drop;
|
||||
}
|
||||
|
||||
public new VTable* VT => (VTable*)mVT;
|
||||
|
||||
public HResult DragEnter(/*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect) mut
|
||||
{
|
||||
return VT.DragEnter(&this, dataObject, grfKeyState, point, ref effect);
|
||||
}
|
||||
|
||||
public HResult DragOver(uint32 grfKeyState, int2 point, ref DropEffect effect) mut
|
||||
{
|
||||
return VT.DragOver(&this, grfKeyState, point, ref effect);
|
||||
}
|
||||
|
||||
public HResult DragLeave() mut
|
||||
{
|
||||
return VT.DragLeave(&this);
|
||||
}
|
||||
|
||||
public HResult Drop(/*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect) mut
|
||||
{
|
||||
return VT.Drop(&this, dataObject, grfKeyState, point, ref effect);
|
||||
}
|
||||
}
|
||||
|
||||
[CRepr]
|
||||
enum DropEffect
|
||||
{
|
||||
None = 0,
|
||||
Copy = 1,
|
||||
Move = 2,
|
||||
Link = 4,
|
||||
Scroll = 0x80000000,
|
||||
}
|
||||
|
||||
abstract class IDropTargetImplBase : RefCounted
|
||||
{
|
||||
[CRepr]
|
||||
private struct IDropTargetImpl : IDropTarget
|
||||
{
|
||||
public void* ClassPtr;
|
||||
}
|
||||
|
||||
IDropTargetImpl impl;
|
||||
|
||||
IDropTarget.VTable vTable;
|
||||
|
||||
public this()
|
||||
{
|
||||
impl = .();
|
||||
impl.[Friend]mVT = &vTable;
|
||||
impl.ClassPtr = Internal.UnsafeCastToPtr(this);
|
||||
|
||||
vTable.QueryInterface = => QueryInterfaceImpl;
|
||||
vTable.AddRef = => AddRefImpl;
|
||||
vTable.Release = => ReleaseImpl;
|
||||
|
||||
vTable.DragEnter = => DragEnterImpl;
|
||||
vTable.DragOver = => DragOverImpl;
|
||||
vTable.DragLeave = => DragLeaveImpl;
|
||||
vTable.Drop = => DropImpl;
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
HResult result = RegisterDragDrop(Application.Instance.Window.[Friend]_windowHandle, &impl);
|
||||
Log.EngineLogger.Assert(result not case .E_OUTOFMEMORY, "Failed to register drag drop handler (E_OUTOFMEMORY). Make sure you called OleInitialize and not CoInitialize[Ex]");
|
||||
Log.EngineLogger.Assert(result case .S_OK);
|
||||
}
|
||||
|
||||
private static IDropTargetImplBase GetInstance(IUnknown* self)
|
||||
{
|
||||
IDropTargetImpl* impl = (.)self;
|
||||
|
||||
return (.)Internal.UnsafeCastToObject(impl.ClassPtr);
|
||||
}
|
||||
|
||||
private static HResult QueryInterfaceImpl(IUnknown* self, ref Guid riid, void** output)
|
||||
{
|
||||
Self instance = GetInstance(self);
|
||||
|
||||
HResult result = .E_NOINTERFACE;
|
||||
*output = null;
|
||||
|
||||
if (riid == IUnknown.IID || riid == IDropTarget.IID)
|
||||
{
|
||||
*output = (IUnknown*)&instance.impl;
|
||||
instance.AddRef();
|
||||
result = .S_OK;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static uint32 AddRefImpl(IUnknown* self)
|
||||
{
|
||||
Self instance = GetInstance(self);
|
||||
|
||||
instance.AddRef();
|
||||
return (uint32)instance.RefCount;
|
||||
}
|
||||
|
||||
private static uint32 ReleaseImpl(IUnknown* self)
|
||||
{
|
||||
Self instance = GetInstance(self);
|
||||
|
||||
uint32 count = (uint32)instance.ReleaseRefNoDelete();
|
||||
|
||||
if (count == 0)
|
||||
delete instance;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// TODO: Data object? KeyState?
|
||||
public abstract Result<DropEffect> OnDragEnter(int2 cursorPosition);
|
||||
public abstract Result<DropEffect> OnDragOver(int2 cursorPosition);
|
||||
public abstract Result<void> OnDragLeave();
|
||||
public abstract Result<DropEffect> OnDrop(int2 cursorPosition);
|
||||
|
||||
[CallingConvention(.Stdcall)]
|
||||
private static HResult DragEnterImpl(IDropTarget* self, /*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
||||
{
|
||||
Self instance = GetInstance(self);
|
||||
|
||||
Result<DropEffect> result = instance.OnDragEnter(point);
|
||||
|
||||
if (result case .Ok(out effect))
|
||||
return .S_OK;
|
||||
|
||||
return .E_FAIL;
|
||||
}
|
||||
|
||||
[CallingConvention(.Stdcall)]
|
||||
private static HResult DragOverImpl(IDropTarget* self, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
||||
{
|
||||
Self instance = GetInstance(self);
|
||||
Result<DropEffect> result = instance.OnDragOver(point);
|
||||
|
||||
if (result case .Ok(out effect))
|
||||
return .S_OK;
|
||||
|
||||
return .E_FAIL;
|
||||
}
|
||||
|
||||
[CallingConvention(.Stdcall)]
|
||||
private static HResult DragLeaveImpl(IDropTarget* self)
|
||||
{
|
||||
Self instance = GetInstance(self);
|
||||
Result<void> result = instance.OnDragLeave();
|
||||
|
||||
if (result case .Ok)
|
||||
return .S_OK;
|
||||
|
||||
return .E_FAIL;
|
||||
}
|
||||
|
||||
[CallingConvention(.Stdcall)]
|
||||
private static HResult DropImpl(IDropTarget* self, /*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
||||
{
|
||||
Self instance = GetInstance(self);
|
||||
Result<DropEffect> result = instance.OnDrop(point);
|
||||
|
||||
if (result case .Ok(out effect))
|
||||
return .S_OK;
|
||||
|
||||
return .E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
bool b1;
|
||||
int32 i32;
|
||||
bool b2;
|
||||
int64 i64;
|
||||
int32 i322;
|
||||
}
|
||||
|
||||
struct SB
|
||||
{
|
||||
int64 i64;
|
||||
int32 i32;
|
||||
int32 i322;
|
||||
bool b1;
|
||||
bool b2;
|
||||
}
|
||||
|
||||
struct SC
|
||||
{
|
||||
bool b1;
|
||||
//filler 56
|
||||
int32 i32;
|
||||
//filler 32
|
||||
bool b2;
|
||||
//filler 56
|
||||
int64 i64;
|
||||
int32 i322;
|
||||
//filler 32
|
||||
}
|
||||
|
||||
public enum DragDropType
|
||||
{
|
||||
Enter,
|
||||
Over,
|
||||
Leave,
|
||||
Drop
|
||||
}
|
||||
|
||||
public class DragDropEvent : Event, IEvent
|
||||
{
|
||||
public override EventType EventType => .DragDropEvent;
|
||||
|
||||
public override StringView Name => "DragDropEvent";
|
||||
|
||||
public override EventCategory Category => .Application;
|
||||
|
||||
public static EventType StaticType => .DragDropEvent;
|
||||
|
||||
public DragDropType DragDropType { get; private set; }
|
||||
public int2 CursorPosition { get; private set; }
|
||||
|
||||
public DropEffect OutDropEffect { get; set; }
|
||||
|
||||
// TODO: Keys, or perhaps just make the listeners query them...
|
||||
|
||||
public this(DragDropType dragDropType, int2 cursorPosition)
|
||||
{
|
||||
DragDropType = dragDropType;
|
||||
CursorPosition = cursorPosition;
|
||||
}
|
||||
}
|
||||
|
||||
namespace GlitchyEngine.Events
|
||||
{
|
||||
public extension EventType
|
||||
{
|
||||
case DragDropEvent;
|
||||
}
|
||||
}
|
||||
Vendored
+1
-1
Submodule GlitchyEngine/vendor/directx updated: a973c396ea...65f5bbbf01
Reference in New Issue
Block a user