xiaoxiao921 / DearImGuiInjection

18 stars 3 forks source link

Need help loading image #5

Closed krulci closed 10 months ago

krulci commented 11 months ago

Hello, I am trying to do ImGui.Image() with the texture I received from game, but I kept getting memory issue

Texture unit_texture = new();
IntPtr unit_texturePtr = IntPtr.Zero;
int width = 15;
int height = 15;
UnityMainThreadDispatcher.Enqueue(() =>
{
    unit_texture = Elements.UnitUtility.LoadUnitIconTexture(100101, 6, false);
    unit_texturePtr = unit_texture.GetNativeTexturePtr();
    width = unit_texture.width;
    height = unit_texture.height;
    ImGui.Image(unit_texturePtr, new System.Numerics.Vector2(width, height));
});
ImGui.End();
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
   at ImGuiNET.ImGuiNative.igImage(IntPtr, System.Numerics.Vector2, System.Numerics.Vector2, System.Numerics.Vector2, System.Numerics.Vector4, System.Numerics.Vector4)
--------------------------------
   at ImGuiNET.ImGui.Image(IntPtr, System.Numerics.Vector2)
   at PrincessStudio.Overlay.CharaEditor+<>c__DisplayClass4_0.<Show>b__0()
   at UnityMainThreadDispatcher+<ActionWrapper>d__8.MoveNext()
   at BepInEx.Unity.IL2CPP.Utils.Collections.Il2CppManagedEnumerator.MoveNext()
   at DynamicClass.Trampoline_ByteThisBepInEx.Unity.IL2CPP.Utils.Collections.Il2CppManagedEnumeratorMoveNext(IntPtr, Il2CppInterop.Runtime.Runtime.Il2CppMethodInfo*)
   at Il2CppInterop.Runtime.IL2CPP.il2cpp_runtime_invoke(IntPtr, IntPtr, Void**, IntPtr ByRef)
   at Il2CppInterop.Runtime.IL2CPP.il2cpp_runtime_invoke(IntPtr, IntPtr, Void**, IntPtr ByRef)
   at UnityEngine.MonoBehaviour.StartCoroutine(Il2CppSystem.Collections.IEnumerator)
   at UnityMainThreadDispatcher+<>c__DisplayClass6_0.<Enqueue>b__0()
   at UnityMainThreadDispatcher.Update()
   at DynamicClass.Trampoline_VoidThisUnityMainThreadDispatcherUpdate(IntPtr, Il2CppInterop.Runtime.Runtime.Il2CppMethodInfo*)
   at DynamicClass.Invoker_VoidThis(IntPtr, Il2CppInterop.Runtime.Runtime.Il2CppMethodInfo*, IntPtr, IntPtr*, IntPtr*)

If I were to move the ImGui.Begin and ImGui.End inside the dispatcher, I do not get any errors but nothing show up

xiaoxiao921 commented 10 months ago
Texture unit_texture = new();
IntPtr unit_texturePtr = IntPtr.Zero;
int width = 15;
int height = 15;
UnityMainThreadDispatcher.Enqueue(() =>
{
    unit_texture = Elements.UnitUtility.LoadUnitIconTexture(100101, 6, false);
    unit_texturePtr = unit_texture.GetNativeTexturePtr();
    width = unit_texture.width;
    height = unit_texture.height;
    ImGui.Image(unit_texturePtr, new System.Numerics.Vector2(width, height)); // Can't work
});
ImGui.End();

You can't call imgui function from the unity main thread, you need to call them from the directx (rendering) thread

krulci commented 10 months ago
Texture unit_texture = new();
IntPtr unit_texturePtr = IntPtr.Zero;
int width = 15;
int height = 15;
UnityMainThreadDispatcher.Enqueue(() =>
{
    unit_texture = Elements.UnitUtility.LoadUnitIconTexture(100101, 6, false);
    unit_texturePtr = unit_texture.GetNativeTexturePtr();
    width = unit_texture.width;
    height = unit_texture.height;
    ImGui.Image(unit_texturePtr, new System.Numerics.Vector2(width, height)); // Can't work
});
ImGui.End();

You can't call imgui function from the unity main thread, you need to call them from the directx (rendering) thread

I have also tried loading it from outside but nothing is printed

krulci commented 10 months ago
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at SharpDX.Direct3D11.PixelShaderStage.SetShaderResources(Int32, Int32, IntPtr)
   at DearImGuiInjection.Backends.ImGuiDX11Impl.RenderDrawData(ImGuiNET.ImDrawData*)
   at DearImGuiInjection.Backends.ImGuiDX11.RenderImGui(SharpDX.DXGI.SwapChain, UInt32, UInt32)
   at RendererFinder.Renderers.DX11Renderer.SwapChainPresentHook(IntPtr, UInt32, UInt32)

This is the error I get with the following code:

public class CharaEditor : Window
    {
        private static CharaEditor instance;
        public static CharaEditor Instance => instance ?? new(PsImGuiWindows.CharaEditor.ToString());
        static Texture texture;
        static IntPtr texturePtr = IntPtr.Zero;
        static int width = 0;
        static int height = 0;
        public CharaEditor(string name, Window parent = null) : base(name, parent)
        {
        }
        public new void Show()
        {
            // Get the current process
            Process currentProcess = Process.GetCurrentProcess();

            // Get the main window handle of the current process
            IntPtr mainWindowHandle = currentProcess.MainWindowHandle;

            if (mainWindowHandle != IntPtr.Zero)
            {
                // Get the window rect (position and size)
                if (GetWindowRect(mainWindowHandle, out RECT windowRect))
                {
                    // Calculate the center coordinates
                    int lengthX = 200;
                    int lengthY = 200;
                    int centerX = (windowRect.Right - windowRect.Left - lengthX) / 2;
                    int centerY = (windowRect.Bottom - windowRect.Top - lengthY) / 2;
                    ImGui.SetNextWindowPos(new System.Numerics.Vector2(centerX, centerY));
                    ImGui.SetNextWindowSize(new System.Numerics.Vector2(lengthX, lengthY));
                    ImGui.Begin("Centered Window");
                    UnityMainThreadDispatcher.Enqueue(() =>
                    {
                        texture = UnitUtility.LoadUnitIconTexture(100101, 6);
                        texturePtr = texture.GetNativeTexturePtr();
                        width = texture.width; 
                        height = texture.height;
                        Console.WriteLine($"EnqueuePtr: {texturePtr}; width: {texture.width}; height: {texture.height};");
                    });
                    if (texturePtr != IntPtr.Zero) ImGui.Image(texturePtr, new System.Numerics.Vector2(60, 60));
                    Console.WriteLine($"GuiPtr: {texturePtr}; width: {width}; height: {height};");
                    ImGui.End();
                }
                else
                {
                    Log.Error("Failed to get window rect.");
                }
            }
            else
            {
                Log.Error("Main window handle not found.");
            }
        }

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    }
xiaoxiao921 commented 10 months ago

Now that I remember, I don't think ImGui support drawing unity texture through GetNativeTexturePtr + ImGui.Image

unity gives a ID3D11Resource vs the desired ID3D11ShaderResourceView that imgui internally use, you'll probably have to mess with the DrawList from imgui manually, since this has nothing to do with this repo in particular i'm closing this

krulci commented 10 months ago

Now that I remember, I don't think ImGui support drawing unity texture through GetNativeTexturePtr + ImGui.Image

unity gives a ID3D11Resource vs the desired ID3D11ShaderResourceView that imgui internally use, you'll probably have to mess with the DrawList from imgui manually, since this has nothing to do with this repo in particular i'm closing this

In this case, how would you load a local image? I tried https://github.com/sharpdx/SharpDX-Samples/blob/master/StoreApp/OldSamplesToBeBackPorted/CommonDX/TextureLoader.cs, but it is using a library that is not compatible with the netstandard2.0.SharpDX this repo is using