Replace the bare-bones stock map with a full Dear ImGui in-game overlay (M key). The overlay shares the same toolbar and compass as the OS popout window: Follow, Pop Out, Gear, rotation compass. Pop Out button is now in the bottom toolbar where it is actually visible. Pressing it (or F10) closes the overlay, waits 0.5 s for the camera to release, then opens the OS popout window. Closing the popout restores the overlay if it was running when the launch was triggered. Pressing M while the popout is open closes the popout and reopens the overlay. Harmony patches intercept MapWindow.Toggle and Show so base-game "Show on map" links and the map hotkey both route through the S3 overlay. MapBypass lets internal S3 calls through without triggering the patch recursively. Camera ownership is enforced in LateUpdate so no base-game script can reset targetTexture before the camera renders. Object.Destroy replaces Release() on both RT teardown paths so the D3D address stays live until end-of-frame and cannot be recycled into a new RT mid-frame.
46 lines
1.5 KiB
C#
46 lines
1.5 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
using S3.Core;
|
|
|
|
namespace S3.Modules.Popout;
|
|
|
|
/// <summary>
|
|
/// Preloads the native S3Native.dll from the mod folder before any P/Invoke.
|
|
///
|
|
/// S³ is a pure-UMM install: there is no winhttp proxy and Unity never calls
|
|
/// UnityPluginLoad for our plugin. By loading the DLL ourselves via its full path,
|
|
/// every [DllImport("S3Native")] in <see cref="Native"/> then binds to it by name.
|
|
/// The native renderer lazily initializes its D3D device from the supplied texture,
|
|
/// so the missing UnityPluginLoad is fine — that lazy path becomes the normal one.
|
|
/// </summary>
|
|
internal static class NativeLoader
|
|
{
|
|
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
|
|
private static extern IntPtr LoadLibrary(string lpFileName);
|
|
|
|
private static bool _loaded;
|
|
|
|
public static bool EnsureLoaded()
|
|
{
|
|
if (_loaded) return true;
|
|
|
|
string dll = Path.Combine(Main.ModEntry.Path, "S3Native.dll");
|
|
if (!File.Exists(dll))
|
|
{
|
|
Log.Error($"[popout] native DLL not found: {dll}");
|
|
return false;
|
|
}
|
|
|
|
IntPtr handle = LoadLibrary(dll);
|
|
if (handle == IntPtr.Zero)
|
|
{
|
|
Log.Error($"[popout] LoadLibrary failed (Win32 error {Marshal.GetLastWin32Error()}): {dll}");
|
|
return false;
|
|
}
|
|
|
|
_loaded = true;
|
|
Log.Info($"[popout] native S3Native.dll loaded from {dll}");
|
|
return true;
|
|
}
|
|
}
|