Page 1 of 1

RenPy Cannot find Python Package Panda3d (for Ursina) and Pywin32 (for win32gui)

Posted: Tue Mar 28, 2023 3:12 am
by AzlanCoding
Hello, I'm trying to put the output of ursina engine into RenPy's display. I've managed to do the same in pygame so I'm assuming that if it is possible in pygame, it would also be possible in RenPy. The following is my code with pygame:

Code: Select all

from ursina import *                    # Import the ursina engine
import pygame
#import numpy as np
import win32gui
from win32con import SW_HIDE
from PIL.Image import frombytes, merge#, tobytes

@staticmethod
def hide_window(name):
    try:
        win32gui.ShowWindow(win32gui.FindWindow(None, name), SW_HIDE)
    except win32gui.error:
        print("Error while finding or hiding window")
        return None

def npImageToSurface(npImage):
    if npImage.dtype.name == 'uint16':
        npImage = (cvImage / 256).astype('uint8')
    size = npImage.shape[1::-1]
    if len(npImage.shape) == 2:
        npImage = np.repeat(npImage.reshape(size[1], size[0], 1), 3, axis = 2)
        format = 'RGB'
    else:
        format = 'RGBA' if npImage.shape[2] == 4 else 'RGB'
        npImage[:, :, [0, 2]] = npImage[:, :, [2, 0]]
    surface = pygame.image.frombuffer(npImage.flatten(), size, format)
    return surface.convert_alpha() if format == 'RGBA' else surface.convert()


pygame.init()


window.title = 'Ursina Output'          # The window title
#window.setMinimized(True)

global PyWin

PyWin = pygame.display.set_mode((1280, 720),pygame.RESIZABLE)

global frames
frames = 0

app = Ursina()    # Initialise your Ursina app




window.borderless = False               # Show a border
window.fullscreen = False               # Do not go Fullscreen
window.exit_button.visible = False      # Do not show the in-game red X that loses the window
#window.fps_counter.enabled = True       # Show the FPS (Frames per second) counter

cube = Entity(model='cube', color=color.orange, scale=(2,2,2))

app.graphicsEngine.renderFrame()

def rgba2rgb( rgba, background=(255,255,255) ):
    row, col, ch = rgba.shape

    if ch == 3:
        return rgba

    assert ch == 4, 'RGBA image has 4 channels.'

    rgb = np.zeros( (row, col, 3), dtype='float32' )
    r, g, b, a = rgba[:,:,0], rgba[:,:,1], rgba[:,:,2], rgba[:,:,3]

    a = np.asarray( a, dtype='float32' ) / 255.0

    R, G, B = background

    rgb[:,:,0] = r * a + (1.0 - a) * R
    rgb[:,:,1] = g * a + (1.0 - a) * G
    rgb[:,:,2] = b * a + (1.0 - a) * B

    return np.asarray( rgb, dtype='uint8' )


def update():
    global frames
    global PyWin
    cube.rotation_y += time.dt * 100    # Rotate every time update is called
    if held_keys['t']:                  # If t is pressed
        print(held_keys['t'])           # Print the value
    dr = app.camNode.getDisplayRegion(0)
    tex = dr.getScreenshot()
    data = tex.getRamImage().getData()
    sx=tex.getXSize()
    sy=tex.getYSize()
    b,g,r,a = frombytes("RGBA",(sx,sy),data).split()
    pyGmImg= pygame.image.fromstring(merge("RGBA",(r,g,b,a)).tobytes(),(sx,sy),"RGBA",True)
    PyWin.fill(0)
    PyWin.blit(pyGmImg, (0,0))
    pygame.display.flip()
    if frames < 2:
        hide_window('Ursina Output')
        frames += 1
app.run()
This is the code in script.rpy:

Code: Select all

init python:
        import os
        os.system("python Scripts/pywin32_postinstall.py -install")
        from ursina import *                    # Import the ursina engine
        #import pygame
        import win32gui
        from win32con import SW_HIDE
        from PIL.Image import frombytes, merge#, tobytes

        @staticmethod
        def hide_window(name):
            try:
                win32gui.ShowWindow(win32gui.FindWindow(None, name), SW_HIDE)
            except win32gui.error:
                print("Error while finding or hiding window")
                return None

        def npImageToSurface(npImage):
            if npImage.dtype.name == 'uint16':
                npImage = (cvImage / 256).astype('uint8')
            size = npImage.shape[1::-1]
            if len(npImage.shape) == 2:
                npImage = np.repeat(npImage.reshape(size[1], size[0], 1), 3, axis = 2)
                format = 'RGB'
            else:
                format = 'RGBA' if npImage.shape[2] == 4 else 'RGB'
                npImage[:, :, [0, 2]] = npImage[:, :, [2, 0]]
            surface = pygame.image.frombuffer(npImage.flatten(), size, format)
            return surface.convert_alpha() if format == 'RGBA' else surface.convert()


        #pygame.init()


        window.title = 'Ursina Output'          # The window title
        #window.setMinimized(True)

        global PyWin

        PyWin = pygame.display.set_mode((1280, 720),pygame.RESIZABLE)

        global frames
        frames = 0

        app = Ursina()    # Initialise your Ursina app




        window.borderless = False               # Show a border
        window.fullscreen = False               # Do not go Fullscreen
        window.exit_button.visible = False      # Do not show the in-game red X that loses the window
        #window.fps_counter.enabled = True       # Show the FPS (Frames per second) counter

        cube = Entity(model='cube', color=color.orange, scale=(2,2,2))

        app.graphicsEngine.renderFrame()

        def rgba2rgb( rgba, background=(255,255,255) ):
            row, col, ch = rgba.shape

            if ch == 3:
                return rgba

            assert ch == 4, 'RGBA image has 4 channels.'

            rgb = np.zeros( (row, col, 3), dtype='float32' )
            r, g, b, a = rgba[:,:,0], rgba[:,:,1], rgba[:,:,2], rgba[:,:,3]

            a = np.asarray( a, dtype='float32' ) / 255.0

            R, G, B = background

            rgb[:,:,0] = r * a + (1.0 - a) * R
            rgb[:,:,1] = g * a + (1.0 - a) * G
            rgb[:,:,2] = b * a + (1.0 - a) * B

            return np.asarray( rgb, dtype='uint8' )


        def update():
            global frames
            global PyWin
            cube.rotation_y += time.dt * 100    # Rotate every time update is called
            if held_keys['t']:                  # If t is pressed
                print(held_keys['t'])           # Print the value
            dr = app.camNode.getDisplayRegion(0)
            tex = dr.getScreenshot()
            data = tex.getRamImage().getData()
            sx=tex.getXSize()
            sy=tex.getYSize()
            b,g,r,a = frombytes("RGBA",(sx,sy),data).split()
            pyGmImg= pygame.image.fromstring(merge("RGBA",(r,g,b,a)).tobytes(),(sx,sy),"RGBA",True)
            render.fill(0)
            render.blit(pyGmImg, (0,0))
            #gui.display.flip()
            if frames < 2:
                hide_window('Ursina Output')
                frames += 1
        app.run()
        
When I launch the project I get this traceback:

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/script.rpy", line 30, in script
    init python:
  File "game/script.rpy", line 30, in script
    init python:
  File "game/script.rpy", line 33, in <module>
    from ursina import *                    # Import the ursina engine
ModuleNotFoundError: No module named 'panda3d.core'

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "D:\renpy-8.0.3-sdk\renpy\bootstrap.py", line 277, in bootstrap
    renpy.main.main()
  File "D:\renpy-8.0.3-sdk\renpy\main.py", line 558, in main
    renpy.game.context().run(node)
  File "game/script.rpy", line 30, in script
    init python:
  File "/home/tom/ab/renpy-build/tmp/install.linux-x86_64/lib/python3.9/site-packages/future/utils/__init__.py", line 441, in raise_
  File "game/script.rpy", line 30, in script
    init python:
  File "D:\renpy-8.0.3-sdk\renpy\ast.py", line 1131, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "D:\renpy-8.0.3-sdk\renpy\python.py", line 1061, in py_exec_bytecode
    exec(bytecode, globals, locals)
  File "game/script.rpy", line 33, in <module>
    from ursina import *                    # Import the ursina engine
  File "D:\renpy-8.0.3-sdk\renpy\loader.py", line 1007, in load_module
    exec(code, mod.__dict__) # type: ignore
  File "python-packages/ursina/__init__.py", line 9, in <module>
  File "D:\renpy-8.0.3-sdk\renpy\loader.py", line 1007, in load_module
    exec(code, mod.__dict__) # type: ignore
  File "python-packages/ursina/window.py", line 4, in <module>
ModuleNotFoundError: No module named 'panda3d.core'

Windows-10-10.0.19044 AMD64
Ren'Py 8.0.3.22090809
RenPy Test Project 1.0
Tue Mar 28 15:10:56 2023

I've installed panda3d, ursina, pywin32 and some other packages using the following command:

Code: Select all

pip install -t /python-packages panda3d ursina pywin32 --ignore-installed
I also made sure I ran this command in the 'game' directory of my RenPy project.
The version packages pip installed were for python 3.10, but RenPy uses 3.9. How can I fix this?

Re: Renpy Cannot find Python Package Panda3d (for Ursina) and Pywin32 (for win32gui)

Posted: Tue Mar 28, 2023 3:54 am
by AzlanCoding
I tried installing python 3.9 and running pip from python3.9 and installing panda3d, but RenPy still cannot find panda3d

Re: RenPy Cannot find Python Package Panda3d (for Ursina) and Pywin32 (for win32gui)

Posted: Tue Mar 28, 2023 8:36 pm
by PyTom
In general, you can't expect Ren'Py to be able to import arbitrary Python packages, especially ones that have native dependencies. I especially wouldn't expect a game engine to run inside another game engine.

Re: RenPy Cannot find Python Package Panda3d (for Ursina) and Pywin32 (for win32gui)

Posted: Fri Mar 31, 2023 4:04 am
by AzlanCoding
But will it work if I build from source? (Not planning to export project into an application)

Re: RenPy Cannot find Python Package Panda3d (for Ursina) and Pywin32 (for win32gui)

Posted: Fri Mar 31, 2023 9:00 pm
by PyTom
AzlanCoding wrote: Fri Mar 31, 2023 4:04 am But will it work if I build from source? (Not planning to export project into an application)
I can't answer that. You can see Ren'Py's build system, renpy-build, which will install all the compilers that Ren'Py uses.