more docs generation work

This commit is contained in:
Roman Trapeznikov 2022-02-14 22:11:40 +03:00
parent 93c5edc2a5
commit b8648c5f33
No known key found for this signature in database
GPG Key ID: 89BED52F1E290F8D
36 changed files with 869 additions and 872 deletions

View File

@ -6,6 +6,7 @@
<w>outdirname</w> <w>outdirname</w>
<w>pagename</w> <w>pagename</w>
<w>pythondir</w> <w>pythondir</w>
<w>templatesdir</w>
<w>unhashable</w> <w>unhashable</w>
</words> </words>
</dictionary> </dictionary>

View File

@ -1 +1 @@
191473689765959071642564573343309028448 93799056966445196696254000169758935495

File diff suppressed because it is too large Load Diff

View File

@ -81,13 +81,14 @@ from ba._collision import Collision, getcollision
app: App app: App
__all__: list[str] = []
# Change everything's listed module to simply 'ba' (instead of 'ba.foo.bar'). # Change everything's listed module to simply 'ba' (instead of 'ba.foo.bar').
def _simplify_module_names() -> None: def _simplify_module_names() -> None:
for attr, obj in globals().items(): for attr, _obj in globals().items():
if not attr.startswith('_'): if not attr.startswith('_'):
if getattr(obj, '__module__', None) not in [None, 'ba']: __all__.append(attr)
obj.__module__ = 'ba'
_simplify_module_names() _simplify_module_names()

View File

@ -32,99 +32,92 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
Examples of Activities include games, score-screens, cutscenes, etc. Examples of Activities include games, score-screens, cutscenes, etc.
A ba.Session has one 'current' Activity at any time, though their existence A ba.Session has one 'current' Activity at any time, though their existence
can overlap during transitions. can overlap during transitions.
Attributes:
settings_raw
The settings dict passed in when the activity was made.
This attribute is deprecated and should be avoided when possible;
activities should pull all values they need from the 'settings' arg
passed to the Activity __init__ call.
teams
The list of ba.Team-s in the Activity. This gets populated just
before on_begin() is called and is updated automatically as players
join or leave the game. (at least in free-for-all mode where every
player gets their own team; in teams mode there are always 2 teams
regardless of the player count).
players
The list of ba.Player-s in the Activity. This gets populated just
before on_begin() is called and is updated automatically as players
join or leave the game.
""" """
# pylint: disable=too-many-public-methods # pylint: disable=too-many-public-methods
# Annotating attr types at the class level lets us introspect at runtime.
settings_raw: dict[str, Any] settings_raw: dict[str, Any]
"""The settings dict passed in when the activity was made.
This attribute is deprecated and should be avoided when possible;
activities should pull all values they need from the 'settings' arg
passed to the Activity __init__ call."""
teams: list[TeamType] teams: list[TeamType]
"""The list of ba.Team-s in the Activity. This gets populated just
before on_begin() is called and is updated automatically as players
join or leave the game. (at least in free-for-all mode where every
player gets their own team; in teams mode there are always 2 teams
regardless of the player count)."""
players: list[PlayerType] players: list[PlayerType]
"""The list of ba.Player-s in the Activity. This gets populated just
before on_begin() is called and is updated automatically as players
join or leave the game."""
# Whether to print every time a player dies. This can be pertinent
# in games such as Death-Match but can be annoying in games where it
# doesn't matter.
announce_player_deaths = False announce_player_deaths = False
"""Whether to print every time a player dies. This can be pertinent
in games such as Death-Match but can be annoying in games where it
doesn't matter."""
# Joining activities are for waiting for initial player joins.
# They are treated slightly differently than regular activities,
# mainly in that all players are passed to the activity at once
# instead of as each joins.
is_joining_activity = False is_joining_activity = False
"""Joining activities are for waiting for initial player joins.
They are treated slightly differently than regular activities,
mainly in that all players are passed to the activity at once
instead of as each joins."""
# Whether game-time should still progress when in menus/etc.
allow_pausing = False allow_pausing = False
"""Whether game-time should still progress when in menus/etc."""
# Whether idle players can potentially be kicked (should not happen in
# menus/etc).
allow_kick_idle_players = True allow_kick_idle_players = True
"""Whether idle players can potentially be kicked (should not happen in
menus/etc)."""
# In vr mode, this determines whether overlay nodes (text, images, etc)
# are created at a fixed position in space or one that moves based on
# the current map. Generally this should be on for games and off for
# transitions/score-screens/etc. that persist between maps.
use_fixed_vr_overlay = False use_fixed_vr_overlay = False
"""In vr mode, this determines whether overlay nodes (text, images, etc)
are created at a fixed position in space or one that moves based on
the current map. Generally this should be on for games and off for
transitions/score-screens/etc. that persist between maps."""
# If True, runs in slow motion and turns down sound pitch.
slow_motion = False slow_motion = False
"""If True, runs in slow motion and turns down sound pitch."""
# Set this to True to inherit slow motion setting from previous
# activity (useful for transitions to avoid hitches).
inherits_slow_motion = False inherits_slow_motion = False
"""Set this to True to inherit slow motion setting from previous
activity (useful for transitions to avoid hitches)."""
# Set this to True to keep playing the music from the previous activity
# (without even restarting it).
inherits_music = False inherits_music = False
"""Set this to True to keep playing the music from the previous activity
(without even restarting it)."""
# Set this to true to inherit VR camera offsets from the previous
# activity (useful for preventing sporadic camera movement
# during transitions).
inherits_vr_camera_offset = False inherits_vr_camera_offset = False
"""Set this to true to inherit VR camera offsets from the previous
activity (useful for preventing sporadic camera movement
during transitions)."""
# Set this to true to inherit (non-fixed) VR overlay positioning from
# the previous activity (useful for prevent sporadic overlay jostling
# during transitions).
inherits_vr_overlay_center = False inherits_vr_overlay_center = False
"""Set this to true to inherit (non-fixed) VR overlay positioning from
the previous activity (useful for prevent sporadic overlay jostling
during transitions)."""
# Set this to true to inherit screen tint/vignette colors from the
# previous activity (useful to prevent sudden color changes during
# transitions).
inherits_tint = False inherits_tint = False
"""Set this to true to inherit screen tint/vignette colors from the
previous activity (useful to prevent sudden color changes during
transitions)."""
# Whether players should be allowed to join in the middle of this
# activity. Note that Sessions may not allow mid-activity-joins even
# if the activity says its ok.
allow_mid_activity_joins: bool = True allow_mid_activity_joins: bool = True
"""Whether players should be allowed to join in the middle of this
activity. Note that Sessions may not allow mid-activity-joins even
if the activity says its ok."""
# If the activity fades or transitions in, it should set the length of
# time here so that previous activities will be kept alive for that
# long (avoiding 'holes' in the screen)
# This value is given in real-time seconds.
transition_time = 0.0 transition_time = 0.0
"""If the activity fades or transitions in, it should set the length of
time here so that previous activities will be kept alive for that
long (avoiding 'holes' in the screen)
This value is given in real-time seconds."""
# Is it ok to show an ad after this activity ends before showing
# the next activity?
can_show_ad_on_death = False can_show_ad_on_death = False
"""Is it ok to show an ad after this activity ends before showing
the next activity?"""
def __init__(self, settings: dict): def __init__(self, settings: dict):
"""Creates an Activity in the current ba.Session. """Creates an Activity in the current ba.Session.
@ -386,11 +379,11 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
return UNHANDLED return UNHANDLED
def has_transitioned_in(self) -> bool: def has_transitioned_in(self) -> bool:
"""Return whether ba.Activity.on_transition_in() has been called.""" """Return whether ba.Activity.on_transition_in has been called."""
return self._has_transitioned_in return self._has_transitioned_in
def has_begun(self) -> bool: def has_begun(self) -> bool:
"""Return whether ba.Activity.on_begin() has been called.""" """Return whether ba.Activity.on_begin has been called."""
return self._has_begun return self._has_begun
def has_ended(self) -> bool: def has_ended(self) -> bool:
@ -398,7 +391,7 @@ class Activity(DependencyComponent, Generic[PlayerType, TeamType]):
return self._has_ended return self._has_ended
def is_transitioning_out(self) -> bool: def is_transitioning_out(self) -> bool:
"""Return whether ba.Activity.on_transition_out() has been called.""" """Return whether ba.Activity.on_transition_out has been called."""
return self._transitioning_out return self._transitioning_out
def transition_in(self, prev_globals: Optional[ba.Node]) -> None: def transition_in(self, prev_globals: Optional[ba.Node]) -> None:

View File

@ -36,14 +36,14 @@ class Actor:
Example: Example:
```python ```python
>>> # Create a flag Actor in our game activity: >>> # Create a flag Actor in our game activity:
>>> from bastd.actor.flag import Flag ... from bastd.actor.flag import Flag
>>> self.flag = Flag(position=(0, 10, 0)) ... self.flag = Flag(position=(0, 10, 0))
>>> ...
>>> # Later, destroy the flag. ... # Later, destroy the flag.
>>> # (provided nothing else is holding a reference to it) ... # (provided nothing else is holding a reference to it)
>>> # We could also just assign a new flag to this value. ... # We could also just assign a new flag to this value.
>>> # Either way, the old flag disappears. ... # Either way, the old flag disappears.
>>> self.flag = None ... self.flag = None
``` ```
This is in contrast to the behavior of the more low level ba.Nodes, This is in contrast to the behavior of the more low level ba.Nodes,
@ -65,7 +65,9 @@ class Actor:
(though its not guaranteed to always have a meaningful effect). (though its not guaranteed to always have a meaningful effect).
In this case the Actor instance will still be around, but its exists() In this case the Actor instance will still be around, but its exists()
and is_alive() methods will both return False. and is_alive() methods will both return False.
```python
>>> self.flag.handlemessage(ba.DieMessage()) >>> self.flag.handlemessage(ba.DieMessage())
```
""" """
def __init__(self) -> None: def __init__(self) -> None:

View File

@ -155,18 +155,23 @@ class _WeakCall:
bar() method 5 seconds later; it will be kept alive even though bar() method 5 seconds later; it will be kept alive even though
we overwrite its variable with None because the bound method we overwrite its variable with None because the bound method
we pass as a timer callback (foo.bar) strong-references it we pass as a timer callback (foo.bar) strong-references it
```python
>>> foo = FooClass() >>> foo = FooClass()
... ba.timer(5.0, foo.bar) ... ba.timer(5.0, foo.bar)
... foo = None ... foo = None
```
EXAMPLE B: this code will *not* keep our object alive; it will die 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 when we overwrite it with None and the timer will be a no-op when it
fires fires
```python
>>> foo = FooClass() >>> foo = FooClass()
... ba.timer(5.0, ba.WeakCall(foo.bar)) ... ba.timer(5.0, ba.WeakCall(foo.bar))
... foo = None ... foo = None
```
EXAMPLE C: Wrap a method call with some positional and keyword args: EXAMPLE C: Wrap a method call with some positional and keyword args:
```python
>>> myweakcall = ba.WeakCall(self.dostuff, argval1, >>> myweakcall = ba.WeakCall(self.dostuff, argval1,
... namedarg=argval2) ... namedarg=argval2)
... # Now we have a single callable to run that whole mess. ... # Now we have a single callable to run that whole mess.
@ -174,6 +179,7 @@ class _WeakCall:
... # (provided my_obj still exists; this will do nothing ... # (provided my_obj still exists; this will do nothing
... # otherwise). ... # otherwise).
... myweakcall() ... myweakcall()
```
Note: additional args and keywords you provide to the WeakCall() Note: additional args and keywords you provide to the WeakCall()
constructor are stored as regular strong-references; you'll need constructor are stored as regular strong-references; you'll need
@ -232,10 +238,12 @@ class _Call:
Example: Example:
Wrap a method call with 1 positional and 1 keyword arg: Wrap a method call with 1 positional and 1 keyword arg:
```python
>>> mycall = ba.Call(myobj.dostuff, argval, namedarg=argval2) >>> mycall = ba.Call(myobj.dostuff, argval, namedarg=argval2)
... # Now we have a single callable to run that whole mess. ... # Now we have a single callable to run that whole mess.
... # ..the same as calling myobj.dostuff(argval, namedarg=argval2) ... # ..the same as calling myobj.dostuff(argval, namedarg=argval2)
... mycall() ... mycall()
```
""" """
self._call = args[0] self._call = args[0]
self._args = args[1:] self._args = args[1:]

View File

@ -18,18 +18,16 @@ class Keyboard:
Keyboards are discoverable by the meta-tag system Keyboards are discoverable by the meta-tag system
and the user can select which one they want to use. and the user can select which one they want to use.
On-screen keyboard uses chars from active ba.Keyboard. On-screen keyboard uses chars from active ba.Keyboard.
Attributes:
name
Displays when user selecting this keyboard.
chars
Used for row/column lengths.
pages
Extra chars like emojis.
nums
The 'num' page.
""" """
name: str name: str
"""Displays when user selecting this keyboard."""
chars: list[tuple[str, ...]] chars: list[tuple[str, ...]]
"""Used for row/column lengths."""
pages: dict[str, tuple[str, ...]] pages: dict[str, tuple[str, ...]]
"""Extra chars like emojis."""
nums: tuple[str, ...] nums: tuple[str, ...]
"""The 'num' page."""

View File

@ -378,19 +378,25 @@ class Lstr:
Examples: Examples:
EXAMPLE 1: specify a string from a resource path EXAMPLE 1: specify a string from a resource path
```python
>>> mynode.text = ba.Lstr(resource='audioSettingsWindow.titleText') >>> mynode.text = ba.Lstr(resource='audioSettingsWindow.titleText')
```
EXAMPLE 2: specify a translated string via a category and english EXAMPLE 2: specify a translated string via a category and english
value; if a translated value is available, it will be used; otherwise value; if a translated value is available, it will be used; otherwise
the english value will be. To see available translation categories, the english value will be. To see available translation categories,
look under the 'translations' resource section. look under the 'translations' resource section.
```python
>>> mynode.text = ba.Lstr(translate=('gameDescriptions', >>> mynode.text = ba.Lstr(translate=('gameDescriptions',
... 'Defeat all enemies')) ... 'Defeat all enemies'))
```
EXAMPLE 3: specify a raw value and some substitutions. Substitutions EXAMPLE 3: specify a raw value and some substitutions. Substitutions
can be used with resource and translate modes as well. can be used with resource and translate modes as well.
```python
>>> mynode.text = ba.Lstr(value='${A} / ${B}', >>> mynode.text = ba.Lstr(value='${A} / ${B}',
... subs=[('${A}', str(score)), ('${B}', str(total))]) ... subs=[('${A}', str(score)), ('${B}', str(total))])
```
EXAMPLE 4: ba.Lstr's can be nested. This example would display the EXAMPLE 4: ba.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_a but replace ${NAME} with the value of the

View File

@ -48,18 +48,15 @@ class Player(Generic[TeamType]):
These correspond to ba.SessionPlayer objects, but are associated with a These correspond to ba.SessionPlayer objects, but are associated with a
single ba.Activity instance. This allows activities to specify their single ba.Activity instance. This allows activities to specify their
own custom ba.Player types. own custom ba.Player types.
Attributes:
actor
The ba.Actor associated with the player.
""" """
# These are instance attrs but we define them at the type level so # These are instance attrs but we define them at the type level so
# their type annotations are introspectable (for docs generation). # their type annotations are introspectable (for docs generation).
character: str character: str
actor: Optional[ba.Actor] actor: Optional[ba.Actor]
"""The ba.Actor associated with the player."""
color: Sequence[float] color: Sequence[float]
highlight: Sequence[float] highlight: Sequence[float]

View File

@ -28,29 +28,21 @@ class ScoreConfig:
"""Settings for how a game handles scores. """Settings for how a game handles scores.
Category: Gameplay Classes Category: Gameplay Classes
Attributes:
label
A label show to the user for scores; 'Score', 'Time Survived', etc.
scoretype
How the score value should be displayed.
lower_is_better
Whether lower scores are preferable. Higher scores are by default.
none_is_winner
Whether a value of None is considered better than other scores.
By default it is not.
version
To change high-score lists used by a game without renaming the game,
change this. Defaults to an empty string.
""" """
label: str = 'Score' label: str = 'Score'
"""A label show to the user for scores; 'Score', 'Time Survived', etc."""
scoretype: ba.ScoreType = ScoreType.POINTS scoretype: ba.ScoreType = ScoreType.POINTS
"""How the score value should be displayed."""
lower_is_better: bool = False lower_is_better: bool = False
"""Whether lower scores are preferable. Higher scores are by default."""
none_is_winner: bool = False none_is_winner: bool = False
"""Whether a value of None is considered better than other scores.
By default it is not."""
version: str = '' version: str = ''
"""To change high-score lists used by a game without renaming the game,
change this. Defaults to an empty string."""

View File

@ -19,7 +19,7 @@ if TYPE_CHECKING:
class Session: class Session:
"""Defines a high level series of ba.Activity-es with a common purpose. """Defines a high level series of ba.Activity-es with a common purpose.
category: Gameplay Classes Category: Gameplay Classes
Examples of sessions are ba.FreeForAllSession, ba.DualTeamSession, and Examples of sessions are ba.FreeForAllSession, ba.DualTeamSession, and
ba.CoopSession. ba.CoopSession.
@ -27,58 +27,48 @@ class Session:
A Session is responsible for wrangling and transitioning between various A Session is responsible for wrangling and transitioning between various
ba.Activity instances such as mini-games and score-screens, and for ba.Activity instances such as mini-games and score-screens, and for
maintaining state between them (players, teams, score tallies, etc). maintaining state between them (players, teams, score tallies, etc).
Attributes:
sessionteams
All the ba.SessionTeams in the Session. Most things should use the
list of ba.Team-s in ba.Activity; not this.
sessionplayers
All ba.SessionPlayers in the Session. Most things should use the
list of ba.Player-s in ba.Activity; not this. Some players, such as
those who have not yet selected a character, will only be
found on this list.
min_players
The minimum number of players who must be present for the Session
to proceed past the initial joining screen.
max_players
The maximum number of players allowed in the Session.
lobby
The ba.Lobby instance where new ba.Player-s go to select a
Profile/Team/etc. before being added to games.
Be aware this value may be None if a Session does not allow
any such selection.
use_teams
Whether this session groups players into an explicit set of
teams. If this is off, a unique team is generated for each
player that joins.
use_team_colors
Whether players on a team should all adopt the colors of that
team instead of their own profile colors. This only applies if
use_teams is enabled.
customdata
A shared dictionary for objects to use as storage on this session.
Ensure that keys here are unique to avoid collisions.
""" """
use_teams: bool = False
use_team_colors: bool = True
# Note: even though these are instance vars, we annotate them at the use_teams: bool = False
# class level so that docs generation can access their types. """Whether this session groups players into an explicit set of
teams. If this is off, a unique team is generated for each
player that joins."""
use_team_colors: bool = True
"""Whether players on a team should all adopt the colors of that
team instead of their own profile colors. This only applies if
use_teams is enabled."""
# Note: even though these are instance vars, we annotate and document them
# at the class level so that looks better and nobody get lost while
# reading large __init__
lobby: ba.Lobby lobby: ba.Lobby
"""The ba.Lobby instance where new ba.Player-s go to select a
Profile/Team/etc. before being added to games.
Be aware this value may be None if a Session does not allow
any such selection."""
max_players: int max_players: int
"""The maximum number of players allowed in the Session."""
min_players: int min_players: int
"""The minimum number of players who must be present for the Session
to proceed past the initial joining screen"""
sessionplayers: list[ba.SessionPlayer] sessionplayers: list[ba.SessionPlayer]
"""All ba.SessionPlayers in the Session. Most things should use the
list of ba.Player-s in ba.Activity; not this. Some players, such as
those who have not yet selected a character, will only be
found on this list."""
customdata: dict customdata: dict
"""A shared dictionary for objects to use as storage on this session.
Ensure that keys here are unique to avoid collisions."""
sessionteams: list[ba.SessionTeam] sessionteams: list[ba.SessionTeam]
"""All the ba.SessionTeams in the Session. Most things should use the
list of ba.Team-s in ba.Activity; not this."""
def __init__(self, def __init__(self,
depsets: Sequence[ba.DependencySet], depsets: Sequence[ba.DependencySet],

View File

@ -22,13 +22,10 @@ class PlayerScoredMessage:
"""Informs something that a ba.Player scored. """Informs something that a ba.Player scored.
Category: Message Classes Category: Message Classes
Attributes:
score
The score value.
""" """
score: int score: int
"""The score value."""
class PlayerRecord: class PlayerRecord:
@ -232,7 +229,7 @@ class PlayerRecord:
class Stats: class Stats:
"""Manages scores and statistics for a ba.Session. """Manages scores and statistics for a ba.Session.
category: Gameplay Classes Category: Gameplay Classes
""" """
def __init__(self) -> None: def __init__(self) -> None:

View File

@ -0,0 +1,20 @@
{% extends "default/module.html.jinja2" %}
{% block style_content %}
{{ super() }}
/* Docstrings */
<style>
.pdoc .docstring {
margin-bottom: 1.5rem;
margin-left: 2rem;
}
</style>
{% endblock %}
{% macro is_public(doc) %}
{% if "(internal)" in doc.docstring %}
{# Returning no text is interpreted as false #}
{% else %}
{{ default_is_public(doc) }}
{% endif %}
{% endmacro %}

View File

@ -25,9 +25,9 @@ void PythonClassCollideModel::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"A reference to a collide-model.\n" "A reference to a collide-model.\n"
"\n" "\n"
"Category: Asset Classes\n" "Category: **Asset Classes**\n"
"\n" "\n"
"Use ba.getcollidemodel() to instantiate one."; "Use ba.getcollidemodel to instantiate one.";
obj->tp_repr = (reprfunc)tp_repr; obj->tp_repr = (reprfunc)tp_repr;
obj->tp_new = tp_new; obj->tp_new = tp_new;
obj->tp_dealloc = (destructor)tp_dealloc; obj->tp_dealloc = (destructor)tp_dealloc;

View File

@ -19,7 +19,7 @@ void PythonClassContext::SetupType(PyTypeObject* obj) {
"\n" "\n"
"A game context state.\n" "A game context state.\n"
"\n" "\n"
"Category: General Utility Classes\n" "Category: **General Utility Classes**\n"
"\n" "\n"
"Many operations such as ba.newnode or ba.gettexture operate\n" "Many operations such as ba.newnode or ba.gettexture operate\n"
"implicitly on the current context. Each ba.Activity has its own\n" "implicitly on the current context. Each ba.Activity has its own\n"
@ -30,46 +30,43 @@ void PythonClassContext::SetupType(PyTypeObject* obj) {
"since timers and other callbacks will take care of saving and\n" "since timers and other callbacks will take care of saving and\n"
"restoring the context automatically, but there may be rare cases where\n" "restoring the context automatically, but there may be rare cases where\n"
"you need to deal with them, such as when loading media in for use in\n" "you need to deal with them, such as when loading media in for use in\n"
"the UI (there is a special 'ui' context for all user-interface-related\n" "the UI (there is a special `'ui'` context for all\n"
"functionality)\n" "user-interface-related functionality).\n"
"\n" "\n"
"When instantiating a ba.Context instance, a single ``'source'`` " "When instantiating a ba.Context instance, a single `'source'` "
"argument\n" "argument\n"
"is passed, which can be one of the following strings/objects:\n\n" "is passed, which can be one of the following strings/objects:\n\n"
"``'empty'``:\n" "`'empty'`:\n"
" Gives an empty context; it can be handy to run code here to ensure\n" "> Gives an empty context; it can be handy to run code here to ensure\n"
" it does no loading of media, creation of nodes, etc.\n" "it does no loading of media, creation of nodes, etc.\n"
"\n" "\n"
"``'current'``:\n" "###### `'current'`\n"
" Sets the context object to the current context.\n" "> Sets the context object to the current context.\n"
"\n" "\n"
"``'ui'``:\n" "###### `'ui'`\n"
" Sets to the UI context. UI functions as well as loading of media to\n" "> Sets to the UI context. UI functions as well as loading of media to\n"
" be used in said functions must happen in the UI context.\n" "be used in said functions must happen in the UI context.\n"
"\n" "\n"
"A ba.Activity instance:\n" "###### A ba.Activity instance\n"
" Gives the context for the provided ba.Activity.\n" "> Gives the context for the provided ba.Activity.\n"
" Most all code run during a game happens in an Activity's Context.\n" " Most all code run during a game happens in an Activity's Context.\n"
"\n" "\n"
"A ba.Session instance:\n" "###### A ba.Session instance\n"
" Gives the context for the provided ba.Session.\n" "> Gives the context for the provided ba.Session.\n"
" Generally a user should not need to run anything here.\n" "Generally a user should not need to run anything here.\n"
"\n" "\n"
"\n" "\n"
"Usage:\n" "##### Usage\n"
" Contexts are generally used with the python 'with' statement, " "Contexts are generally used with the python 'with' statement, which\n"
"which\n" "sets the context as current on entry and resets it to the previous\n"
" sets the context as current on entry and resets it to the previous\n" "value on exit.\n"
" value on exit.\n"
"\n" "\n"
"Example:\n" "##### Example\n"
" Load a few textures into the UI context\n" "Load a few textures into the UI context\n"
" (for use in widgets, etc):\n" "(for use in widgets, etc):\n"
" ```python\n" ">>> with ba.Context('ui'):\n"
" >>> with ba.Context('ui'):\n" "... tex1 = ba.gettexture('foo_tex_1')\n"
" ... tex1 = ba.gettexture('foo_tex_1')\n" "... tex2 = ba.gettexture('foo_tex_2')\n";
" ... tex2 = ba.gettexture('foo_tex_2')\n"
" ```\n";
obj->tp_new = tp_new; obj->tp_new = tp_new;
obj->tp_dealloc = (destructor)tp_dealloc; obj->tp_dealloc = (destructor)tp_dealloc;

View File

@ -16,7 +16,7 @@ void PythonClassContextCall::SetupType(PyTypeObject* obj) {
"\n" "\n"
"A context-preserving callable.\n" "A context-preserving callable.\n"
"\n" "\n"
"Category: General Utility Classes\n" "Category: **General Utility Classes**\n"
"\n" "\n"
"A ContextCall wraps a callable object along with a reference\n" "A ContextCall wraps a callable object along with a reference\n"
"to the current context (see ba.Context); it handles restoring the\n" "to the current context (see ba.Context); it handles restoring the\n"
@ -38,23 +38,20 @@ void PythonClassContextCall::SetupType(PyTypeObject* obj) {
"shutdown, whereas ba.WeakCall simply looks at whether the target\n" "shutdown, whereas ba.WeakCall simply looks at whether the target\n"
"object still exists.\n" "object still exists.\n"
"\n" "\n"
"Examples:\n" "##### Examples\n"
" Example A: code like this can inadvertently prevent our activity\n" "**Example A:** code like this can inadvertently prevent our activity\n"
" (self) from ending until the operation completes, since the bound\n" "(self) from ending until the operation completes, since the bound\n"
" method we're passing (self.dosomething) contains a " "method we're passing (self.dosomething) contains a strong-reference\n"
"strong-reference\n" "to self).\n"
" to self).\n" ">>> start_some_long_action(callback_when_done=self.dosomething)\n"
" >>> start_some_long_action(callback_when_done=self.dosomething)\n"
"\n" "\n"
" Example B: in this case our activity (self) can still die\n" "**Example B:** in this case our activity (self) can still die\n"
" properly; the callback will clear itself when the activity starts\n" "properly; the callback will clear itself when the activity starts\n"
" shutting down, becoming a harmless no-op and releasing the " "shutting down, becoming a harmless no-op and releasing the reference\n"
"reference\n" "to our activity.\n"
" to our activity.\n" "\n"
" ```python\n" ">>> start_long_action(\n"
" >>> start_long_action(\n" "... callback_when_done=ba.ContextCall(self.mycallback))\n";
" ... callback_when_done=ba.ContextCall(self.mycallback))\n"
" ```\n";
obj->tp_new = tp_new; obj->tp_new = tp_new;
obj->tp_dealloc = (destructor)tp_dealloc; obj->tp_dealloc = (destructor)tp_dealloc;

View File

@ -24,9 +24,9 @@ void PythonClassData::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"A reference to a data object.\n" "A reference to a data object.\n"
"\n" "\n"
"Category: Asset Classes\n" "Category: **Asset Classes**\n"
"\n" "\n"
"Use ba.getdata() to instantiate one."; "Use ba.getdata to instantiate one.";
obj->tp_repr = (reprfunc)tp_repr; obj->tp_repr = (reprfunc)tp_repr;
obj->tp_new = tp_new; obj->tp_new = tp_new;
obj->tp_dealloc = (destructor)tp_dealloc; obj->tp_dealloc = (destructor)tp_dealloc;

View File

@ -19,7 +19,7 @@ void PythonClassInputDevice::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"An input-device such as a gamepad, touchscreen, or keyboard.\n" "An input-device such as a gamepad, touchscreen, or keyboard.\n"
"\n" "\n"
"Category: Gameplay Classes\n" "Category: **Gameplay Classes**\n"
"\n" "\n"
"Attributes:\n" "Attributes:\n"
"\n" "\n"

View File

@ -280,147 +280,151 @@ PyMethodDef PythonClassMaterial::tp_methods[] = {
"\n" "\n"
"Add one or more actions to the material, optionally with conditions.\n" "Add one or more actions to the material, optionally with conditions.\n"
"\n" "\n"
"Conditions:\n" "##### Conditions\n"
" Conditions are provided as tuples which can be combined\n" "Conditions are provided as tuples which can be combined\n"
" to form boolean logic. A single condition might look like\n" "to form boolean logic. A single condition might look like\n"
" ``('condition_name', cond_arg)``, or a more complex nested one\n" "`('condition_name', cond_arg)`, or a more complex nested one\n"
" might look like ``(('some_condition', cond_arg), 'or',\n" "might look like `(('some_condition', cond_arg), 'or',\n"
" ('another_condition', cond2_arg))``.\n" "('another_condition', cond2_arg))`.\n"
"\n" "\n"
" ``'and'``, ``'or'``, and ``'xor'`` are available to chain\n" "`'and'`, `'or'`, and `'xor'` are available to chain\n"
" together 2 conditions, as seen above.\n" "together 2 conditions, as seen above.\n"
"\n" "\n"
"Available Conditions:\n" "##### Available Conditions\n"
" ``('they_have_material', material)`` - does the part we\'re\n" "###### `('they_have_material', material)`\n"
" hitting have a given ba.Material?\n" "> Does the part we\'re hitting have a given ba.Material?\n"
"\n" "\n"
" ``('they_dont_have_material', material)`` - does the part we\'re\n" "###### `('they_dont_have_material', material)`\n"
" hitting not have a given ba.Material?\n" "> Does the part we\'re hitting not have a given ba.Material?\n"
"\n" "\n"
" ``('eval_colliding')`` - is ``'collide'`` true at this point\n" "###### `('eval_colliding')`\n"
" in material evaluation? (see the modify_part_collision action)\n" "> Is `'collide'` true at this point\n"
"in material evaluation? (see the `modify_part_collision` action)\n"
"\n" "\n"
" ``('eval_not_colliding')`` - is 'collide' false at this point\n" "###### `('eval_not_colliding')`\n"
" in material evaluation? (see the modify_part_collision action)\n" "> Is 'collide' false at this point\n"
"in material evaluation? (see the `modify_part_collision` action)\n"
"\n" "\n"
" ``('we_are_younger_than', age)`` - is our part younger than\n" "###### `('we_are_younger_than', age)`\n"
" ``'age'`` (in milliseconds)?\n" "> Is our part younger than `age` (in milliseconds)?\n"
"\n" "\n"
" ``('we_are_older_than', age)`` - is our part older than ``'age'``\n" "###### `('we_are_older_than', age)`\n"
" (in milliseconds)?\n" "> Is our part older than `age` (in milliseconds)?\n"
"\n" "\n"
" ``('they_are_younger_than', age)`` - is the part we're hitting\n" "###### `('they_are_younger_than', age)`\n"
" younger than ``'age'`` (in milliseconds)?\n" "> Is the part we're hitting younger than `age` (in milliseconds)?\n"
"\n" "\n"
" ``('they_are_older_than', age)`` - is the part we're hitting\n" "###### `('they_are_older_than', age)`\n"
" older than ``'age'`` (in milliseconds)?\n" "> Is the part we're hitting older than `age` (in milliseconds)?\n"
"\n" "\n"
" ``('they_are_same_node_as_us')`` - does the part we're hitting\n" "###### `('they_are_same_node_as_us')`\n"
" belong to the same ba.Node as us?\n" "> Does the part we're hitting belong to the same ba.Node as us?\n"
"\n" "\n"
" ``('they_are_different_node_than_us')`` - does the part we're\n" "###### `('they_are_different_node_than_us')`\n"
" hitting belong to a different ba.Node than us?\n" "> Does the part we're hitting belong to a different ba.Node than us?\n"
"\n" "\n"
"Actions:\n" "##### Actions\n"
" In a similar manner, actions are specified as tuples.\n" "In a similar manner, actions are specified as tuples.\n"
" Multiple actions can be specified by providing a tuple\n" "Multiple actions can be specified by providing a tuple\n"
" of tuples.\n" "of tuples.\n"
"\n" "\n"
"Available Actions:\n" "##### Available Actions\n"
" ``('call', when, callable)`` - calls the provided callable;\n" "###### `('call', when, callable)`\n"
" ``'when'`` can be either ``'at_connect'`` or ``'at_disconnect'``.\n" "> Calls the provided callable;\n"
" ``'at_connect'`` means to fire\n" "`when` can be either `'at_connect'` or `'at_disconnect'`.\n"
" when the two parts first come in contact; ``'at_disconnect'``\n" "`'at_connect'` means to fire\n"
" means to fire once they cease being in contact.\n" "when the two parts first come in contact; `'at_disconnect'`\n"
"means to fire once they cease being in contact.\n"
"\n" "\n"
" ``('message', who, when, message_obj)`` - sends a message object;\n" "###### `('message', who, when, message_obj)`\n"
" ``'who'`` can\n" "> Sends a message object;\n"
" be either ``'our_node'`` or ``'their_node'``, ``'when'`` can be\n" "`who` can be either `'our_node'` or `'their_node'`, `when` can be\n"
" ``'at_connect'`` or\n" "`'at_connect'` or `'at_disconnect'`, and `message_obj` is the message\n"
" ``'at_disconnect'``, and message_obj is the message object to send.\n" "object to send.\n"
" This has the same effect as calling the node's\n" "This has the same effect as calling the node's\n"
" ba.Node.handlemessage method.\n" "ba.Node.handlemessage method.\n"
"\n" "\n"
" ``('modify_part_collision', attr, value)`` - changes some\n" "###### `('modify_part_collision', attr, value)`\n"
" characteristic of the physical collision that will occur between\n" "> Changes some\n"
" our part and their part. This change will remain in effect as\n" "characteristic of the physical collision that will occur between\n"
" long as the two parts remain overlapping. This means if you have a\n" "our part and their part. This change will remain in effect as\n"
" part with a material that turns ``'collide'`` off against parts\n" "long as the two parts remain overlapping. This means if you have a\n"
" younger than 100ms, and it touches another part that is 50ms old,\n" "part with a material that turns `'collide'` off against parts\n"
" it will continue to not collide with that part until they separate,\n" "younger than 100ms, and it touches another part that is 50ms old,\n"
" even if the 100ms threshold is passed. Options for attr/value are:\n" "it will continue to not collide with that part until they separate,\n"
" ``'physical'`` (boolean value; whether a *physical* response will\n" "even if the 100ms threshold is passed. Options for attr/value are:\n"
" occur at all), ``'friction'`` (float value; how friction-y the\n" "`'physical'` (boolean value; whether a *physical* response will\n"
" physical response will be), ``'collide'`` (boolean value;\n" "occur at all), `'friction'` (float value; how friction-y the\n"
" whether *any* collision will occur at all, including non-physical\n" "physical response will be), `'collide'` (boolean value;\n"
" stuff like callbacks), ``'use_node_collide'``\n" "whether *any* collision will occur at all, including non-physical\n"
" (boolean value; whether to honor modify_node_collision\n" "stuff like callbacks), `'use_node_collide'`\n"
" overrides for this collision), ``'stiffness'`` (float value,\n" "(boolean value; whether to honor modify_node_collision\n"
" how springy the physical response is), ``'damping'`` (float\n" "overrides for this collision), `'stiffness'` (float value,\n"
" value, how damped the physical response is), ``'bounce'`` (float\n" "how springy the physical response is), `'damping'` (float\n"
" value; how bouncy the physical response is)." "value, how damped the physical response is), `'bounce'` (float\n"
"value; how bouncy the physical response is)."
"\n" "\n"
" ``('modify_node_collision', attr, value)`` - similar to\n" "###### `('modify_node_collision', attr, value)`\n"
" ``modify_part_collision``, but operates at a node-level.\n" "> Similar to\n"
" collision attributes set here will remain in effect as long as\n" "`modify_part_collision`, but operates at a node-level.\n"
" *anything* from our part's node and their part's node overlap.\n" "collision attributes set here will remain in effect as long as\n"
" A key use of this functionality is to prevent new nodes from\n" "*anything* from our part's node and their part's node overlap.\n"
" colliding with each other if they appear overlapped;\n" "A key use of this functionality is to prevent new nodes from\n"
" if ``modify_part_collision`` is used, only the individual\n" "colliding with each other if they appear overlapped;\n"
" parts that were overlapping would avoid contact, but other parts\n" "if `modify_part_collision` is used, only the individual\n"
" could still contact leaving the two nodes 'tangled up'. Using\n" "parts that were overlapping would avoid contact, but other parts\n"
" ``modify_node_collision ensures`` that the nodes must completely\n" "could still contact leaving the two nodes 'tangled up'. Using\n"
" separate before they can start colliding. Currently the only attr\n" "`modify_node_collision` ensures that the nodes must completely\n"
" available here is ``'collide'`` (a boolean value).\n" "separate before they can start colliding. Currently the only attr\n"
"available here is `'collide'` (a boolean value).\n"
"\n" "\n"
" ``('sound', sound, volume)`` - plays a ba.Sound when a collision\n" "###### `('sound', sound, volume)`\n"
" occurs, at a given volume, regardless of the collision speed/etc.\n" "> Plays a ba.Sound when a collision\n"
"occurs, at a given volume, regardless of the collision speed/etc.\n"
"\n" "\n"
" ``('impact_sound', sound, targetImpulse, volume)`` - plays a sound\n" "###### `('impact_sound', sound, targetImpulse, volume)`\n"
" when a collision occurs, based on the speed of impact.\n" "> Plays a sound\n"
" Provide a ba.Sound, a target-impulse, and a volume.\n" "when a collision occurs, based on the speed of impact.\n"
"Provide a ba.Sound, a target-impulse, and a volume.\n"
"\n" "\n"
" ``('skid_sound', sound, targetImpulse, volume)`` - plays a sound\n" "###### `('skid_sound', sound, targetImpulse, volume)`\n"
" during a collision when parts are 'scraping' against each other.\n" "> Plays a sound\n"
" Provide a ba.Sound, a target-impulse, and a volume.\n" "during a collision when parts are 'scraping' against each other.\n"
"Provide a ba.Sound, a target-impulse, and a volume.\n"
"\n" "\n"
" ``('roll_sound', sound, targetImpulse, volume)`` - plays a sound\n" "###### `('roll_sound', sound, targetImpulse, volume)`\n"
" during a collision when parts are 'rolling' against each other.\n" "> Plays a sound\n"
" Provide a ba.Sound, a target-impulse, and a volume.\n" "during a collision when parts are 'rolling' against each other.\n"
"Provide a ba.Sound, a target-impulse, and a volume.\n"
"\n" "\n"
"Examples:\n" "##### Examples\n"
" example 1: create a material that lets us ignore\n" "**Example 1:** create a material that lets us ignore\n"
" collisions against any nodes we touch in the first\n" "collisions against any nodes we touch in the first\n"
" 100 ms of our existence; handy for preventing us from\n" "100 ms of our existence; handy for preventing us from\n"
" exploding outward if we spawn on top of another object:\n" "exploding outward if we spawn on top of another object:\n"
" ```python\n" ">>> m = ba.Material()\n"
" >>> m = ba.Material()\n" "... m.add_actions(\n"
" ... m.add_actions(\n" "... conditions=(('we_are_younger_than', 100),\n"
" ... conditions=(('we_are_younger_than', 100),\n" "... 'or', ('they_are_younger_than', 100)),\n"
" ... 'or', ('they_are_younger_than', 100)),\n" "... actions=('modify_node_collision', 'collide', False))\n"
" ... actions=('modify_node_collision', 'collide', False))\n"
" ```\n"
"\n" "\n"
" example 2: send a ba.DieMessage to anything we touch, but cause\n" "**Example 2:** send a ba.DieMessage to anything we touch, but cause\n"
" no physical response. This should cause any ba.Actor to drop dead:\n" "no physical response. This should cause any ba.Actor to drop dead:\n"
" ```python\n" "```python\n"
" >>> m = ba.Material()\n" ">>> m = ba.Material()\n"
" ... m.add_actions(\n" "... m.add_actions(\n"
" ... actions=(('modify_part_collision', 'physical', False),\n" "... actions=(('modify_part_collision', 'physical', False),\n"
" ... ('message', 'their_node', 'at_connect',\n" "... ('message', 'their_node', 'at_connect',\n"
" ... ba.DieMessage())))\n" "... ba.DieMessage())))\n"
" ```\n"
"\n" "\n"
" example 3: play some sounds when we're contacting the ground:\n" "**Example 3:** play some sounds when we're contacting the ground:\n"
" ```python\n" "```python\n"
" >>> m = ba.Material()\n" ">>> m = ba.Material()\n"
" ... m.add_actions(\n" "... m.add_actions(\n"
" ... conditions=('they_have_material',\n" "... conditions=('they_have_material',\n"
" shared.footing_material),\n" "... shared.footing_material),\n"
" ... actions=(('impact_sound', ba.getsound('metalHit'), 2, 5),\n" "... actions=(('impact_sound', ba.getsound('metalHit'), 2, 5),\n"
" ... ('skid_sound', ba.getsound('metalSkid'), 2, 5)))\n" "... ('skid_sound', ba.getsound('metalSkid'), 2, 5)))\n"},
" ```\n"
"\n"},
{"__dir__", (PyCFunction)Dir, METH_NOARGS, {"__dir__", (PyCFunction)Dir, METH_NOARGS,
"allows inclusion of our custom attrs in standard python dir()"}, "allows inclusion of our custom attrs in standard python dir()"},

View File

@ -24,7 +24,7 @@ void PythonClassModel::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"A reference to a model.\n" "A reference to a model.\n"
"\n" "\n"
"Category: Asset Classes\n" "Category: **Asset Classes**\n"
"\n" "\n"
"Models are used for drawing.\n" "Models are used for drawing.\n"
"Use ba.getmodel() to instantiate one."; "Use ba.getmodel() to instantiate one.";

View File

@ -34,8 +34,8 @@ void PythonClassNode::SetupType(PyTypeObject* obj) {
"to a game node; *not* the node itself. This means a Node's\n" "to a game node; *not* the node itself. This means a Node's\n"
"lifecycle is completely independent of how many Python references\n" "lifecycle is completely independent of how many Python references\n"
"to it exist. To explicitly add a new node to the game, use\n" "to it exist. To explicitly add a new node to the game, use\n"
"ba.newnode(), and to explicitly delete one, use ba.Node.delete().\n" "ba.newnode, and to explicitly delete one, use ba.Node.delete.\n"
"ba.Node.exists() can be used to determine if a Node still points to\n" "ba.Node.exists can be used to determine if a Node still points to\n"
"a live node in the game.\n" "a live node in the game.\n"
"\n" "\n"
"You can use ba.Node(None) to instantiate an invalid\n" "You can use ba.Node(None) to instantiate an invalid\n"
@ -413,7 +413,7 @@ PyMethodDef PythonClassNode::tp_methods[] = {
{"delete", (PyCFunction)Delete, METH_VARARGS | METH_KEYWORDS, {"delete", (PyCFunction)Delete, METH_VARARGS | METH_KEYWORDS,
"delete(ignore_missing: bool = True) -> None\n" "delete(ignore_missing: bool = True) -> None\n"
"\n" "\n"
"Delete the node. Ignores already-deleted nodes if ignore_missing\n" "Delete the node. Ignores already-deleted nodes if `ignore_missing`\n"
"is True; otherwise a ba.NodeNotFoundError is thrown."}, "is True; otherwise a ba.NodeNotFoundError is thrown."},
{"handlemessage", (PyCFunction)HandleMessage, METH_VARARGS, {"handlemessage", (PyCFunction)HandleMessage, METH_VARARGS,
"handlemessage(*args: Any) -> None\n" "handlemessage(*args: Any) -> None\n"
@ -423,7 +423,7 @@ PyMethodDef PythonClassNode::tp_methods[] = {
"All standard message objects are forwarded along to the ba.Node's\n" "All standard message objects are forwarded along to the ba.Node's\n"
"delegate for handling (generally the ba.Actor that made the node).\n" "delegate for handling (generally the ba.Actor that made the node).\n"
"\n" "\n"
"ba.Nodes are unique, however, in that they can be passed a second\n" "ba.Node-s are unique, however, in that they can be passed a second\n"
"form of message; 'node-messages'. These consist of a string type-name\n" "form of message; 'node-messages'. These consist of a string type-name\n"
"as a first argument along with the args specific to that type name\n" "as a first argument along with the args specific to that type name\n"
"as additional arguments.\n" "as additional arguments.\n"
@ -445,13 +445,11 @@ PyMethodDef PythonClassNode::tp_methods[] = {
"setting the target attribute to any value or connecting another\n" "setting the target attribute to any value or connecting another\n"
"node attribute to it.\n" "node attribute to it.\n"
"\n" "\n"
"Example:\n" "##### Example\n"
" Create a locator and attach a light to it:\n" "Create a locator and attach a light to it:\n"
" ```python\n" ">>> light = ba.newnode('light')\n"
" >>> light = ba.newnode('light')\n" "... loc = ba.newnode('locator', attrs={'position': (0, 10, 0)})\n"
" ... loc = ba.newnode('locator', attrs={'position': (0, 10, 0)})\n" "... loc.connectattr('position', light, 'position')\n"},
" ... loc.connectattr('position', light, 'position')\n"
" ```\n"},
{"__dir__", (PyCFunction)Dir, METH_NOARGS, {"__dir__", (PyCFunction)Dir, METH_NOARGS,
"allows inclusion of our custom attrs in standard python dir()"}, "allows inclusion of our custom attrs in standard python dir()"},
{nullptr}}; {nullptr}};

View File

@ -46,14 +46,14 @@ void PythonClassSessionPlayer::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"A reference to a player in the ba.Session.\n" "A reference to a player in the ba.Session.\n"
"\n" "\n"
"Category: Gameplay Classes\n" "Category: **Gameplay Classes**\n"
"\n" "\n"
"These are created and managed internally and\n" "These are created and managed internally and\n"
"provided to your Session/Activity instances.\n" "provided to your ba.Session/ba.Activity instances.\n"
"Be aware that, like ba.Nodes, ba.SessionPlayer objects are 'weak'\n" "Be aware that, like ba.Nodes, ba.SessionPlayer objects are 'weak'\n"
"references under-the-hood; a player can leave the game at\n" "references under-the-hood; a player can leave the game at\n"
" any point. For this reason, you should make judicious use of the\n" " any point. For this reason, you should make judicious use of the\n"
"ba.SessionPlayer.exists() method (or boolean operator) to ensure\n" "ba.SessionPlayer.exists method (or boolean operator) to ensure\n"
"that a SessionPlayer is still present if retaining references to one\n" "that a SessionPlayer is still present if retaining references to one\n"
"for any length of time.\n" "for any length of time.\n"
"\n" "\n"

View File

@ -24,9 +24,9 @@ void PythonClassSound::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"A reference to a sound.\n" "A reference to a sound.\n"
"\n" "\n"
"Category: Asset Classes\n" "Category: **Asset Classes**\n"
"\n" "\n"
"Use ba.getsound() to instantiate one."; "Use ba.getsound to instantiate one.";
obj->tp_repr = (reprfunc)tp_repr; obj->tp_repr = (reprfunc)tp_repr;
obj->tp_new = tp_new; obj->tp_new = tp_new;
obj->tp_dealloc = (destructor)tp_dealloc; obj->tp_dealloc = (destructor)tp_dealloc;

View File

@ -24,7 +24,7 @@ void PythonClassTexture::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"A reference to a texture.\n" "A reference to a texture.\n"
"\n" "\n"
"Category: Asset Classes\n" "Category: **Asset Classes**\n"
"\n" "\n"
"Use ba.gettexture() to instantiate one."; "Use ba.gettexture() to instantiate one.";
obj->tp_repr = (reprfunc)tp_repr; obj->tp_repr = (reprfunc)tp_repr;

View File

@ -19,7 +19,7 @@ void PythonClassTimer::SetupType(PyTypeObject* obj) {
"\n" "\n"
"Timers are used to run code at later points in time.\n" "Timers are used to run code at later points in time.\n"
"\n" "\n"
"Category: General Utility Classes\n" "Category: **General Utility Classes**\n"
"\n" "\n"
"This class encapsulates a timer in the current ba.Context.\n" "This class encapsulates a timer in the current ba.Context.\n"
"The underlying timer will be destroyed when either this object is\n" "The underlying timer will be destroyed when either this object is\n"
@ -27,38 +27,41 @@ void PythonClassTimer::SetupType(PyTypeObject* obj) {
"do not want to worry about keeping a reference to your timer around,\n" "do not want to worry about keeping a reference to your timer around,\n"
"you should use the ba.timer() function instead.\n" "you should use the ba.timer() function instead.\n"
"\n" "\n"
"time: length of time (in seconds by default) that the timer will wait\n" "###### time\n"
"> Length of time (in seconds by default) that the timer will wait\n"
"before firing. Note that the actual delay experienced may vary\n" "before firing. Note that the actual delay experienced may vary\n"
"depending on the timetype. (see below)\n" "depending on the timetype. (see below)\n"
"\n" "\n"
"call: A callable Python object. Note that the timer will retain a\n" "###### call\n"
"> A callable Python object. Note that the timer will retain a\n"
"strong reference to the callable for as long as it exists, so you\n" "strong reference to the callable for as long as it exists, so you\n"
"may want to look into concepts such as ba.WeakCall if that is not\n" "may want to look into concepts such as ba.WeakCall if that is not\n"
"desired.\n" "desired.\n"
"\n" "\n"
"repeat: if True, the timer will fire repeatedly, with each successive\n" "###### repeat\n"
"> If True, the timer will fire repeatedly, with each successive\n"
"firing having the same delay as the first.\n" "firing having the same delay as the first.\n"
"\n" "\n"
"timetype: A ba.TimeType value determining which timeline the timer is\n" "###### timetype\n"
"> A ba.TimeType value determining which timeline the timer is\n"
"placed onto.\n" "placed onto.\n"
"\n" "\n"
"timeformat: A ba.TimeFormat value determining how the passed time is\n" "###### timeformat\n"
"> A ba.TimeFormat value determining how the passed time is\n"
"interpreted.\n" "interpreted.\n"
"\n" "\n"
"Example:\n" "##### Example\n"
" Use a Timer object to print repeatedly for a few seconds:\n" "\n"
" ```python\n" "Use a Timer object to print repeatedly for a few seconds:\n"
" >>> def say_it():\n" ">>> def say_it():\n"
" ... ba.screenmessage('BADGER!')\n" "... ba.screenmessage('BADGER!')\n"
" ... def stop_saying_it():\n" "... def stop_saying_it():\n"
" ... self.t = None\n" "... self.t = None\n"
" ... ba.screenmessage('MUSHROOM MUSHROOM!')\n" "... ba.screenmessage('MUSHROOM MUSHROOM!')\n"
" ... # Create our timer; it will run as long as we have the self.t " "... # Create our timer; it will run as long as we have the self.t ref.\n"
"ref.\n" "... self.t = ba.Timer(0.3, say_it, repeat=True)\n"
" ... self.t = ba.Timer(0.3, say_it, repeat=True)\n" "... # Now fire off a one-shot timer to kill it.\n"
" ... # Now fire off a one-shot timer to kill it.\n" "... ba.timer(3.89, stop_saying_it)\n";
" ... ba.timer(3.89, stop_saying_it)\n"
" ```\n";
obj->tp_new = tp_new; obj->tp_new = tp_new;
obj->tp_dealloc = (destructor)tp_dealloc; obj->tp_dealloc = (destructor)tp_dealloc;
} }

View File

@ -29,7 +29,7 @@ void PythonClassVec3::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"A vector of 3 floats.\n" "A vector of 3 floats.\n"
"\n" "\n"
"Category: General Utility Classes\n" "Category: **General Utility Classes**\n"
"\n" "\n"
"These can be created the following ways (checked in this order):\n" "These can be created the following ways (checked in this order):\n"
"- with no args, all values are set to 0\n" "- with no args, all values are set to 0\n"

View File

@ -22,11 +22,11 @@ void PythonClassWidget::SetupType(PyTypeObject* obj) {
obj->tp_doc = obj->tp_doc =
"Internal type for low level UI elements; buttons, windows, etc.\n" "Internal type for low level UI elements; buttons, windows, etc.\n"
"\n" "\n"
"Category: User Interface Classes\n" "Category: **User Interface Classes**\n"
"\n" "\n"
"This class represents a weak reference to a widget object\n" "This class represents a weak reference to a widget object\n"
"in the internal c++ layer. Currently, functions such as\n" "in the internal C++ layer. Currently, functions such as\n"
"ba.buttonwidget() must be used to instantiate or edit these."; "ba.buttonwidget must be used to instantiate or edit these.";
obj->tp_new = tp_new; obj->tp_new = tp_new;
obj->tp_dealloc = (destructor)tp_dealloc; obj->tp_dealloc = (destructor)tp_dealloc;
obj->tp_repr = (reprfunc)tp_repr; obj->tp_repr = (reprfunc)tp_repr;

View File

@ -926,7 +926,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"log(message: str, to_stdout: bool = True,\n" "log(message: str, to_stdout: bool = True,\n"
" to_server: bool = True) -> None\n" " to_server: bool = True) -> None\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Log a message. This goes to the default logging mechanism depending\n" "Log a message. This goes to the default logging mechanism depending\n"
"on the platform (stdout on mac, android log on android, etc).\n" "on the platform (stdout on mac, android log on android, etc).\n"
@ -989,7 +989,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Quit the game.\n" "Quit the game.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"On systems like android, 'soft' will end the activity but keep the\n" "On systems like android, 'soft' will end the activity but keep the\n"
"app running."}, "app running."},
@ -1003,7 +1003,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Print a message to the local client's screen, in a given color.\n" "Print a message to the local client's screen, in a given color.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"If 'top' is True, the message will go to the top message area.\n" "If 'top' is True, the message will go to the top message area.\n"
"For 'top' messages, 'image' can be a texture to display alongside " "For 'top' messages, 'image' can be a texture to display alongside "
@ -1027,41 +1027,34 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Schedule a call to run at a later point in time.\n" "Schedule a call to run at a later point in time.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"This function adds a timer to the current ba.Context.\n" "This function adds a timer to the current ba.Context.\n"
"This timer cannot be canceled or modified once created. If you\n" "This timer cannot be canceled or modified once created. If you\n"
" require the ability to do so, use the ba.Timer class instead.\n" " require the ability to do so, use the ba.Timer class instead.\n"
"\n" "\n"
"Arguments:\n" "##### Arguments\n"
" time (float):\n" "###### time (float):\n"
" Length of time (in seconds by default) that the timer will " "> Length of time (in seconds by default) that the timer will wait\n"
"wait\n" "before firing. Note that the actual delay experienced may vary\n "
" before firing. Note that the actual delay experienced may " "depending on the timetype. (see below)\n"
"vary\n "
" depending on the timetype. (see below)\n"
"\n" "\n"
" call (Callable[[], Any]):\n" "###### call (Callable[[], Any])\n"
" A callable Python object. Note that the timer will retain a\n" "> A callable Python object. Note that the timer will retain a\n"
" strong reference to the callable for as long as it exists, " "strong reference to the callable for as long as it exists, so you\n"
"so you\n" "may want to look into concepts such as ba.WeakCall if that is not\n"
" may want to look into concepts such as ba.WeakCall if that " "desired.\n"
"is not\n"
" desired.\n"
"\n" "\n"
" repeat (bool):\n" "###### repeat (bool)\n"
" If True, the timer will fire repeatedly, with each " "> If True, the timer will fire repeatedly, with each successive\n"
"successive\n" "firing having the same delay as the first.\n"
" firing having the same delay as the first.\n"
"\n" "\n"
"###### timetype (ba.TimeType)\n"
"> Can be either `SIM`, `BASE`, or `REAL`. It defaults to\n"
"`SIM`.\n"
"\n" "\n"
" timetype (ba.TimeType):\n" "###### timeformat (ba.TimeFormat)\n"
" Can be either ``SIM``, ``BASE``, or ``REAL``. It defaults " "> Defaults to seconds but can also be milliseconds.\n"
"to\n"
" ``SIM``.\n"
"\n"
" timeformat (ba.TimeFormat):\n"
" Defaults to seconds but can also be milliseconds.\n"
"\n" "\n"
"- SIM time maps to local simulation time in ba.Activity or " "- SIM time maps to local simulation time in ba.Activity or "
"ba.Session\n" "ba.Session\n"
@ -1081,15 +1074,13 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"backgrounded, system time changing, etc.)\n" "backgrounded, system time changing, etc.)\n"
"Real time timers are currently only available in the UI context.\n" "Real time timers are currently only available in the UI context.\n"
"\n" "\n"
"Examples:\n" "##### Examples\n"
" Print some stuff through time:\n" "Print some stuff through time:\n"
" ```python\n" ">>> ba.screenmessage('hello from now!')\n"
" >>> ba.screenmessage('hello from now!')\n" ">>> ba.timer(1.0, ba.Call(ba.screenmessage, 'hello from the "
" >>> ba.timer(1.0, ba.Call(ba.screenmessage, 'hello from the "
"future!'))\n" "future!'))\n"
" >>> ba.timer(2.0, ba.Call(ba.screenmessage,\n" ">>> ba.timer(2.0, ba.Call(ba.screenmessage,\n"
" ... 'hello from the future 2!'))\n" "... 'hello from the future 2!'))\n"},
" ```\n"},
{"time", (PyCFunction)PyTime, METH_VARARGS | METH_KEYWORDS, {"time", (PyCFunction)PyTime, METH_VARARGS | METH_KEYWORDS,
"time(timetype: ba.TimeType = TimeType.SIM,\n" "time(timetype: ba.TimeType = TimeType.SIM,\n"
@ -1098,32 +1089,32 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return the current time.\n" "Return the current time.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"The time returned depends on the current ba.Context and timetype.\n" "The time returned depends on the current ba.Context and timetype.\n"
"\n" "\n"
"timetype can be either SIM, BASE, or REAL. It defaults to\n" "timetype can be either SIM, BASE, or REAL. It defaults to\n"
"SIM. Types are explained below:\n" "SIM. Types are explained below:\n"
"\n" "\n"
"SIM time maps to local simulation time in ba.Activity or ba.Session\n" "- SIM time maps to local simulation time in ba.Activity or "
"ba.Session\n"
"Contexts. This means that it may progress slower in slow-motion " "Contexts. This means that it may progress slower in slow-motion "
"play\n" "play\n"
"modes, stop when the game is paused, etc. This time type is not\n" "modes, stop when the game is paused, etc. This time type is not\n"
"available in UI contexts.\n" "available in UI contexts.\n"
"\n" "- BASE time is also linked to gameplay in ba.Activity or ba.Session\n"
"BASE time is also linked to gameplay in ba.Activity or ba.Session\n"
"Contexts, but it progresses at a constant rate regardless of\n " "Contexts, but it progresses at a constant rate regardless of\n "
"slow-motion states or pausing. It can, however, slow down or stop\n" "slow-motion states or pausing. It can, however, slow down or stop\n"
"in certain cases such as network outages or game slowdowns due to\n" "in certain cases such as network outages or game slowdowns due to\n"
"cpu load. Like 'sim' time, this is unavailable in UI contexts.\n" "cpu load. Like 'sim' time, this is unavailable in UI contexts.\n"
"\n" "- REAL time always maps to actual clock time with a bit of "
"REAL time always maps to actual clock time with a bit of filtering\n" "filtering\n"
"added, regardless of Context. (the filtering prevents it from " "added, regardless of Context. (The filtering prevents it from going\n"
"going\n"
"backwards or jumping forward by large amounts due to the app being\n" "backwards or jumping forward by large amounts due to the app being\n"
"backgrounded, system time changing, etc.)\n" "backgrounded, system time changing, etc.)\n"
"Real time timers are currently only available in the UI context.\n"
"\n" "\n"
"the 'timeformat' arg defaults to SECONDS which returns float " "The 'timeformat' arg defaults to SECONDS which returns float "
"seconds,\n" "seconds,\n"
"but it can also be MILLISECONDS to return integer milliseconds.\n" "but it can also be MILLISECONDS to return integer milliseconds.\n"
"\n" "\n"
@ -1136,7 +1127,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Pushes a call onto the event loop to be run during the next cycle.\n" "Pushes a call onto the event loop to be run during the next cycle.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"This can be handy for calls that are disallowed from within other\n" "This can be handy for calls that are disallowed from within other\n"
"callbacks, etc.\n" "callbacks, etc.\n"
@ -1155,7 +1146,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return the current ba.Activity instance.\n" "Return the current ba.Activity instance.\n"
"\n" "\n"
"Category: Gameplay Functions\n" "Category: **Gameplay Functions**\n"
"\n" "\n"
"Note that this is based on context; thus code run in a timer " "Note that this is based on context; thus code run in a timer "
"generated\n" "generated\n"
@ -1171,7 +1162,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Instantiates a ba.Activity given a type object.\n" "Instantiates a ba.Activity given a type object.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Activities require special setup and thus cannot be directly\n" "Activities require special setup and thus cannot be directly\n"
"instantiated; you must go through this function."}, "instantiated; you must go through this function."},
@ -1220,7 +1211,7 @@ auto PythonMethodsApp::GetMethods() -> std::vector<PyMethodDef> {
{"getsession", (PyCFunction)PyGetSession, METH_VARARGS | METH_KEYWORDS, {"getsession", (PyCFunction)PyGetSession, METH_VARARGS | METH_KEYWORDS,
"getsession(doraise: bool = True) -> <varies>\n" "getsession(doraise: bool = True) -> <varies>\n"
"\n" "\n"
"Category: Gameplay Functions\n" "Category: **Gameplay Functions**\n"
"\n" "\n"
"Returns the current ba.Session instance.\n" "Returns the current ba.Session instance.\n"
"Note that this is based on context; thus code being run in the UI\n" "Note that this is based on context; thus code being run in the UI\n"

View File

@ -685,7 +685,7 @@ auto PythonMethodsGameplay::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Emit particles, smoke, etc. into the fx sim layer.\n" "Emit particles, smoke, etc. into the fx sim layer.\n"
"\n" "\n"
"Category: Gameplay Functions\n" "Category: **Gameplay Functions**\n"
"\n" "\n"
"The fx sim layer is a secondary dynamics simulation that runs in\n" "The fx sim layer is a secondary dynamics simulation that runs in\n"
"the background and just looks pretty; it does not affect gameplay.\n" "the background and just looks pretty; it does not affect gameplay.\n"
@ -698,17 +698,17 @@ auto PythonMethodsGameplay::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Play a ba.Sound a single time.\n" "Play a ba.Sound a single time.\n"
"\n" "\n"
"Category: Gameplay Functions\n" "Category: **Gameplay Functions**\n"
"\n" "\n"
"If position is not provided, the sound will be at a constant volume\n" "If position is not provided, the sound will be at a constant volume\n"
"everywhere. Position should be a float tuple of size 3."}, "everywhere. Position should be a float tuple of size 3."},
{"camerashake", (PyCFunction)PyCameraShake, METH_VARARGS | METH_KEYWORDS, {"camerashake", (PyCFunction)PyCameraShake, METH_VARARGS | METH_KEYWORDS,
"camerashake(intensity: float = 1.0) -> None\n" "camerashake(intensity: float = 1.0) -> None\n"
"\n" "\n"
"Shake the camera.\n" "Shake the camera.\n"
"\n" "\n"
"Category: Gameplay Functions\n" "Category: **Gameplay Functions**\n"
"\n" "\n"
"Note that some cameras and/or platforms (such as VR) may not display\n" "Note that some cameras and/or platforms (such as VR) may not display\n"
"camera-shake, so do not rely on this always being visible to the\n" "camera-shake, so do not rely on this always being visible to the\n"
@ -719,7 +719,7 @@ auto PythonMethodsGameplay::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return collision related values\n" "Return collision related values\n"
"\n" "\n"
"Category: Gameplay Functions\n" "Category: **Gameplay Functions**\n"
"\n" "\n"
"Returns a single collision value or tuple of values such as location,\n" "Returns a single collision value or tuple of values such as location,\n"
"depth, nodes involved, etc. Only call this in the handler of a\n" "depth, nodes involved, etc. Only call this in the handler of a\n"
@ -730,14 +730,14 @@ auto PythonMethodsGameplay::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return all nodes in the current ba.Context." "Return all nodes in the current ba.Context."
"\n" "\n"
"Category: Gameplay Functions"}, "Category: **Gameplay Functions**"},
{"printnodes", PyPrintNodes, METH_VARARGS, {"printnodes", PyPrintNodes, METH_VARARGS,
"printnodes() -> None\n" "printnodes() -> None\n"
"\n" "\n"
"Print various info about existing nodes; useful for debugging.\n" "Print various info about existing nodes; useful for debugging.\n"
"\n" "\n"
"Category: Gameplay Functions"}, "Category: **Gameplay Functions**"},
{"newnode", (PyCFunction)PyNewNode, METH_VARARGS | METH_KEYWORDS, {"newnode", (PyCFunction)PyNewNode, METH_VARARGS | METH_KEYWORDS,
"newnode(type: str, owner: ba.Node = None,\n" "newnode(type: str, owner: ba.Node = None,\n"
@ -746,7 +746,7 @@ auto PythonMethodsGameplay::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Add a node of the given type to the game.\n" "Add a node of the given type to the game.\n"
"\n" "\n"
"Category: Gameplay Functions\n" "Category: **Gameplay Functions**\n"
"\n" "\n"
"If a dict is provided for 'attributes', the node's initial attributes\n" "If a dict is provided for 'attributes', the node's initial attributes\n"
"will be set based on them.\n" "will be set based on them.\n"

View File

@ -423,7 +423,7 @@ auto PythonMethodsGraphics::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Given a color tuple, return a color safe to display as text.\n" "Given a color tuple, return a color safe to display as text.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Accepts tuples of length 3 or 4. This will slightly brighten very\n" "Accepts tuples of length 3 or 4. This will slightly brighten very\n"
"dark colors, etc."}, "dark colors, etc."},
@ -433,7 +433,7 @@ auto PythonMethodsGraphics::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Get a unicode string representing a special character.\n" "Get a unicode string representing a special character.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Note that these utilize the private-use block of unicode characters\n" "Note that these utilize the private-use block of unicode characters\n"
"(U+E000-U+F8FF) and are specific to the game; exporting or rendering\n" "(U+E000-U+F8FF) and are specific to the game; exporting or rendering\n"

View File

@ -468,7 +468,7 @@ auto PythonMethodsMedia::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return a collide-model, loading it if necessary.\n" "Return a collide-model, loading it if necessary.\n"
"\n" "\n"
"Category: Asset Functions\n" "Category: **Asset Functions**\n"
"\n" "\n"
"Collide-models are used in physics calculations for such things as\n" "Collide-models are used in physics calculations for such things as\n"
"terrain.\n" "terrain.\n"
@ -491,7 +491,7 @@ auto PythonMethodsMedia::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return a model, loading it if necessary.\n" "Return a model, loading it if necessary.\n"
"\n" "\n"
"Category: Asset Functions\n" "Category: **Asset Functions**\n"
"\n" "\n"
"Note that this function returns immediately even if the media has yet\n" "Note that this function returns immediately even if the media has yet\n"
"to be loaded. To avoid hitches, instantiate your media objects in\n" "to be loaded. To avoid hitches, instantiate your media objects in\n"
@ -510,7 +510,7 @@ auto PythonMethodsMedia::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return a sound, loading it if necessary.\n" "Return a sound, loading it if necessary.\n"
"\n" "\n"
"Category: Asset Functions\n" "Category: **Asset Functions**\n"
"\n" "\n"
"Note that this function returns immediately even if the media has yet\n" "Note that this function returns immediately even if the media has yet\n"
"to be loaded. To avoid hitches, instantiate your media objects in\n" "to be loaded. To avoid hitches, instantiate your media objects in\n"
@ -529,7 +529,7 @@ auto PythonMethodsMedia::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return a data, loading it if necessary.\n" "Return a data, loading it if necessary.\n"
"\n" "\n"
"Category: Asset Functions\n" "Category: **Asset Functions**\n"
"\n" "\n"
"Note that this function returns immediately even if the media has yet\n" "Note that this function returns immediately even if the media has yet\n"
"to be loaded. To avoid hitches, instantiate your media objects in\n" "to be loaded. To avoid hitches, instantiate your media objects in\n"
@ -548,7 +548,7 @@ auto PythonMethodsMedia::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return a texture, loading it if necessary.\n" "Return a texture, loading it if necessary.\n"
"\n" "\n"
"Category: Asset Functions\n" "Category: **Asset Functions**\n"
"\n" "\n"
"Note that this function returns immediately even if the media has yet\n" "Note that this function returns immediately even if the media has yet\n"
"to be loaded. To avoid hitches, instantiate your media objects in\n" "to be loaded. To avoid hitches, instantiate your media objects in\n"

View File

@ -791,7 +791,7 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return whether this platform supports clipboard operations at all.\n" "Return whether this platform supports clipboard operations at all.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"If this returns False, UIs should not show 'copy to clipboard'\n" "If this returns False, UIs should not show 'copy to clipboard'\n"
"buttons, etc."}, "buttons, etc."},
@ -800,7 +800,7 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return whether there is currently text on the clipboard.\n" "Return whether there is currently text on the clipboard.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"This will return False if no system clipboard is available; no need\n" "This will return False if no system clipboard is available; no need\n"
" to call ba.clipboard_available() separately."}, " to call ba.clipboard_available() separately."},
@ -810,18 +810,18 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Copy a string to the system clipboard.\n" "Copy a string to the system clipboard.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Ensure that ba.clipboard_available() returns True before adding\n" "Ensure that ba.clipboard_available returns True before adding\n"
" buttons/etc. that make use of this functionality."}, " buttons/etc. that make use of this functionality."},
{"clipboard_get_text", (PyCFunction)PyClipboardGetText, METH_NOARGS, {"clipboard_get_text", (PyCFunction)PyClipboardGetText, METH_NOARGS,
"clipboard_get_text() -> str\n" "clipboard_get_text() -> str\n"
"\n" "\n"
"Return text currently on the system clipboard.\n" "Return text currently on the system clipboard.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Ensure that ba.clipboard_has_text() returns True before calling\n" "Ensure that ba.clipboard_has_text returns True before calling\n"
" this function."}, " this function."},
{"printobjects", (PyCFunction)PyPrintObjects, {"printobjects", (PyCFunction)PyPrintObjects,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
@ -829,7 +829,7 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Print debugging info about game objects.\n" "Print debugging info about game objects.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"This call only functions in debug builds of the game.\n" "This call only functions in debug builds of the game.\n"
"It prints various info about the current object count, etc."}, "It prints various info about the current object count, etc."},
@ -839,20 +839,18 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Return whether this is the first time running a line of code.\n" "Return whether this is the first time running a line of code.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"This is used by 'print_once()' type calls to keep from overflowing\n" "This is used by 'print_once()' type calls to keep from overflowing\n"
"logs. The call functions by registering the filename and line where\n" "logs. The call functions by registering the filename and line where\n"
"The call is made from. Returns True if this location has not been\n" "The call is made from. Returns True if this location has not been\n"
"registered already, and False if it has.\n" "registered already, and False if it has.\n"
"\n" "\n"
"Example:\n" "##### Example\n"
" This print will only fire for the first loop iteration:\n" "This print will only fire for the first loop iteration:\n"
" ```python\n" ">>> for i in range(10):\n"
" >>> for i in range(10):\n" "... if ba.do_once():\n"
" ... if ba.do_once():\n" "... print('Hello once from loop!')\n"},
" ... print('Hello once from loop!')\n"
" ```\n"},
{"_app", (PyCFunction)PyApp, METH_VARARGS | METH_KEYWORDS, {"_app", (PyCFunction)PyApp, METH_VARARGS | METH_KEYWORDS,
"_app() -> ba.App\n" "_app() -> ba.App\n"
@ -904,7 +902,7 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Used for analytics to see where in the app players spend their time.\n" "Used for analytics to see where in the app players spend their time.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Generally called when opening a new window or entering some UI.\n" "Generally called when opening a new window or entering some UI.\n"
"'screen' should be a string description of an app location\n" "'screen' should be a string description of an app location\n"
@ -1006,7 +1004,7 @@ auto PythonMethodsSystem::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"(internal)\n" "(internal)\n"
"\n" "\n"
"Category: General Utility Functions"}, "Category: **General Utility Functions**"},
{"print_context", (PyCFunction)PyPrintContext, {"print_context", (PyCFunction)PyPrintContext,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,

View File

@ -2331,7 +2331,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Open a provided URL.\n" "Open a provided URL.\n"
"\n" "\n"
"Category: General Utility Functions\n" "Category: **General Utility Functions**\n"
"\n" "\n"
"Open the provided url in a web-browser, or display the URL\n" "Open the provided url in a web-browser, or display the URL\n"
"string in a window if that isn't possible.\n"}, "string in a window if that isn't possible.\n"},
@ -2395,7 +2395,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"(internal)\n" "(internal)\n"
"\n" "\n"
"Category: General Utility Functions"}, "Category: **General Utility Functions**"},
{"show_progress_bar", (PyCFunction)PyShowProgressBar, {"show_progress_bar", (PyCFunction)PyShowProgressBar,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
@ -2403,7 +2403,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"(internal)\n" "(internal)\n"
"\n" "\n"
"Category: General Utility Functions"}, "Category: **General Utility Functions**"},
{"show_app_invite", (PyCFunction)PyShowAppInvite, {"show_app_invite", (PyCFunction)PyShowAppInvite,
METH_VARARGS | METH_KEYWORDS, METH_VARARGS | METH_KEYWORDS,
@ -2413,7 +2413,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"(internal)\n" "(internal)\n"
"\n" "\n"
"Category: General Utility Functions"}, "Category: **General Utility Functions**"},
{"show_ad", (PyCFunction)PyShowAd, METH_VARARGS | METH_KEYWORDS, {"show_ad", (PyCFunction)PyShowAd, METH_VARARGS | METH_KEYWORDS,
"show_ad(purpose: str, on_completion_call: Callable[[], None] = None)\n" "show_ad(purpose: str, on_completion_call: Callable[[], None] = None)\n"
@ -2508,7 +2508,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a button widget.\n" "Create or edit a button widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2534,7 +2534,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a check-box widget.\n" "Create or edit a check-box widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2555,7 +2555,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit an image widget.\n" "Create or edit an image widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2583,7 +2583,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a column widget.\n" "Create or edit a column widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2625,7 +2625,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a container widget.\n" "Create or edit a container widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2643,7 +2643,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a row widget.\n" "Create or edit a row widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2666,7 +2666,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a scroll widget.\n" "Create or edit a scroll widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2688,7 +2688,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a horizontal scroll widget.\n" "Create or edit a horizontal scroll widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2719,7 +2719,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Create or edit a text widget.\n" "Create or edit a text widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n" "Pass a valid existing ba.Widget as 'edit' to modify it; otherwise\n"
"a new one is created and returned. Arguments that are not set to None\n" "a new one is created and returned. Arguments that are not set to None\n"
@ -2734,7 +2734,7 @@ auto PythonMethodsUI::GetMethods() -> std::vector<PyMethodDef> {
"\n" "\n"
"Edit common attributes of any widget.\n" "Edit common attributes of any widget.\n"
"\n" "\n"
"Category: User Interface Functions\n" "Category: **User Interface Functions**\n"
"\n" "\n"
"Unlike other UI calls, this can only be used to edit, not to " "Unlike other UI calls, this can only be used to edit, not to "
"create.\n"}, "create.\n"},

View File

@ -80,15 +80,17 @@ def generate(projroot: str) -> None:
# Make sure we're running from the dir above this script. # Make sure we're running from the dir above this script.
os.chdir(projroot) os.chdir(projroot)
pythondir = str( templatesdir = (Path(projroot) / 'assets' / 'src' / 'pdoc' /
Path(projroot, 'assets', 'src', 'ba_data', 'python').absolute()) 'templates').absolute()
sys.path.append(pythondir) pythondir = (Path(projroot) / 'assets' / 'src' / 'ba_data' /
outdirname = Path('build', 'docs_html').absolute() 'python').absolute()
outdirname = (Path(projroot) / 'build' / 'docs_html').absolute()
sys.path.append(str(pythondir))
try: try:
pdoc.render.configure(docformat='google', pdoc.render.configure(search=True,
search=True, show_source=True,
show_source=True) template_directory=templatesdir)
pdoc.pdoc('ba', 'bastd', output_directory=outdirname) pdoc.pdoc('ba', 'bastd', output_directory=outdirname)
except Exception as exc: except Exception as exc:
import traceback import traceback

View File

@ -252,7 +252,8 @@ def _writefuncs(parent: Any, funcnames: Sequence[str], indent: int,
f'unknown returns value: {returns} for {funcname}') f'unknown returns value: {returns} for {funcname}')
returnspc = indstr + ' ' returnspc = indstr + ' '
returnstr = ('\n' + returnspc).join(returnstr.strip().splitlines()) returnstr = ('\n' + returnspc).join(returnstr.strip().splitlines())
docstr_out = _formatdoc(docstr, indent + 4, funcname=funcname) docstr_out = _formatdoc(_filterdoc(docstr, funcname=funcname),
indent + 4)
out += spcstr + defsline + docstr_out + f'{returnspc}{returnstr}\n' out += spcstr + defsline + docstr_out + f'{returnspc}{returnstr}\n'
return out return out
@ -470,11 +471,7 @@ def _special_class_cases(classname: str) -> str:
return out return out
def _formatdoc(docstr: str, def _filterdoc(docstr: str, funcname: Optional[str] = None) -> str:
indent: int,
funcname: Optional[str] = None) -> str:
out = ''
indentstr = indent * ' '
docslines = docstr.splitlines() docslines = docstr.splitlines()
if (funcname and docslines and docslines[0] if (funcname and docslines and docslines[0]
@ -484,14 +481,48 @@ def _formatdoc(docstr: str,
_, docstr = docstr.split('\n\n', maxsplit=1) _, docstr = docstr.split('\n\n', maxsplit=1)
docslines = docstr.splitlines() docslines = docstr.splitlines()
# Assuming that each line between 'Attributes:' and '\n\n' belongs to
# attrs descriptions.
empty_lines_count = 0
attributes_line: Optional[int] = None
attrs_definitions_last_line: Optional[int] = None
for i, line in enumerate(docslines):
if line.strip() in ['Attrs:', 'Attributes:']:
if attributes_line is not None:
raise Exception("Multiple 'Attributes:' lines found")
attributes_line = i
if not line.strip():
empty_lines_count += 1
else:
empty_lines_count = 0
if empty_lines_count >= 2 and attributes_line is not None:
# It seems attribute definitions ended.
attrs_definitions_last_line = i
break
if attrs_definitions_last_line is None:
attrs_definitions_last_line = len(docslines) - 1
return '\n'.join(docslines[:attributes_line] +
docslines[attrs_definitions_last_line + 1:])
def _formatdoc(docstr: str,
indent: int,
no_end_newline: bool = False,
inner_indent: int = 0) -> str:
out = ''
indentstr = indent * ' '
inner_indent_str = inner_indent * ' '
docslines = docstr.splitlines()
if len(docslines) == 1: if len(docslines) == 1:
out += '\n' + indentstr + '"""' + docslines[0] + '"""\n' out += '\n' + indentstr + '"""' + docslines[0] + '"""\n'
else: else:
for i, line in enumerate(docslines): for i, line in enumerate(docslines):
if i != 0 and line != '': if i != 0 and line != '':
docslines[i] = indentstr + line docslines[i] = indentstr + inner_indent_str + line
out += ('\n' + indentstr + '"""' + '\n'.join(docslines) + '\n' + out += ('\n' + indentstr + '"""' + '\n'.join(docslines) +
indentstr + '"""\n') ('' if no_end_newline else '\n' + indentstr) + '"""\n')
return out return out
@ -514,7 +545,7 @@ def _writeclasses(module: ModuleType, classnames: Sequence[str]) -> str:
docstr = cls.__doc__ docstr = cls.__doc__
# classname is constructor name # classname is constructor name
out += _formatdoc(docstr, 4, funcname=classname) out += _formatdoc(_filterdoc(docstr, funcname=classname), 4)
# Create a public constructor if it has one. # Create a public constructor if it has one.
# If the first docs line appears to be a function signature # If the first docs line appears to be a function signature
@ -548,6 +579,12 @@ def _writeclasses(module: ModuleType, classnames: Sequence[str]) -> str:
for attr in attrs: for attr in attrs:
if attr.attr_type is not None: if attr.attr_type is not None:
out += f' {attr.name}: {attr.attr_type}\n' out += f' {attr.name}: {attr.attr_type}\n'
if attr.docs:
out += _formatdoc(_filterdoc(attr.docs),
indent=4,
inner_indent=3,
no_end_newline=True)
out += '\n'
else: else:
raise Exception(f'Found untyped attr in' raise Exception(f'Found untyped attr in'
f' {classname} docs: {attr.name}') f' {classname} docs: {attr.name}')