Challenges Integrating Ogre in WPF with SWIG and D3DImage Topic is solved

Problems building or running the engine, queries about how to use features etc.
User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

Ogre Version: 14.3 :?:
OS: Windows :?:
Hey everyone :D ,

I've been trying to use Ogre in WPF, but it's been quite challenging. I found some older discussions about this, but they were using Mogre, and a lot has changed with SWIG.

I've created some projects with WinForms, and they work really well because each user control in WinForms has its own Handle, allowing me to display Ogre directly in the control using that Handle. However, in WPF, only the main window has a Handle. I created a custom user control in WinForms and used it in WPF with a WindowsFormsHost, but it’s not exactly what I need. What I really want is to display Ogre in a window (like a PictureBox or Panel) within the main WPF window, so I can add buttons around it to manipulate events in Ogre. The last thing I tried was using D3DImage, but it's not going so well. I know it’s possible because I have a project using this setup with Mogre, but now that I’m trying it with Ogre and SWIG, it’s been tough.

Last edited by Arthurfernandes on Wed Nov 27, 2024 5:17 pm, edited 2 times in total.
paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

it would be helpful, if you share how you did things with Mogre and how you tried to replicate them with SWIG.

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

So, basically, what I'm trying to do is "translate" this old project (https://www.codeproject.com/KB/WPF/OgreInTheWpf.aspx), which uses Mogre, to a new version with SWIG. However, some methods and functions have changed since then.

In the main class, OgreImage, there are basically two problems:

Image

Image


Some updates!

I attempted to modify the load resource function using the new methods provided by SWIG, and here's how it works now. While it may not be elegant, it is functional.

Image

However, I'm still facing an issue with the following line: _renTarget = _texture.getBuffer().getRenderTarget();. It throws the exception: System.ApplicationException: 'invalid vector subscript'.

Image

Image

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

Hey guys, another update! :D

So apparently, SWIG didn’t handle everything correctly. The error in the getRenderTarget() function was due to the TextureUsage enum being missing in the project. I took the enum from the source code, converted it to C#, and now it works—I can get the Render Target! There are other enums that either don’t exist or, worse, exist but are empty, so be careful when trying to use them.

My advice to anyone attempting to use Ogre with SWIG is not to trust the generated code 100%. If something really strange happens, check the original C++ source code.

With all that said, I’m now stuck on another error that’s a bit trickier. After getting the render target, I need a back buffer to point to and render Ogre, but something strange is happening. In Mogre code, there’s a function in the RenderTarget class that gets a custom attribute (see the picture above). I need to pass the attribute I want along with a pointer.

Image

However, the RenderTarget class always returns an error, regardless of any parameter I pass. I discovered that getCustomAttribute is in OgreD3D11RenderWindow too, but I can’t access this class for some reason. Anyway, another day, another error. If I figure this out, I’ll update you all! (All prints above are from the source code).

Image

Image

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

yeah the getIterator() API was deprecated in favor of the foreach style in C++ and thus never added to SWIG at all.

The TextureUsage enum is explicitly ignored here:
https://github.com/OGRECave/ogre/blob/a ... gre.i#L193

I forgot why exactly, but I guess you get type conflicts in C#, if you dont ignore it.

for getCustomAttribute, you might need to explicitly state pData is an output parameter like this:
https://github.com/OGRECave/ogre/blob/a ... gre.i#L567

also, as you have found, D3D11 does not support the same attributes as D3D9, which you use in your original code.

Code: Select all

Finally, I would appreciate if you post your code, using this tag, instead of doing screenshots :)
User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

My apologies for using images instead of code; I'm just an intern, haha! :lol:

I've created a GitHub repository (https://github.com/Arthurfernades/Ogre-3D-with-WPF) to keep everything updated in real time.

After correctly getting the pointer, I've run into a significant challenge: D3DImage can't run DirectX11 natively. The only solution I found so far is to use SharpDX as a wrapper to manually integrate DirectX11 with D3DImage. I'm not sure if this will work, but I haven't found any other options. If anyone knows a better way, please let me know—I’m feeling a bit desperate since this may not be possible to work around

rpgplayerrobin
Gnoll
Posts: 676
Joined: Wed Mar 18, 2009 3:03 am
x 379

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by rpgplayerrobin »

This topic is a bit specific, have you tried getting help from ChatGPT?

For me, it said that you can setup a windows form widget in WPF and then render to that instead (which has a window handle), but ChatGPT is sometimes wrong of course:
https://chatgpt.com/share/6728fbea-444c ... 1d4ffccb43

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

rpgplayerrobin wrote: Mon Nov 04, 2024 5:55 pm

This topic is a bit specific, have you tried getting help from ChatGPT?

For me, it said that you can setup a windows form widget in WPF and then render to that instead (which has a window handle), but ChatGPT is sometimes wrong of course:
https://chatgpt.com/share/6728fbea-444c ... 1d4ffccb43

I created a project using Windows Host, but it doesn't fully meet my needs. I can share it if you’d like; it’s fully functional. Windows Host renders Ogre in a separate window, whereas I’m trying to render directly in WPF using a native component like D3DImage, which would only draw the content I need from Ogre. :|

rpgplayerrobin
Gnoll
Posts: 676
Joined: Wed Mar 18, 2009 3:03 am
x 379

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by rpgplayerrobin »

So it is impossible to add WindowsFormsHost to just any WPF widget?

Like this:

Code: Select all

WindowsFormsHost host = new WindowsFormsHost();
System.Windows.Forms.Panel panel = new System.Windows.Forms.Panel();
host.Child = panel;
MainGrid.Children.Add(host);

Also, there seems to be many things to test if you ask ChatGPT on how to solve this issue, have you tried all of them?

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

It's completely possible, and I’ve already done it, but that’s not what I’m aiming to accomplish right now. In older versions of Ogre with DirectX9, it was possible to render into a D3DImage component in WPF. However, with DirectX11, this approach has become technically unfeasible. Now, I'm exploring other methods to achieve this. ChatGPT provided me with some options, and I'm currently attempting to use SharpDX.

If anyone knows something about using SharpDX with Ogre, please let me know—it would be really helpful.

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

Arthurfernandes wrote: Mon Nov 04, 2024 5:46 pm

After correctly getting the pointer, I've run into a significant challenge: D3DImage can't run DirectX11 natively.

yeah.. I recommend doing this in two steps:

  1. get the MOGRE code for D3D9 running on recent SWIG Ogre with D3D9
  2. port that code to D3D11: https://stackoverflow.com/questions/117 ... directx-11

then you verify that the basic idea is working and can research the issues individually

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

paroj wrote: Tue Nov 05, 2024 12:39 pm
Arthurfernandes wrote: Mon Nov 04, 2024 5:46 pm

After correctly getting the pointer, I've run into a significant challenge: D3DImage can't run DirectX11 natively.

yeah.. I recommend doing this in two steps:

  1. get the MOGRE code for D3D9 running on recent SWIG Ogre with D3D9
  2. port that code to D3D11: https://stackoverflow.com/questions/117 ... directx-11

then you verify that the basic idea is working and can research the issues individually

I’ll try using version 13.6.5. In the meantime, I’m trying to understand how SharpDX works, and here’s a snapshot of the code:

Code: Select all

device = new Device(DriverType.Hardware, DeviceCreationFlags.Debug | DeviceCreationFlags.BgraSupport, FeatureLevel.Level_11_0);

var textureDescription = new Texture2DDescription()
{
    Width = width,
    Height = height,
    ArraySize = 1,
    BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
    Usage = ResourceUsage.Default,
    CpuAccessFlags = CpuAccessFlags.None,
    Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
    MipLevels = 1,
    OptionFlags = ResourceOptionFlags.SharedKeyedmutex,
    SampleDescription = new SampleDescription(1, 0)
};

Texture2D texture = new Texture2D(device, textureDescription);

context = device.ImmediateContext;

Direct3DEx d9context = new Direct3DEx();

SharpDX.Direct3D9.Device d9device = new SharpDX.Direct3D9.Device(d9context,
                                                                 0,
                                                                 DeviceType.Hardware,
                                                                 IntPtr.Zero,
                                                                 CreateFlags.HardwareVertexProcessing,
                                                                 new SharpDX.Direct3D9.PresentParameters()
                                                                 {
                                                                     Windowed = true,
                                                                     SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard,
                                                                     DeviceWindowHandle = new WindowInteropHelper(window).Handle,
                                                                     PresentationInterval = PresentInterval.Default,
                                                                 });

IntPtr renderTextureHandle = texture.QueryInterface<SharpDX.DXGI.Resource>().SharedHandle;


SharpDX.Direct3D9.Texture d9texture = new SharpDX.Direct3D9.Texture(d9device,
                                                                    texture.Description.Width,
                                                                    texture.Description.Height,
                                                                    1,
                                                                    SharpDX.Direct3D9.Usage.RenderTarget,
                                                                    SharpDX.Direct3D9.Format.A8R8G8B8,
                                                                    Pool.Default,
                                                                    ref renderTextureHandle);

d3dImage.Lock();
d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, d9texture.GetSurfaceLevel(0).NativePointer);
d3dImage.Unlock();

If I could get Ogre’s DX11 output in a way that SharpDX can read, maybe this would work. However, I’m not sure how to 'transfer' the Ogre 3D rendering output to SharpDX rendering.

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

I’m having trouble generating the Direct3D9 DLL. CMake was picking up the old DirectX9 path, but Windows 10 no longer uses it. So, I had to download the SDK and manually change the path in the FindDirectX.cmake file to "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)".

Code: Select all

  # construct search paths
  set(DirectX9_PREFIX_PATH 
  "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)"
  )

Now CMake recognizes DirectX9, but after the build finishes, the RenderSystems folder doesn’t generate the Direct3D9 folder, only Direct3D11 and some GL folders. Is there anything else I need to change in order to generate the Direct3D9 DLL?

Image

rpgplayerrobin
Gnoll
Posts: 676
Joined: Wed Mar 18, 2009 3:03 am
x 379

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by rpgplayerrobin »

One thing that comes to mind is this:

Windows no longer installs Direct3D9 redist, but it does come preinstalled with Direct3D11 redists.
So if you are trying to ship a game with (or use) Direct3D9, you must first make sure it is installed on the computer (and you might even have to restart your computer).

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

Arthurfernandes wrote: Thu Nov 07, 2024 5:39 pm

I’m having trouble generating the Direct3D9 DLL. CMake was picking up the old DirectX9 path, but Windows 10 no longer uses it. So, I had to download the SDK and manually change the path in the FindDirectX.cmake file to "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)".

Now CMake recognizes DirectX9, but after the build finishes, the RenderSystems folder doesn’t generate the Direct3D9 folder, only Direct3D11 and some GL folders. Is there anything else I need to change in order to generate the Direct3D9 DLL?

check the CMake output where it says what parts are enabled

Code: Select all

...
Building rendersystems:
  + OpenGL
  + OpenGL 3+
...

also note that the prebuilt SDK comes with D3D9 and C# bindings: https://cloudsmith.io/~ogrecave/repos/ogre/packages/

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

Since @paroj suggested trying with DX9, I've been working on that, and now I'm stuck with something that could be useful in both DX9 and DX11.

The error I'm encountering now is related to the surface pointer I'm trying to use. Basically, after initializing Ogre with a basic scene featuring Sinbad, I call a function to create my render texture.

Code: Select all

public void InitRenderTarget()
{
    texturePtr = TextureManager.getSingleton().createManual(
        "SharedTexture",
        ResourceGroupManager.DEFAULT_RESOURCE_GROUP_NAME,
        TextureType.TEX_TYPE_2D,
        800,
        600,
        32,
        0,
        PixelFormat.PF_R8G8B8A8,
        (int)0x20);

renderTarget = texturePtr.getBuffer().getRenderTarget();            
}

After this, I use the renderTarget to get the custom attribute "DDBACKBUFFER" and set my D3DImage back buffer with the pointer from renderTarget.getCustomAttribute(). Here's the issue: in the old version using Mogre, renderTarget.getCustomAttribute() used to accept two parameters. One was a string indicating the attribute you wanted to use, and the other was an output parameter for a pointer, like this code in Mogre:

Code: Select all

IntPtr surface;
_renTarget.GetCustomAttribute("DDBACKBUFFER", out surface);
SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface, true);

The problem now is that renderTarget.getCustomAttribute() doesn't accept output parameters anymore. Essentially, you're given a pointer that can only be passed without using out or ref. The method is now like this:

Code: Select all

public unsafe void AttachRenderTarget()
{
    try
    {
        IntPtr surface = IntPtr.Zero
        
renderTarget.getCustomAttribute("DDBACKBUFFER", surface); Lock(); SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface, false); } finally { Unlock(); } }

When running the code, an error occurs: "System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'". What I'm trying to do now is use renderTarget.getCustomAttribute("DDBACKBUFFER"), which returns a uint, but after converting the uint to an IntPtr, the same error occurs, but this time on the SetBackBuffer line.

Code: Select all

public unsafe void AttachRenderTarget()
{
    try
    {        
uint p; IntPtr surface = IntPtr.Zero; p = renderTarget.getCustomAttribute("DDBACKBUFFER"); surface = new IntPtr(p); Lock(); SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface, false); } finally { Unlock(); } }

Here is how the code looks now.

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

Another thing I forgot to mention: when I set auto-update to false in the Render System, nothing happens, and only a white WPF screen appears. However, if I change it to true, Ogre shows up, but it appears in the WPF window rather than in the D3DImage as I want.

Code: Select all

IntPtr hWnd = IntPtr.Zero;

foreach (PresentationSource source in PresentationSource.CurrentSources)
{
    var hwndSource = (source as HwndSource);
    if (hwndSource != null)
    {
        hWnd = hwndSource.Handle;
        break;
    }
}

NameValueMap miscParams = new NameValueMap
{
    ["FSAA"] = "0",
    ["Full Screen"] = "No",
    ["VSync"] = "No",
    ["sRGB Gamma Conversion"] = "No",
    ["externalWindowHandle"] = hWnd.ToString()
};

RenderWindow renderWindow = root.createRenderWindow(
    "Window Forms Ogre", //Render Targer name
    1, // Width
    1, // Height
    false, // Windowed mode
    miscParams
    );

renderWindow.setAutoUpdated(true);

Image

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

Last but not least, I made some changes to the code. I think I now have the correct pointer to the texture I created, but there's still no sign of Sinbad. :(

Code: Select all

public unsafe void AttachRenderTarget()
{
    try
    {
        var surface = IntPtr.Zero;

    byte[] buffer = new byte[sizeof(IntPtr)];

    GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);

    renderTarget.getCustomAttribute("DDBACKBUFFER", handle.AddrOfPinnedObject());

    /*uint p = renderTarget.getCustomAttribute("DDBACKBUFFER");
    var surface = new IntPtr(p);*/

    surface = (IntPtr)BitConverter.ToInt64(buffer, 0);                

    Lock();
    SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface, false);
}
finally
{
    Unlock();
}
}

Image

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

Arthurfernandes wrote: Mon Nov 18, 2024 4:40 pm

When running the code, an error occurs: "System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'". What I'm trying to do now is use renderTarget.getCustomAttribute("DDBACKBUFFER"), which returns a uint, but after converting the uint to an IntPtr, the same error occurs, but this time on the SetBackBuffer line.

this is a issue with the SWIG bindings. They need a fix along the lines of (untested):
https://github.com/OGRECave/ogre/pull/3261

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

Arthurfernandes wrote: Mon Nov 18, 2024 5:23 pm

Another thing I forgot to mention: when I set auto-update to false in the Render System, nothing happens, and only a white WPF screen appears. However, if I change it to true, Ogre shows up, but it appears in the WPF window rather than in the D3DImage as I want.

probably you want a hidden main window instead of using the WPF window as the main window. If you pass the WPF window to Ogre you are basically saying: "overwrite the contents of this".

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

paroj wrote: Mon Nov 18, 2024 6:53 pm
Arthurfernandes wrote: Mon Nov 18, 2024 4:40 pm

When running the code, an error occurs: "System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'". What I'm trying to do now is use renderTarget.getCustomAttribute("DDBACKBUFFER"), which returns a uint, but after converting the uint to an IntPtr, the same error occurs, but this time on the SetBackBuffer line.

this is a issue with the SWIG bindings. They need a fix along the lines of (untested):
https://github.com/OGRECave/ogre/pull/3261

While SWING bindings are incorrect, is it possible to use them in another way like this, or are these two approaches completely different?

Code: Select all

public unsafe void AttachRenderTarget()
{
    	try
    	{
        	uint p = renderTarget.getCustomAttribute("DDBACKBUFFER");
		IntPtr surface = new IntPtr(p);
        
renderTarget.getCustomAttribute("DDBACKBUFFER", surface); Lock(); SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface, false); } finally { Unlock(); } }

If it is possible, how can I resolve the "System.AccessViolationException" error?

PS: I made some updates to the current version of the code: https://github.com/Arthurfernades/Ogre-3D-with-WPF.

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

the problem with using uint is that it is (probably) 32bit wide, while pointers on a 64bit system are 64bit wide.
So what you are doing gives you a truncated pointer which results in an access violation. So you need to use the IntPtr(Int64) constructor. Then your workaround should work.
Try printing the pointer value to check whether it is 64bit.

If you are able to build the bindings yourself, you can also try modifying this method to read & return void*:
https://github.com/OGRECave/ogre/blob/a ... get.h#L244

then the bindings should work too.

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

paroj wrote: Tue Nov 19, 2024 4:49 pm

the problem with using uint is that it is (probably) 32bit wide, while pointers on a 64bit system are 64bit wide.
So what you are doing gives you a truncated pointer which results in an access violation. So you need to use the IntPtr(Int64) constructor. Then your workaround should work.
Try printing the pointer value to check whether it is 64bit.

If you are able to build the bindings yourself, you can also try modifying this method to read & return void*:
https://github.com/OGRECave/ogre/blob/a ... get.h#L244

then the bindings should work too.

Even after the changes, I'm still getting the error. At least now I can get an IntPtr 'natively.' I made changes to the SWIG-generated files. Could this be a problem? I need to change the method in .h file?

Image

paroj
OGRE Team Member
OGRE Team Member
Posts: 2106
Joined: Sun Mar 30, 2014 2:51 pm
x 1132

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by paroj »

Changing the .cs files is not enough. I tested and properly fixed the bindings in the pull request linked above. You can wait until the master build is updated.

User avatar
Arthurfernandes
Gnoblar
Posts: 19
Joined: Mon Oct 28, 2024 10:50 pm
x 1

Re: Challenges Integrating Ogre in WPF with SWIG and D3DImage

Post by Arthurfernandes »

paroj wrote: Wed Nov 20, 2024 1:42 am

Changing the .cs files is not enough. I tested and properly fixed the bindings in the pull request linked above. You can wait until the master build is updated.

This part is now working well, and no errors appear after building with the new version. However, the image is still not showing. Do you have any tips on where I might look for something missing or wrong in the code?