mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-02-08 00:30:22 +08:00
Restored NodeActor, tidying, minor gameplay fixes.
This commit is contained in:
parent
3e7ed8c0e3
commit
bc600f602e
2
.idea/dictionaries/ericf.xml
generated
2
.idea/dictionaries/ericf.xml
generated
@ -479,6 +479,7 @@
|
|||||||
<w>dxml</w>
|
<w>dxml</w>
|
||||||
<w>dynload</w>
|
<w>dynload</w>
|
||||||
<w>eachother</w>
|
<w>eachother</w>
|
||||||
|
<w>eaddrnotavail</w>
|
||||||
<w>easteregghunt</w>
|
<w>easteregghunt</w>
|
||||||
<w>edcc</w>
|
<w>edcc</w>
|
||||||
<w>editcontroller</w>
|
<w>editcontroller</w>
|
||||||
@ -1132,6 +1133,7 @@
|
|||||||
<w>nline</w>
|
<w>nline</w>
|
||||||
<w>nlines</w>
|
<w>nlines</w>
|
||||||
<w>nntplib</w>
|
<w>nntplib</w>
|
||||||
|
<w>nodeactor</w>
|
||||||
<w>nodepos</w>
|
<w>nodepos</w>
|
||||||
<w>nodpi</w>
|
<w>nodpi</w>
|
||||||
<w>nofiles</w>
|
<w>nofiles</w>
|
||||||
|
|||||||
@ -35,6 +35,7 @@
|
|||||||
"ba_data/python/ba/__pycache__/_modutils.cpython-37.opt-1.pyc",
|
"ba_data/python/ba/__pycache__/_modutils.cpython-37.opt-1.pyc",
|
||||||
"ba_data/python/ba/__pycache__/_music.cpython-37.opt-1.pyc",
|
"ba_data/python/ba/__pycache__/_music.cpython-37.opt-1.pyc",
|
||||||
"ba_data/python/ba/__pycache__/_netutils.cpython-37.opt-1.pyc",
|
"ba_data/python/ba/__pycache__/_netutils.cpython-37.opt-1.pyc",
|
||||||
|
"ba_data/python/ba/__pycache__/_nodeactor.cpython-37.opt-1.pyc",
|
||||||
"ba_data/python/ba/__pycache__/_playlist.cpython-37.opt-1.pyc",
|
"ba_data/python/ba/__pycache__/_playlist.cpython-37.opt-1.pyc",
|
||||||
"ba_data/python/ba/__pycache__/_powerup.cpython-37.opt-1.pyc",
|
"ba_data/python/ba/__pycache__/_powerup.cpython-37.opt-1.pyc",
|
||||||
"ba_data/python/ba/__pycache__/_profile.cpython-37.opt-1.pyc",
|
"ba_data/python/ba/__pycache__/_profile.cpython-37.opt-1.pyc",
|
||||||
@ -84,6 +85,7 @@
|
|||||||
"ba_data/python/ba/_modutils.py",
|
"ba_data/python/ba/_modutils.py",
|
||||||
"ba_data/python/ba/_music.py",
|
"ba_data/python/ba/_music.py",
|
||||||
"ba_data/python/ba/_netutils.py",
|
"ba_data/python/ba/_netutils.py",
|
||||||
|
"ba_data/python/ba/_nodeactor.py",
|
||||||
"ba_data/python/ba/_playlist.py",
|
"ba_data/python/ba/_playlist.py",
|
||||||
"ba_data/python/ba/_powerup.py",
|
"ba_data/python/ba/_powerup.py",
|
||||||
"ba_data/python/ba/_profile.py",
|
"ba_data/python/ba/_profile.py",
|
||||||
|
|||||||
@ -207,6 +207,7 @@ SCRIPT_TARGETS_PY_1 = \
|
|||||||
build/ba_data/python/ba/_account.py \
|
build/ba_data/python/ba/_account.py \
|
||||||
build/ba_data/python/ba/_music.py \
|
build/ba_data/python/ba/_music.py \
|
||||||
build/ba_data/python/ba/_lang.py \
|
build/ba_data/python/ba/_lang.py \
|
||||||
|
build/ba_data/python/ba/_nodeactor.py \
|
||||||
build/ba_data/python/ba/_teamgame.py \
|
build/ba_data/python/ba/_teamgame.py \
|
||||||
build/ba_data/python/ba/ui/__init__.py \
|
build/ba_data/python/ba/ui/__init__.py \
|
||||||
build/ba_data/python/bastd/mainmenu.py \
|
build/ba_data/python/bastd/mainmenu.py \
|
||||||
@ -444,6 +445,7 @@ SCRIPT_TARGETS_PYC_1 = \
|
|||||||
build/ba_data/python/ba/__pycache__/_account.cpython-37.opt-1.pyc \
|
build/ba_data/python/ba/__pycache__/_account.cpython-37.opt-1.pyc \
|
||||||
build/ba_data/python/ba/__pycache__/_music.cpython-37.opt-1.pyc \
|
build/ba_data/python/ba/__pycache__/_music.cpython-37.opt-1.pyc \
|
||||||
build/ba_data/python/ba/__pycache__/_lang.cpython-37.opt-1.pyc \
|
build/ba_data/python/ba/__pycache__/_lang.cpython-37.opt-1.pyc \
|
||||||
|
build/ba_data/python/ba/__pycache__/_nodeactor.cpython-37.opt-1.pyc \
|
||||||
build/ba_data/python/ba/__pycache__/_teamgame.cpython-37.opt-1.pyc \
|
build/ba_data/python/ba/__pycache__/_teamgame.cpython-37.opt-1.pyc \
|
||||||
build/ba_data/python/ba/ui/__pycache__/__init__.cpython-37.opt-1.pyc \
|
build/ba_data/python/ba/ui/__pycache__/__init__.cpython-37.opt-1.pyc \
|
||||||
build/ba_data/python/bastd/__pycache__/mainmenu.cpython-37.opt-1.pyc \
|
build/ba_data/python/bastd/__pycache__/mainmenu.cpython-37.opt-1.pyc \
|
||||||
@ -953,6 +955,11 @@ build/ba_data/python/ba/__pycache__/_lang.cpython-37.opt-1.pyc: \
|
|||||||
@echo Compiling script: $^
|
@echo Compiling script: $^
|
||||||
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||||
|
|
||||||
|
build/ba_data/python/ba/__pycache__/_nodeactor.cpython-37.opt-1.pyc: \
|
||||||
|
build/ba_data/python/ba/_nodeactor.py
|
||||||
|
@echo Compiling script: $^
|
||||||
|
@rm -rf $@ && $(TOOLS_DIR)/snippets compile_python_files $^ && chmod 444 $@
|
||||||
|
|
||||||
build/ba_data/python/ba/__pycache__/_teamgame.cpython-37.opt-1.pyc: \
|
build/ba_data/python/ba/__pycache__/_teamgame.cpython-37.opt-1.pyc: \
|
||||||
build/ba_data/python/ba/_teamgame.py
|
build/ba_data/python/ba/_teamgame.py
|
||||||
@echo Compiling script: $^
|
@echo Compiling script: $^
|
||||||
|
|||||||
@ -34,7 +34,7 @@ NOTE: This file was autogenerated by gendummymodule; do not edit by hand.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# (hash we can use to see if this file is out of date)
|
# (hash we can use to see if this file is out of date)
|
||||||
# SOURCES_HASH=279775284016994471710131432123768789736
|
# SOURCES_HASH=92329394206923431348342003830010439152
|
||||||
|
|
||||||
# I'm sorry Pylint. I know this file saddens you. Be strong.
|
# I'm sorry Pylint. I know this file saddens you. Be strong.
|
||||||
# pylint: disable=useless-suppression
|
# pylint: disable=useless-suppression
|
||||||
@ -161,8 +161,8 @@ class Context:
|
|||||||
sets the context as current on entry and resets it to the previous
|
sets the context as current on entry and resets it to the previous
|
||||||
value on exit.
|
value on exit.
|
||||||
|
|
||||||
# example: load a few textures into the UI context
|
# Example: load a few textures into the UI context
|
||||||
# (for use in widgets, etc)
|
# (for use in widgets, etc):
|
||||||
with ba.Context('ui'):
|
with ba.Context('ui'):
|
||||||
tex1 = ba.gettexture('foo_tex_1')
|
tex1 = ba.gettexture('foo_tex_1')
|
||||||
tex2 = ba.gettexture('foo_tex_2')
|
tex2 = ba.gettexture('foo_tex_2')
|
||||||
@ -667,7 +667,7 @@ class Node:
|
|||||||
target attribute to any value or connecting another node attribute
|
target attribute to any value or connecting another node attribute
|
||||||
to it.
|
to it.
|
||||||
|
|
||||||
# example: create a locator and attach a light to it
|
# Example: create a locator and attach a light to it:
|
||||||
light = ba.newnode('light')
|
light = ba.newnode('light')
|
||||||
loc = ba.newnode('locator', attrs={'position': (0,10,0)})
|
loc = ba.newnode('locator', attrs={'position': (0,10,0)})
|
||||||
loc.connectattr('position', light, 'position')
|
loc.connectattr('position', light, 'position')
|
||||||
@ -1044,7 +1044,7 @@ class Timer:
|
|||||||
the 'timeformat' arg defaults to SECONDS but can also be MILLISECONDS
|
the 'timeformat' arg defaults to SECONDS but can also be MILLISECONDS
|
||||||
if you want to pass time as milliseconds.
|
if you want to pass time as milliseconds.
|
||||||
|
|
||||||
# example: use a Timer object to print repeatedly for a few seconds:
|
# Example: use a Timer object to print repeatedly for a few seconds:
|
||||||
def say_it():
|
def say_it():
|
||||||
ba.screenmessage('BADGER!')
|
ba.screenmessage('BADGER!')
|
||||||
def stop_saying_it():
|
def stop_saying_it():
|
||||||
@ -1745,6 +1745,11 @@ def do_once() -> bool:
|
|||||||
logs. The call functions by registering the filename and line where
|
logs. The call functions by registering the filename and line where
|
||||||
The call is made from. Returns True if this location has not been
|
The call is made from. Returns True if this location has not been
|
||||||
registered already, and False if it has.
|
registered already, and False if it has.
|
||||||
|
|
||||||
|
# Example: this print will only fire for the first loop iteration:
|
||||||
|
for i in range(10):
|
||||||
|
if ba.do_once():
|
||||||
|
print('Hello once from loop!')
|
||||||
"""
|
"""
|
||||||
return bool()
|
return bool()
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,7 @@ from _ba import (CollideModel, Context, ContextCall, Data, InputDevice,
|
|||||||
charstr, textwidget, time, timer, open_url, widget)
|
charstr, textwidget, time, timer, open_url, widget)
|
||||||
from ba._activity import Activity
|
from ba._activity import Activity
|
||||||
from ba._actor import Actor
|
from ba._actor import Actor
|
||||||
|
from ba._nodeactor import NodeActor
|
||||||
from ba._app import App
|
from ba._app import App
|
||||||
from ba._coopgame import CoopGameActivity
|
from ba._coopgame import CoopGameActivity
|
||||||
from ba._coopsession import CoopSession
|
from ba._coopsession import CoopSession
|
||||||
|
|||||||
@ -558,12 +558,12 @@ class Activity(DependencyComponent):
|
|||||||
|
|
||||||
def create_player_node(self, player: ba.Player) -> ba.Node:
|
def create_player_node(self, player: ba.Player) -> ba.Node:
|
||||||
"""Create the 'player' node associated with the provided ba.Player."""
|
"""Create the 'player' node associated with the provided ba.Player."""
|
||||||
from ba import _actor
|
from ba._nodeactor import NodeActor
|
||||||
with _ba.Context(self):
|
with _ba.Context(self):
|
||||||
node = _ba.newnode('player', attrs={'playerID': player.get_id()})
|
node = _ba.newnode('player', attrs={'playerID': player.get_id()})
|
||||||
# FIXME: Should add a dedicated slot for this on ba.Player
|
# FIXME: Should add a dedicated slot for this on ba.Player
|
||||||
# instead of cluttering up their gamedata dict.
|
# instead of cluttering up their gamedata dict.
|
||||||
player.gamedata['_playernode'] = _actor.Actor(node)
|
player.gamedata['_playernode'] = NodeActor(node)
|
||||||
return node
|
return node
|
||||||
|
|
||||||
def begin(self, session: ba.Session) -> None:
|
def begin(self, session: ba.Session) -> None:
|
||||||
|
|||||||
@ -37,24 +37,25 @@ T = TypeVar('T', bound='Actor')
|
|||||||
class Actor:
|
class Actor:
|
||||||
"""High level logical entities in a game/activity.
|
"""High level logical entities in a game/activity.
|
||||||
|
|
||||||
category: Gameplay Classes
|
Category: Gameplay Classes
|
||||||
|
|
||||||
Actors act as controllers, combining some number of ba.Nodes,
|
Actors act as controllers, combining some number of ba.Nodes,
|
||||||
ba.Textures, ba.Sounds, etc. into one cohesive unit.
|
ba.Textures, ba.Sounds, etc. into a high-level cohesive unit.
|
||||||
|
|
||||||
Some example actors include ba.Bomb, ba.Flag, and ba.Spaz.
|
Some example actors include Bomb, Flag, and Spaz classes in bastd.
|
||||||
|
|
||||||
One key feature of Actors is that they generally 'die'
|
One key feature of Actors is that they generally 'die'
|
||||||
(killing off or transitioning out their nodes) when the last Python
|
(killing off or transitioning out their nodes) when the last Python
|
||||||
reference to them disappears, so you can use logic such as:
|
reference to them disappears, so you can use logic such as:
|
||||||
|
|
||||||
# create a flag Actor in our game activity
|
# Create a flag Actor in our game activity:
|
||||||
self.flag = ba.Flag(position=(0, 10, 0))
|
from bastd.actor.flag import Flag
|
||||||
|
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,
|
||||||
@ -69,30 +70,25 @@ class Actor:
|
|||||||
takes a single arbitrary object as an argument. This provides a safe way
|
takes a single arbitrary object as an argument. This provides a safe way
|
||||||
to communicate between ba.Actor, ba.Activity, ba.Session, and any other
|
to communicate between ba.Actor, ba.Activity, ba.Session, and any other
|
||||||
class providing a handlemessage() method. The most universally handled
|
class providing a handlemessage() method. The most universally handled
|
||||||
message type for actors is the ba.DieMessage.
|
message type for Actors is the ba.DieMessage.
|
||||||
|
|
||||||
# another way to kill the flag from the example above:
|
# Another way to kill the flag from the example above:
|
||||||
# we can safely call this on any type with a 'handlemessage' method
|
# We can safely call this on any type with a 'handlemessage' method
|
||||||
# (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.
|
||||||
self.flag.handlemessage(ba.DieMessage())
|
self.flag.handlemessage(ba.DieMessage())
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, node: ba.Node = None):
|
def __init__(self) -> None:
|
||||||
"""Instantiates an Actor in the current ba.Activity.
|
"""Instantiates an Actor in the current ba.Activity."""
|
||||||
|
|
||||||
If 'node' is provided, it is stored as the 'node' attribute
|
# FIXME: Actor should not be require to have a 'node' attr.
|
||||||
and the default ba.Actor.handlemessage() and ba.Actor.exists()
|
|
||||||
implementations will apply to it. This allows the creation of
|
|
||||||
simple node-wrapping Actors without having to create a new subclass.
|
|
||||||
"""
|
|
||||||
self.node: Optional[ba.Node] = None
|
self.node: Optional[ba.Node] = None
|
||||||
|
|
||||||
activity = _ba.getactivity()
|
activity = _ba.getactivity()
|
||||||
self._activity = weakref.ref(activity)
|
self._activity = weakref.ref(activity)
|
||||||
activity.add_actor_weak_ref(self)
|
activity.add_actor_weak_ref(self)
|
||||||
if node is not None:
|
|
||||||
self.node = node
|
|
||||||
|
|
||||||
def __del__(self) -> None:
|
def __del__(self) -> None:
|
||||||
try:
|
try:
|
||||||
@ -112,14 +108,9 @@ class Actor:
|
|||||||
The default implementation will handle ba.DieMessages by
|
The default implementation will handle ba.DieMessages by
|
||||||
calling self.node.delete() if self contains a 'node' attribute.
|
calling self.node.delete() if self contains a 'node' attribute.
|
||||||
"""
|
"""
|
||||||
from ba import _messages
|
from ba._error import UNHANDLED
|
||||||
from ba import _error
|
del msg # Unused.
|
||||||
if isinstance(msg, _messages.DieMessage):
|
return UNHANDLED
|
||||||
node = getattr(self, 'node', None)
|
|
||||||
if node is not None:
|
|
||||||
node.delete()
|
|
||||||
return None
|
|
||||||
return _error.UNHANDLED
|
|
||||||
|
|
||||||
def _handlemessage_sanity_check(self) -> None:
|
def _handlemessage_sanity_check(self) -> None:
|
||||||
if self.is_expired():
|
if self.is_expired():
|
||||||
@ -178,18 +169,13 @@ class Actor:
|
|||||||
deleted without affecting the game; this call is often used
|
deleted without affecting the game; this call is often used
|
||||||
when pruning lists of Actors, such as with ba.Actor.autoretain()
|
when pruning lists of Actors, such as with ba.Actor.autoretain()
|
||||||
|
|
||||||
The default implementation of this method returns 'node.exists()'
|
The default implementation of this method always return True.
|
||||||
if the Actor has a 'node' attr; otherwise True.
|
|
||||||
|
|
||||||
Note that the boolean operator for the Actor class calls this method,
|
Note that the boolean operator for the Actor class calls this method,
|
||||||
so a simple "if myactor" test will conveniently do the right thing
|
so a simple "if myactor" test will conveniently do the right thing
|
||||||
even if myactor is set to None.
|
even if myactor is set to None.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# As a default, if we have a 'node' attr, return whether it exists.
|
|
||||||
node: ba.Node = getattr(self, 'node', None)
|
|
||||||
if node is not None:
|
|
||||||
return node.exists()
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __bool__(self) -> bool:
|
def __bool__(self) -> bool:
|
||||||
|
|||||||
@ -638,7 +638,8 @@ class App:
|
|||||||
activity = _ba.get_foreground_host_activity()
|
activity = _ba.get_foreground_host_activity()
|
||||||
if (activity is not None and activity.allow_pausing
|
if (activity is not None and activity.allow_pausing
|
||||||
and not _ba.have_connected_clients()):
|
and not _ba.have_connected_clients()):
|
||||||
from ba import _gameutils, _actor, _lang
|
from ba import _gameutils, _lang
|
||||||
|
from ba._nodeactor import NodeActor
|
||||||
# FIXME: Shouldn't be touching scene stuff here;
|
# FIXME: Shouldn't be touching scene stuff here;
|
||||||
# should just pass the request on to the host-session.
|
# should just pass the request on to the host-session.
|
||||||
with _ba.Context(activity):
|
with _ba.Context(activity):
|
||||||
@ -648,7 +649,7 @@ class App:
|
|||||||
globs.paused = True
|
globs.paused = True
|
||||||
|
|
||||||
# FIXME: This should not be an attr on Actor.
|
# FIXME: This should not be an attr on Actor.
|
||||||
activity.paused_text = _actor.Actor(
|
activity.paused_text = NodeActor(
|
||||||
_ba.newnode(
|
_ba.newnode(
|
||||||
'text',
|
'text',
|
||||||
attrs={
|
attrs={
|
||||||
|
|||||||
@ -80,8 +80,8 @@ class CoopGameActivity(GameActivity):
|
|||||||
|
|
||||||
def _show_standard_scores_to_beat_ui(self,
|
def _show_standard_scores_to_beat_ui(self,
|
||||||
scores: List[Dict[str, Any]]) -> None:
|
scores: List[Dict[str, Any]]) -> None:
|
||||||
from ba import _gameutils
|
from ba._gameutils import timestring, animate
|
||||||
from ba import _actor
|
from ba._nodeactor import NodeActor
|
||||||
from ba._enums import TimeFormat
|
from ba._enums import TimeFormat
|
||||||
display_type = self.get_score_type()
|
display_type = self.get_score_type()
|
||||||
if scores is not None:
|
if scores is not None:
|
||||||
@ -92,16 +92,14 @@ class CoopGameActivity(GameActivity):
|
|||||||
# Now make a display for the most recent challenge.
|
# Now make a display for the most recent challenge.
|
||||||
for score in scores:
|
for score in scores:
|
||||||
if score['type'] == 'score_challenge':
|
if score['type'] == 'score_challenge':
|
||||||
tval = (
|
tval = (score['player'] + ': ' + timestring(
|
||||||
score['player'] + ': ' +
|
|
||||||
(_gameutils.timestring(
|
|
||||||
int(score['value']) * 10,
|
int(score['value']) * 10,
|
||||||
timeformat=TimeFormat.MILLISECONDS).evaluate()
|
timeformat=TimeFormat.MILLISECONDS).evaluate()
|
||||||
if display_type == 'time' else str(score['value'])))
|
if display_type == 'time' else str(score['value']))
|
||||||
hattach = 'center' if display_type == 'time' else 'left'
|
hattach = 'center' if display_type == 'time' else 'left'
|
||||||
halign = 'center' if display_type == 'time' else 'left'
|
halign = 'center' if display_type == 'time' else 'left'
|
||||||
pos = (20, -70) if display_type == 'time' else (20, -130)
|
pos = (20, -70) if display_type == 'time' else (20, -130)
|
||||||
txt = _actor.Actor(
|
txt = NodeActor(
|
||||||
_ba.newnode('text',
|
_ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
@ -115,11 +113,7 @@ class CoopGameActivity(GameActivity):
|
|||||||
'text': tval
|
'text': tval
|
||||||
})).autoretain()
|
})).autoretain()
|
||||||
assert txt.node is not None
|
assert txt.node is not None
|
||||||
_gameutils.animate(txt.node, 'scale', {
|
animate(txt.node, 'scale', {1.0: 0.0, 1.1: 0.7, 1.2: 0.6})
|
||||||
1.0: 0.0,
|
|
||||||
1.1: 0.7,
|
|
||||||
1.2: 0.6
|
|
||||||
})
|
|
||||||
break
|
break
|
||||||
|
|
||||||
# FIXME: this is now redundant with activityutils.get_score_info();
|
# FIXME: this is now redundant with activityutils.get_score_info();
|
||||||
@ -279,8 +273,8 @@ class CoopGameActivity(GameActivity):
|
|||||||
should_beep = True
|
should_beep = True
|
||||||
break
|
break
|
||||||
if should_beep and self._life_warning_beep is None:
|
if should_beep and self._life_warning_beep is None:
|
||||||
from ba import _actor
|
from ba._nodeactor import NodeActor
|
||||||
self._life_warning_beep = _actor.Actor(
|
self._life_warning_beep = NodeActor(
|
||||||
_ba.newnode('sound',
|
_ba.newnode('sound',
|
||||||
attrs={
|
attrs={
|
||||||
'sound': self._warn_beeps_sound,
|
'sound': self._warn_beeps_sound,
|
||||||
|
|||||||
@ -703,7 +703,7 @@ class GameActivity(Activity):
|
|||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
from ba._freeforallsession import FreeForAllSession
|
from ba._freeforallsession import FreeForAllSession
|
||||||
from ba._gameutils import animate
|
from ba._gameutils import animate
|
||||||
from ba._actor import Actor
|
from ba._nodeactor import NodeActor
|
||||||
sb_name = self.get_instance_scoreboard_display_string()
|
sb_name = self.get_instance_scoreboard_display_string()
|
||||||
|
|
||||||
# the description can be either a string or a sequence with args
|
# the description can be either a string or a sequence with args
|
||||||
@ -731,7 +731,7 @@ class GameActivity(Activity):
|
|||||||
yval -= 16
|
yval -= 16
|
||||||
sbpos = ((15, yval) if isinstance(self.session, FreeForAllSession) else
|
sbpos = ((15, yval) if isinstance(self.session, FreeForAllSession) else
|
||||||
(15, yval))
|
(15, yval))
|
||||||
self._game_scoreboard_name_text = Actor(
|
self._game_scoreboard_name_text = NodeActor(
|
||||||
_ba.newnode("text",
|
_ba.newnode("text",
|
||||||
attrs={
|
attrs={
|
||||||
'text': sb_name,
|
'text': sb_name,
|
||||||
@ -756,7 +756,7 @@ class GameActivity(Activity):
|
|||||||
descpos = (((17, -44 +
|
descpos = (((17, -44 +
|
||||||
10) if isinstance(self.session, FreeForAllSession) else
|
10) if isinstance(self.session, FreeForAllSession) else
|
||||||
(17, -44 + 10)))
|
(17, -44 + 10)))
|
||||||
self._game_scoreboard_description_text = Actor(
|
self._game_scoreboard_description_text = NodeActor(
|
||||||
_ba.newnode(
|
_ba.newnode(
|
||||||
"text",
|
"text",
|
||||||
attrs={
|
attrs={
|
||||||
@ -1163,13 +1163,13 @@ class GameActivity(Activity):
|
|||||||
"""
|
"""
|
||||||
from ba._gameutils import sharedobj
|
from ba._gameutils import sharedobj
|
||||||
from ba._general import WeakCall
|
from ba._general import WeakCall
|
||||||
from ba._actor import Actor
|
from ba._nodeactor import NodeActor
|
||||||
if duration <= 0.0:
|
if duration <= 0.0:
|
||||||
return
|
return
|
||||||
self._standard_time_limit_time = int(duration)
|
self._standard_time_limit_time = int(duration)
|
||||||
self._standard_time_limit_timer = _ba.Timer(
|
self._standard_time_limit_timer = _ba.Timer(
|
||||||
1.0, WeakCall(self._standard_time_limit_tick), repeat=True)
|
1.0, WeakCall(self._standard_time_limit_tick), repeat=True)
|
||||||
self._standard_time_limit_text = Actor(
|
self._standard_time_limit_text = NodeActor(
|
||||||
_ba.newnode('text',
|
_ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
@ -1180,7 +1180,7 @@ class GameActivity(Activity):
|
|||||||
'flatness': 1.0,
|
'flatness': 1.0,
|
||||||
'scale': 0.9
|
'scale': 0.9
|
||||||
}))
|
}))
|
||||||
self._standard_time_limit_text_input = Actor(
|
self._standard_time_limit_text_input = NodeActor(
|
||||||
_ba.newnode('timedisplay',
|
_ba.newnode('timedisplay',
|
||||||
attrs={
|
attrs={
|
||||||
'time2': duration * 1000,
|
'time2': duration * 1000,
|
||||||
@ -1237,7 +1237,7 @@ class GameActivity(Activity):
|
|||||||
If the time-limit expires, end_game() will be called.
|
If the time-limit expires, end_game() will be called.
|
||||||
"""
|
"""
|
||||||
from ba._general import WeakCall
|
from ba._general import WeakCall
|
||||||
from ba._actor import Actor
|
from ba._nodeactor import NodeActor
|
||||||
from ba._enums import TimeType
|
from ba._enums import TimeType
|
||||||
if duration <= 0.0:
|
if duration <= 0.0:
|
||||||
return
|
return
|
||||||
@ -1251,7 +1251,7 @@ class GameActivity(Activity):
|
|||||||
WeakCall(self._tournament_time_limit_tick),
|
WeakCall(self._tournament_time_limit_tick),
|
||||||
repeat=True,
|
repeat=True,
|
||||||
timetype=TimeType.BASE)
|
timetype=TimeType.BASE)
|
||||||
self._tournament_time_limit_title_text = Actor(
|
self._tournament_time_limit_title_text = NodeActor(
|
||||||
_ba.newnode('text',
|
_ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'bottom',
|
'v_attach': 'bottom',
|
||||||
@ -1266,7 +1266,7 @@ class GameActivity(Activity):
|
|||||||
'scale': 0.5,
|
'scale': 0.5,
|
||||||
'text': Lstr(resource='tournamentText')
|
'text': Lstr(resource='tournamentText')
|
||||||
}))
|
}))
|
||||||
self._tournament_time_limit_text = Actor(
|
self._tournament_time_limit_text = NodeActor(
|
||||||
_ba.newnode('text',
|
_ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'bottom',
|
'v_attach': 'bottom',
|
||||||
@ -1280,7 +1280,7 @@ class GameActivity(Activity):
|
|||||||
'flatness': 1.0,
|
'flatness': 1.0,
|
||||||
'scale': 0.9
|
'scale': 0.9
|
||||||
}))
|
}))
|
||||||
self._tournament_time_limit_text_input = Actor(
|
self._tournament_time_limit_text_input = NodeActor(
|
||||||
_ba.newnode('timedisplay',
|
_ba.newnode('timedisplay',
|
||||||
attrs={
|
attrs={
|
||||||
'timemin': 0,
|
'timemin': 0,
|
||||||
|
|||||||
@ -441,7 +441,7 @@ def cameraflash(duration: float = 999.0) -> None:
|
|||||||
"""
|
"""
|
||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
import random
|
import random
|
||||||
from ba._actor import Actor
|
from ba._nodeactor import NodeActor
|
||||||
x_spread = 10
|
x_spread = 10
|
||||||
y_spread = 5
|
y_spread = 5
|
||||||
positions = [[-x_spread, -y_spread], [0, -y_spread], [0, y_spread],
|
positions = [[-x_spread, -y_spread], [0, -y_spread], [0, y_spread],
|
||||||
@ -455,7 +455,7 @@ def cameraflash(duration: float = 999.0) -> None:
|
|||||||
# noinspection PyTypeHints
|
# noinspection PyTypeHints
|
||||||
activity.camera_flash_data = [] # type: ignore
|
activity.camera_flash_data = [] # type: ignore
|
||||||
for i in range(6):
|
for i in range(6):
|
||||||
light = Actor(
|
light = NodeActor(
|
||||||
_ba.newnode("light",
|
_ba.newnode("light",
|
||||||
attrs={
|
attrs={
|
||||||
'position': (positions[i][0], 0, positions[i][1]),
|
'position': (positions[i][0], 0, positions[i][1]),
|
||||||
|
|||||||
@ -159,7 +159,7 @@ class _WeakCall:
|
|||||||
Instantiate a WeakCall; pass a callable as the first
|
Instantiate a WeakCall; pass a callable as the first
|
||||||
arg, followed by any number of arguments or keywords.
|
arg, followed by any number of arguments or keywords.
|
||||||
|
|
||||||
# example: wrap a method call with some positional and
|
# Example: wrap a method call with some positional and
|
||||||
# keyword args:
|
# keyword args:
|
||||||
myweakcall = ba.WeakCall(myobj.dostuff, argval1, namedarg=argval2)
|
myweakcall = ba.WeakCall(myobj.dostuff, argval1, namedarg=argval2)
|
||||||
|
|
||||||
@ -211,7 +211,7 @@ class _Call:
|
|||||||
Instantiate a Call; pass a callable as the first
|
Instantiate a Call; pass a callable as the first
|
||||||
arg, followed by any number of arguments or keywords.
|
arg, followed by any number of arguments or keywords.
|
||||||
|
|
||||||
# Example: wrap a method call with 1 positional and 1 keyword arg.
|
# Example: wrap a method call with 1 positional and 1 keyword arg:
|
||||||
mycall = ba.Call(myobj.dostuff, argval1, namedarg=argval2)
|
mycall = ba.Call(myobj.dostuff, argval1, namedarg=argval2)
|
||||||
|
|
||||||
# Now we have a single callable to run that whole mess.
|
# Now we have a single callable to run that whole mess.
|
||||||
|
|||||||
@ -42,8 +42,8 @@ class JoinInfo:
|
|||||||
# pylint: disable=too-many-locals
|
# pylint: disable=too-many-locals
|
||||||
from ba import _input
|
from ba import _input
|
||||||
from ba._lang import Lstr
|
from ba._lang import Lstr
|
||||||
from ba import _actor
|
from ba._nodeactor import NodeActor
|
||||||
from ba import _general
|
from ba._general import WeakCall
|
||||||
from ba._enums import SpecialChar
|
from ba._enums import SpecialChar
|
||||||
can_switch_teams = (len(lobby.teams) > 1)
|
can_switch_teams = (len(lobby.teams) > 1)
|
||||||
self._state = 0
|
self._state = 0
|
||||||
@ -79,7 +79,7 @@ class JoinInfo:
|
|||||||
join_str = Lstr(resource='pressAnyButtonToJoinText')
|
join_str = Lstr(resource='pressAnyButtonToJoinText')
|
||||||
|
|
||||||
flatness = 1.0 if _ba.app.vr_mode else 0.0
|
flatness = 1.0 if _ba.app.vr_mode else 0.0
|
||||||
self._text = _actor.Actor(
|
self._text = NodeActor(
|
||||||
_ba.newnode('text',
|
_ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'position': (0, -40),
|
'position': (0, -40),
|
||||||
@ -109,9 +109,7 @@ class JoinInfo:
|
|||||||
' ' + _ba.charstr(SpecialChar.RIGHT_ARROW))])
|
' ' + _ba.charstr(SpecialChar.RIGHT_ARROW))])
|
||||||
] if can_switch_teams else []) + [msg1] + [msg3] + [join_str])
|
] if can_switch_teams else []) + [msg1] + [msg3] + [join_str])
|
||||||
|
|
||||||
self._timer = _ba.Timer(4.0,
|
self._timer = _ba.Timer(4.0, WeakCall(self._update), repeat=True)
|
||||||
_general.WeakCall(self._update),
|
|
||||||
repeat=True)
|
|
||||||
|
|
||||||
def _update(self) -> None:
|
def _update(self) -> None:
|
||||||
assert self._text.node
|
assert self._text.node
|
||||||
@ -393,7 +391,7 @@ class Chooser:
|
|||||||
|
|
||||||
def reload_profiles(self) -> None:
|
def reload_profiles(self) -> None:
|
||||||
"""Reload all player profiles."""
|
"""Reload all player profiles."""
|
||||||
from ba import _general
|
from ba._general import json_prep
|
||||||
app = _ba.app
|
app = _ba.app
|
||||||
|
|
||||||
# Re-construct our profile index and other stuff since the profile
|
# Re-construct our profile index and other stuff since the profile
|
||||||
@ -422,7 +420,7 @@ class Chooser:
|
|||||||
# (non-unicode/non-json) version.
|
# (non-unicode/non-json) version.
|
||||||
# Make sure they conform to our standards
|
# Make sure they conform to our standards
|
||||||
# (unicode strings, no tuples, etc)
|
# (unicode strings, no tuples, etc)
|
||||||
self.profiles = _general.json_prep(self.profiles)
|
self.profiles = json_prep(self.profiles)
|
||||||
|
|
||||||
# Filter out any characters we're unaware of.
|
# Filter out any characters we're unaware of.
|
||||||
for profile in list(self.profiles.items()):
|
for profile in list(self.profiles.items()):
|
||||||
@ -551,7 +549,7 @@ class Chooser:
|
|||||||
def _set_ready(self, ready: bool) -> None:
|
def _set_ready(self, ready: bool) -> None:
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
from bastd.ui.profile import browser as pbrowser
|
from bastd.ui.profile import browser as pbrowser
|
||||||
from ba import _general
|
from ba._general import Call
|
||||||
profilename = self._profilenames[self._profileindex]
|
profilename = self._profilenames[self._profileindex]
|
||||||
|
|
||||||
# Handle '_edit' as a special case.
|
# Handle '_edit' as a special case.
|
||||||
@ -566,26 +564,23 @@ class Chooser:
|
|||||||
|
|
||||||
if not ready:
|
if not ready:
|
||||||
self._player.assign_input_call(
|
self._player.assign_input_call(
|
||||||
'leftPress',
|
'leftPress', Call(self.handlemessage,
|
||||||
_general.Call(self.handlemessage, ChangeMessage('team', -1)))
|
ChangeMessage('team', -1)))
|
||||||
self._player.assign_input_call(
|
self._player.assign_input_call(
|
||||||
'rightPress',
|
'rightPress', Call(self.handlemessage,
|
||||||
_general.Call(self.handlemessage, ChangeMessage('team', 1)))
|
ChangeMessage('team', 1)))
|
||||||
self._player.assign_input_call(
|
self._player.assign_input_call(
|
||||||
'bombPress',
|
'bombPress',
|
||||||
_general.Call(self.handlemessage,
|
Call(self.handlemessage, ChangeMessage('character', 1)))
|
||||||
ChangeMessage('character', 1)))
|
|
||||||
self._player.assign_input_call(
|
self._player.assign_input_call(
|
||||||
'upPress',
|
'upPress',
|
||||||
_general.Call(self.handlemessage,
|
Call(self.handlemessage, ChangeMessage('profileindex', -1)))
|
||||||
ChangeMessage('profileindex', -1)))
|
|
||||||
self._player.assign_input_call(
|
self._player.assign_input_call(
|
||||||
'downPress',
|
'downPress',
|
||||||
_general.Call(self.handlemessage,
|
Call(self.handlemessage, ChangeMessage('profileindex', 1)))
|
||||||
ChangeMessage('profileindex', 1)))
|
|
||||||
self._player.assign_input_call(
|
self._player.assign_input_call(
|
||||||
('jumpPress', 'pickUpPress', 'punchPress'),
|
('jumpPress', 'pickUpPress', 'punchPress'),
|
||||||
_general.Call(self.handlemessage, ChangeMessage('ready', 1)))
|
Call(self.handlemessage, ChangeMessage('ready', 1)))
|
||||||
self._ready = False
|
self._ready = False
|
||||||
self._update_text()
|
self._update_text()
|
||||||
self._player.set_name('untitled', real=False)
|
self._player.set_name('untitled', real=False)
|
||||||
@ -595,7 +590,7 @@ class Chooser:
|
|||||||
'jumpPress', 'bombPress', 'pickUpPress'), self._do_nothing)
|
'jumpPress', 'bombPress', 'pickUpPress'), self._do_nothing)
|
||||||
self._player.assign_input_call(
|
self._player.assign_input_call(
|
||||||
('jumpPress', 'bombPress', 'pickUpPress', 'punchPress'),
|
('jumpPress', 'bombPress', 'pickUpPress', 'punchPress'),
|
||||||
_general.Call(self.handlemessage, ChangeMessage('ready', 0)))
|
Call(self.handlemessage, ChangeMessage('ready', 0)))
|
||||||
|
|
||||||
# Store the last profile picked by this input for reuse.
|
# Store the last profile picked by this input for reuse.
|
||||||
input_device = self._player.get_input_device()
|
input_device = self._player.get_input_device()
|
||||||
|
|||||||
53
assets/src/ba_data/python/ba/_nodeactor.py
Normal file
53
assets/src/ba_data/python/ba/_nodeactor.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# Copyright (c) 2011-2020 Eric Froemling
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
# -----------------------------------------------------------------------------
|
||||||
|
"""Defines NodeActor class."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from ba._messages import DieMessage
|
||||||
|
from ba._actor import Actor
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
import ba
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class NodeActor(Actor):
|
||||||
|
"""A simple ba.Actor type that wraps a single ba.Node.
|
||||||
|
|
||||||
|
Category: Gameplay Classes
|
||||||
|
|
||||||
|
This Actor will delete its Node when told to die, and it's
|
||||||
|
exists() call will return whether the Node still exists or not.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, node: ba.Node):
|
||||||
|
super().__init__()
|
||||||
|
self.node = node
|
||||||
|
|
||||||
|
def handlemessage(self, msg: Any) -> Any:
|
||||||
|
if isinstance(msg, DieMessage):
|
||||||
|
if self.node:
|
||||||
|
self.node.delete()
|
||||||
|
return None
|
||||||
|
return super().handlemessage(msg)
|
||||||
@ -65,7 +65,7 @@ class TeamBaseSession(Session):
|
|||||||
team_names = None
|
team_names = None
|
||||||
team_colors = None
|
team_colors = None
|
||||||
|
|
||||||
print('FIXME: TEAM BASE SESSION WOULD CALC DEPS.')
|
# print('FIXME: TEAM BASE SESSION WOULD CALC DEPS.')
|
||||||
depsets: Sequence[ba.DependencySet] = []
|
depsets: Sequence[ba.DependencySet] = []
|
||||||
super().__init__(depsets,
|
super().__init__(depsets,
|
||||||
team_names=team_names,
|
team_names=team_names,
|
||||||
|
|||||||
@ -867,7 +867,7 @@ class CoopScoreScreen(ba.Activity):
|
|||||||
ba.timer(5.0, ba.WeakCall(self._show_tips))
|
ba.timer(5.0, ba.WeakCall(self._show_tips))
|
||||||
|
|
||||||
def _play_drumroll(self) -> None:
|
def _play_drumroll(self) -> None:
|
||||||
ba.Actor(
|
ba.NodeActor(
|
||||||
ba.newnode('sound',
|
ba.newnode('sound',
|
||||||
attrs={
|
attrs={
|
||||||
'sound': self.drum_roll_sound,
|
'sound': self.drum_roll_sound,
|
||||||
@ -1314,7 +1314,7 @@ class CoopScoreScreen(ba.Activity):
|
|||||||
star_tex = ba.gettexture('star')
|
star_tex = ba.gettexture('star')
|
||||||
star_x = 135 + offs_x
|
star_x = 135 + offs_x
|
||||||
for _i in range(stars):
|
for _i in range(stars):
|
||||||
img = ba.Actor(
|
img = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'texture': star_tex,
|
'texture': star_tex,
|
||||||
@ -1329,7 +1329,7 @@ class CoopScoreScreen(ba.Activity):
|
|||||||
ba.animate(img.node, 'opacity', {0.15: 0, 0.4: 1})
|
ba.animate(img.node, 'opacity', {0.15: 0, 0.4: 1})
|
||||||
star_x += 60
|
star_x += 60
|
||||||
for _i in range(3 - stars):
|
for _i in range(3 - stars):
|
||||||
img = ba.Actor(
|
img = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'texture': star_tex,
|
'texture': star_tex,
|
||||||
@ -1355,7 +1355,7 @@ class CoopScoreScreen(ba.Activity):
|
|||||||
transition_delay=1.0).autoretain()
|
transition_delay=1.0).autoretain()
|
||||||
stx = xval + 20
|
stx = xval + 20
|
||||||
for _i2 in range(count):
|
for _i2 in range(count):
|
||||||
img2 = ba.Actor(
|
img2 = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'texture': star_tex,
|
'texture': star_tex,
|
||||||
|
|||||||
@ -89,7 +89,7 @@ class RespawnIcon:
|
|||||||
texture = icon['texture']
|
texture = icon['texture']
|
||||||
h_offs = -10
|
h_offs = -10
|
||||||
ipos = (-40 - h_offs if on_right else 40 + h_offs, -180 + offs)
|
ipos = (-40 - h_offs if on_right else 40 + h_offs, -180 + offs)
|
||||||
self._image: Optional[ba.Actor] = ba.Actor(
|
self._image: Optional[ba.NodeActor] = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'texture': texture,
|
'texture': texture,
|
||||||
@ -108,7 +108,7 @@ class RespawnIcon:
|
|||||||
ba.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7})
|
ba.animate(self._image.node, 'opacity', {0.0: 0, 0.2: 0.7})
|
||||||
|
|
||||||
npos = (-40 - h_offs if on_right else 40 + h_offs, -205 + 49 + offs)
|
npos = (-40 - h_offs if on_right else 40 + h_offs, -205 + 49 + offs)
|
||||||
self._name: Optional[ba.Actor] = ba.Actor(
|
self._name: Optional[ba.NodeActor] = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
@ -128,7 +128,7 @@ class RespawnIcon:
|
|||||||
ba.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5})
|
ba.animate(self._name.node, 'scale', {0: 0, 0.1: 0.5})
|
||||||
|
|
||||||
tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs)
|
tpos = (-60 - h_offs if on_right else 60 + h_offs, -192 + offs)
|
||||||
self._text: Optional[ba.Actor] = ba.Actor(
|
self._text: Optional[ba.NodeActor] = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'position': tpos,
|
'position': tpos,
|
||||||
|
|||||||
@ -72,7 +72,7 @@ class _Entry:
|
|||||||
self._backing_color = [0.05 + c * 0.1 for c in safe_team_color]
|
self._backing_color = [0.05 + c * 0.1 for c in safe_team_color]
|
||||||
|
|
||||||
opacity = (0.8 if vrmode else 0.8) if self._do_cover else 0.5
|
opacity = (0.8 if vrmode else 0.8) if self._do_cover else 0.5
|
||||||
self._backing = ba.Actor(
|
self._backing = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'scale': (self._width, self._height),
|
'scale': (self._width, self._height),
|
||||||
@ -84,7 +84,7 @@ class _Entry:
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
self._barcolor = safe_team_color
|
self._barcolor = safe_team_color
|
||||||
self._bar = ba.Actor(
|
self._bar = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'opacity': 0.7,
|
'opacity': 0.7,
|
||||||
@ -112,7 +112,7 @@ class _Entry:
|
|||||||
self._bar_position.connectattr('output', self._bar.node, 'position')
|
self._bar_position.connectattr('output', self._bar.node, 'position')
|
||||||
self._cover_color = safe_team_color
|
self._cover_color = safe_team_color
|
||||||
if self._do_cover:
|
if self._do_cover:
|
||||||
self._cover = ba.Actor(
|
self._cover = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'scale':
|
'scale':
|
||||||
@ -128,7 +128,7 @@ class _Entry:
|
|||||||
clr = safe_team_color
|
clr = safe_team_color
|
||||||
maxwidth = 130.0 * (1.0 - scoreboard.score_split)
|
maxwidth = 130.0 * (1.0 - scoreboard.score_split)
|
||||||
flatness = ((1.0 if vrmode else 0.5) if self._do_cover else 1.0)
|
flatness = ((1.0 if vrmode else 0.5) if self._do_cover else 1.0)
|
||||||
self._score_text = ba.Actor(
|
self._score_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'h_attach': 'left',
|
'h_attach': 'left',
|
||||||
@ -169,7 +169,7 @@ class _Entry:
|
|||||||
team_name_label = ba.Lstr(value=team_name_label)
|
team_name_label = ba.Lstr(value=team_name_label)
|
||||||
|
|
||||||
flatness = ((1.0 if vrmode else 0.5) if self._do_cover else 1.0)
|
flatness = ((1.0 if vrmode else 0.5) if self._do_cover else 1.0)
|
||||||
self._name_text = ba.Actor(
|
self._name_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'h_attach': 'left',
|
'h_attach': 'left',
|
||||||
|
|||||||
@ -58,10 +58,10 @@ class BombDiedMessage:
|
|||||||
def get_factory() -> SpazFactory:
|
def get_factory() -> SpazFactory:
|
||||||
"""Return the shared ba.SpazFactory object, creating it if necessary."""
|
"""Return the shared ba.SpazFactory object, creating it if necessary."""
|
||||||
# pylint: disable=cyclic-import
|
# pylint: disable=cyclic-import
|
||||||
|
from bastd.actor.spazfactory import SpazFactory
|
||||||
activity = ba.getactivity()
|
activity = ba.getactivity()
|
||||||
factory = getattr(activity, 'shared_spaz_factory', None)
|
factory = getattr(activity, 'shared_spaz_factory', None)
|
||||||
if factory is None:
|
if factory is None:
|
||||||
from bastd.actor.spazfactory import SpazFactory
|
|
||||||
# noinspection PyTypeHints
|
# noinspection PyTypeHints
|
||||||
factory = activity.shared_spaz_factory = SpazFactory() # type: ignore
|
factory = activity.shared_spaz_factory = SpazFactory() # type: ignore
|
||||||
assert isinstance(factory, SpazFactory)
|
assert isinstance(factory, SpazFactory)
|
||||||
@ -693,9 +693,9 @@ class Spaz(ba.Actor):
|
|||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches
|
||||||
if __debug__ is True:
|
if __debug__ is True:
|
||||||
self._handlemessage_sanity_check()
|
self._handlemessage_sanity_check()
|
||||||
assert self.node
|
|
||||||
|
|
||||||
if isinstance(msg, ba.PickedUpMessage):
|
if isinstance(msg, ba.PickedUpMessage):
|
||||||
|
if self.node:
|
||||||
self.node.handlemessage("hurt_sound")
|
self.node.handlemessage("hurt_sound")
|
||||||
self.node.handlemessage("picked_up")
|
self.node.handlemessage("picked_up")
|
||||||
# this counts as a hit
|
# this counts as a hit
|
||||||
@ -713,7 +713,7 @@ class Spaz(ba.Actor):
|
|||||||
ba.timer(0.001, ba.WeakCall(self._hit_self, msg.intensity))
|
ba.timer(0.001, ba.WeakCall(self._hit_self, msg.intensity))
|
||||||
|
|
||||||
elif isinstance(msg, ba.PowerupMessage):
|
elif isinstance(msg, ba.PowerupMessage):
|
||||||
if self._dead:
|
if self._dead or not self.node:
|
||||||
return True
|
return True
|
||||||
if self.pick_up_powerup_callback is not None:
|
if self.pick_up_powerup_callback is not None:
|
||||||
self.pick_up_powerup_callback(self)
|
self.pick_up_powerup_callback(self)
|
||||||
@ -1069,14 +1069,15 @@ class Spaz(ba.Actor):
|
|||||||
newdamage = max(damage - 200, self.hitpoints - 10)
|
newdamage = max(damage - 200, self.hitpoints - 10)
|
||||||
damage = newdamage
|
damage = newdamage
|
||||||
self.node.handlemessage("flash")
|
self.node.handlemessage("flash")
|
||||||
# if we're holding something, drop it
|
|
||||||
|
# If we're holding something, drop it.
|
||||||
if damage > 0.0 and self.node.hold_node:
|
if damage > 0.0 and self.node.hold_node:
|
||||||
# self.node.hold_node = ba.Node(None)
|
# self.node.hold_node = ba.Node(None)
|
||||||
self.node.hold_node = None
|
self.node.hold_node = None
|
||||||
self.hitpoints -= damage
|
self.hitpoints -= damage
|
||||||
self.node.hurt = 1.0 - float(
|
self.node.hurt = 1.0 - float(
|
||||||
self.hitpoints) / self.hitpoints_max
|
self.hitpoints) / self.hitpoints_max
|
||||||
# if we're cursed, *any* damage blows us up
|
# If we're cursed, *any* damage blows us up.
|
||||||
if self._cursed and damage > 0:
|
if self._cursed and damage > 0:
|
||||||
ba.timer(
|
ba.timer(
|
||||||
0.05, ba.WeakCall(self.curse_explode,
|
0.05, ba.WeakCall(self.curse_explode,
|
||||||
@ -1103,6 +1104,7 @@ class Spaz(ba.Actor):
|
|||||||
self._dead = True
|
self._dead = True
|
||||||
self.hitpoints = 0
|
self.hitpoints = 0
|
||||||
if msg.immediate:
|
if msg.immediate:
|
||||||
|
if self.node:
|
||||||
self.node.delete()
|
self.node.delete()
|
||||||
elif self.node:
|
elif self.node:
|
||||||
self.node.hurt = 1.0
|
self.node.hurt = 1.0
|
||||||
@ -1117,11 +1119,15 @@ class Spaz(ba.Actor):
|
|||||||
elif isinstance(msg, ba.StandMessage):
|
elif isinstance(msg, ba.StandMessage):
|
||||||
self._last_stand_pos = (msg.position[0], msg.position[1],
|
self._last_stand_pos = (msg.position[0], msg.position[1],
|
||||||
msg.position[2])
|
msg.position[2])
|
||||||
self.node.handlemessage("stand", msg.position[0], msg.position[1],
|
if self.node:
|
||||||
msg.position[2], msg.angle)
|
self.node.handlemessage("stand", msg.position[0],
|
||||||
|
msg.position[1], msg.position[2],
|
||||||
|
msg.angle)
|
||||||
elif isinstance(msg, CurseExplodeMessage):
|
elif isinstance(msg, CurseExplodeMessage):
|
||||||
self.curse_explode()
|
self.curse_explode()
|
||||||
elif isinstance(msg, PunchHitMessage):
|
elif isinstance(msg, PunchHitMessage):
|
||||||
|
if not self.node:
|
||||||
|
return None
|
||||||
node = ba.get_collision_info("opposing_node")
|
node = ba.get_collision_info("opposing_node")
|
||||||
|
|
||||||
# only allow one hit per node per punch
|
# only allow one hit per node per punch
|
||||||
@ -1178,6 +1184,9 @@ class Spaz(ba.Actor):
|
|||||||
ppos[2], punchdir[0], punchdir[1],
|
ppos[2], punchdir[0], punchdir[1],
|
||||||
punchdir[2], mag)
|
punchdir[2], mag)
|
||||||
elif isinstance(msg, PickupMessage):
|
elif isinstance(msg, PickupMessage):
|
||||||
|
if not self.node:
|
||||||
|
return None
|
||||||
|
|
||||||
opposing_node, opposing_body = ba.get_collision_info(
|
opposing_node, opposing_body = ba.get_collision_info(
|
||||||
'opposing_node', 'opposing_body')
|
'opposing_node', 'opposing_body')
|
||||||
|
|
||||||
|
|||||||
@ -354,7 +354,7 @@ class CaptureTheFlagGame(ba.TeamGameActivity):
|
|||||||
team.gamedata['touch_return_timer_ticking'] = None
|
team.gamedata['touch_return_timer_ticking'] = None
|
||||||
return # No need to return when its at home.
|
return # No need to return when its at home.
|
||||||
if team.gamedata['touch_return_timer_ticking'] is None:
|
if team.gamedata['touch_return_timer_ticking'] is None:
|
||||||
team.gamedata['touch_return_timer_ticking'] = ba.Actor(
|
team.gamedata['touch_return_timer_ticking'] = ba.NodeActor(
|
||||||
ba.newnode('sound',
|
ba.newnode('sound',
|
||||||
attrs={
|
attrs={
|
||||||
'sound': self._ticking_sound,
|
'sound': self._ticking_sound,
|
||||||
|
|||||||
@ -293,7 +293,7 @@ class ChosenOneGame(ba.TeamGameActivity):
|
|||||||
0.3 + c * 0.7
|
0.3 + c * 0.7
|
||||||
for c in ba.normalized_color(player.team.color)
|
for c in ba.normalized_color(player.team.color)
|
||||||
]
|
]
|
||||||
light = player.gamedata['chosen_light'] = ba.Actor(
|
light = player.gamedata['chosen_light'] = ba.NodeActor(
|
||||||
ba.newnode('light',
|
ba.newnode('light',
|
||||||
attrs={
|
attrs={
|
||||||
"intensity": 0.6,
|
"intensity": 0.6,
|
||||||
|
|||||||
@ -449,7 +449,7 @@ class EliminationGame(ba.TeamGameActivity):
|
|||||||
self.setup_standard_time_limit(self.settings['Time Limit'])
|
self.setup_standard_time_limit(self.settings['Time Limit'])
|
||||||
self.setup_standard_powerup_drops()
|
self.setup_standard_powerup_drops()
|
||||||
if self._solo_mode:
|
if self._solo_mode:
|
||||||
self._vs_text = ba.Actor(
|
self._vs_text = ba.NodeActor(
|
||||||
ba.newnode("text",
|
ba.newnode("text",
|
||||||
attrs={
|
attrs={
|
||||||
'position': (0, 105),
|
'position': (0, 105),
|
||||||
|
|||||||
@ -157,7 +157,7 @@ class FootballTeamGame(ba.TeamGameActivity):
|
|||||||
self._spawn_flag()
|
self._spawn_flag()
|
||||||
defs = self.map.defs
|
defs = self.map.defs
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.Actor(
|
ba.NodeActor(
|
||||||
ba.newnode('region',
|
ba.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes['goal1'][0:3],
|
'position': defs.boxes['goal1'][0:3],
|
||||||
@ -166,7 +166,7 @@ class FootballTeamGame(ba.TeamGameActivity):
|
|||||||
'materials': (self.score_region_material, )
|
'materials': (self.score_region_material, )
|
||||||
})))
|
})))
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.Actor(
|
ba.NodeActor(
|
||||||
ba.newnode('region',
|
ba.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes['goal2'][0:3],
|
'position': defs.boxes['goal2'][0:3],
|
||||||
@ -279,7 +279,7 @@ class FootballTeamGame(ba.TeamGameActivity):
|
|||||||
elif isinstance(msg, stdflag.FlagDeathMessage):
|
elif isinstance(msg, stdflag.FlagDeathMessage):
|
||||||
if not self.has_ended():
|
if not self.has_ended():
|
||||||
self._flag_respawn_timer = ba.Timer(3.0, self._spawn_flag)
|
self._flag_respawn_timer = ba.Timer(3.0, self._spawn_flag)
|
||||||
self._flag_respawn_light = ba.Actor(
|
self._flag_respawn_light = ba.NodeActor(
|
||||||
ba.newnode('light',
|
ba.newnode('light',
|
||||||
attrs={
|
attrs={
|
||||||
'position': self._flag_spawn_pos,
|
'position': self._flag_spawn_pos,
|
||||||
@ -406,7 +406,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
# Set up the two score regions.
|
# Set up the two score regions.
|
||||||
defs = self.map.defs
|
defs = self.map.defs
|
||||||
self.score_regions.append(
|
self.score_regions.append(
|
||||||
ba.Actor(
|
ba.NodeActor(
|
||||||
ba.newnode('region',
|
ba.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes['goal1'][0:3],
|
'position': defs.boxes['goal1'][0:3],
|
||||||
@ -415,7 +415,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
'materials': [self._score_region_material]
|
'materials': [self._score_region_material]
|
||||||
})))
|
})))
|
||||||
self.score_regions.append(
|
self.score_regions.append(
|
||||||
ba.Actor(
|
ba.NodeActor(
|
||||||
ba.newnode('region',
|
ba.newnode('region',
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes['goal2'][0:3],
|
'position': defs.boxes['goal2'][0:3],
|
||||||
@ -516,7 +516,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
starttime_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
|
starttime_ms = ba.time(timeformat=ba.TimeFormat.MILLISECONDS)
|
||||||
assert isinstance(starttime_ms, int)
|
assert isinstance(starttime_ms, int)
|
||||||
self._starttime_ms = starttime_ms
|
self._starttime_ms = starttime_ms
|
||||||
self._time_text = ba.Actor(
|
self._time_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
@ -529,7 +529,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
'scale': 1.3,
|
'scale': 1.3,
|
||||||
'text': ''
|
'text': ''
|
||||||
}))
|
}))
|
||||||
self._time_text_input = ba.Actor(
|
self._time_text_input = ba.NodeActor(
|
||||||
ba.newnode('timedisplay', attrs={'showsubseconds': True}))
|
ba.newnode('timedisplay', attrs={'showsubseconds': True}))
|
||||||
ba.sharedobj('globals').connectattr('time', self._time_text_input.node,
|
ba.sharedobj('globals').connectattr('time', self._time_text_input.node,
|
||||||
'time2')
|
'time2')
|
||||||
@ -844,7 +844,7 @@ class FootballCoopGame(ba.CoopGameActivity):
|
|||||||
elif isinstance(msg, stdflag.FlagDeathMessage):
|
elif isinstance(msg, stdflag.FlagDeathMessage):
|
||||||
assert isinstance(msg.flag, FootballFlag)
|
assert isinstance(msg.flag, FootballFlag)
|
||||||
msg.flag.respawn_timer = ba.Timer(3.0, self._spawn_flag)
|
msg.flag.respawn_timer = ba.Timer(3.0, self._spawn_flag)
|
||||||
self._flag_respawn_light = ba.Actor(
|
self._flag_respawn_light = ba.NodeActor(
|
||||||
ba.newnode('light',
|
ba.newnode('light',
|
||||||
attrs={
|
attrs={
|
||||||
'position': self._flag_spawn_pos,
|
'position': self._flag_spawn_pos,
|
||||||
|
|||||||
@ -222,7 +222,7 @@ class HockeyGame(ba.TeamGameActivity):
|
|||||||
defs = self.map.defs
|
defs = self.map.defs
|
||||||
self._score_regions = []
|
self._score_regions = []
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.Actor(
|
ba.NodeActor(
|
||||||
ba.newnode("region",
|
ba.newnode("region",
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes["goal1"][0:3],
|
'position': defs.boxes["goal1"][0:3],
|
||||||
@ -231,7 +231,7 @@ class HockeyGame(ba.TeamGameActivity):
|
|||||||
'materials': [self._score_region_material]
|
'materials': [self._score_region_material]
|
||||||
})))
|
})))
|
||||||
self._score_regions.append(
|
self._score_regions.append(
|
||||||
ba.Actor(
|
ba.NodeActor(
|
||||||
ba.newnode("region",
|
ba.newnode("region",
|
||||||
attrs={
|
attrs={
|
||||||
'position': defs.boxes["goal2"][0:3],
|
'position': defs.boxes["goal2"][0:3],
|
||||||
|
|||||||
@ -170,7 +170,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
'sound': ba.getsound('ding')
|
'sound': ba.getsound('ding')
|
||||||
}]
|
}]
|
||||||
|
|
||||||
self._spawn_info_text = ba.Actor(
|
self._spawn_info_text = ba.NodeActor(
|
||||||
ba.newnode("text",
|
ba.newnode("text",
|
||||||
attrs={
|
attrs={
|
||||||
'position': (15, -130),
|
'position': (15, -130),
|
||||||
@ -1049,7 +1049,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
('${A}', ba.Lstr(resource='timeBonusText')),
|
('${A}', ba.Lstr(resource='timeBonusText')),
|
||||||
('${B}', str(self._time_bonus)),
|
('${B}', str(self._time_bonus)),
|
||||||
])
|
])
|
||||||
self._time_bonus_text = ba.Actor(
|
self._time_bonus_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
@ -1075,7 +1075,7 @@ class OnslaughtGame(ba.CoopGameActivity):
|
|||||||
('' if self._preset in ['endless', 'endless_tournament'] else
|
('' if self._preset in ['endless', 'endless_tournament'] else
|
||||||
('/' + str(len(self._waves)))))
|
('/' + str(len(self._waves)))))
|
||||||
])
|
])
|
||||||
self._wave_text = ba.Actor(
|
self._wave_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
|
|||||||
@ -406,7 +406,7 @@ class RaceGame(ba.TeamGameActivity):
|
|||||||
self._team_finish_pts = 100
|
self._team_finish_pts = 100
|
||||||
|
|
||||||
# Throw a timer up on-screen.
|
# Throw a timer up on-screen.
|
||||||
self._time_text = ba.Actor(
|
self._time_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
|
|||||||
@ -134,7 +134,7 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
super().on_transition_in()
|
super().on_transition_in()
|
||||||
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
self._scoreboard = Scoreboard(label=ba.Lstr(resource='scoreText'),
|
||||||
score_split=0.5)
|
score_split=0.5)
|
||||||
self._score_region = ba.Actor(
|
self._score_region = ba.NodeActor(
|
||||||
ba.newnode(
|
ba.newnode(
|
||||||
'region',
|
'region',
|
||||||
attrs={
|
attrs={
|
||||||
@ -365,7 +365,7 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
l_offs = (-80 if interface_type == 'small' else
|
l_offs = (-80 if interface_type == 'small' else
|
||||||
-40 if interface_type == 'medium' else 0)
|
-40 if interface_type == 'medium' else 0)
|
||||||
|
|
||||||
self._lives_bg = ba.Actor(
|
self._lives_bg = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'texture': self._heart_tex,
|
'texture': self._heart_tex,
|
||||||
@ -379,7 +379,7 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
# FIXME; should not set things based on vr mode.
|
# FIXME; should not set things based on vr mode.
|
||||||
# (won't look right to non-vr connected clients, etc)
|
# (won't look right to non-vr connected clients, etc)
|
||||||
vrmode = ba.app.vr_mode
|
vrmode = ba.app.vr_mode
|
||||||
self._lives_text = ba.Actor(
|
self._lives_text = ba.NodeActor(
|
||||||
ba.newnode(
|
ba.newnode(
|
||||||
'text',
|
'text',
|
||||||
attrs={
|
attrs={
|
||||||
@ -943,7 +943,7 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
subs=[('${A}', ba.Lstr(resource='timeBonusText')),
|
subs=[('${A}', ba.Lstr(resource='timeBonusText')),
|
||||||
('${B}', str(int(self._time_bonus * self._time_bonus_mult)))
|
('${B}', str(int(self._time_bonus * self._time_bonus_mult)))
|
||||||
])
|
])
|
||||||
self._time_bonus_text = ba.Actor(
|
self._time_bonus_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
@ -973,7 +973,7 @@ class RunaroundGame(ba.CoopGameActivity):
|
|||||||
('' if self._preset in ['endless', 'endless_tournament'] else
|
('' if self._preset in ['endless', 'endless_tournament'] else
|
||||||
('/' + str(len(self._waves)))))
|
('/' + str(len(self._waves)))))
|
||||||
])
|
])
|
||||||
self._wave_text = ba.Actor(
|
self._wave_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
|
|||||||
@ -67,7 +67,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
# FIXME: Need a node attr for vr-specific-scale.
|
# FIXME: Need a node attr for vr-specific-scale.
|
||||||
scale = (0.9 if
|
scale = (0.9 if
|
||||||
(app.interface_type == 'small' or vr_mode) else 0.7)
|
(app.interface_type == 'small' or vr_mode) else 0.7)
|
||||||
self.my_name = ba.Actor(
|
self.my_name = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'bottom',
|
'v_attach': 'bottom',
|
||||||
@ -86,7 +86,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
# empty-ish screen.
|
# empty-ish screen.
|
||||||
tval = ba.Lstr(resource='hostIsNavigatingMenusText',
|
tval = ba.Lstr(resource='hostIsNavigatingMenusText',
|
||||||
subs=[('${HOST}', _ba.get_account_display_string())])
|
subs=[('${HOST}', _ba.get_account_display_string())])
|
||||||
self._host_is_navigating_text = ba.Actor(
|
self._host_is_navigating_text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'text': tval,
|
'text': tval,
|
||||||
@ -130,7 +130,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
text = ba.Lstr(value='${V}', subs=[('${V}', app.version)])
|
text = ba.Lstr(value='${V}', subs=[('${V}', app.version)])
|
||||||
scale = 0.9 if (interface_type == 'small' or vr_mode) else 0.7
|
scale = 0.9 if (interface_type == 'small' or vr_mode) else 0.7
|
||||||
color = (1, 1, 1, 1) if vr_mode else (0.5, 0.6, 0.5, 0.7)
|
color = (1, 1, 1, 1) if vr_mode else (0.5, 0.6, 0.5, 0.7)
|
||||||
self.version = ba.Actor(
|
self.version = ba.NodeActor(
|
||||||
ba.newnode(
|
ba.newnode(
|
||||||
'text',
|
'text',
|
||||||
attrs={
|
attrs={
|
||||||
@ -153,7 +153,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
self.beta_info = self.beta_info_2 = None
|
self.beta_info = self.beta_info_2 = None
|
||||||
if app.test_build and not app.kiosk_mode:
|
if app.test_build and not app.kiosk_mode:
|
||||||
pos = (230, 125) if app.kiosk_mode else (230, 35)
|
pos = (230, 125) if app.kiosk_mode else (230, 35)
|
||||||
self.beta_info = ba.Actor(
|
self.beta_info = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'center',
|
'v_attach': 'center',
|
||||||
@ -191,7 +191,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
gnode.vignette_outer = (0.45, 0.55, 0.54)
|
gnode.vignette_outer = (0.45, 0.55, 0.54)
|
||||||
gnode.vignette_inner = (0.99, 0.98, 0.98)
|
gnode.vignette_inner = (0.99, 0.98, 0.98)
|
||||||
|
|
||||||
self.bottom = ba.Actor(
|
self.bottom = ba.NodeActor(
|
||||||
ba.newnode('terrain',
|
ba.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': bottom_model,
|
'model': bottom_model,
|
||||||
@ -200,7 +200,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
'reflection_scale': [0.45],
|
'reflection_scale': [0.45],
|
||||||
'color_texture': color_texture
|
'color_texture': color_texture
|
||||||
}))
|
}))
|
||||||
self.vr_bottom_fill = ba.Actor(
|
self.vr_bottom_fill = ba.NodeActor(
|
||||||
ba.newnode('terrain',
|
ba.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': vr_bottom_fill_model,
|
'model': vr_bottom_fill_model,
|
||||||
@ -208,7 +208,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
'vr_only': True,
|
'vr_only': True,
|
||||||
'color_texture': color_texture
|
'color_texture': color_texture
|
||||||
}))
|
}))
|
||||||
self.vr_top_fill = ba.Actor(
|
self.vr_top_fill = ba.NodeActor(
|
||||||
ba.newnode('terrain',
|
ba.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': vr_top_fill_model,
|
'model': vr_top_fill_model,
|
||||||
@ -216,7 +216,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
'lighting': False,
|
'lighting': False,
|
||||||
'color_texture': bgtex
|
'color_texture': bgtex
|
||||||
}))
|
}))
|
||||||
self.terrain = ba.Actor(
|
self.terrain = ba.NodeActor(
|
||||||
ba.newnode('terrain',
|
ba.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': model,
|
'model': model,
|
||||||
@ -224,7 +224,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
'reflection': 'soft',
|
'reflection': 'soft',
|
||||||
'reflection_scale': [0.3]
|
'reflection_scale': [0.3]
|
||||||
}))
|
}))
|
||||||
self.trees = ba.Actor(
|
self.trees = ba.NodeActor(
|
||||||
ba.newnode('terrain',
|
ba.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': trees_model,
|
'model': trees_model,
|
||||||
@ -233,7 +233,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
'reflection_scale': [0.1],
|
'reflection_scale': [0.1],
|
||||||
'color_texture': trees_texture
|
'color_texture': trees_texture
|
||||||
}))
|
}))
|
||||||
self.bgterrain = ba.Actor(
|
self.bgterrain = ba.NodeActor(
|
||||||
ba.newnode('terrain',
|
ba.newnode('terrain',
|
||||||
attrs={
|
attrs={
|
||||||
'model': bgmodel,
|
'model': bgmodel,
|
||||||
@ -380,7 +380,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
color2 = ((1, 1, 1, 1) if ba.app.vr_mode else
|
color2 = ((1, 1, 1, 1) if ba.app.vr_mode else
|
||||||
(0.7, 0.65, 0.75, 1.0))
|
(0.7, 0.65, 0.75, 1.0))
|
||||||
shadow = (1.0 if ba.app.vr_mode else 0.4)
|
shadow = (1.0 if ba.app.vr_mode else 0.4)
|
||||||
self._text = ba.Actor(
|
self._text = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'v_attach': 'top',
|
'v_attach': 'top',
|
||||||
@ -652,7 +652,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
vr_depth_offset: float = 0.0,
|
vr_depth_offset: float = 0.0,
|
||||||
shadow: bool = False) -> None:
|
shadow: bool = False) -> None:
|
||||||
if shadow:
|
if shadow:
|
||||||
word_obj = ba.Actor(
|
word_obj = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'position': (x, y),
|
'position': (x, y),
|
||||||
@ -669,7 +669,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
}))
|
}))
|
||||||
self._word_actors.append(word_obj)
|
self._word_actors.append(word_obj)
|
||||||
else:
|
else:
|
||||||
word_obj = ba.Actor(
|
word_obj = ba.NodeActor(
|
||||||
ba.newnode('text',
|
ba.newnode('text',
|
||||||
attrs={
|
attrs={
|
||||||
'position': (x, y),
|
'position': (x, y),
|
||||||
@ -776,7 +776,7 @@ class MainMenuActivity(ba.Activity):
|
|||||||
mopaque = (None if custom_texture is not None else ba.getmodel('logo'))
|
mopaque = (None if custom_texture is not None else ba.getmodel('logo'))
|
||||||
mtrans = (None if custom_texture is not None else
|
mtrans = (None if custom_texture is not None else
|
||||||
ba.getmodel('logoTransparent'))
|
ba.getmodel('logoTransparent'))
|
||||||
logo = ba.Actor(
|
logo = ba.NodeActor(
|
||||||
ba.newnode('image',
|
ba.newnode('image',
|
||||||
attrs={
|
attrs={
|
||||||
'texture': ltex,
|
'texture': ltex,
|
||||||
|
|||||||
@ -180,7 +180,7 @@ class GatherWindow(ba.Window):
|
|||||||
self._scroll_width = self._width - scroll_buffer_h
|
self._scroll_width = self._width - scroll_buffer_h
|
||||||
self._scroll_height = self._height - 180.0
|
self._scroll_height = self._height - 180.0
|
||||||
|
|
||||||
# not actually using a scroll widget anymore; just an image
|
# Not actually using a scroll widget anymore; just an image.
|
||||||
scroll_left = (self._width - self._scroll_width) * 0.5
|
scroll_left = (self._width - self._scroll_width) * 0.5
|
||||||
scroll_bottom = self._height - self._scroll_height - 79 - 48
|
scroll_bottom = self._height - self._scroll_height - 79 - 48
|
||||||
buffer_h = 10
|
buffer_h = 10
|
||||||
@ -214,8 +214,8 @@ class GatherWindow(ba.Window):
|
|||||||
or _ba.get_account_type() != 'Google Play'):
|
or _ba.get_account_type() != 'Google Play'):
|
||||||
account.show_sign_in_prompt('Google Play')
|
account.show_sign_in_prompt('Google Play')
|
||||||
else:
|
else:
|
||||||
# if there's google play people connected to us, inform the user
|
# If there's google play people connected to us, inform the user
|
||||||
# that they will get disconnected.. otherwise just go ahead..
|
# that they will get disconnected. Otherwise just go ahead.
|
||||||
google_player_count = (_ba.get_google_play_party_client_count())
|
google_player_count = (_ba.get_google_play_party_client_count())
|
||||||
if google_player_count > 0:
|
if google_player_count > 0:
|
||||||
confirm.ConfirmWindow(
|
confirm.ConfirmWindow(
|
||||||
@ -246,25 +246,25 @@ class GatherWindow(ba.Window):
|
|||||||
return
|
return
|
||||||
self._current_tab = tab
|
self._current_tab = tab
|
||||||
|
|
||||||
# we wanna preserve our current tab between runs
|
# We wanna preserve our current tab between runs.
|
||||||
cfg = ba.app.config
|
cfg = ba.app.config
|
||||||
cfg['Gather Tab'] = tab
|
cfg['Gather Tab'] = tab
|
||||||
cfg.commit()
|
cfg.commit()
|
||||||
|
|
||||||
# update tab colors based on which is selected
|
# Update tab colors based on which is selected.
|
||||||
tabs.update_tab_button_colors(self._tab_buttons, tab)
|
tabs.update_tab_button_colors(self._tab_buttons, tab)
|
||||||
|
|
||||||
# (re)create scroll widget
|
# (Re)create scroll widget.
|
||||||
if self._tab_container:
|
if self._tab_container:
|
||||||
self._tab_container.delete()
|
self._tab_container.delete()
|
||||||
scroll_left = (self._width - self._scroll_width) * 0.5
|
scroll_left = (self._width - self._scroll_width) * 0.5
|
||||||
scroll_bottom = self._height - self._scroll_height - 79 - 48
|
scroll_bottom = self._height - self._scroll_height - 79 - 48
|
||||||
|
|
||||||
# a place where tabs can store data to get cleared when switching to
|
# A place where tabs can store data to get cleared when switching to
|
||||||
# a different tab
|
# a different tab.
|
||||||
self._tab_data = {}
|
self._tab_data = {}
|
||||||
|
|
||||||
# so we can still select root level widgets with direction buttons
|
# So we can still select root level widgets with direction buttons.
|
||||||
def _simple_message(tab2: str,
|
def _simple_message(tab2: str,
|
||||||
message: ba.Lstr,
|
message: ba.Lstr,
|
||||||
string_height: float,
|
string_height: float,
|
||||||
@ -331,7 +331,7 @@ class GatherWindow(ba.Window):
|
|||||||
('${BUTTON}',
|
('${BUTTON}',
|
||||||
ba.charstr(ba.SpecialChar.TOP_BUTTON))])
|
ba.charstr(ba.SpecialChar.TOP_BUTTON))])
|
||||||
|
|
||||||
# let's not talk about sharing in vr-mode; its tricky to fit more
|
# Let's not talk about sharing in vr-mode; its tricky to fit more
|
||||||
# than one head in a VR-headset ;-)
|
# than one head in a VR-headset ;-)
|
||||||
if not ba.app.vr_mode:
|
if not ba.app.vr_mode:
|
||||||
msg = ba.Lstr(
|
msg = ba.Lstr(
|
||||||
@ -472,8 +472,8 @@ class GatherWindow(ba.Window):
|
|||||||
up_widget=self._tab_buttons[tab])
|
up_widget=self._tab_buttons[tab])
|
||||||
ba.widget(edit=self._internet_join_text, right_widget=txt)
|
ba.widget(edit=self._internet_join_text, right_widget=txt)
|
||||||
|
|
||||||
# attempt to fetch our local address so we have it for
|
# Attempt to fetch our local address so we have it for
|
||||||
# error messages
|
# error messages.
|
||||||
self._internet_local_address = None
|
self._internet_local_address = None
|
||||||
|
|
||||||
class AddrFetchThread(threading.Thread):
|
class AddrFetchThread(threading.Thread):
|
||||||
@ -501,9 +501,9 @@ class GatherWindow(ba.Window):
|
|||||||
ba.pushcall(ba.Call(self._call, val),
|
ba.pushcall(ba.Call(self._call, val),
|
||||||
from_other_thread=True)
|
from_other_thread=True)
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception()
|
# FIXME: Should filter out expected errors and
|
||||||
# FIXME: Should screen out expected errors and
|
|
||||||
# report others here.
|
# report others here.
|
||||||
|
ba.print_exception()
|
||||||
|
|
||||||
AddrFetchThread(ba.WeakCall(
|
AddrFetchThread(ba.WeakCall(
|
||||||
self._internet_fetch_local_addr_cb)).start()
|
self._internet_fetch_local_addr_cb)).start()
|
||||||
@ -518,8 +518,8 @@ class GatherWindow(ba.Window):
|
|||||||
timetype=ba.TimeType.REAL)
|
timetype=ba.TimeType.REAL)
|
||||||
}
|
}
|
||||||
|
|
||||||
# also update it immediately so we don't have to wait for the
|
# Also update it immediately so we don't have to wait for the
|
||||||
# initial query..
|
# initial query.
|
||||||
self._update_internet_tab()
|
self._update_internet_tab()
|
||||||
|
|
||||||
elif tab == 'local_network':
|
elif tab == 'local_network':
|
||||||
@ -545,8 +545,8 @@ class GatherWindow(ba.Window):
|
|||||||
ba.WeakCall(self.update),
|
ba.WeakCall(self.update),
|
||||||
timetype=ba.TimeType.REAL,
|
timetype=ba.TimeType.REAL,
|
||||||
repeat=True)
|
repeat=True)
|
||||||
# go ahead and run a few *almost* immediately so we don't
|
# Go ahead and run a few *almost* immediately so we don't
|
||||||
# have to wait a second
|
# have to wait a second.
|
||||||
self.update()
|
self.update()
|
||||||
ba.timer(0.25,
|
ba.timer(0.25,
|
||||||
ba.WeakCall(self.update),
|
ba.WeakCall(self.update),
|
||||||
@ -566,7 +566,8 @@ class GatherWindow(ba.Window):
|
|||||||
t_scale = 1.6
|
t_scale = 1.6
|
||||||
for child in self._columnwidget.get_children():
|
for child in self._columnwidget.get_children():
|
||||||
child.delete()
|
child.delete()
|
||||||
# grab this now this since adding widgets will change it
|
|
||||||
|
# Grab this now this since adding widgets will change it.
|
||||||
last_selected_host = self._last_selected_host
|
last_selected_host = self._last_selected_host
|
||||||
hosts = _ba.host_scan_cycle()
|
hosts = _ba.host_scan_cycle()
|
||||||
for i, host in enumerate(hosts):
|
for i, host in enumerate(hosts):
|
||||||
@ -843,7 +844,7 @@ class GatherWindow(ba.Window):
|
|||||||
color=(1, 0, 0))
|
color=(1, 0, 0))
|
||||||
ba.playsound(ba.getsound('error'))
|
ba.playsound(ba.getsound('error'))
|
||||||
else:
|
else:
|
||||||
# store for later
|
# Store for later.
|
||||||
cfg2 = ba.app.config
|
cfg2 = ba.app.config
|
||||||
cfg2['Last Manual Party Connect Address'] = addr2
|
cfg2['Last Manual Party Connect Address'] = addr2
|
||||||
cfg2.commit()
|
cfg2.commit()
|
||||||
@ -866,7 +867,6 @@ class GatherWindow(ba.Window):
|
|||||||
tscl = 0.85
|
tscl = 0.85
|
||||||
tspc = 25
|
tspc = 25
|
||||||
|
|
||||||
# v -= 35
|
|
||||||
def _safe_set_text(txt3: ba.Widget,
|
def _safe_set_text(txt3: ba.Widget,
|
||||||
val: Union[str, ba.Lstr],
|
val: Union[str, ba.Lstr],
|
||||||
success: bool = True) -> None:
|
success: bool = True) -> None:
|
||||||
@ -875,11 +875,10 @@ class GatherWindow(ba.Window):
|
|||||||
text=val,
|
text=val,
|
||||||
color=(0, 1, 0) if success else (1, 1, 0))
|
color=(0, 1, 0) if success else (1, 1, 0))
|
||||||
|
|
||||||
# this currently doesn't work from china since we go through a
|
# This currently doesn't work from china since we go through a
|
||||||
# reverse proxy there
|
# reverse proxy there.
|
||||||
# EDIT - it should work now; our proxy server forwards along
|
# UPDATE: it should work now; our proxy server forwards along
|
||||||
# original IPs
|
# original IPs.
|
||||||
# app = ba.app
|
|
||||||
do_internet_check = True
|
do_internet_check = True
|
||||||
|
|
||||||
def do_it(v2: float, cnt2: Optional[ba.Widget]) -> None:
|
def do_it(v2: float, cnt2: Optional[ba.Widget]) -> None:
|
||||||
@ -940,6 +939,7 @@ class GatherWindow(ba.Window):
|
|||||||
from_other_thread=True)
|
from_other_thread=True)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
err_str = str(exc)
|
err_str = str(exc)
|
||||||
|
|
||||||
# FIXME: Should look at exception types here,
|
# FIXME: Should look at exception types here,
|
||||||
# not strings.
|
# not strings.
|
||||||
if 'Network is unreachable' in err_str:
|
if 'Network is unreachable' in err_str:
|
||||||
@ -1024,14 +1024,15 @@ class GatherWindow(ba.Window):
|
|||||||
text='')
|
text='')
|
||||||
|
|
||||||
self._doing_access_check = False
|
self._doing_access_check = False
|
||||||
self._access_check_count = 0 # cap our refreshes eventually..
|
self._access_check_count = 0 # Cap our refreshes eventually.
|
||||||
self._tab_data['access_check_timer'] = ba.Timer(
|
self._tab_data['access_check_timer'] = ba.Timer(
|
||||||
10.0,
|
10.0,
|
||||||
ba.WeakCall(self._access_check_update, t_addr,
|
ba.WeakCall(self._access_check_update, t_addr,
|
||||||
t_accessible, t_accessible_extra),
|
t_accessible, t_accessible_extra),
|
||||||
repeat=True,
|
repeat=True,
|
||||||
timetype=ba.TimeType.REAL)
|
timetype=ba.TimeType.REAL)
|
||||||
# kick initial off
|
|
||||||
|
# Kick initial off.
|
||||||
self._access_check_update(t_addr, t_accessible,
|
self._access_check_update(t_addr, t_accessible,
|
||||||
t_accessible_extra)
|
t_accessible_extra)
|
||||||
if check_button:
|
if check_button:
|
||||||
@ -1061,7 +1062,7 @@ class GatherWindow(ba.Window):
|
|||||||
if playsound:
|
if playsound:
|
||||||
ba.playsound(ba.getsound('click01'))
|
ba.playsound(ba.getsound('click01'))
|
||||||
|
|
||||||
# if we're switching in from elsewhere, reset our selection
|
# If we're switching in from elsewhere, reset our selection.
|
||||||
# (prevents selecting something way down the list if we switched away
|
# (prevents selecting something way down the list if we switched away
|
||||||
# and came back)
|
# and came back)
|
||||||
if self._internet_tab != value:
|
if self._internet_tab != value:
|
||||||
@ -1077,7 +1078,7 @@ class GatherWindow(ba.Window):
|
|||||||
edit=self._internet_host_text,
|
edit=self._internet_host_text,
|
||||||
color=active_color if value == 'host' else inactive_color)
|
color=active_color if value == 'host' else inactive_color)
|
||||||
|
|
||||||
# clear anything in existence..
|
# Clear anything in existence.
|
||||||
for widget in [
|
for widget in [
|
||||||
self._internet_host_scrollwidget,
|
self._internet_host_scrollwidget,
|
||||||
self._internet_host_name_text,
|
self._internet_host_name_text,
|
||||||
@ -1095,7 +1096,6 @@ class GatherWindow(ba.Window):
|
|||||||
self._internet_join_status_text,
|
self._internet_join_status_text,
|
||||||
self._internet_host_dedicated_server_info_text
|
self._internet_host_dedicated_server_info_text
|
||||||
]:
|
]:
|
||||||
# widget = getattr(self, attr, None)
|
|
||||||
if widget is not None:
|
if widget is not None:
|
||||||
widget.delete()
|
widget.delete()
|
||||||
|
|
||||||
@ -1107,9 +1107,10 @@ class GatherWindow(ba.Window):
|
|||||||
v -= 25
|
v -= 25
|
||||||
is_public_enabled = _ba.get_public_party_enabled()
|
is_public_enabled = _ba.get_public_party_enabled()
|
||||||
if value == 'join':
|
if value == 'join':
|
||||||
# reset this so we do an immediate refresh query
|
# Reset this so we do an immediate refresh query.
|
||||||
self._internet_join_last_refresh_time = -99999.0
|
self._internet_join_last_refresh_time = -99999.0
|
||||||
# reset our list of public parties
|
|
||||||
|
# Reset our list of public parties.
|
||||||
self._public_parties = {}
|
self._public_parties = {}
|
||||||
self._last_public_party_list_rebuild_time = 0
|
self._last_public_party_list_rebuild_time = 0
|
||||||
self._first_public_party_list_rebuild_time = None
|
self._first_public_party_list_rebuild_time = None
|
||||||
@ -1125,8 +1126,7 @@ class GatherWindow(ba.Window):
|
|||||||
shadow=0.0,
|
shadow=0.0,
|
||||||
h_align='center',
|
h_align='center',
|
||||||
v_align='center')
|
v_align='center')
|
||||||
# noinspection PyUnreachableCode
|
if bool(False):
|
||||||
if False: # pylint: disable=using-constant-test
|
|
||||||
self._internet_join_party_language_label = ba.textwidget(
|
self._internet_join_party_language_label = ba.textwidget(
|
||||||
text=ba.Lstr(
|
text=ba.Lstr(
|
||||||
resource='settingsWindowAdvanced.languageText'),
|
resource='settingsWindowAdvanced.languageText'),
|
||||||
@ -1192,8 +1192,6 @@ class GatherWindow(ba.Window):
|
|||||||
color=(0.6, 0.6, 0.6),
|
color=(0.6, 0.6, 0.6),
|
||||||
position=(c_width * 0.5, c_height * 0.5))
|
position=(c_width * 0.5, c_height * 0.5))
|
||||||
|
|
||||||
# t_scale = 1.6
|
|
||||||
|
|
||||||
if value == 'host':
|
if value == 'host':
|
||||||
v -= 30
|
v -= 30
|
||||||
party_name_text = ba.Lstr(
|
party_name_text = ba.Lstr(
|
||||||
@ -1313,15 +1311,15 @@ class GatherWindow(ba.Window):
|
|||||||
color=ba.app.infotextcolor,
|
color=ba.app.infotextcolor,
|
||||||
position=(c_width * 0.5, v))
|
position=(c_width * 0.5, v))
|
||||||
|
|
||||||
# if public sharing is already on,
|
# If public sharing is already on,
|
||||||
# launch a status-check immediately
|
# launch a status-check immediately.
|
||||||
if _ba.get_public_party_enabled():
|
if _ba.get_public_party_enabled():
|
||||||
self._do_internet_status_check()
|
self._do_internet_status_check()
|
||||||
|
|
||||||
# now add a lock icon overlay for if we don't have pro
|
# Now add a lock icon overlay for if we don't have pro.
|
||||||
icon = self._internet_lock_icon
|
icon = self._internet_lock_icon
|
||||||
if icon and self._internet_lock_icon:
|
if icon and self._internet_lock_icon:
|
||||||
self._internet_lock_icon.delete() # kill any existing
|
self._internet_lock_icon.delete() # Kill any existing.
|
||||||
self._internet_lock_icon = ba.imagewidget(
|
self._internet_lock_icon = ba.imagewidget(
|
||||||
parent=self._tab_container,
|
parent=self._tab_container,
|
||||||
position=(c_width * 0.5 - 60, c_height * 0.5 - 50),
|
position=(c_width * 0.5 - 60, c_height * 0.5 - 50),
|
||||||
@ -1354,11 +1352,11 @@ class GatherWindow(ba.Window):
|
|||||||
def _on_public_party_query_result(
|
def _on_public_party_query_result(
|
||||||
self, result: Optional[Dict[str, Any]]) -> None:
|
self, result: Optional[Dict[str, Any]]) -> None:
|
||||||
with ba.Context('ui'):
|
with ba.Context('ui'):
|
||||||
# any time we get any result at all, kill our loading status
|
# Any time we get any result at all, kill our loading status.
|
||||||
status_text = self._internet_join_status_text
|
status_text = self._internet_join_status_text
|
||||||
if status_text:
|
if status_text:
|
||||||
# don't show results if not signed in (probably didn't get any
|
# Don't show results if not signed in
|
||||||
# anyway)
|
# (probably didn't get any anyway).
|
||||||
if _ba.get_account_state() != 'signed_in':
|
if _ba.get_account_state() != 'signed_in':
|
||||||
ba.textwidget(edit=status_text,
|
ba.textwidget(edit=status_text,
|
||||||
text=ba.Lstr(resource='notSignedInText'))
|
text=ba.Lstr(resource='notSignedInText'))
|
||||||
@ -1378,11 +1376,11 @@ class GatherWindow(ba.Window):
|
|||||||
partyval['claimed'] = False
|
partyval['claimed'] = False
|
||||||
|
|
||||||
for party_in in parties_in:
|
for party_in in parties_in:
|
||||||
# party is indexed by (ADDR)_(PORT)
|
# Party is indexed by (ADDR)_(PORT)
|
||||||
party_key = party_in['a'] + '_' + str(party_in['p'])
|
party_key = party_in['a'] + '_' + str(party_in['p'])
|
||||||
party = self._public_parties.get(party_key)
|
party = self._public_parties.get(party_key)
|
||||||
if party is None:
|
if party is None:
|
||||||
# if this party is new to us, init it..
|
# If this party is new to us, init it.
|
||||||
index = self._next_public_party_entry_index
|
index = self._next_public_party_entry_index
|
||||||
self._next_public_party_entry_index = index + 1
|
self._next_public_party_entry_index = index + 1
|
||||||
party = self._public_parties[party_key] = {
|
party = self._public_parties[party_key] = {
|
||||||
@ -1395,7 +1393,8 @@ class GatherWindow(ba.Window):
|
|||||||
'index':
|
'index':
|
||||||
index,
|
index,
|
||||||
}
|
}
|
||||||
# now, new or not, update its values
|
|
||||||
|
# Now, new or not, update its values.
|
||||||
party['queue'] = party_in.get('q')
|
party['queue'] = party_in.get('q')
|
||||||
party['port'] = party_in.get('p')
|
party['port'] = party_in.get('p')
|
||||||
party['name'] = party_in['n']
|
party['name'] = party_in['n']
|
||||||
@ -1407,7 +1406,7 @@ class GatherWindow(ba.Window):
|
|||||||
party['ping_interval'] = 0.001 * party_in['pi']
|
party['ping_interval'] = 0.001 * party_in['pi']
|
||||||
party['stats_addr'] = party_in['sa']
|
party['stats_addr'] = party_in['sa']
|
||||||
|
|
||||||
# prune unclaimed party entries
|
# Prune unclaimed party entries.
|
||||||
self._public_parties = {
|
self._public_parties = {
|
||||||
key: val
|
key: val
|
||||||
for key, val in list(self._public_parties.items())
|
for key, val in list(self._public_parties.items())
|
||||||
@ -1423,8 +1422,9 @@ class GatherWindow(ba.Window):
|
|||||||
cur_time = ba.time(ba.TimeType.REAL)
|
cur_time = ba.time(ba.TimeType.REAL)
|
||||||
if self._first_public_party_list_rebuild_time is None:
|
if self._first_public_party_list_rebuild_time is None:
|
||||||
self._first_public_party_list_rebuild_time = cur_time
|
self._first_public_party_list_rebuild_time = cur_time
|
||||||
# update faster for the first few seconds;
|
|
||||||
# then ease off to keep the list from jumping around
|
# Update faster for the first few seconds;
|
||||||
|
# then ease off to keep the list from jumping around.
|
||||||
since_first = cur_time - self._first_public_party_list_rebuild_time
|
since_first = cur_time - self._first_public_party_list_rebuild_time
|
||||||
wait_time = (1.0 if since_first < 2.0 else
|
wait_time = (1.0 if since_first < 2.0 else
|
||||||
2.5 if since_first < 10.0 else 5.0)
|
2.5 if since_first < 10.0 else 5.0)
|
||||||
@ -1433,23 +1433,23 @@ class GatherWindow(ba.Window):
|
|||||||
return
|
return
|
||||||
self._last_public_party_list_rebuild_time = cur_time
|
self._last_public_party_list_rebuild_time = cur_time
|
||||||
|
|
||||||
# first off, check for the existence of our column widget;
|
# First off, check for the existence of our column widget;
|
||||||
# if we don't have this, we're done
|
# if we don't have this, we're done.
|
||||||
columnwidget = self._internet_host_columnwidget
|
columnwidget = self._internet_host_columnwidget
|
||||||
if not columnwidget:
|
if not columnwidget:
|
||||||
return
|
return
|
||||||
|
|
||||||
with ba.Context('ui'):
|
with ba.Context('ui'):
|
||||||
|
|
||||||
# now kill and recreate all widgets
|
# Now kill and recreate all widgets.
|
||||||
for widget in columnwidget.get_children():
|
for widget in columnwidget.get_children():
|
||||||
widget.delete()
|
widget.delete()
|
||||||
|
|
||||||
# sort - show queue-enabled ones first and sort by lowest ping
|
# Sort - show queue-enabled ones first and sort by lowest ping.
|
||||||
ordered_parties = sorted(
|
ordered_parties = sorted(
|
||||||
list(self._public_parties.values()),
|
list(self._public_parties.values()),
|
||||||
key=lambda p: (
|
key=lambda p: (
|
||||||
p['queue'] is None, # show non-queued last
|
p['queue'] is None, # Show non-queued last.
|
||||||
p['ping'] if p['ping'] is not None else 999999,
|
p['ping'] if p['ping'] is not None else 999999,
|
||||||
p['index'],
|
p['index'],
|
||||||
p))
|
p))
|
||||||
@ -1457,22 +1457,19 @@ class GatherWindow(ba.Window):
|
|||||||
first = True
|
first = True
|
||||||
|
|
||||||
sub_scroll_width = 830
|
sub_scroll_width = 830
|
||||||
# rval = random.randrange(4, 10)
|
|
||||||
# print 'doing', rval
|
|
||||||
# ordered_parties = ordered_parties[:rval]
|
|
||||||
lineheight = 42
|
lineheight = 42
|
||||||
sub_scroll_height = lineheight * len(ordered_parties) + 50
|
sub_scroll_height = lineheight * len(ordered_parties) + 50
|
||||||
ba.containerwidget(edit=columnwidget,
|
ba.containerwidget(edit=columnwidget,
|
||||||
size=(sub_scroll_width, sub_scroll_height))
|
size=(sub_scroll_width, sub_scroll_height))
|
||||||
|
|
||||||
# ew; this rebuilding generates deferred selection callbacks
|
# Ew; this rebuilding generates deferred selection callbacks
|
||||||
# so we need to generated deferred ignore notices for ourself
|
# so we need to generated deferred ignore notices for ourself.
|
||||||
def refresh_on() -> None:
|
def refresh_on() -> None:
|
||||||
self._refreshing_public_party_list = True
|
self._refreshing_public_party_list = True
|
||||||
|
|
||||||
ba.pushcall(refresh_on)
|
ba.pushcall(refresh_on)
|
||||||
|
|
||||||
# janky - allow escaping if there's nothing in us
|
# Janky - allow escaping if there's nothing in us.
|
||||||
ba.containerwidget(edit=self._internet_host_scrollwidget,
|
ba.containerwidget(edit=self._internet_host_scrollwidget,
|
||||||
claims_up_down=(len(ordered_parties) > 0))
|
claims_up_down=(len(ordered_parties) > 0))
|
||||||
|
|
||||||
@ -1504,8 +1501,7 @@ class GatherWindow(ba.Window):
|
|||||||
if existing_selection == (party['address'], 'name'):
|
if existing_selection == (party['address'], 'name'):
|
||||||
ba.containerwidget(edit=columnwidget,
|
ba.containerwidget(edit=columnwidget,
|
||||||
selected_child=party['name_widget'])
|
selected_child=party['name_widget'])
|
||||||
# noinspection PyUnreachableCode
|
if bool(False):
|
||||||
if False: # pylint: disable=using-constant-test
|
|
||||||
party['language_widget'] = ba.textwidget(
|
party['language_widget'] = ba.textwidget(
|
||||||
text=ba.Lstr(translate=('languages',
|
text=ba.Lstr(translate=('languages',
|
||||||
party['language'])),
|
party['language'])),
|
||||||
@ -1621,20 +1617,20 @@ class GatherWindow(ba.Window):
|
|||||||
def _update_internet_tab(self) -> None:
|
def _update_internet_tab(self) -> None:
|
||||||
# pylint: disable=too-many-statements
|
# pylint: disable=too-many-statements
|
||||||
|
|
||||||
# special case - if a party-queue window is up, don't do any of this
|
# Special case: if a party-queue window is up, don't do any of this
|
||||||
# (keeps things smoother)
|
# (keeps things smoother).
|
||||||
if ba.app.have_party_queue_window:
|
if ba.app.have_party_queue_window:
|
||||||
return
|
return
|
||||||
|
|
||||||
# if we've got a party-name text widget, keep its value plugged
|
# If we've got a party-name text widget, keep its value plugged
|
||||||
# into our public host name...
|
# into our public host name.
|
||||||
text = self._internet_host_name_text
|
text = self._internet_host_name_text
|
||||||
if text:
|
if text:
|
||||||
name = cast(str,
|
name = cast(str,
|
||||||
ba.textwidget(query=self._internet_host_name_text))
|
ba.textwidget(query=self._internet_host_name_text))
|
||||||
_ba.set_public_party_name(name)
|
_ba.set_public_party_name(name)
|
||||||
|
|
||||||
# show/hide the lock icon depending on if we've got pro
|
# Show/hide the lock icon depending on if we've got pro.
|
||||||
icon = self._internet_lock_icon
|
icon = self._internet_lock_icon
|
||||||
if icon:
|
if icon:
|
||||||
if self._is_internet_locked():
|
if self._is_internet_locked():
|
||||||
@ -1657,17 +1653,17 @@ class GatherWindow(ba.Window):
|
|||||||
callback=ba.WeakCall(self._on_public_party_query_result))
|
callback=ba.WeakCall(self._on_public_party_query_result))
|
||||||
_ba.run_transactions()
|
_ba.run_transactions()
|
||||||
|
|
||||||
# go through our existing public party entries firing off pings
|
# Go through our existing public party entries firing off pings
|
||||||
# for any that have timed out
|
# for any that have timed out.
|
||||||
for party in list(self._public_parties.values()):
|
for party in list(self._public_parties.values()):
|
||||||
if (party['next_ping_time'] <= now
|
if (party['next_ping_time'] <= now
|
||||||
and ba.app.ping_thread_count < 15):
|
and ba.app.ping_thread_count < 15):
|
||||||
|
|
||||||
# make sure to fully catch up and not to multi-ping if
|
# Make sure to fully catch up and not to multi-ping if
|
||||||
# we're way behind somehow..
|
# we're way behind somehow.
|
||||||
while party['next_ping_time'] <= now:
|
while party['next_ping_time'] <= now:
|
||||||
# crank the interval up for high-latency parties to
|
# Crank the interval up for high-latency parties to
|
||||||
# save us some work
|
# save us some work.
|
||||||
mult = 1
|
mult = 1
|
||||||
if party['ping'] is not None:
|
if party['ping'] is not None:
|
||||||
mult = (10 if party['ping'] > 300 else
|
mult = (10 if party['ping'] > 300 else
|
||||||
@ -1682,8 +1678,6 @@ class GatherWindow(ba.Window):
|
|||||||
call: Callable[[str, int, Optional[int]],
|
call: Callable[[str, int, Optional[int]],
|
||||||
Optional[int]]):
|
Optional[int]]):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
# need utf8 here to avoid an error on our minimum
|
|
||||||
# bundled python
|
|
||||||
self._address = address
|
self._address = address
|
||||||
self._port = port
|
self._port = port
|
||||||
self._call = call
|
self._call = call
|
||||||
@ -1701,11 +1695,9 @@ class GatherWindow(ba.Window):
|
|||||||
|
|
||||||
accessible = False
|
accessible = False
|
||||||
starttime = time.time()
|
starttime = time.time()
|
||||||
# send a simple ping and wait for a response;
|
|
||||||
# if we get it, they're accessible...
|
|
||||||
|
|
||||||
# send a few pings and wait a second for
|
# Send a few pings and wait a second for
|
||||||
# a response
|
# a response.
|
||||||
sock.settimeout(1)
|
sock.settimeout(1)
|
||||||
for _i in range(3):
|
for _i in range(3):
|
||||||
sock.send(b'\x0b')
|
sock.send(b'\x0b')
|
||||||
@ -1728,12 +1720,25 @@ class GatherWindow(ba.Window):
|
|||||||
from_other_thread=True)
|
from_other_thread=True)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
import errno
|
import errno
|
||||||
# ignore harmless errors
|
|
||||||
if exc.errno != errno.EHOSTUNREACH:
|
# Ignore harmless errors.
|
||||||
ba.print_exception('error on ping',
|
if exc.errno == errno.EHOSTUNREACH:
|
||||||
|
pass
|
||||||
|
elif exc.errno == errno.EADDRNOTAVAIL:
|
||||||
|
if self._port == 0:
|
||||||
|
# This has happened. Ignore.
|
||||||
|
pass
|
||||||
|
elif ba.do_once():
|
||||||
|
print(
|
||||||
|
f'Got EADDRNOTAVAIL on gather ping'
|
||||||
|
f' for addr {self._address}'
|
||||||
|
f' port {self._port}.')
|
||||||
|
else:
|
||||||
|
ba.print_exception('Error on gather ping.',
|
||||||
once=True)
|
once=True)
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception('error on ping', once=True)
|
ba.print_exception('Error on gather ping',
|
||||||
|
once=True)
|
||||||
ba.app.ping_thread_count -= 1
|
ba.app.ping_thread_count -= 1
|
||||||
|
|
||||||
PingThread(party['address'], party['port'],
|
PingThread(party['address'], party['port'],
|
||||||
@ -1741,8 +1746,8 @@ class GatherWindow(ba.Window):
|
|||||||
|
|
||||||
def _ping_callback(self, address: str, port: Optional[int],
|
def _ping_callback(self, address: str, port: Optional[int],
|
||||||
result: Optional[int]) -> None:
|
result: Optional[int]) -> None:
|
||||||
# Look for a widget corresponding to this target; if we find one,
|
# Look for a widget corresponding to this target.
|
||||||
# update our list.
|
# If we find one, update our list.
|
||||||
party = self._public_parties.get(address + '_' + str(port))
|
party = self._public_parties.get(address + '_' + str(port))
|
||||||
if party is not None:
|
if party is not None:
|
||||||
# We now smooth ping a bit to reduce jumping around in the list
|
# We now smooth ping a bit to reduce jumping around in the list
|
||||||
@ -1755,9 +1760,11 @@ class GatherWindow(ba.Window):
|
|||||||
(1.0 - smoothing) * result)
|
(1.0 - smoothing) * result)
|
||||||
else:
|
else:
|
||||||
party['ping'] = result
|
party['ping'] = result
|
||||||
if 'ping_widget' not in party:
|
|
||||||
pass # This can happen if we switch away and then back to the
|
# This can happen if we switch away and then back to the
|
||||||
# client tab while pings are in flight.
|
# client tab while pings are in flight.
|
||||||
|
if 'ping_widget' not in party:
|
||||||
|
pass
|
||||||
elif party['ping_widget']:
|
elif party['ping_widget']:
|
||||||
self._rebuild_public_party_list()
|
self._rebuild_public_party_list()
|
||||||
|
|
||||||
@ -1946,7 +1953,7 @@ class GatherWindow(ba.Window):
|
|||||||
ba.app.window_states[self.__class__.__name__] = {
|
ba.app.window_states[self.__class__.__name__] = {
|
||||||
'sel_name': sel_name,
|
'sel_name': sel_name,
|
||||||
'tab': self._current_tab,
|
'tab': self._current_tab,
|
||||||
'internetTab': self._internet_tab
|
'internet_tab': self._internet_tab
|
||||||
}
|
}
|
||||||
except Exception:
|
except Exception:
|
||||||
ba.print_exception('error saving state for', self.__class__)
|
ba.print_exception('error saving state for', self.__class__)
|
||||||
@ -1955,7 +1962,7 @@ class GatherWindow(ba.Window):
|
|||||||
try:
|
try:
|
||||||
winstate = ba.app.window_states.get(self.__class__.__name__, {})
|
winstate = ba.app.window_states.get(self.__class__.__name__, {})
|
||||||
sel_name = winstate.get('sel_name', None)
|
sel_name = winstate.get('sel_name', None)
|
||||||
self._internet_tab = winstate.get('internetTab', 'join')
|
self._internet_tab = winstate.get('internet_tab', 'join')
|
||||||
current_tab = ba.app.config.get('Gather Tab', None)
|
current_tab = ba.app.config.get('Gather Tab', None)
|
||||||
if current_tab is None or current_tab not in self._tab_buttons:
|
if current_tab is None or current_tab not in self._tab_buttons:
|
||||||
current_tab = 'about'
|
current_tab = 'about'
|
||||||
|
|||||||
@ -75,7 +75,7 @@ class CallbackSet(Generic[CT]):
|
|||||||
# passed.
|
# passed.
|
||||||
|
|
||||||
# To use this, simply assign your call type to this Call for type checking:
|
# To use this, simply assign your call type to this Call for type checking:
|
||||||
# example:
|
# Example:
|
||||||
# class _MyCallWrapper:
|
# class _MyCallWrapper:
|
||||||
# <runtime class defined here>
|
# <runtime class defined here>
|
||||||
# if TYPE_CHECKING:
|
# if TYPE_CHECKING:
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
<li><a href="#class_ba_Actor">ba.Actor</a></li>
|
<li><a href="#class_ba_Actor">ba.Actor</a></li>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#class_ba_Map">ba.Map</a></li>
|
<li><a href="#class_ba_Map">ba.Map</a></li>
|
||||||
|
<li><a href="#class_ba_NodeActor">ba.NodeActor</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<li><a href="#class_ba_Chooser">ba.Chooser</a></li>
|
<li><a href="#class_ba_Chooser">ba.Chooser</a></li>
|
||||||
<li><a href="#class_ba_InputDevice">ba.InputDevice</a></li>
|
<li><a href="#class_ba_InputDevice">ba.InputDevice</a></li>
|
||||||
@ -537,21 +538,22 @@ is a convenient way to access this same functionality.</p>
|
|||||||
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
|
|
||||||
<p> Actors act as controllers, combining some number of <a href="#class_ba_Node">ba.Nodes</a>,
|
<p> Actors act as controllers, combining some number of <a href="#class_ba_Node">ba.Nodes</a>,
|
||||||
<a href="#class_ba_Texture">ba.Textures</a>, <a href="#class_ba_Sound">ba.Sounds</a>, etc. into one cohesive unit.</p>
|
<a href="#class_ba_Texture">ba.Textures</a>, <a href="#class_ba_Sound">ba.Sounds</a>, etc. into a high-level cohesive unit.</p>
|
||||||
|
|
||||||
<p> Some example actors include ba.Bomb, ba.Flag, and ba.Spaz.</p>
|
<p> Some example actors include Bomb, Flag, and Spaz classes in bastd.</p>
|
||||||
|
|
||||||
<p> One key feature of Actors is that they generally 'die'
|
<p> One key feature of Actors is that they generally 'die'
|
||||||
(killing off or transitioning out their nodes) when the last Python
|
(killing off or transitioning out their nodes) when the last Python
|
||||||
reference to them disappears, so you can use logic such as:</p>
|
reference to them disappears, so you can use logic such as:</p>
|
||||||
|
|
||||||
<pre><span><em><small> # create a flag Actor in our game activity</small></em></span>
|
<pre><span><em><small> # Create a flag Actor in our game activity:</small></em></span>
|
||||||
self.flag = ba.Flag(position=(0, 10, 0))</pre>
|
from bastd.actor.flag import Flag
|
||||||
|
self.flag = Flag(position=(0, 10, 0))</pre>
|
||||||
|
|
||||||
<pre><span><em><small> # later, destroy the flag..</small></em></span>
|
<pre><span><em><small> # Later, destroy the flag.</small></em></span>
|
||||||
<span><em><small> # (provided nothing else is holding a reference to it)</small></em></span>
|
<span><em><small> # (provided nothing else is holding a reference to it)</small></em></span>
|
||||||
<span><em><small> # we could also just assign a new flag to this value.</small></em></span>
|
<span><em><small> # We could also just assign a new flag to this value.</small></em></span>
|
||||||
<span><em><small> # either way, the old flag disappears.</small></em></span>
|
<span><em><small> # Either way, the old flag disappears.</small></em></span>
|
||||||
self.flag = None</pre>
|
self.flag = None</pre>
|
||||||
|
|
||||||
<p> This is in contrast to the behavior of the more low level <a href="#class_ba_Node">ba.Nodes</a>,
|
<p> This is in contrast to the behavior of the more low level <a href="#class_ba_Node">ba.Nodes</a>,
|
||||||
@ -566,13 +568,13 @@ is a convenient way to access this same functionality.</p>
|
|||||||
takes a single arbitrary object as an argument. This provides a safe way
|
takes a single arbitrary object as an argument. This provides a safe way
|
||||||
to communicate between <a href="#class_ba_Actor">ba.Actor</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_Session">ba.Session</a>, and any other
|
to communicate between <a href="#class_ba_Actor">ba.Actor</a>, <a href="#class_ba_Activity">ba.Activity</a>, <a href="#class_ba_Session">ba.Session</a>, and any other
|
||||||
class providing a handlemessage() method. The most universally handled
|
class providing a handlemessage() method. The most universally handled
|
||||||
message type for actors is the <a href="#class_ba_DieMessage">ba.DieMessage</a>.</p>
|
message type for Actors is the <a href="#class_ba_DieMessage">ba.DieMessage</a>.</p>
|
||||||
|
|
||||||
<pre><span><em><small> # another way to kill the flag from the example above:</small></em></span>
|
<pre><span><em><small> # Another way to kill the flag from the example above:</small></em></span>
|
||||||
<span><em><small> # we can safely call this on any type with a 'handlemessage' method</small></em></span>
|
<span><em><small> # We can safely call this on any type with a 'handlemessage' method</small></em></span>
|
||||||
<span><em><small> # (though its not guaranteed to always have a meaningful effect)</small></em></span>
|
<span><em><small> # (though its not guaranteed to always have a meaningful effect).</small></em></span>
|
||||||
<span><em><small> # in this case the Actor instance will still be around, but its exists()</small></em></span>
|
<span><em><small> # In this case the Actor instance will still be around, but its exists()</small></em></span>
|
||||||
<span><em><small> # and is_alive() methods will both return False</small></em></span>
|
<span><em><small> # and is_alive() methods will both return False.</small></em></span>
|
||||||
self.flag.handlemessage(<a href="#class_ba_DieMessage">ba.DieMessage</a>())
|
self.flag.handlemessage(<a href="#class_ba_DieMessage">ba.DieMessage</a>())
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -590,15 +592,10 @@ is a convenient way to access this same functionality.</p>
|
|||||||
<h5><a href="#method_ba_Actor____init__"><constructor></a>, <a href="#method_ba_Actor__autoretain">autoretain()</a>, <a href="#method_ba_Actor__exists">exists()</a>, <a href="#method_ba_Actor__getactivity">getactivity()</a>, <a href="#method_ba_Actor__handlemessage">handlemessage()</a>, <a href="#method_ba_Actor__is_alive">is_alive()</a>, <a href="#method_ba_Actor__is_expired">is_expired()</a>, <a href="#method_ba_Actor__on_expire">on_expire()</a></h5>
|
<h5><a href="#method_ba_Actor____init__"><constructor></a>, <a href="#method_ba_Actor__autoretain">autoretain()</a>, <a href="#method_ba_Actor__exists">exists()</a>, <a href="#method_ba_Actor__getactivity">getactivity()</a>, <a href="#method_ba_Actor__handlemessage">handlemessage()</a>, <a href="#method_ba_Actor__is_alive">is_alive()</a>, <a href="#method_ba_Actor__is_expired">is_expired()</a>, <a href="#method_ba_Actor__on_expire">on_expire()</a></h5>
|
||||||
<dl>
|
<dl>
|
||||||
<dt><h4><a name="method_ba_Actor____init__"><constructor></a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Actor____init__"><constructor></a></dt></h4><dd>
|
||||||
<p><span>ba.Actor(node: <a href="#class_ba_Node">ba.Node</a> = None)</span></p>
|
<p><span>ba.Actor()</span></p>
|
||||||
|
|
||||||
<p>Instantiates an Actor in the current <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
<p>Instantiates an Actor in the current <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||||
|
|
||||||
<p>If 'node' is provided, it is stored as the 'node' attribute
|
|
||||||
and the default <a href="#method_ba_Actor__handlemessage">ba.Actor.handlemessage</a>() and <a href="#method_ba_Actor__exists">ba.Actor.exists</a>()
|
|
||||||
implementations will apply to it. This allows the creation of
|
|
||||||
simple node-wrapping Actors without having to create a new subclass.</p>
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt><h4><a name="method_ba_Actor__autoretain">autoretain()</a></dt></h4><dd>
|
<dt><h4><a name="method_ba_Actor__autoretain">autoretain()</a></dt></h4><dd>
|
||||||
<p><span>autoretain(self: T) -> T</span></p>
|
<p><span>autoretain(self: T) -> T</span></p>
|
||||||
@ -627,8 +624,7 @@ their corpse is visible; this is about presence, not being 'alive'
|
|||||||
deleted without affecting the game; this call is often used
|
deleted without affecting the game; this call is often used
|
||||||
when pruning lists of Actors, such as with <a href="#method_ba_Actor__autoretain">ba.Actor.autoretain</a>()</p>
|
when pruning lists of Actors, such as with <a href="#method_ba_Actor__autoretain">ba.Actor.autoretain</a>()</p>
|
||||||
|
|
||||||
<p>The default implementation of this method returns 'node.exists()'
|
<p>The default implementation of this method always return True.</p>
|
||||||
if the Actor has a 'node' attr; otherwise True.</p>
|
|
||||||
|
|
||||||
<p>Note that the boolean operator for the Actor class calls this method,
|
<p>Note that the boolean operator for the Actor class calls this method,
|
||||||
so a simple "if myactor" test will conveniently do the right thing
|
so a simple "if myactor" test will conveniently do the right thing
|
||||||
@ -1106,7 +1102,7 @@ when done.</p>
|
|||||||
<p>Instantiate a Call; pass a callable as the first
|
<p>Instantiate a Call; pass a callable as the first
|
||||||
arg, followed by any number of arguments or keywords.</p>
|
arg, followed by any number of arguments or keywords.</p>
|
||||||
|
|
||||||
<pre><span><em><small># Example: wrap a method call with 1 positional and 1 keyword arg.</small></em></span>
|
<pre><span><em><small># Example: wrap a method call with 1 positional and 1 keyword arg:</small></em></span>
|
||||||
mycall = ba.Call(myobj.dostuff, argval1, namedarg=argval2)</pre>
|
mycall = ba.Call(myobj.dostuff, argval1, namedarg=argval2)</pre>
|
||||||
|
|
||||||
<pre><span><em><small># Now we have a single callable to run that whole mess.</small></em></span>
|
<pre><span><em><small># Now we have a single callable to run that whole mess.</small></em></span>
|
||||||
@ -1345,8 +1341,8 @@ Usage:</strong></p>
|
|||||||
sets the context as current on entry and resets it to the previous
|
sets the context as current on entry and resets it to the previous
|
||||||
value on exit.</p>
|
value on exit.</p>
|
||||||
|
|
||||||
<pre><span><em><small># example: load a few textures into the UI context</small></em></span>
|
<pre><span><em><small># Example: load a few textures into the UI context</small></em></span>
|
||||||
<span><em><small># (for use in widgets, etc)</small></em></span>
|
<span><em><small># (for use in widgets, etc):</small></em></span>
|
||||||
with <a href="#class_ba_Context">ba.Context</a>('ui'):
|
with <a href="#class_ba_Context">ba.Context</a>('ui'):
|
||||||
tex1 = <a href="#function_ba_gettexture">ba.gettexture</a>('foo_tex_1')
|
tex1 = <a href="#function_ba_gettexture">ba.gettexture</a>('foo_tex_1')
|
||||||
tex2 = <a href="#function_ba_gettexture">ba.gettexture</a>('foo_tex_2')</pre>
|
tex2 = <a href="#function_ba_gettexture">ba.gettexture</a>('foo_tex_2')</pre>
|
||||||
@ -3250,7 +3246,7 @@ the two nodes exist. The connection can be severed by setting the
|
|||||||
target attribute to any value or connecting another node attribute
|
target attribute to any value or connecting another node attribute
|
||||||
to it.</p>
|
to it.</p>
|
||||||
|
|
||||||
<pre><span><em><small># example: create a locator and attach a light to it</small></em></span>
|
<pre><span><em><small># Example: create a locator and attach a light to it:</small></em></span>
|
||||||
light = <a href="#function_ba_newnode">ba.newnode</a>('light')
|
light = <a href="#function_ba_newnode">ba.newnode</a>('light')
|
||||||
loc = <a href="#function_ba_newnode">ba.newnode</a>('locator', attrs={'position': (0,10,0)})
|
loc = <a href="#function_ba_newnode">ba.newnode</a>('locator', attrs={'position': (0,10,0)})
|
||||||
loc.connectattr('position', light, 'position')</pre>
|
loc.connectattr('position', light, 'position')</pre>
|
||||||
@ -3311,6 +3307,48 @@ Node-messages communicate directly with the low-level node layer
|
|||||||
and are delivered simultaneously on all game clients,
|
and are delivered simultaneously on all game clients,
|
||||||
acting as an alternative to setting node attributes.</p>
|
acting as an alternative to setting node attributes.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<hr>
|
||||||
|
<h2><strong><a name="class_ba_NodeActor">ba.NodeActor</a></strong></h3>
|
||||||
|
<p>inherits from: <a href="#class_ba_Actor">ba.Actor</a></p>
|
||||||
|
<p>A simple <a href="#class_ba_Actor">ba.Actor</a> type that wraps a single <a href="#class_ba_Node">ba.Node</a>.</p>
|
||||||
|
|
||||||
|
<p>Category: <a href="#class_category_Gameplay_Classes">Gameplay Classes</a></p>
|
||||||
|
|
||||||
|
<p> This Actor will delete its Node when told to die, and it's
|
||||||
|
exists() call will return whether the Node still exists or not.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3>Attributes:</h3>
|
||||||
|
<dl>
|
||||||
|
<dt><h4><a name="attr_ba_NodeActor__activity">activity</a></h4></dt><dd>
|
||||||
|
<p><span><a href="#class_ba_Activity">ba.Activity</a></span></p>
|
||||||
|
<p>The Activity this Actor was created in.</p>
|
||||||
|
|
||||||
|
<p> Raises a <a href="#class_ba_ActivityNotFoundError">ba.ActivityNotFoundError</a> if the Activity no longer exists.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<h3>Methods Inherited:</h3>
|
||||||
|
<h5><a href="#method_ba_Actor__autoretain">autoretain()</a>, <a href="#method_ba_Actor__exists">exists()</a>, <a href="#method_ba_Actor__getactivity">getactivity()</a>, <a href="#method_ba_Actor__is_alive">is_alive()</a>, <a href="#method_ba_Actor__is_expired">is_expired()</a>, <a href="#method_ba_Actor__on_expire">on_expire()</a></h5>
|
||||||
|
<h3>Methods Defined or Overridden:</h3>
|
||||||
|
<h5><a href="#method_ba_NodeActor____init__"><constructor></a>, <a href="#method_ba_NodeActor__handlemessage">handlemessage()</a></h5>
|
||||||
|
<dl>
|
||||||
|
<dt><h4><a name="method_ba_NodeActor____init__"><constructor></a></dt></h4><dd>
|
||||||
|
<p><span>ba.NodeActor(node: <a href="#class_ba_Node">ba.Node</a>)</span></p>
|
||||||
|
|
||||||
|
<p>Instantiates an Actor in the current <a href="#class_ba_Activity">ba.Activity</a>.</p>
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt><h4><a name="method_ba_NodeActor__handlemessage">handlemessage()</a></dt></h4><dd>
|
||||||
|
<p><span>handlemessage(self, msg: Any) -> Any</span></p>
|
||||||
|
|
||||||
|
<p>General message handling; can be passed any <a href="#class_category_Message_Classes">message object</a>.</p>
|
||||||
|
|
||||||
|
<p>The default implementation will handle <a href="#class_ba_DieMessage">ba.DieMessages</a> by
|
||||||
|
calling self.node.delete() if self contains a 'node' attribute.</p>
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<hr>
|
<hr>
|
||||||
@ -4652,7 +4690,7 @@ Real time timers are currently only available in the UI context.</p>
|
|||||||
<p>the 'timeformat' arg defaults to SECONDS but can also be MILLISECONDS
|
<p>the 'timeformat' arg defaults to SECONDS but can also be MILLISECONDS
|
||||||
if you want to pass time as milliseconds.</p>
|
if you want to pass time as milliseconds.</p>
|
||||||
|
|
||||||
<pre><span><em><small># example: use a Timer object to print repeatedly for a few seconds:</small></em></span>
|
<pre><span><em><small># Example: use a Timer object to print repeatedly for a few seconds:</small></em></span>
|
||||||
def say_it():
|
def say_it():
|
||||||
<a href="#function_ba_screenmessage">ba.screenmessage</a>('BADGER!')
|
<a href="#function_ba_screenmessage">ba.screenmessage</a>('BADGER!')
|
||||||
def stop_saying_it():
|
def stop_saying_it():
|
||||||
@ -4817,7 +4855,7 @@ self.t = <a href="#class_ba_Timer">ba.Timer</a>(0.3, say_it, repeat=True)
|
|||||||
<p>Instantiate a WeakCall; pass a callable as the first
|
<p>Instantiate a WeakCall; pass a callable as the first
|
||||||
arg, followed by any number of arguments or keywords.</p>
|
arg, followed by any number of arguments or keywords.</p>
|
||||||
|
|
||||||
<pre><span><em><small># example: wrap a method call with some positional and</small></em></span>
|
<pre><span><em><small># Example: wrap a method call with some positional and</small></em></span>
|
||||||
<span><em><small># keyword args:</small></em></span>
|
<span><em><small># keyword args:</small></em></span>
|
||||||
myweakcall = ba.WeakCall(myobj.dostuff, argval1, namedarg=argval2)</pre>
|
myweakcall = ba.WeakCall(myobj.dostuff, argval1, namedarg=argval2)</pre>
|
||||||
|
|
||||||
@ -5149,6 +5187,11 @@ logs. The call functions by registering the filename and line where
|
|||||||
The call is made from. Returns True if this location has not been
|
The call is made from. Returns True if this location has not been
|
||||||
registered already, and False if it has.</p>
|
registered already, and False if it has.</p>
|
||||||
|
|
||||||
|
<pre><span><em><small># Example: this print will only fire for the first loop iteration:</small></em></span>
|
||||||
|
for i in range(10):
|
||||||
|
if <a href="#function_ba_do_once">ba.do_once</a>():
|
||||||
|
print('Hello once from loop!')</pre>
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
<h2><strong><a name="function_ba_emitfx">ba.emitfx()</a></strong></h3>
|
<h2><strong><a name="function_ba_emitfx">ba.emitfx()</a></strong></h3>
|
||||||
<p><span>emitfx(position: Sequence[float],
|
<p><span>emitfx(position: Sequence[float],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user