Possible Bug - Only absolute file paths work with LibFree()

Hi,
So I’m trying to use LibLoad and LibFree to load tiles in and out of my open world. The loading part works fine, but I have a problem where I have to specify an absolute file path to use LibFree(). Here is what my code looks like :

from bge import logic, eventsimport GameLogic
import bge


controller = GameLogic.getCurrentController()
obj = controller.owner
name = obj.name


path = "//" + name + ".blend"


def load():
    logic.LibLoad(path, "Scene")


def free():
    logic.LibFree(path)

This script is attached to an object in my world, for example an empty named F4. Than the code finds “F4.Blend” in the local directory and loads it. Everything works fine at first, but this DOES NOT WORK for unloading the blend using LibFree. if I change the last line of the code to be:

logic.LibFree("C:\\Users\\ThisIsMyUserName\\Desktop\\Game\\F4.blend")

Than everything works fine. But this isn’t practical, especially if I use this on any computer other than my own. Is there a way I can use local directories for LibFree?

ALWAYS WORK IN GLOBAL PATHS.

Every time in your program that you have a relative path, the first thing you should do is globalify it. This is simple: bge.logic.expandPath. Once you’ve done that, you know that unless the use does something strange, your path be valid, and does not depend on the working directory of the game.

So if your code, instead, was:


from bge import logic, eventsimport GameLogic
import bge

controller = GameLogic.getCurrentController()
obj = controller.owner
name = obj.name

path = bge.logic.expandPath("//" + name + ".blend")

def load():
    logic.LibLoad(path, "Scene")

def free():
    logic.LibFree(path)

Then it would work.

Also, I’d prefer your script to read:

import bge

controller = bge.logic.getCurrentController()
obj = controller.owner
name = obj.name

path = bge.logic.expandPath("//" + name + ".blend")

def load():
    logic.LibLoad(path, "Scene")


def free():
    logic.LibFree(path)

No need to do all those other imports. GameLogic is deprecated in favour of bge.logic, and if you’re importing bge, there’s no point doing any "from bge import " because you can access it using bge._

1 Like

LibFree() does not need a path. Why should it? It does not work with files, it works with data in memory.

The single parameter if LibFree is the name of the library. You get the library name when you create the library via LibNew [explicit name] or via LibLoad [implicit]. LibLoad provides the library name via the return value.

On LibLoad the library name does not matter as you have no influence on it. Just store the name somewhere to be used on LibFree.

Examples

load_asset:


import bge

controller = bge.logic.getCurrentController()

if all(sensor.positive for sensor in controller.sensors):
    
    status = bge.logic.LibLoad("//asset.blend", "Scene")
    owner = controller.owner
    owner["loaded_library_name"] = status.libraryName
    print( "loaded " + status.libraryName )

unload_asset:


import bge

controller = bge.logic.getCurrentController()
owner = controller.owner

if (all(sensor.positive for sensor in controller.sensors) and
   "loaded_library_name" in owner):
    libraryName = owner.get("loaded_library_name")
    bge.logic.LibFree(libraryName)
    del owner["loaded_library_name"]
    print( "unloaded", libraryName)

Remark

I’m pretty sure the absolute path as library name is chosen to avoid loading the same blend file multiple times.