Ballistica Logo

babase package

Submodules

babase.modutils module

Functionality related to modding.

babase.modutils.create_user_system_scripts() None[source]

Set up a copy of Ballistica app scripts under user scripts dir.

(for editing and experimenting)

babase.modutils.delete_user_system_scripts() None[source]

Clean out the scripts created by create_user_system_scripts().

babase.modutils.get_human_readable_user_scripts_path() str[source]

Return a human readable location of user-scripts.

This is NOT a valid filesystem path; may be something like “(SD Card)”.

babase.modutils.show_user_scripts() None[source]

Open or nicely print the location of the user-scripts directory.

Module contents

Common shared Ballistica components.

For modding purposes, this package should generally not be used directly. Instead one should use purpose-built packages such as bascenev1 or bauiv1 which themselves import various functionality from here and reexpose it in a more focused way.

class babase.AccountV2Handle

Bases: object

Handle for interacting with a V2 account.

This class supports the ‘with’ statement, which is how it is used with some operations such as cloud messaging.

accountid: str
logins: dict[LoginType, LoginInfo]
tag: str
workspaceid: str | None
workspacename: str | None
class babase.AccountV2Subsystem

Bases: object

Subsystem for modern account handling in the app.

Category: App Classes

Access the single shared instance of this class at ‘ba.app.plus.accounts’.

do_get_primary() AccountV2Handle | None[source]

Internal - should be overridden by subclass.

have_primary_credentials() bool[source]

Are credentials currently set for the primary app account?

Note that this does not mean these credentials have been checked for validity; only that they exist. If/when credentials are validated, the ‘primary’ account handle will be set.

on_active_logins_changed(logins: dict[LoginType, str]) None[source]

Should be called when logins for the active account change.

on_app_loading() None[source]

Should be called at standard on_app_loading time.

on_cloud_connectivity_changed(connected: bool) None[source]

Should be called with cloud connectivity changes.

on_implicit_login_state_changed(login_type: LoginType, state: LoginAdapter.ImplicitLoginState | None) None[source]

Called when implicit login state changes.

Login systems that tend to sign themselves in/out in the background are considered implicit. We may choose to honor or ignore their states, allowing the user to opt for other login types even if the default implicit one can’t be explicitly logged out or otherwise controlled.

on_implicit_sign_in(login_type: LoginType, login_id: str, display_name: str) None[source]

An implicit sign-in happened (called by native layer).

on_implicit_sign_out(login_type: LoginType) None[source]

An implicit sign-out happened (called by native layer).

on_no_initial_primary_account() None[source]

Callback run if the app has no primary account after launch.

Either this callback or on_primary_account_changed will be called within a few seconds of app launch; the app can move forward with the startup sequence at that point.

on_primary_account_changed(account: AccountV2Handle | None) None[source]

Callback run after the primary account changes.

Will be called with None on log-outs and when new credentials are set but have not yet been verified.

property primary: AccountV2Handle | None

The primary account for the app, or None if not logged in.

set_primary_credentials(credentials: str | None) None[source]

Set credentials for the primary app account.

exception babase.ActivityNotFoundError

Bases: NotFoundError

Exception raised when an expected bascenev1.Activity does not exist.

Category: Exception Classes

exception babase.ActorNotFoundError

Bases: NotFoundError

Exception raised when an expected actor does not exist.

Category: Exception Classes

class babase.App

Bases: object

A class for high level app functionality and state.

Category: App Classes

Use babase.app to access the single shared instance of this class.

Note that properties not documented here should be considered internal and subject to change without warning.

class DefaultAppModeSelector[source]

Bases: AppModeSelector

Decides which AppModes to use to handle AppIntents.

This default version is generated by the project updater based on the ‘default_app_modes’ value in the projectconfig.

It is also possible to modify app mode selection behavior by setting app.mode_selector to an instance of a custom AppModeSelector subclass. This is a good way to go if you are modifying app behavior dynamically via a plugin instead of statically in a spinoff project.

app_mode_for_intent(intent: AppIntent) type[AppMode] | None[source]

Given an AppIntent, return the AppMode that should handle it.

If None is returned, the AppIntent will be ignored.

This may be called in a background thread, so avoid any calls limited to logic thread use/etc.

testable_app_modes() list[type[AppMode]][source]

Return a list of modes to appear in the dev-console app-mode ui.

The user can switch between these app modes for testing. App-modes will be passed an AppIntentDefault when selected by the user.

Note that in normal circumstances AppModes should never be selected explicitly by the user but rather determined implicitly based on AppIntents.

SHUTDOWN_TASK_TIMEOUT_SECONDS = 5
class State(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

High level state the app can be in.

INITING = 2
LOADING = 3
NATIVE_BOOTSTRAPPING = 1
NOT_STARTED = 0
RUNNING = 4
SHUTDOWN_COMPLETE = 7
SHUTTING_DOWN = 6
SUSPENDED = 5
property active: bool

Whether the app is currently front and center.

This will be False when the app is hidden, other activities are covering it, etc. (depending on the platform).

add_shutdown_task(coro: Coroutine[None, None, None]) None[source]

Add a task to be run on app shutdown.

Note that shutdown tasks will be canceled after App.SHUTDOWN_TASK_TIMEOUT_SECONDS if they are still running.

property asyncio_loop: asyncio.AbstractEventLoop

The logic thread’s asyncio event loop.

This allow async tasks to be run in the logic thread.

Generally you should call App.create_async_task() to schedule async code to run instead of using this directly. That will handle retaining the task and logging errors automatically. Only schedule tasks onto asyncio_loop yourself when you intend to hold on to the returned task and await its results. Releasing the task reference can lead to subtle bugs such as unreported errors and garbage-collected tasks disappearing before their work is done.

Note that, at this time, the asyncio loop is encapsulated and explicitly stepped by the engine’s logic thread loop and thus things like asyncio.get_running_loop() will unintuitively not return this loop from most places in the logic thread; only from within a task explicitly created in this loop. Hopefully this situation will be improved in the future with a unified event loop.

property classic: ClassicAppSubsystem | None

Our classic subsystem (if available).

property config: babase.AppConfig

The babase.AppConfig instance representing the app’s config state.

create_async_task(coro: Coroutine[Any, Any, T], *, name: str | None = None) None[source]

Create a fully managed async task.

This will automatically retain and release a reference to the task and log any exceptions that occur in it. If you need to await a task or otherwise need more control, schedule a task directly using App.asyncio_loop.

Handle a deep link URL.

health_monitor: AppHealthMonitor
lang: LanguageSubsystem
property mode_selector: babase.AppModeSelector

Controls which app-modes are used for handling given intents.

Plugins can override this to change high level app behavior and spinoff projects can change the default implementation for the same effect.

on_initial_sign_in_complete() None[source]

Called when initial sign-in (or lack thereof) completes.

This normally gets called by the plus subsystem. The initial-sign-in process may include tasks such as syncing account workspaces or other data so it may take a substantial amount of time.

on_native_active_changed() None[source]

Called by the native layer when the app active state changes.

on_native_bootstrapping_complete() None[source]

Called by the native layer once its ready to rock.

on_native_shutdown() None[source]

Called by the native layer when the app starts shutting down.

on_native_shutdown_complete() None[source]

Called by the native layer when the app is done shutting down.

on_native_start() None[source]

Called by the native layer when the app is being started.

on_native_suspend() None[source]

Called by the native layer when the app is suspended.

on_native_unsuspend() None[source]

Called by the native layer when the app suspension ends.

plugins: PluginSubsystem
property plus: PlusAppSubsystem | None

Our plus subsystem (if available).

postinit() None[source]

Called after we’ve been inited and assigned to babase.app.

Anything that accesses babase.app as part of its init process must go here instead of __init__.

push_apply_app_config() None[source]

Internal. Use app.config.apply() to apply app config changes.

read_config() None[source]

(internal)

register_subsystem(subsystem: AppSubsystem) None[source]

Called by the AppSubsystem class. Do not use directly.

run() None[source]

Run the app to completion.

Note that this only works on builds where Ballistica manages its own event loop.

set_intent(intent: AppIntent) None[source]

Set the intent for the app.

Intent defines what the app is trying to do at a given time. This call is asynchronous; the intent switch will happen in the logic thread in the near future. If set_intent is called repeatedly before the change takes place, the final intent to be set will be used.

set_ui_scale(scale: babase.UIScale) None[source]

Change ui-scale on the fly.

Currently this is mainly for debugging and will not be called as part of normal app operation.

threadpool_submit_no_wait(call: Callable[[], Any]) None[source]

Submit a call to the app threadpool where result is not needed.

Normally, doing work in a thread-pool involves creating a future and waiting for its result, which is an important step because it propagates any Exceptions raised by the submitted work. When the result in not important, however, this call can be used. The app will log any exceptions that occur.

property ui_v1: UIV1AppSubsystem

Our ui_v1 subsystem (always available).

class babase.AppConfig

Bases: dict

A special dict that holds the game’s persistent configuration values.

Category: App Classes

It also provides methods for fetching values with app-defined fallback defaults, applying contained values to the game, and committing the config to storage.

Call babase.appconfig() to get the single shared instance of this class.

AppConfig data is stored as json on disk on so make sure to only place json-friendly values in it (dict, list, str, float, int, bool). Be aware that tuples will be quietly converted to lists when stored.

apply() None[source]

Apply config values to the running app.

This call is thread-safe and asynchronous; changes will happen in the next logic event loop cycle.

apply_and_commit() None[source]

Run apply() followed by commit(); for convenience.

(This way the commit() will not occur if apply() hits invalid data)

builtin_keys() list[str][source]

Return the list of valid key names recognized by babase.AppConfig.

This set of keys can be used with resolve(), default_value(), etc. It does not vary across platforms and may include keys that are obsolete or not relevant on the current running version. (for instance, VR related keys on non-VR platforms). This is to minimize the amount of platform checking necessary)

Note that it is perfectly legal to store arbitrary named data in the config, but in that case it is up to the user to test for the existence of the key in the config dict, fall back to consistent defaults, etc.

commit() None[source]

Commits the config to local storage.

Note that this call is asynchronous so the actual write to disk may not occur immediately.

default_value(key: str) Any[source]

Given a string key, return its predefined default value.

This is the value that will be returned by babase.AppConfig.resolve() if the key is not present in the config dict or of an incompatible type.

Raises an Exception for unrecognized key names. To get the list of keys supported by this method, use babase.AppConfig.builtin_keys(). Note that it is perfectly legal to store other data in the config; it just needs to be accessed through standard dict methods and missing values handled manually.

resolve(key: str) Any[source]

Given a string key, return a config value (type varies).

This will substitute application defaults for values not present in the config dict, filter some invalid values, etc. Note that these values do not represent the state of the app; simply the state of its config. Use babase.App to access actual live state.

Raises an Exception for unrecognized key names. To get the list of keys supported by this method, use babase.AppConfig.builtin_keys(). Note that it is perfectly legal to store other data in the config; it just needs to be accessed through standard dict methods and missing values handled manually.

class babase.AppHealthMonitor

Bases: AppSubsystem

Logs things like app-not-responding issues.

on_app_loading() None[source]

Called when the app reaches the loading state.

Note that subsystems created after the app switches to the loading state will not receive this callback. Subsystems created by plugins are an example of this.

on_app_suspend() None[source]

Called when the app enters the suspended state.

on_app_unsuspend() None[source]

Called when the app exits the suspended state.

class babase.AppIntent

Bases: object

A high level directive given to the app.

Category: App Classes

class babase.AppIntentDefault

Bases: AppIntent

Tells the app to simply run in its default mode.

class babase.AppIntentExec(code: str)

Bases: AppIntent

Tells the app to exec some Python code.

class babase.AppMode

Bases: object

A high level mode for the app.

Category: App Classes

classmethod can_handle_intent(intent: AppIntent) bool[source]

Return whether this mode can handle the provided intent.

For this to return True, the AppMode must claim to support the provided intent (via its _supports_intent() method) AND the AppExperience associated with the AppMode must be supported by the current app and runtime environment.

classmethod get_app_experience() AppExperience[source]

Return the overall experience provided by this mode.

handle_intent(intent: AppIntent) None[source]

Handle an intent.

on_activate() None[source]

Called when the mode is being activated.

on_app_active_changed() None[source]

Called when ba*.app.active changes while this mode is active.

The app-mode may want to take action such as pausing a running game in such cases.

on_deactivate() None[source]

Called when the mode is being deactivated.

class babase.AppModeSelector

Bases: object

Defines which AppModes are available or used to handle given AppIntents.

Category: App Classes

The app calls an instance of this class when passed an AppIntent to determine which AppMode to use to handle the intent. Plugins or spinoff projects can modify high level app behavior by replacing or modifying the app’s mode-selector.

app_mode_for_intent(intent: AppIntent) type[AppMode] | None[source]

Given an AppIntent, return the AppMode that should handle it.

If None is returned, the AppIntent will be ignored.

This may be called in a background thread, so avoid any calls limited to logic thread use/etc.

testable_app_modes() list[type[AppMode]][source]

Return a list of modes to appear in the dev-console app-mode ui.

The user can switch between these app modes for testing. App-modes will be passed an AppIntentDefault when selected by the user.

Note that in normal circumstances AppModes should never be selected explicitly by the user but rather determined implicitly based on AppIntents.

class babase.AppSubsystem

Bases: object

Base class for an app subsystem.

Category: App Classes

An app ‘subsystem’ is a bit of a vague term, as pieces of the app can technically be any class and are not required to use this, but building one out of this base class provides conveniences such as predefined callbacks during app state changes.

Subsystems must be registered with the app before it completes its transition to the ‘running’ state.

do_apply_app_config() None[source]

Called when the app config should be applied.

on_app_loading() None[source]

Called when the app reaches the loading state.

Note that subsystems created after the app switches to the loading state will not receive this callback. Subsystems created by plugins are an example of this.

on_app_running() None[source]

Called when the app reaches the running state.

on_app_shutdown() None[source]

Called when the app begins shutting down.

on_app_shutdown_complete() None[source]

Called when the app completes shutting down.

on_app_suspend() None[source]

Called when the app enters the suspended state.

on_app_unsuspend() None[source]

Called when the app exits the suspended state.

on_screen_change() None[source]

Called when screen dimensions or ui-scale changes.

reset() None[source]

Reset the subsystem to a default state.

This is called when switching app modes, but may be called at other times too.

class babase.AppTimer(time: float, call: Callable[[], Any], repeat: bool = False)[source]

Bases: object

Timers are used to run code at later points in time.

Category: General Utility Classes

This class encapsulates a timer based on app-time. The underlying timer will be destroyed when this object is no longer referenced. If you do not want to worry about keeping a reference to your timer around, use the babase.apptimer() function instead to get a one-off timer.

##### Arguments ###### time > Length of time in seconds that the timer will wait before firing.

###### call > A callable Python object. Remember that the timer will retain a strong reference to the callable for as long as it exists, so you may want to look into concepts such as babase.WeakCall if that is not desired.

###### repeat > If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

##### Example

Use a Timer object to print repeatedly for a few seconds: … def say_it(): … babase.screenmessage(‘BADGER!’) … def stop_saying_it(): … global g_timer … g_timer = None … babase.screenmessage(‘MUSHROOM MUSHROOM!’) … # Create our timer; it will run as long as we have the self.t ref. … g_timer = babase.AppTimer(0.3, say_it, repeat=True) … # Now fire off a one-shot timer to kill it. … babase.apptimer(3.89, stop_saying_it)

class babase.Call(*args: Any, **keywds: Any)

Bases: object

Wraps a callable and arguments into a single callable object.

Category: General Utility Classes

The callable is strong-referenced so it won’t die until this object does.

WARNING: This is exactly the same as Python’s built in functools.partial(). Use functools.partial instead of this for new code, as this will probably be deprecated at some point.

Note that a bound method (ex: myobj.dosomething) contains a reference to self (myobj in that case), so you will be keeping that object alive too. Use babase.WeakCall if you want to pass a method to a callback without keeping its object alive.

class babase.ContextCall(call: Callable)[source]

Bases: object

A context-preserving callable.

Category: General Utility Classes

A ContextCall wraps a callable object along with a reference to the current context (see babase.ContextRef); it handles restoring the context when run and automatically clears itself if the context it belongs to dies.

Generally you should not need to use this directly; all standard Ballistica callbacks involved with timers, materials, UI functions, etc. handle this under-the-hood so you don’t have to worry about it. The only time it may be necessary is if you are implementing your own callbacks, such as a worker thread that does some action and then runs some game code when done. By wrapping said callback in one of these, you can ensure that you will not inadvertently be keeping the current activity alive or running code in a torn-down (expired) context_ref.

You can also use babase.WeakCall for similar functionality, but ContextCall has the added bonus that it will not run during context_ref shutdown, whereas babase.WeakCall simply looks at whether the target object instance still exists.

##### Examples Example A: code like this can inadvertently prevent our activity (self) from ending until the operation completes, since the bound method we’re passing (self.dosomething) contains a strong-reference to self). >>> start_some_long_action(callback_when_done=self.dosomething)

Example B: in this case our activity (self) can still die properly; the callback will clear itself when the activity starts shutting down, becoming a harmless no-op and releasing the reference to our activity.

>>> start_long_action(
...     callback_when_done=babase.ContextCall(self.mycallback))
exception babase.ContextError

Bases: Exception

Exception raised when a call is made in an invalid context.

Category: Exception Classes

Examples of this include calling UI functions within an Activity context or calling scene manipulation functions outside of a game context.

class babase.ContextRef[source]

Bases: object

Store or use a ballistica context.

Category: General Utility Classes

Many operations such as bascenev1.newnode() or bascenev1.gettexture() operate implicitly on a current ‘context’. A context is some sort of state that functionality can implicitly use. Context determines, for example, which scene nodes or textures get added to without having to specify it explicitly in the newnode()/gettexture() call. Contexts can also affect object lifecycles; for example a babase.ContextCall will become a no-op when the context it was created in is destroyed.

In general, if you are a modder, you should not need to worry about contexts; mod code should mostly be getting run in the correct context and timers and other callbacks will take care of saving and restoring contexts automatically. There may be rare cases, however, where you need to deal directly with contexts, and that is where this class comes in.

Creating a babase.ContextRef() will capture a reference to the current context. Other modules may provide ways to access their contexts; for example a bascenev1.Activity instance has a ‘context’ attribute. You can also use babase.ContextRef.empty() to create a reference to no context. Some code such as UI calls may expect this and may complain if you try to use them within a context.

##### Usage ContextRefs are generally used with the Python ‘with’ statement, which sets the context they point to as current on entry and resets it to the previous value on exit.

##### Example Explicitly create a few UI bits with no context set. (UI stuff may complain if called within a context): >>> with bui.ContextRef.empty(): … my_container = bui.containerwidget()

classmethod empty() ContextRef[source]

Return a ContextRef pointing to no context.

This is useful when code should be run free of a context. For example, UI code generally insists on being run this way. Otherwise, callbacks set on the UI could inadvertently stop working due to a game activity ending, which would be unintuitive behavior.

is_empty() bool[source]

Whether the context was created as empty.

is_expired() bool[source]

Whether the context has expired.

exception babase.DelegateNotFoundError

Bases: NotFoundError

Exception raised when an expected delegate object does not exist.

Category: Exception Classes

class babase.DevConsoleSubsystem

Bases: object

Subsystem for wrangling the dev console.

The single instance of this class can be found at babase.app.devconsole. The dev-console is a simple always-available UI intended for use by developers; not end users. Traditionally it is available by typing a backtick (`) key on a keyboard, but now can be accessed via an on-screen button (see settings/advanced to enable said button).

do_refresh_tab(tabname: str) None[source]

Called by the C++ layer when a tab should be filled out.

class babase.DevConsoleTab

Bases: object

Defines behavior for a tab in the dev-console.

property base_scale: float

A scale value set depending on the app’s UI scale.

Dev-console tabs can incorporate this into their UI sizes and positions if they desire. This must be done manually however.

button(label: str, pos: tuple[float, float], size: tuple[float, float], call: Callable[[], Any] | None = None, *, h_anchor: Literal['left', 'center', 'right'] = 'center', label_scale: float = 1.0, corner_radius: float = 8.0, style: Literal['normal', 'light'] = 'normal') None[source]

Add a button to the tab being refreshed.

property height: float

Return the current tab height. Only call during refreshes.

python_terminal() None[source]

Add a Python Terminal to the tab being refreshed.

refresh() None[source]

Called when the tab should refresh itself.

request_refresh() None[source]

The tab can call this to request that it be refreshed.

text(text: str, pos: tuple[float, float], *, h_anchor: Literal['left', 'center', 'right'] = 'center', h_align: Literal['left', 'center', 'right'] = 'center', v_align: Literal['top', 'center', 'bottom', 'none'] = 'center', scale: float = 1.0) None[source]

Add a button to the tab being refreshed.

property width: float

Return the current tab width. Only call during refreshes.

class babase.DevConsoleTabEntry(name: str, factory: Callable[[], DevConsoleTab])

Bases: object

Represents a distinct tab in the dev-console.

factory: Callable[[], DevConsoleTab]
name: str
class babase.DisplayTimer(time: float, call: Callable[[], Any], repeat: bool = False)[source]

Bases: object

Timers are used to run code at later points in time.

Category: General Utility Classes

This class encapsulates a timer based on display-time. The underlying timer will be destroyed when this object is no longer referenced. If you do not want to worry about keeping a reference to your timer around, use the babase.displaytimer() function instead to get a one-off timer.

Display-time is a time value intended to be used for animation and other visual purposes. It will generally increment by a consistent amount each frame. It will pass at an overall similar rate to AppTime, but trades accuracy for smoothness.

##### Arguments ###### time > Length of time in seconds that the timer will wait before firing.

###### call > A callable Python object. Remember that the timer will retain a strong reference to the callable for as long as it exists, so you may want to look into concepts such as babase.WeakCall if that is not desired.

###### repeat > If True, the timer will fire repeatedly, with each successive firing having the same delay as the first.

##### Example

Use a Timer object to print repeatedly for a few seconds: … def say_it(): … babase.screenmessage(‘BADGER!’) … def stop_saying_it(): … global g_timer … g_timer = None … babase.screenmessage(‘MUSHROOM MUSHROOM!’) … # Create our timer; it will run as long as we have the self.t ref. … g_timer = babase.DisplayTimer(0.3, say_it, repeat=True) … # Now fire off a one-shot timer to kill it. … babase.displaytimer(3.89, stop_saying_it)

class babase.EmptyAppMode

Bases: AppMode

An AppMode that does not do much at all.

classmethod get_app_experience() AppExperience[source]

Return the overall experience provided by this mode.

handle_intent(intent: AppIntent) None[source]

Handle an intent.

on_activate() None[source]

Called when the mode is being activated.

on_deactivate() None[source]

Called when the mode is being deactivated.

class babase.Env[source]

Bases: object

Unchanging values for the current running app instance. Access the single shared instance of this class at babase.app.env.

android: bool

Is this build targeting an Android based OS?

api_version: int

The app’s api version.

Only Python modules and packages associated with the current API version number will be detected by the game (see the ba_meta tag). This value will change whenever substantial backward-incompatible changes are introduced to Ballistica APIs. When that happens, modules/packages should be updated accordingly and set to target the newer API version number.

arcade: bool

Whether the app is targeting an arcade-centric experience.

config_file_path: str

Where the app’s config file is stored on disk.

data_directory: str

Where bundled static app data lives.

debug: bool

Whether the app is running in debug mode.

Debug builds generally run substantially slower than non-debug builds due to compiler optimizations being disabled and extra checks being run.

demo: bool

Whether the app is targeting a demo experience.

device_name: str

Human readable name of the device running this app.

engine_build_number: int

Integer build number for the engine.

This value increases by at least 1 with each release of the engine. It is independent of the human readable version string.

engine_version: str

Human-readable version string for the engine; something like ‘1.3.24’.

This should not be interpreted as a number; it may contain string elements such as ‘alpha’, ‘beta’, ‘test’, etc. If a numeric version is needed, use build_number.

gui: bool

Whether the app is running with a gui.

This is the opposite of headless.

headless: bool

Whether the app is running headlessly (without a gui).

This is the opposite of gui.

python_directory_app: str | None

Path where the app expects its bundled modules to live.

Be aware that this value may be None if Ballistica is running in a non-standard environment, and that python-path modifications may cause modules to be loaded from other locations.

python_directory_app_site: str | None

Path where the app expects its bundled pip modules to live.

Be aware that this value may be None if Ballistica is running in a non-standard environment, and that python-path modifications may cause modules to be loaded from other locations.

python_directory_user: str | None

Path where the app expects its user scripts (mods) to live.

Be aware that this value may be None if Ballistica is running in a non-standard environment, and that python-path modifications may cause modules to be loaded from other locations.

supports_soft_quit: bool

Whether the running app supports ‘soft’ quit options.

This generally applies to mobile derived OSs, where an act of ‘quitting’ may leave the app running in the background waiting in case it is used again.

test: bool

Whether the app is running in test mode.

Test mode enables extra checks and features that are useful for release testing but which do not slow the game down significantly.

tv: bool

Whether the app is targeting a TV-centric experience.

vr: bool

Whether the app is currently running in VR.

class babase.Existable(*args, **kwargs)

Bases: Protocol

A Protocol for objects supporting an exists() method.

Category: Protocols

exists() bool[source]

Whether this object exists.

exception babase.InputDeviceNotFoundError

Bases: NotFoundError

Exception raised when an expected input-device does not exist.

Category: Exception Classes

class babase.InputType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Types of input a controller can send to the game.

Category: Enums

BOMB_PRESS = 8
BOMB_RELEASE = 9
DOWN_PRESS = 25
DOWN_RELEASE = 26
FLY_PRESS = 13
FLY_RELEASE = 14
HOLD_POSITION_PRESS = 17
HOLD_POSITION_RELEASE = 18
JUMP_PRESS = 4
JUMP_RELEASE = 5
LEFT_PRESS = 19
LEFT_RELEASE = 20
LEFT_RIGHT = 3
PICK_UP_PRESS = 10
PICK_UP_RELEASE = 11
PUNCH_PRESS = 6
PUNCH_RELEASE = 7
RIGHT_PRESS = 21
RIGHT_RELEASE = 22
RUN = 12
START_PRESS = 15
START_RELEASE = 16
UP_DOWN = 2
UP_PRESS = 23
UP_RELEASE = 24
class babase.LanguageSubsystem

Bases: AppSubsystem

Language functionality for the app.

Category: App Classes

Access the single instance of this class at ‘babase.app.lang’.

property available_languages: list[str]

A list of all available languages.

Note that languages that may be present in game assets but which are not displayable on the running version of the game are not included here.

do_apply_app_config() None[source]

Called when the app config should be applied.

get_resource(resource: str, fallback_resource: str | None = None, fallback_value: Any = None) Any[source]

Return a translation resource by name.

DEPRECATED; use babase.Lstr functionality for these purposes.

is_custom_unicode_char(char: str) bool[source]

Return whether a char is in the custom unicode range we use.

property language: str

The current active language for the app.

This can be selected explicitly by the user or may be set automatically based on locale or other factors.

property locale: str

Raw country/language code detected by the game (such as ‘en_US’).

Generally for language-specific code you should look at babase.App.language, which is the language the game is using (which may differ from locale if the user sets a language, etc.)

setlanguage(language: str | dict | None, print_change: bool = True, store_to_config: bool = True) None[source]

Set the active app language.

Pass None to use OS default language.

testlanguage(langid: str) None[source]

Set the app to test an in-progress language.

Pass a language id from the translation editor website as ‘langid’; something like ‘Gibberish_3263’. Once set to testing, the engine will repeatedly download and apply that same test language, so changes can be made to it and observed live.

translate(category: str, strval: str, raise_exceptions: bool = False, print_errors: bool = False) str[source]

Translate a value (or return the value if no translation available)

DEPRECATED; use babase.Lstr functionality for these purposes.

class babase.LoginAdapter(login_type: LoginType)

Bases: object

Allows using implicit login types in an explicit way.

Some login types such as Google Play Game Services or Game Center are basically always present and often do not provide a way to log out from within a running app, so this adapter exists to use them in a flexible manner by ‘attaching’ and ‘detaching’ from an always-present login, allowing for its use alongside other login types. It also provides common functionality for server-side account verification and other handy bits.

class ImplicitLoginState(login_id: str, display_name: str)[source]

Bases: object

Describes the current state of an implicit login.

display_name: str
login_id: str
class SignInResult(credentials: str)[source]

Bases: object

Describes the final result of a sign-in attempt.

credentials: str
get_sign_in_token(completion_cb: Callable[[str | None], None]) None[source]

Get a sign-in token from the adapter back end.

This token is then passed to the master-server to complete the sign-in process. The adapter can use this opportunity to bring up account creation UI, call its internal sign_in function, etc. as needed. The provided completion_cb should then be called with either a token or None if sign in failed or was cancelled.

is_back_end_active() bool[source]

Is this adapter’s back-end currently active?

on_app_loading() None[source]

Should be called for each adapter in on_app_loading.

on_back_end_active_change(active: bool) None[source]

Called when active state for the back-end is (possibly) changing.

Meant to be overridden by subclasses. Being active means that the implicit login provided by the back-end is actually being used by the app. It should therefore register unlocked achievements, leaderboard scores, allow viewing native UIs, etc. When not active it should ignore everything and behave as if signed out, even if it technically is still signed in.

set_active_logins(logins: dict[LoginType, str]) None[source]

Keep the adapter informed of actively used logins.

This should be called by the app’s account subsystem to keep adapters up to date on the full set of logins attached to the currently-in-use account. Note that the logins dict passed in should be immutable as only a reference to it is stored, not a copy.

set_implicit_login_state(state: ImplicitLoginState | None) None[source]

Keep the adapter informed of implicit login states.

This should be called by the adapter back-end when an account of their associated type gets logged in or out.

sign_in(result_cb: Callable[[LoginAdapter, SignInResult | Exception], None], description: str) None[source]

Attempt to sign in via this adapter.

This can be called even if the back-end is not implicitly signed in; the adapter will attempt to sign in if possible. An exception will be returned if the sign-in attempt fails.

class babase.LoginInfo(name: str)

Bases: object

Basic info about a login available in the app.plus.accounts section.

name: str
class babase.Lstr(*args: Any, **keywds: Any)

Bases: object

Used to define strings in a language-independent way.

Category: General Utility Classes

These should be used whenever possible in place of hard-coded strings so that in-game or UI elements show up correctly on all clients in their currently-active language.

To see available resource keys, look at any of the bs_language_*.py files in the game or the translations pages at legacy.ballistica.net/translate.

##### Examples EXAMPLE 1: specify a string from a resource path >>> mynode.text = babase.Lstr(resource=’audioSettingsWindow.titleText’)

EXAMPLE 2: specify a translated string via a category and english value; if a translated value is available, it will be used; otherwise the english value will be. To see available translation categories, look under the ‘translations’ resource section. >>> mynode.text = babase.Lstr(translate=(‘gameDescriptions’, … ‘Defeat all enemies’))

EXAMPLE 3: specify a raw value and some substitutions. Substitutions can be used with resource and translate modes as well. >>> mynode.text = babase.Lstr(value=’${A} / ${B}’, … subs=[(‘${A}’, str(score)), (‘${B}’, str(total))])

EXAMPLE 4: babase.Lstr’s can be nested. This example would display the resource at res_a but replace ${NAME} with the value of the resource at res_b >>> mytextnode.text = babase.Lstr( … resource=’res_a’, … subs=[(‘${NAME}’, babase.Lstr(resource=’res_b’))])

evaluate() str[source]

Evaluate the Lstr and returns a flat string in the current language.

You should avoid doing this as much as possible and instead pass and store Lstr values.

static from_json(json_string: str) babase.Lstr[source]

Given a json string, returns a babase.Lstr. Does no validation.

is_flat_value() bool[source]

Return whether the Lstr is a ‘flat’ value.

This is defined as a simple string value incorporating no translations, resources, or substitutions. In this case it may be reasonable to replace it with a raw string value, perform string manipulation on it, etc.

exception babase.MapNotFoundError

Bases: NotFoundError

Exception raised when an expected bascenev1.Map does not exist.

Category: Exception Classes

class babase.MetadataSubsystem

Bases: object

Subsystem for working with script metadata in the app.

Category: App Classes

Access the single shared instance of this class at ‘babase.app.meta’.

load_exported_classes(cls: type[T], completion_cb: Callable[[list[type[T]]], None], completion_cb_in_bg_thread: bool = False) None[source]

High level function to load meta-exported classes.

Will wait for scanning to complete if necessary, and will load all registered classes of a particular type in a background thread before calling the passed callback in the logic thread. Errors may be logged to messaged to the user in some way but the callback will be called regardless. To run the completion callback directly in the bg thread where the loading work happens, pass completion_cb_in_bg_thread=True.

start_extra_scan() None[source]

Proceed to the extra_scan_dirs portion of the scan.

This is for parts of the scan that must be delayed until workspace sync completion or other such events. This must be called exactly once.

start_scan(scan_complete_cb: Callable[[], None]) None[source]

Begin the overall scan.

This will start scanning built in directories (which for vanilla installs should be the vast majority of the work). This should only be called once.

exception babase.NodeNotFoundError

Bases: NotFoundError

Exception raised when an expected Node does not exist.

Category: Exception Classes

exception babase.NotFoundError

Bases: Exception

Exception raised when a referenced object does not exist.

Category: Exception Classes

class babase.Permission(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Permissions that can be requested from the OS.

Category: Enums

STORAGE = 0
exception babase.PlayerNotFoundError

Bases: NotFoundError

Exception raised when an expected player does not exist.

Category: Exception Classes

class babase.Plugin

Bases: object

A plugin to alter app behavior in some way.

Category: App Classes

Plugins are discoverable by the meta-tag system and the user can select which ones they want to enable. Enabled plugins are then called at specific times as the app is running in order to modify its behavior in some way.

has_settings_ui() bool[source]

Called to ask if we have settings UI we can show.

on_app_running() None[source]

Called when the app reaches the running state.

on_app_shutdown() None[source]

Called when the app is beginning the shutdown process.

on_app_shutdown_complete() None[source]

Called when the app has completed the shutdown process.

on_app_suspend() None[source]

Called when the app enters the suspended state.

on_app_unsuspend() None[source]

Called when the app exits the suspended state.

show_settings_ui(source_widget: Any | None) None[source]

Called to show our settings UI.

class babase.PluginSpec(class_path: str, loadable: bool)

Bases: object

Represents a plugin the engine knows about.

Category: App Classes

The ‘enabled’ attr represents whether this plugin is set to load. Getting or setting that attr affects the corresponding app-config key. Remember to commit the app-config after making any changes.

The ‘attempted_load’ attr will be True if the engine has attempted to load the plugin. If ‘attempted_load’ is True for a PluginSpec but the ‘plugin’ attr is None, it means there was an error loading the plugin. If a plugin’s api-version does not match the running app, if a new plugin is detected with auto-enable-plugins disabled, or if the user has explicitly disabled a plugin, the engine will not even attempt to load it.

attempt_load_if_enabled() Plugin | None[source]

Possibly load the plugin and log any errors.

property enabled: bool

Whether the user wants this plugin to load.

class babase.PluginSubsystem

Bases: AppSubsystem

Subsystem for plugin handling in the app.

Category: App Classes

Access the single shared instance of this class at ba.app.plugins.

AUTO_ENABLE_NEW_PLUGINS_CONFIG_KEY = 'Auto Enable New Plugins'
AUTO_ENABLE_NEW_PLUGINS_DEFAULT = True
load_plugins() None[source]

(internal)

on_app_running() None[source]

Called when the app reaches the running state.

on_app_shutdown() None[source]

Called when the app begins shutting down.

on_app_shutdown_complete() None[source]

Called when the app completes shutting down.

on_app_suspend() None[source]

Called when the app enters the suspended state.

on_app_unsuspend() None[source]

Called when the app exits the suspended state.

on_meta_scan_complete() None[source]

Called when meta-scanning is complete.

class babase.QuitType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Types of input a controller can send to the game.

Category: Enums

‘soft’ may hide/reset the app but keep the process running, depending

on the platform.

‘back’ is a variant of ‘soft’ which may give ‘back-button-pressed’

behavior depending on the platform. (returning to some previous activity instead of dumping to the home screen, etc.)

‘hard’ leads to the process exiting. This generally should be avoided

on platforms such as mobile.

BACK = 1
HARD = 2
SOFT = 0
exception babase.SessionNotFoundError

Bases: NotFoundError

Exception raised when an expected session does not exist.

Category: Exception Classes

exception babase.SessionPlayerNotFoundError

Bases: NotFoundError

Exception raised when an expected session-player does not exist.

Category: Exception Classes

exception babase.SessionTeamNotFoundError

Bases: NotFoundError

Exception raised when an expected session-team does not exist.

Category: Exception Classes

class babase.SimpleSound[source]

Bases: object

A simple sound wrapper for internal use.

Do not use for gameplay code as it will only play locally.

play() None[source]

Play the sound locally.

class babase.SpecialChar(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Special characters the game can print.

Category: Enums

BACK = 10
BOTTOM_BUTTON = 7
CROWN = 64
DELETE = 8
DICE_BUTTON1 = 31
DICE_BUTTON2 = 32
DICE_BUTTON3 = 33
DICE_BUTTON4 = 34
DOWN_ARROW = 0
DPAD_CENTER_BUTTON = 15
DRAGON = 69
EYE_BALL = 66
FAST_FORWARD_BUTTON = 14
FEDORA = 62
FIREBALL = 76
FLAG_ALGERIA = 81
FLAG_ARGENTINA = 92
FLAG_AUSTRALIA = 85
FLAG_BRAZIL = 50
FLAG_CANADA = 54
FLAG_CHILE = 94
FLAG_CHINA = 52
FLAG_CZECH_REPUBLIC = 84
FLAG_EGYPT = 79
FLAG_FRANCE = 57
FLAG_GERMANY = 49
FLAG_INDIA = 55
FLAG_INDONESIA = 58
FLAG_IRAN = 90
FLAG_ITALY = 59
FLAG_JAPAN = 56
FLAG_KUWAIT = 80
FLAG_MALAYSIA = 83
FLAG_MEXICO = 48
FLAG_NETHERLANDS = 61
FLAG_PHILIPPINES = 93
FLAG_POLAND = 91
FLAG_QATAR = 78
FLAG_RUSSIA = 51
FLAG_SAUDI_ARABIA = 82
FLAG_SINGAPORE = 86
FLAG_SOUTH_KOREA = 60
FLAG_UNITED_ARAB_EMIRATES = 77
FLAG_UNITED_KINGDOM = 53
FLAG_UNITED_STATES = 47
HAL = 63
HEART = 68
HELMET = 70
LEFT_ARROW = 2
LEFT_BUTTON = 5
LOCAL_ACCOUNT = 45
LOGO_FLAT = 11
MIKIROG = 95
MOON = 74
MUSHROOM = 71
NINJA_STAR = 72
OUYA_BUTTON_A = 25
OUYA_BUTTON_O = 22
OUYA_BUTTON_U = 23
OUYA_BUTTON_Y = 24
PARTY_ICON = 36
PAUSE_BUTTON = 21
PLAY_BUTTON = 20
PLAY_PAUSE_BUTTON = 13
PLAY_STATION_CIRCLE_BUTTON = 17
PLAY_STATION_CROSS_BUTTON = 16
PLAY_STATION_SQUARE_BUTTON = 19
PLAY_STATION_TRIANGLE_BUTTON = 18
REWIND_BUTTON = 12
RIGHT_ARROW = 3
RIGHT_BUTTON = 6
SHIFT = 9
SKULL = 67
SPIDER = 75
TEST_ACCOUNT = 37
TICKET = 28
TICKET_BACKING = 38
TOKEN = 26
TOP_BUTTON = 4
TROPHY0A = 42
TROPHY0B = 43
TROPHY1 = 39
TROPHY2 = 40
TROPHY3 = 41
TROPHY4 = 44
UP_ARROW = 1
VIKING_HELMET = 73
YIN_YANG = 65
class babase.StringEditAdapter(description: str, initial_text: str, max_length: int | None, screen_space_center: tuple[float, float] | None)

Bases: object

Represents a string editing operation on some object.

Editable objects such as text widgets or in-app-consoles can subclass this to make their contents editable on all platforms.

There can only be one string-edit at a time for the app. New StringEdits will attempt to register themselves as the globally active one in their constructor, but this may not succeed. When creating a StringEditAdapter, always check its ‘is_valid()’ value after creating it. If this is False, it was not able to set itself as the global active one and should be discarded.

apply(new_text: str) None[source]

Should be called by the owner when editing is complete.

Note that in some cases this call may be a no-op (such as if this StringEditAdapter is no longer the globally active one).

can_be_replaced() bool[source]

Return whether this adapter can be replaced by a new one.

This is mainly a safeguard to allow adapters whose drivers have gone away without calling apply or cancel to time out and be replaced with new ones.

cancel() None[source]

Should be called by the owner when editing is cancelled.

class babase.StringEditSubsystem

Bases: object

Full string-edit state for the app.

exception babase.TeamNotFoundError

Bases: NotFoundError

Exception raised when an expected bascenev1.Team does not exist.

Category: Exception Classes

class babase.UIScale(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

The overall scale the UI is being rendered for. Note that this is independent of pixel resolution. For example, a phone and a desktop PC might render the game at similar pixel resolutions but the size they display content at will vary significantly.

Category: Enums

‘large’ is used for devices such as desktop PCs where fine details can

be clearly seen. UI elements are generally smaller on the screen and more content can be seen at once.

‘medium’ is used for devices such as tablets, TVs, or VR headsets.

This mode strikes a balance between clean readability and amount of content visible.

‘small’ is used primarily for phones or other small devices where

content needs to be presented as large and clear in order to remain readable from an average distance.

LARGE = 2
MEDIUM = 1
SMALL = 0
class babase.Vec3[source]
class babase.Vec3(value: float)
class babase.Vec3(values: Sequence[float])
class babase.Vec3(x: float, y: float, z: float)

Bases: Sequence[float]

A vector of 3 floats.

Category: General Utility Classes

These can be created the following ways (checked in this order): - with no args, all values are set to 0 - with a single numeric arg, all values are set to that value - with a single three-member sequence arg, sequence values are copied - otherwise assumes individual x/y/z args (positional or keywords)

cross(other: Vec3) Vec3[source]

Returns the cross product of this vector and another.

dot(other: Vec3) float[source]

Returns the dot product of this vector and another.

length() float[source]

Returns the length of the vector.

normalized() Vec3[source]

Returns a normalized version of the vector.

x: float

The vector’s X component.

y: float

The vector’s Y component.

z: float

The vector’s Z component.

class babase.WeakCall(*args: Any, **keywds: Any)

Bases: object

Wrap a callable and arguments into a single callable object.

Category: General Utility Classes

When passed a bound method as the callable, the instance portion of it is weak-referenced, meaning the underlying instance is free to die if all other references to it go away. Should this occur, calling the WeakCall is simply a no-op.

Think of this as a handy way to tell an object to do something at some point in the future if it happens to still exist.

##### Examples EXAMPLE A: this code will create a FooClass instance and call its bar() method 5 seconds later; it will be kept alive even though we overwrite its variable with None because the bound method we pass as a timer callback (foo.bar) strong-references it >>> foo = FooClass() … babase.apptimer(5.0, foo.bar) … foo = None

EXAMPLE B: This code will not keep our object alive; it will die when we overwrite it with None and the timer will be a no-op when it fires >>> foo = FooClass() … babase.apptimer(5.0, ba.WeakCall(foo.bar)) … foo = None

EXAMPLE C: Wrap a method call with some positional and keyword args: >>> myweakcall = babase.WeakCall(self.dostuff, argval1, … namedarg=argval2) … # Now we have a single callable to run that whole mess. … # The same as calling myobj.dostuff(argval1, namedarg=argval2) … # (provided my_obj still exists; this will do nothing … # otherwise). … myweakcall()

Note: additional args and keywords you provide to the WeakCall() constructor are stored as regular strong-references; you’ll need to wrap them in weakrefs manually if desired.

exception babase.WidgetNotFoundError

Bases: NotFoundError

Exception raised when an expected widget does not exist.

Category: Exception Classes

babase.add_clean_frame_callback(call: Callable) None[source]

(internal)

Provide an object to be called once the next non-progress-bar-frame has been rendered. Useful for queueing things to load in the background without elongating any current progress-bar-load.

babase.allows_ticket_sales() bool[source]

(internal)

babase.android_get_external_files_dir() str[source]

(internal)

Returns the android external storage path, or None if there is none on this device

babase.appname() str[source]

(internal)

babase.appnameupper() str[source]

(internal)

Return whether this build of the game can display full unicode such as Emoji, Asian languages, etc.

babase.apptime() babase.AppTime[source]

Return the current app-time in seconds.

Category: General Utility Functions

App-time is a monotonic time value; it starts at 0.0 when the app launches and will never jump by large amounts or go backwards, even if the system time changes. Its progression will pause when the app is in a suspended state.

Note that the AppTime returned here is simply float; it just has a unique type in the type-checker’s eyes to help prevent it from being accidentally used with time functionality expecting other time types.

babase.apptimer(time: float, call: Callable[[], Any]) None[source]

Schedule a callable object to run based on app-time.

Category: General Utility Functions

This function creates a one-off timer which cannot be canceled or modified once created. If you require the ability to do so, or need a repeating timer, use the babase.AppTimer class instead.

##### Arguments ###### time (float) > Length of time in seconds that the timer will wait before firing.

###### call (Callable[[], Any]) > A callable Python object. Note that the timer will retain a strong reference to the callable for as long as the timer exists, so you may want to look into concepts such as babase.WeakCall if that is not desired.

##### Examples Print some stuff through time: >>> babase.screenmessage(‘hello from now!’) >>> babase.apptimer(1.0, babase.Call(babase.screenmessage,

‘hello from the future!’))

>>> babase.apptimer(2.0, babase.Call(babase.screenmessage,
...                       'hello from the future 2!'))
babase.asset_loads_allowed() bool[source]

(internal)

babase.charstr(char_id: babase.SpecialChar) str[source]

Get a unicode string representing a special character.

Category: General Utility Functions

Note that these utilize the private-use block of unicode characters (U+E000-U+F8FF) and are specific to the game; exporting or rendering them elsewhere will be meaningless.

See babase.SpecialChar for the list of available characters.

babase.clipboard_get_text() str[source]

Return text currently on the system clipboard.

Category: General Utility Functions

Ensure that babase.clipboard_has_text() returns True before calling

this function.

babase.clipboard_has_text() bool[source]

Return whether there is currently text on the clipboard.

Category: General Utility Functions

This will return False if no system clipboard is available; no need

to call babase.clipboard_is_supported() separately.

babase.clipboard_is_supported() bool[source]

Return whether this platform supports clipboard operations at all.

Category: General Utility Functions

If this returns False, UIs should not show ‘copy to clipboard’ buttons, etc.

babase.clipboard_set_text(value: str) None[source]

Copy a string to the system clipboard.

Category: General Utility Functions

Ensure that babase.clipboard_is_supported() returns True before adding

buttons/etc. that make use of this functionality.

babase.commit_app_config() None

Commit the config to persistent storage.

Category: General Utility Functions

(internal)

babase.displaytime() babase.DisplayTime[source]

Return the current display-time in seconds.

Category: General Utility Functions

Display-time is a time value intended to be used for animation and other visual purposes. It will generally increment by a consistent amount each frame. It will pass at an overall similar rate to AppTime, but trades accuracy for smoothness.

Note that the value returned here is simply a float; it just has a unique type in the type-checker’s eyes to help prevent it from being accidentally used with time functionality expecting other time types.

babase.displaytimer(time: float, call: Callable[[], Any]) None[source]

Schedule a callable object to run based on display-time.

Category: General Utility Functions

This function creates a one-off timer which cannot be canceled or modified once created. If you require the ability to do so, or need a repeating timer, use the babase.DisplayTimer class instead.

Display-time is a time value intended to be used for animation and other visual purposes. It will generally increment by a consistent amount each frame. It will pass at an overall similar rate to AppTime, but trades accuracy for smoothness.

##### Arguments ###### time (float) > Length of time in seconds that the timer will wait before firing.

###### call (Callable[[], Any]) > A callable Python object. Note that the timer will retain a strong reference to the callable for as long as the timer exists, so you may want to look into concepts such as babase.WeakCall if that is not desired.

##### Examples Print some stuff through time: >>> babase.screenmessage(‘hello from now!’) >>> babase.displaytimer(1.0, babase.Call(babase.screenmessage, … ‘hello from the future!’)) >>> babase.displaytimer(2.0, babase.Call(babase.screenmessage, … ‘hello from the future 2!’))

babase.do_once() bool[source]

Return whether this is the first time running a line of code.

Category: General Utility Functions

This is used by ‘print_once()’ type calls to keep from overflowing logs. The call functions by registering the filename and line where The call is made from. Returns True if this location has not been registered already, and False if it has.

##### Example This print will only fire for the first loop iteration: >>> for i in range(10): … if babase.do_once(): … print(‘HelloWorld once from loop!’)

babase.env() dict[source]

(internal)

Returns a dict containing general info about the operating environment such as version, platform, etc. This info is now exposed through babase.App; refer to those docs for info on specific elements.

babase.existing(obj: ExistableT | None) ExistableT | None

Convert invalid references to None for any babase.Existable object.

Category: Gameplay Functions

To best support type checking, it is important that invalid references not be passed around and instead get converted to values of None. That way the type checker can properly flag attempts to pass possibly-dead objects (FooType | None) into functions expecting only live ones (FooType), etc. This call can be used on any ‘existable’ object (one with an exists() method) and will convert it to a None value if it does not exist.

For more info, see notes on ‘existables’ here: https://ballistica.net/wiki/Coding-Style-Guide

babase.fade_screen(to: int = 0, time: float = 0.25, endcall: Callable[[], None] | None = None) None[source]

(internal)

Fade the local game screen in our out from black over a duration of time. if “to” is 0, the screen will fade out to black. Otherwise it will fade in from black. If endcall is provided, it will be run after a completely faded frame is drawn.

babase.fatal_error(message: str) None[source]

Trigger a fatal error. Use this in situations where it is not possible for the engine to continue on in a useful way. This can sometimes help provide more clear information at the exact source of a problem as compared to raising an Exception. In the vast majority of cases, however, Exceptions should be preferred.

babase.fullscreen_control_available() bool[source]

(internal)

babase.fullscreen_control_get() bool[source]

(internal)

babase.fullscreen_control_key_shortcut() str | None[source]

(internal)

babase.fullscreen_control_set(val: bool) None[source]

(internal)

babase.garbage_collect() None

Run an explicit pass of garbage collection.

category: General Utility Functions

May also print warnings/etc. if collection takes too long or if uncollectible objects are found (so use this instead of simply gc.collect().

babase.get_display_resolution() tuple[int, int] | None[source]

(internal)

Return the currently selected display resolution for fullscreen display. Returns None if resolutions cannot be directly set.

babase.get_immediate_return_code() int | None[source]

(internal)

babase.get_input_idle_time() float[source]

Return seconds since any local input occurred (touch, keypress, etc.).

babase.get_ip_address_type(addr: str) AddressFamily

Return socket.AF_INET6 or socket.AF_INET4 for the provided address.

babase.get_low_level_config_value(key: str, default_value: int) int[source]

(internal)

babase.get_max_graphics_quality() str[source]

(internal)

Return the max graphics-quality supported on the current hardware.

babase.get_remote_app_name() babase.Lstr

(internal)

babase.get_replays_dir() str[source]

(internal)

babase.get_string_height(string: str, suppress_warning: bool = False) float[source]

(internal)

Given a string, returns its height using the standard small app font.

babase.get_string_width(string: str, suppress_warning: bool = False) float[source]

(internal)

Given a string, returns its width using the standard small app font.

babase.get_type_name(cls: type) str

Return a full type name including module for a class.

babase.get_ui_scale() str[source]

(internal)

babase.get_v1_cloud_log_file_path() str[source]

(internal)

Return the path to the app log file.

babase.getclass(name: str, subclassof: type[T], check_sdlib_modulename_clash: bool = False) type[T]

Given a full class name such as foo.bar.MyClass, return the class.

Category: General Utility Functions

The class will be checked to make sure it is a subclass of the provided ‘subclassof’ class, and a TypeError will be raised if not.

babase.getsimplesound(name: str) SimpleSound[source]

(internal).

babase.handle_leftover_v1_cloud_log_file() None

Handle an un-uploaded v1-cloud-log from a previous run.

babase.has_user_run_commands() bool[source]

(internal)

babase.have_chars(text: str) bool[source]

(internal)

babase.have_permission(permission: babase.Permission) bool[source]

(internal)

babase.in_logic_thread() bool[source]

(internal)

Returns whether or not the current thread is the logic thread.

babase.in_main_menu() bool[source]

(internal)

Returns whether or not the app-mode is currently in a main menu situation (as opposed to gameplay).

babase.increment_analytics_count(name: str, increment: int = 1) None[source]

(internal)

babase.invoke_main_menu() None[source]

High level call to bring up the main menu if it is not present.

This is essentially the same as pressing the menu button on a controller.

babase.is_browser_likely_available() bool

Return whether a browser likely exists on the current device.

category: General Utility Functions

If this returns False you may want to avoid calling babase.show_url() with any lengthy addresses. (ba.show_url() will display an address as a string in a window if unable to bring up a browser, but that is only useful for simple URLs.)

babase.is_os_playing_music() bool[source]

(internal)

Tells whether the OS is currently playing music of some sort.

(Used to determine whether the app should avoid playing its own)

babase.is_point_in_box(pnt: Sequence[float], box: Sequence[float]) bool

Return whether a given point is within a given box.

category: General Utility Functions

For use with standard def boxes (position|rotate|scale).

babase.is_xcode_build() bool[source]

(internal)

babase.lock_all_input() None[source]

(internal)

Prevents all keyboard, mouse, and gamepad events from being processed.

babase.mac_music_app_get_playlists() list[str][source]

(internal)

babase.mac_music_app_get_volume() int[source]

(internal)

babase.mac_music_app_init() None[source]

(internal)

babase.mac_music_app_play_playlist(playlist: str) bool[source]

(internal)

babase.mac_music_app_set_volume(volume: int) None[source]

(internal)

babase.mac_music_app_stop() None[source]

(internal)

babase.music_player_play(files: Any) None[source]

(internal)

Starts internal music file playback (for internal use)

babase.music_player_set_volume(volume: float) None[source]

(internal)

Sets internal music player volume (for internal use)

babase.music_player_shutdown() None[source]

(internal)

Finalizes internal music file playback (for internal use)

babase.music_player_stop() None[source]

(internal)

Stops internal music file playback (for internal use)

babase.native_review_request() None[source]

(internal)

babase.native_review_request_supported() bool[source]

(internal)

babase.native_stack_trace() str | None[source]

Return a native stack trace as a string, or None if not available.

Category: General Utility Functions

Stack traces contain different data and formatting across platforms. Only use them for debugging.

babase.normalized_color(color: Sequence[float]) tuple[float, ...]

Scale a color so its largest value is 1; useful for coloring lights.

category: General Utility Functions

babase.open_file_externally(path: str) None[source]

(internal)

Open the provided file in the default external app.

babase.open_url(address: str, force_fallback: bool = False) None[source]

Open the provided URL.

Category: General Utility Functions

Attempts to open the provided url in a web-browser. If that is not possible (or force_fallback is True), instead displays the url as a string and/or qrcode.

babase.overlay_web_browser_close() bool[source]

Close any open overlay web browser.

Category: General Utility Functions

babase.overlay_web_browser_is_open() bool[source]

Return whether an overlay web browser is open currently.

Category: General Utility Functions

babase.overlay_web_browser_is_supported() bool[source]

Return whether an overlay web browser is supported here.

Category: General Utility Functions

An overlay web browser is a small dialog that pops up over the top of the main engine window. It can be used for performing simple tasks such as sign-ins.

babase.overlay_web_browser_open_url(address: str) None[source]

Open the provided URL in an overlayw web browser.

Category: General Utility Functions

An overlay web browser is a small dialog that pops up over the top of the main engine window. It can be used for performing simple tasks such as sign-ins.

babase.print_error(err_str: str, once: bool = False) None

Print info about an error along with pertinent context state.

Category: General Utility Functions

Prints all positional arguments provided along with various info about the current context. Pass the keyword ‘once’ as True if you want the call to only happen one time from an exact calling location.

babase.print_exception(*args: Any, **keywds: Any) None

Print info about an exception along with pertinent context state.

Category: General Utility Functions

Prints all arguments provided along with various info about the current context and the outstanding exception. Pass the keyword ‘once’ as True if you want the call to only happen one time from an exact calling location.

babase.print_load_info() None[source]

(internal)

Category: General Utility Functions

babase.push_back_press() None[source]

(internal)

babase.pushcall(call: Callable, from_other_thread: bool = False, suppress_other_thread_warning: bool = False, other_thread_use_fg_context: bool = False, raw: bool = False) None[source]

Push a call to the logic event-loop. Category: General Utility Functions

This call expects to be used in the logic thread, and will automatically save and restore the babase.Context to behave seamlessly.

If you want to push a call from outside of the logic thread, however, you can pass ‘from_other_thread’ as True. In this case the call will always run in the UI context_ref on the logic thread or whichever context_ref is in the foreground if other_thread_use_fg_context is True. Passing raw=True will disable thread checks and context_ref sets/restores.

babase.quit(confirm: bool = False, quit_type: babase.QuitType | None = None) None[source]

Quit the app.

Category: General Utility Functions

If ‘confirm’ is True, a confirm dialog will be presented if conditions allow; otherwise the quit will still be immediate. See docs for babase.QuitType for explanations of the optional ‘quit_type’ arg.

babase.reload_media() None[source]

(internal)

Reload all currently loaded game media; useful for development/debugging.

babase.request_permission(permission: babase.Permission) None[source]

(internal)

babase.safecolor(color: Sequence[float], target_intensity: float = 0.6) tuple[float, ...][source]

Given a color tuple, return a color safe to display as text.

Category: General Utility Functions

Accepts tuples of length 3 or 4. This will slightly brighten very dark colors, etc.

babase.screenmessage(message: str | babase.Lstr, color: Sequence[float] | None = None, log: bool = False) None[source]

Print a message to the local client’s screen, in a given color.

Category: General Utility Functions

Note that this version of the function is purely for local display. To broadcast screen messages in network play, look for methods such as broadcastmessage() provided by the scene-version packages.

babase.set_analytics_screen(screen: str) None[source]

Used for analytics to see where in the app players spend their time.

Category: General Utility Functions

Generally called when opening a new window or entering some UI. ‘screen’ should be a string description of an app location (‘Main Menu’, etc.)

babase.set_low_level_config_value(key: str, value: int) None[source]

(internal)

babase.set_thread_name(name: str) None[source]

(internal)

Sets the name of the current thread (on platforms where this is available). EventLoop names are only for debugging and should not be used in logic, as naming behavior can vary across platforms.

babase.set_ui_input_device(input_device_id: int | None) None[source]

(internal)

Sets the input-device that currently owns the user interface.

babase.set_ui_scale(scale: str) None[source]

(internal)

babase.show_progress_bar() None[source]

(internal)

Category: General Utility Functions

babase.shutdown_suppress_begin() bool[source]

(internal)

babase.shutdown_suppress_count() int[source]

(internal)

babase.shutdown_suppress_end() None[source]

(internal)

babase.storagename(suffix: str | None = None) str

Generate a unique name for storing class data in shared places.

Category: General Utility Functions

This consists of a leading underscore, the module path at the call site with dots replaced by underscores, the containing class’s qualified name, and the provided suffix. When storing data in public places such as ‘customdata’ dicts, this minimizes the chance of collisions with other similarly named classes.

Note that this will function even if called in the class definition.

##### Examples Generate a unique name for storage purposes: >>> class MyThingie: … # This will give something like … # ‘_mymodule_submodule_mythingie_data’. … _STORENAME = babase.storagename(‘data’) … … # Use that name to store some data in the Activity we were … # passed. … def __init__(self, activity): … activity.customdata[self._STORENAME] = {}

babase.supports_max_fps() bool[source]

(internal)

babase.supports_vsync() bool[source]

(internal)

babase.timestring(timeval: float | int, centi: bool = True) babase.Lstr

Generate a babase.Lstr for displaying a time value.

Category: General Utility Functions

Given a time value, returns a babase.Lstr with: (hours if > 0 ) : minutes : seconds : (centiseconds if centi=True).

WARNING: the underlying Lstr value is somewhat large so don’t use this to rapidly update Node text values for an onscreen timer or you may consume significant network bandwidth. For that purpose you should use a ‘timedisplay’ Node and attribute connections.

babase.unlock_all_input() None[source]

(internal)

Resumes normal keyboard, mouse, and gamepad event processing.

babase.user_agent_string() str[source]

(internal)

babase.utf8_all(data: Any) Any

Convert any unicode data in provided sequence(s) to utf8 bytes.

babase.vec3validate(value: Sequence[float]) Sequence[float]

Ensure a value is valid for use as a Vec3.

category: General Utility Functions

Raises a TypeError exception if not. Valid values include any type of sequence consisting of 3 numeric values. Returns the same value as passed in (but with a definite type so this can be used to disambiguate ‘Any’ types). Generally this should be used in ‘if __debug__’ or assert clauses to keep runtime overhead minimal.

babase.verify_object_death(obj: object) None

Warn if an object does not get freed within a short period.

Category: General Utility Functions

This can be handy to detect and prevent memory/resource leaks.

babase.workspaces_in_use() bool[source]

(internal)

Returns whether workspaces functionality has been enabled at any point this run.