mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 21:01:52 +00:00
Implemented base class for Com Interface implementations
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using DirectX.Common;
|
||||||
|
using GlitchyEngine.Platform.Windows.Com;
|
||||||
|
|
||||||
|
namespace GlitchyEditor.Platform.Windows;
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
|
public struct IDropSource : IUnknown
|
||||||
|
{
|
||||||
|
public const new Guid IID = .(0x00000121, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46);
|
||||||
|
|
||||||
|
public new VTable* VT { get => (.)mVT; }
|
||||||
|
|
||||||
|
public HResult QueryContinueDrag(BigBool fEscapePressed, uint32 grfKeyState) mut => VT.QueryContinueDrag(&this, fEscapePressed, grfKeyState);
|
||||||
|
public HResult GiveFeedback(DropEffect dwEffect) mut => VT.GiveFeedback(&this, dwEffect);
|
||||||
|
|
||||||
|
[CRepr]
|
||||||
|
public struct VTable : IUnknown.VTable
|
||||||
|
{
|
||||||
|
public new function [CallingConvention(.Stdcall)] HResult(IDropSource* self, BigBool fEscapePressed, uint32 grfKeyState) QueryContinueDrag;
|
||||||
|
public new function [CallingConvention(.Stdcall)] HResult(IDropSource* self, DropEffect dwEffect) GiveFeedback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class IDropSourceImplBase : IUnknownImplBase<IDropSource, IDropSource.VTable>
|
||||||
|
{
|
||||||
|
protected override void InitVTable(ref IDropSource.VTable vTable)
|
||||||
|
{
|
||||||
|
vTable.QueryContinueDrag = => QueryContinueDragImpl;
|
||||||
|
vTable.GiveFeedback = => GiveFeedbackImpl;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall)]
|
||||||
|
private static HResult QueryContinueDragImpl(IDropSource* self, BigBool fEscapePressed, uint32 grfKeyState)
|
||||||
|
{
|
||||||
|
Self instance = GetInstance<Self>(self);
|
||||||
|
|
||||||
|
// TODO: Translate keyStates (MK_CONTROL, etc...)
|
||||||
|
|
||||||
|
if (instance.QueryContinueDrag(fEscapePressed, grfKeyState) case .Ok)
|
||||||
|
{
|
||||||
|
return .S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall)]
|
||||||
|
private static HResult GiveFeedbackImpl(IDropSource* self, DropEffect effect)
|
||||||
|
{
|
||||||
|
Self instance = GetInstance<Self>(self);
|
||||||
|
|
||||||
|
if (instance.GiveFeedback(effect) case .Ok)
|
||||||
|
{
|
||||||
|
return .S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Result<void> QueryContinueDrag(bool escapePressed, uint32 grfKeyState);
|
||||||
|
public abstract Result<void> GiveFeedback(DropEffect effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyDropSource : IDropSourceImplBase
|
||||||
|
{
|
||||||
|
public override Result<void> QueryContinueDrag(bool escapePressed, uint32 grfKeyState)
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Result<void> GiveFeedback(DropEffect effect)
|
||||||
|
{
|
||||||
|
Runtime.NotImplemented();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -9,6 +9,7 @@ using static System.Windows;
|
|||||||
using GlitchyEngine.Math;
|
using GlitchyEngine.Math;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using GlitchyEngine.Platform.Windows.Com;
|
||||||
|
|
||||||
namespace GlitchyEditor.Platform.Windows;
|
namespace GlitchyEditor.Platform.Windows;
|
||||||
|
|
||||||
@@ -191,28 +192,10 @@ public enum TYMED : int32
|
|||||||
NULL = 0,
|
NULL = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class IDropTargetImplBase : RefCounted
|
abstract class IDropTargetImplBase : IUnknownImplBase<IDropTarget, IDropTarget.VTable>
|
||||||
{
|
{
|
||||||
[CRepr]
|
protected override void InitVTable(ref IDropTarget.VTable vTable)
|
||||||
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.DragEnter = => DragEnterImpl;
|
||||||
vTable.DragOver = => DragOverImpl;
|
vTable.DragOver = => DragOverImpl;
|
||||||
vTable.DragLeave = => DragLeaveImpl;
|
vTable.DragLeave = => DragLeaveImpl;
|
||||||
@@ -221,7 +204,7 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
|
|
||||||
public void Register()
|
public void Register()
|
||||||
{
|
{
|
||||||
HResult result = RegisterDragDrop(Application.Instance.Window.[Friend]_windowHandle, &impl);
|
HResult result = RegisterDragDrop(Application.Instance.Window.[Friend]_windowHandle, InterfacePtr);
|
||||||
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 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);
|
Log.EngineLogger.Assert(result case .S_OK);
|
||||||
}
|
}
|
||||||
@@ -234,50 +217,6 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
OleUninitialize();
|
OleUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
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?
|
// TODO: Data object? KeyState?
|
||||||
public abstract Result<DropEffect> OnDragEnter(int2 cursorPosition);
|
public abstract Result<DropEffect> OnDragEnter(int2 cursorPosition);
|
||||||
public abstract Result<DropEffect> OnDragOver(int2 cursorPosition);
|
public abstract Result<DropEffect> OnDragOver(int2 cursorPosition);
|
||||||
@@ -287,7 +226,7 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
[CallingConvention(.Stdcall)]
|
[CallingConvention(.Stdcall)]
|
||||||
private static HResult DragEnterImpl(IDropTarget* self, /*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
private static HResult DragEnterImpl(IDropTarget* self, /*IDataObject*/ IUnknown* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
||||||
{
|
{
|
||||||
Self instance = GetInstance(self);
|
Self instance = GetInstance<Self>(self);
|
||||||
|
|
||||||
Result<DropEffect> result = instance.OnDragEnter(point);
|
Result<DropEffect> result = instance.OnDragEnter(point);
|
||||||
|
|
||||||
@@ -300,7 +239,7 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
[CallingConvention(.Stdcall)]
|
[CallingConvention(.Stdcall)]
|
||||||
private static HResult DragOverImpl(IDropTarget* self, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
private static HResult DragOverImpl(IDropTarget* self, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
||||||
{
|
{
|
||||||
Self instance = GetInstance(self);
|
Self instance = GetInstance<Self>(self);
|
||||||
Result<DropEffect> result = instance.OnDragOver(point);
|
Result<DropEffect> result = instance.OnDragOver(point);
|
||||||
|
|
||||||
if (result case .Ok(out effect))
|
if (result case .Ok(out effect))
|
||||||
@@ -312,7 +251,7 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
[CallingConvention(.Stdcall)]
|
[CallingConvention(.Stdcall)]
|
||||||
private static HResult DragLeaveImpl(IDropTarget* self)
|
private static HResult DragLeaveImpl(IDropTarget* self)
|
||||||
{
|
{
|
||||||
Self instance = GetInstance(self);
|
Self instance = GetInstance<Self>(self);
|
||||||
Result<void> result = instance.OnDragLeave();
|
Result<void> result = instance.OnDragLeave();
|
||||||
|
|
||||||
if (result case .Ok)
|
if (result case .Ok)
|
||||||
@@ -330,7 +269,7 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
[CallingConvention(.Stdcall)]
|
[CallingConvention(.Stdcall)]
|
||||||
private static HResult DropImpl(IDropTarget* self, IDataObject* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
private static HResult DropImpl(IDropTarget* self, IDataObject* dataObject, uint32 grfKeyState, int2 point, ref DropEffect effect)
|
||||||
{
|
{
|
||||||
Self instance = GetInstance(self);
|
Self instance = GetInstance<Self>(self);
|
||||||
|
|
||||||
// render the data into stgm using the data description in fmte
|
// render the data into stgm using the data description in fmte
|
||||||
FORMATETC format = .()
|
FORMATETC format = .()
|
||||||
@@ -368,7 +307,7 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
int endIndex = paths.Length;
|
int endIndex = paths.Length;
|
||||||
|
|
||||||
// StringViews might be invalid until fixup step down below
|
// StringViews might be invalid until fixup step down below
|
||||||
files.Add(StringView(paths, startIndex, endIndex - startIndex));
|
files.Add(StringView(paths, startIndex, endIndex - startIndex - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,7 +320,7 @@ abstract class IDropTargetImplBase : RefCounted
|
|||||||
for (ref StringView path in ref files)
|
for (ref StringView path in ref files)
|
||||||
{
|
{
|
||||||
path.Ptr = paths.Ptr + index;
|
path.Ptr = paths.Ptr + index;
|
||||||
index += path.Length;
|
index += path.Length + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<DropEffect> result = instance.OnDrop(point, files);
|
Result<DropEffect> result = instance.OnDrop(point, files);
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using DirectX.Common;
|
||||||
|
using GlitchyEngine.Core;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace GlitchyEngine.Platform.Windows.Com;
|
||||||
|
|
||||||
|
/// Base class for implementation of an COM-Interface using a Beef-Class.
|
||||||
|
abstract class IUnknownImplBase<TInterface, TVTable> : RefCounter where TInterface : IUnknown, struct where TVTable : IUnknown.VTable
|
||||||
|
{
|
||||||
|
[CRepr]
|
||||||
|
protected struct InterfaceImpl<TInterface>
|
||||||
|
{
|
||||||
|
public TInterface Base;
|
||||||
|
public void* ClassPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
InterfaceImpl<TInterface> impl;
|
||||||
|
|
||||||
|
private static TVTable vTable;
|
||||||
|
|
||||||
|
protected TInterface* InterfacePtr => (TInterface*)&impl;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
impl = .();
|
||||||
|
impl.Base.[Friend]mVT = (IUnknown.VTable*)&vTable;
|
||||||
|
impl.ClassPtr = Internal.UnsafeCastToPtr(this);
|
||||||
|
|
||||||
|
if (vTable.QueryInterface == null)
|
||||||
|
{
|
||||||
|
vTable.QueryInterface = => QueryInterfaceImpl;
|
||||||
|
vTable.AddRef = => AddRefImpl;
|
||||||
|
vTable.Release = => ReleaseImpl;
|
||||||
|
|
||||||
|
InitVTable(ref vTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void InitVTable(ref TVTable vTable);
|
||||||
|
|
||||||
|
/// Get the beef instance from the interface.
|
||||||
|
protected static T GetInstance<T>(IUnknown* self) where T : class
|
||||||
|
{
|
||||||
|
InterfaceImpl<TInterface>* impl = (.)self;
|
||||||
|
|
||||||
|
Object beefInstance = Internal.UnsafeCastToObject(impl.ClassPtr);
|
||||||
|
|
||||||
|
Debug.Assert(beefInstance is T);
|
||||||
|
|
||||||
|
return (T)beefInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall)]
|
||||||
|
private static HResult QueryInterfaceImpl(IUnknown* self, ref Guid riid, void** output)
|
||||||
|
{
|
||||||
|
Self instance = GetInstance<Self>(self);
|
||||||
|
|
||||||
|
HResult result = .E_NOINTERFACE;
|
||||||
|
*output = null;
|
||||||
|
|
||||||
|
if (riid == IUnknown.IID || riid == TInterface.IID)
|
||||||
|
{
|
||||||
|
*output = (IUnknown*)&instance.impl;
|
||||||
|
instance.AddRef();
|
||||||
|
result = .S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall)]
|
||||||
|
private static uint32 AddRefImpl(IUnknown* self)
|
||||||
|
{
|
||||||
|
Self instance = GetInstance<Self>(self);
|
||||||
|
|
||||||
|
instance.AddRef();
|
||||||
|
return (uint32)instance.RefCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall)]
|
||||||
|
private static uint32 ReleaseImpl(IUnknown* self)
|
||||||
|
{
|
||||||
|
Self instance = GetInstance<Self>(self);
|
||||||
|
|
||||||
|
uint32 count = (uint32)instance.ReleaseRefNoDelete();
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
delete instance;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user