showbase: Annotate basic `Loader` methods (#1723)
This commit is contained in:
parent
a7f8c57681
commit
8de98592ca
|
|
@ -2,9 +2,13 @@
|
|||
sound, music, shaders and fonts from disk.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
__all__ = ['Loader']
|
||||
|
||||
from panda3d.core import (
|
||||
AsyncTask,
|
||||
AudioManager,
|
||||
ConfigVariableBool,
|
||||
Filename,
|
||||
FontPool,
|
||||
|
|
@ -24,13 +28,15 @@ from panda3d.core import (
|
|||
from panda3d.core import Loader as PandaLoader
|
||||
from direct.directnotify.DirectNotifyGlobal import directNotify
|
||||
from direct.showbase.DirectObject import DirectObject
|
||||
from . import ShowBase
|
||||
import warnings
|
||||
import sys
|
||||
from typing import Any, Callable, Iterable
|
||||
|
||||
# You can specify a phaseChecker callback to check
|
||||
# a modelPath to see if it is being loaded in the correct
|
||||
# phase
|
||||
phaseChecker = None
|
||||
phaseChecker: Callable[[str, LoaderOptions], object] | None = None
|
||||
|
||||
|
||||
class Loader(DirectObject):
|
||||
|
|
@ -49,16 +55,23 @@ class Loader(DirectObject):
|
|||
# This indicates that this class behaves like a Future.
|
||||
_asyncio_future_blocking = False
|
||||
|
||||
def __init__(self, loader, numObjects, gotList, callback, extraArgs):
|
||||
def __init__(
|
||||
self,
|
||||
loader: Loader | None,
|
||||
numObjects: int,
|
||||
gotList: bool,
|
||||
callback: Callable[..., object] | None,
|
||||
extraArgs: list,
|
||||
) -> None:
|
||||
self._loader = loader
|
||||
self.objects = [None] * numObjects
|
||||
self.objects: list[Any | None] = [None] * numObjects
|
||||
self.gotList = gotList
|
||||
self.callback = callback
|
||||
self.extraArgs = extraArgs
|
||||
self.requests = set()
|
||||
self.requestList = []
|
||||
self.requests: set[AsyncTask] = set()
|
||||
self.requestList: list[AsyncTask] = []
|
||||
|
||||
def gotObject(self, index, object):
|
||||
def gotObject(self, index: int, object) -> None:
|
||||
self.objects[index] = object
|
||||
|
||||
if not self.requests:
|
||||
|
|
@ -79,7 +92,7 @@ class Loader(DirectObject):
|
|||
self.requests = None
|
||||
self.requestList = None
|
||||
|
||||
def cancelled(self):
|
||||
def cancelled(self) -> bool:
|
||||
"Returns true if the request was cancelled."
|
||||
return self.requestList is None
|
||||
|
||||
|
|
@ -87,7 +100,7 @@ class Loader(DirectObject):
|
|||
"Returns true if all the requests were finished or cancelled."
|
||||
return not self.requests
|
||||
|
||||
def result(self):
|
||||
def result(self) -> Any:
|
||||
"Returns the results, suspending the thread to wait if necessary."
|
||||
for r in list(self.requests):
|
||||
r.wait()
|
||||
|
|
@ -126,26 +139,26 @@ class Loader(DirectObject):
|
|||
yield await req
|
||||
|
||||
# special methods
|
||||
def __init__(self, base=None):
|
||||
def __init__(self, base: ShowBase.ShowBase | None = None) -> None:
|
||||
self.base = base
|
||||
self.loader = PandaLoader.getGlobalPtr()
|
||||
|
||||
self._requests = {}
|
||||
self._requests: dict[AsyncTask, tuple[Loader._Callback, int]] = {}
|
||||
|
||||
self.hook = "async_loader_%s" % (Loader.loaderIndex)
|
||||
Loader.loaderIndex += 1
|
||||
|
||||
def destroy(self):
|
||||
def destroy(self) -> None:
|
||||
self.ignore(self.hook)
|
||||
self.loader.stopThreads()
|
||||
del self.base
|
||||
|
||||
def _init_base(self, base):
|
||||
def _init_base(self, base: ShowBase.ShowBase) -> None:
|
||||
self.base = base
|
||||
self.accept(self.hook, self.__gotAsyncObject)
|
||||
|
||||
@classmethod
|
||||
def _loadPythonFileTypes(cls):
|
||||
def _loadPythonFileTypes(cls) -> None:
|
||||
if cls._loadedPythonFileTypes:
|
||||
return
|
||||
|
||||
|
|
@ -168,10 +181,18 @@ class Loader(DirectObject):
|
|||
cls._loadedPythonFileTypes = True
|
||||
|
||||
# model loading funcs
|
||||
def loadModel(self, modelPath, loaderOptions = None, noCache = None,
|
||||
allowInstance = False, okMissing = None,
|
||||
callback = None, extraArgs = [], priority = None,
|
||||
blocking = None):
|
||||
def loadModel(
|
||||
self,
|
||||
modelPath: str | list[str] | tuple[str, ...] | set[str],
|
||||
loaderOptions: LoaderOptions | None = None,
|
||||
noCache: bool | None = None,
|
||||
allowInstance: bool = False,
|
||||
okMissing: bool | None = None,
|
||||
callback: Callable[..., object] | None = None,
|
||||
extraArgs: list = [],
|
||||
priority: int | None = None,
|
||||
blocking: bool | None = None,
|
||||
) -> Any:
|
||||
"""
|
||||
Attempts to load a model or models from one or more relative
|
||||
pathnames. If the input modelPath is a string (a single model
|
||||
|
|
@ -255,6 +276,7 @@ class Loader(DirectObject):
|
|||
if allowInstance:
|
||||
loaderOptions.setFlags(loaderOptions.getFlags() | LoaderOptions.LFAllowInstance)
|
||||
|
||||
modelList: Iterable[str]
|
||||
if not isinstance(modelPath, (tuple, list, set)):
|
||||
# We were given a single model pathname.
|
||||
modelList = [modelPath]
|
||||
|
|
@ -949,7 +971,7 @@ class Loader(DirectObject):
|
|||
TexturePool.releaseTexture(texture)
|
||||
|
||||
# sound loading funcs
|
||||
def loadSfx(self, *args, **kw):
|
||||
def loadSfx(self, *args, **kw) -> Any:
|
||||
"""Loads one or more sound files, specifically designated as a
|
||||
"sound effect" file (that is, uses the sfxManager to load the
|
||||
sound). There is no distinction between sound effect files
|
||||
|
|
@ -959,6 +981,7 @@ class Loader(DirectObject):
|
|||
independently of the other group."""
|
||||
|
||||
# showbase-created sfxManager should always be at front of list
|
||||
assert self.base is not None
|
||||
if self.base.sfxManagerList:
|
||||
return self.loadSound(self.base.sfxManagerList[0], *args, **kw)
|
||||
return None
|
||||
|
|
@ -976,8 +999,14 @@ class Loader(DirectObject):
|
|||
else:
|
||||
return None
|
||||
|
||||
def loadSound(self, manager, soundPath, positional = False,
|
||||
callback = None, extraArgs = []):
|
||||
def loadSound(
|
||||
self,
|
||||
manager: AudioManager,
|
||||
soundPath: str | tuple[str, ...] | list[str] | set[str],
|
||||
positional: bool = False,
|
||||
callback: Callable[..., object] | None = None,
|
||||
extraArgs: list = [],
|
||||
) -> Any:
|
||||
"""Loads one or more sound files, specifying the particular
|
||||
AudioManager that should be used to load them. The soundPath
|
||||
may be either a single filename, or a list of filenames. If a
|
||||
|
|
@ -987,6 +1016,7 @@ class Loader(DirectObject):
|
|||
|
||||
from panda3d.core import AudioLoadRequest
|
||||
|
||||
soundList: Iterable[str]
|
||||
if not isinstance(soundPath, (tuple, list, set)):
|
||||
# We were given a single sound pathname or a MovieAudio instance.
|
||||
soundList = [soundPath]
|
||||
|
|
@ -1112,7 +1142,7 @@ class Loader(DirectObject):
|
|||
else:
|
||||
callback(*(origModelList + extraArgs))
|
||||
|
||||
def __gotAsyncObject(self, request):
|
||||
def __gotAsyncObject(self, request: AsyncTask) -> None:
|
||||
"""A model or sound file or some such thing has just been
|
||||
loaded asynchronously by the sub-thread. Add it to the list
|
||||
of loaded objects, and call the appropriate callback when it's
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ import sys
|
|||
|
||||
@pytest.fixture
|
||||
def loader():
|
||||
return Loader(base=None)
|
||||
loader = Loader(base=None)
|
||||
yield loader
|
||||
loader.destroy()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
|
|||
Loading…
Reference in New Issue