using System.Runtime.InteropServices;
using UnityEngine; // For Debug.LogWarning, Color
using System; // For IntPtr
// Define C# equivalent of your custom enum from C++ header
// Place this outside the static class if other scripts need it directly
public enum CoVinceOverlayTextAlignment
{
LEFT = 0x01,
CENTER = 0x02,
RIGHT = 0x04,
TOP = 0x08,
VCENTER = 0x10,
BOTTOM = 0x20
}
// Define C# equivalent of your HRESULTs from C++ header
// Place this outside the static class if other scripts need it directly
public enum OverlayHResult : int
{
// Standard Success
S_OK = 0,
// Standard Errors (Use unchecked cast for negative hex literals)
E_FAIL = unchecked((int)0x80004005),
E_POINTER = unchecked((int)0x80004003),
E_INVALIDARG = unchecked((int)0x80070057),
E_OUTOFMEMORY = unchecked((int)0x8007000E),
E_NOTIMPL = unchecked((int)0x80004001), // Not Implemented
// Custom Errors (Calculated from MAKE_HRESULT(1, 19, code))
COVINCE_E_WINDOW_CREATION_FAILED = unchecked((int)0x80130001), // Code 1
COVINCE_E_ALREADY_INITIALIZED = unchecked((int)0x80130002), // Code 2 (Maybe unused)
COVINCE_E_NOT_INITIALIZED = unchecked((int)0x80130003), // Code 3
COVINCE_E_INVALID_MONITOR_INDEX = unchecked((int)0x80130004), // Code 4
COVINCE_E_STRING_COPY_FAILED = unchecked((int)0x80130005), // Code 5
COVINCE_E_TEXT_TOO_LONG = unchecked((int)0x80130006), // Code 6
COVINCE_E_CLASS_REGISTRATION_FAILED = unchecked((int)0x80130007), // Code 7
COVINCE_E_GENERIC_ERROR = unchecked((int)0x80130064) // Code 100
}
/// <summary>
/// Static wrapper class for interacting with the native CoVince Windows Overlay DLL.
/// Handles platform checks and provides safe methods.
/// Only functional on Windows Editor (x64) and Windows Standalone (x64).
/// </summary>
public static class NativeOverlayInterface
{
// --- Determine Platform Support and DLL Name ---
#if UNITY_EDITOR_WIN && UNITY_64
// Windows Editor 64-bit: Use Debug 64-bit DLL
private const string DllName = "CoVinceWindowsOverlay_DB_x64";
private const bool _IsSupported = true;
#elif UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64
// Standalone Windows 64-bit ONLY: Use Release 64-bit DLL
private const string DllName = "CoVinceWindowsOverlay_RL_x64";
private const bool _IsSupported = true;
#else
// All other platforms OR unsupported Windows architectures (e.g., x86 Standalone)
private const string DllName = "BuildTargetNotSupported"; // Dummy name
private const bool _IsSupported = false;
#endif
// Public property to check support from other scripts
public static bool IsSupportedPlatform => _IsSupported;
// --- Actual DLL Imports (Only declared on supported targets) ---
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ShowOverlay")]
private static extern int ShowOverlay_Internal([MarshalAs(UnmanagedType.LPWStr)] string text, bool showText, int borderWidth, int r, int g, int b, int fontSize, int alignment);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ShowOverlayOnMonitor")]
private static extern int ShowOverlayOnMonitor_Internal(int monitorIndex, [MarshalAs(UnmanagedType.LPWStr)] string text, bool showText, int borderWidth, int r, int g, int b, int fontSize, int alignment);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "HideOverlay")]
private static extern int HideOverlay_Internal();
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ShowOverlayText")]
private static extern int ShowOverlayText_Internal(bool show);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayText")]
private static extern int UpdateOverlayText_Internal([MarshalAs(UnmanagedType.LPWStr)] string text);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayFontSize")]
private static extern int UpdateOverlayFontSize_Internal(int fontSize);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayWidth")]
private static extern int UpdateOverlayWidth_Internal(int borderWidth);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayColor")]
private static extern int UpdateOverlayColor_Internal(int r, int g, int b);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "UpdateOverlayAlignment")]
private static extern int UpdateOverlayAlignment_Internal(int alignment); // Pass enum as int
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "AddOrUpdatePointer")]
private static extern int AddOrUpdatePointer_Internal([MarshalAs(UnmanagedType.LPWStr)] string userId, [MarshalAs(UnmanagedType.LPWStr)] string userName, int x, int y, [MarshalAs(UnmanagedType.LPWStr)] string imagePath, int desiredWidth, int desiredHeight);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "RemovePointer")]
private static extern int RemovePointer_Internal([MarshalAs(UnmanagedType.LPWStr)] string userId);
[DllImport(DllName, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ClearAllPointers")]
private static extern int ClearAllPointers_Internal();
// Add any other necessary DllImports here...
#endif // End of Windows x64 / Editor specific DllImports
// --- Public Static Wrapper Methods (Defined for ALL platforms) ---
// These provide a consistent API for other scripts to call.
public static OverlayHResult ShowOverlay(string text, bool showText, int borderWidth, Color color, int fontSize, CoVinceOverlayTextAlignment alignment)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int r = (int)(color.r * 255); int g = (int)(color.g * 255); int b = (int)(color.b * 255);
int result = ShowOverlay_Internal(text ?? "", showText, borderWidth, r, g, b, fontSize, (int)alignment);
if (result != 0) Debug.LogWarning($"ShowOverlay failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
Debug.LogWarning("NativeOverlayInterface.ShowOverlay not supported on this build target.");
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult ShowOverlayOnMonitor(int monitorIndex, string text, bool showText, int borderWidth, Color color, int fontSize, CoVinceOverlayTextAlignment alignment)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int r = (int)(color.r * 255); int g = (int)(color.g * 255); int b = (int)(color.b * 255);
int result = ShowOverlayOnMonitor_Internal(monitorIndex, text ?? "", showText, borderWidth, r, g, b, fontSize, (int)alignment);
if (result != 0) Debug.LogWarning($"ShowOverlayOnMonitor failed for index {monitorIndex}. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
Debug.LogWarning("NativeOverlayInterface.ShowOverlayOnMonitor not supported on this build target.");
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult HideOverlay()
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = HideOverlay_Internal();
if (result != 0) Debug.LogWarning($"HideOverlay failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
return OverlayHResult.S_OK; // Hiding non-existent overlay is fine
#endif
}
public static OverlayHResult ShowOverlayText(bool show)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = ShowOverlayText_Internal(show);
if (result != 0) Debug.LogWarning($"ShowOverlayText failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult UpdateOverlayText(string text)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = UpdateOverlayText_Internal(text ?? "");
if (result != 0) Debug.LogWarning($"UpdateOverlayText failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult UpdateOverlayFontSize(int fontSize)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = UpdateOverlayFontSize_Internal(fontSize);
if (result != 0) Debug.LogWarning($"UpdateOverlayFontSize failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult UpdateOverlayWidth(int borderWidth)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = UpdateOverlayWidth_Internal(borderWidth);
if (result != 0) Debug.LogWarning($"UpdateOverlayWidth failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult UpdateOverlayColor(Color color)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int r = (int)(color.r * 255); int g = (int)(color.g * 255); int b = (int)(color.b * 255);
int result = UpdateOverlayColor_Internal(r, g, b);
if (result != 0) Debug.LogWarning($"UpdateOverlayColor failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult UpdateOverlayAlignment(CoVinceOverlayTextAlignment alignment)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = UpdateOverlayAlignment_Internal((int)alignment);
if (result != 0) Debug.LogWarning($"UpdateOverlayAlignment failed. HRESULT: 0x{result:X}");
return (OverlayHResult)result;
#else
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult AddOrUpdatePointer(string userId, string userName, int x, int y, string imagePath, int desiredWidth, int desiredHeight)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = AddOrUpdatePointer_Internal(userId, userName ?? "Unknown", x, y, imagePath, desiredWidth, desiredHeight);
// Don't log warning here by default, as E_FAIL from image load is expected if file missing
// if (result != 0 && result != (int)OverlayHResult.E_FAIL) Debug.LogWarning($"AddOrUpdatePointer returned non-success HRESULT for {userId}: 0x{result:X}");
return (OverlayHResult)result;
#else
Debug.LogWarning("NativeOverlayInterface.AddOrUpdatePointer not supported on this build target.");
return OverlayHResult.E_NOTIMPL;
#endif
}
public static OverlayHResult RemovePointer(string userId)
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = RemovePointer_Internal(userId);
if (result != 0) Debug.LogWarning($"RemovePointer failed for {userId}. HRESULT: 0x{result:X}"); // S_OK expected even if not found
return (OverlayHResult)result;
#else
return OverlayHResult.E_NOTIMPL; // Or S_OK? E_NOTIMPL seems better.
#endif
}
public static OverlayHResult ClearAllPointers()
{
#if UNITY_EDITOR_WIN || (UNITY_STANDALONE_WIN && UNITY_STANDALONE_WIN64)
int result = ClearAllPointers_Internal();
if (result != 0) Debug.LogWarning($"ClearAllPointers failed. HRESULT: 0x{result:X}"); // Should likely return S_OK
return (OverlayHResult)result;
#else
return OverlayHResult.S_OK; // Clearing non-existent pointers is fine
#endif
}
} // End Class