Merge branch 'efroemling:master' into master

This commit is contained in:
Vishal 2023-11-30 23:01:17 +05:30 committed by GitHub
commit f2f13b3cc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 155 additions and 71 deletions

56
.efrocachemap generated
View File

@ -4060,26 +4060,26 @@
"build/assets/windows/Win32/ucrtbased.dll": "2def5335207d41b21b9823f6805997f1",
"build/assets/windows/Win32/vc_redist.x86.exe": "b08a55e2e77623fe657bea24f223a3ae",
"build/assets/windows/Win32/vcruntime140d.dll": "865b2af4d1e26a1a8073c89acb06e599",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "d1b736e6185c6a77cabad635afe97d1c",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "93c74c5b4f9b7f528b0802aa7a23f677",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "36cba560a8171836dd7c9c6ff0ef9218",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "6e1d80e717d34d8594588d22a002e8f9",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "36a88b7c6b86f1acdd32ee4651496297",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "86399e9fed0bd310390595036e5a2567",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "f359b4e02f83e4aa04d7d0165b864de8",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "e244e4b6e699ccf65ccde669153290df",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d31b4e34e21c25455380afa50ecf0fe7",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "3d1d0b4dd7df23c3c7e9958286211229",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "de5e043bf03efece2aa8a9ab3362749e",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "3bd9856b27825995919c9d0bbe6809cb",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "4e58688f6d42481fa175d6f0d43f8ab7",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "a05c25cdef7d3e81067c9645136a7b77",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "5501e98f9cea647b25a3702e26da5b31",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "8ef08bf21aeef91beecce31b79661a1a",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "51318d5ab8b474a01466eed83b8d9553",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "ea7ab32e245bb804cd09c9d111a7c10b",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "caabdfd17f1df3608a68cc96315ed4d5",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "8a9ed3e4672af09f5ea1b81d59dfb84f",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "9fe23e06319e4e256b9fa88814a14afa",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "4306acae21ce88235f9d1589086866e7",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "75e4f7d3a3df67dedd079ec3f4441094",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "bd5eda13f239b81886ac80596d6ade73",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "0805235a92dd91f96d43ea54575eecac",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "07589a61b11cbc5fca0bbc8b7fc1c955",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "f28629761060c8152168b6792b71adae",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "1cfd1a33474cdb31834994f626385ed0",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "d50879a92d9d344c376f6f196d78d1be",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "78cd0edf2698f197f2acd80ca364fae7",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "d656f47118ebc3af57c40423cb258bc8",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "75df540b27779342a7c696e1bdbe593f",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "76f0dfacaa9ea67e45e8ccf3bb3bc1c6",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "2acc754bed825a9265e0621dc09899e0",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "62c2b6190de8784ea8750ea50e6a2304",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "e57358fd9a948a8ce82a54cdd5c766fc",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "d36e3303e13049eae5e7ec19861d300e",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "46971a2ca1e3021e52ea5d0f4938d2ff",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "19ebd36613cf62c4bd50e70b93371368",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "49ef5905b6e9e1a9caaed3d1c1da4ea5",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "c22901e06e88a55cce0b4e08bbf41a4c",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "a27963487e346338e4c216bd4fbb9e2a",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "c22901e06e88a55cce0b4e08bbf41a4c",
@ -4096,14 +4096,14 @@
"build/prefab/lib/mac_x86_64_gui/release/libballisticaplus.a": "852fe46c736082611a831a618923c241",
"build/prefab/lib/mac_x86_64_server/debug/libballisticaplus.a": "36fbda7829ed5c2862c34feb09b03402",
"build/prefab/lib/mac_x86_64_server/release/libballisticaplus.a": "852fe46c736082611a831a618923c241",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "23dbca6f6f4c8b9061e68af17d79791b",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "639bb72656fb6f5b21ac525b9098854a",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "d0a0820657e11771d1e393d47af23c17",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "62f9d32dcc6c74421f1a3f88abf07777",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "2d38cd1723c7b1a9a1b19d206d5a17a5",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "8e4304d0b16fa16038fc1660eb06c350",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "08120b7a6b3845cf729c1defcc6e90ec",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "f5d59b0bce6cb0e43da92a5863bb963c",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.lib": "38b4b5b85a9bafdb76222d0f0c962b06",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitGenericPlus.pdb": "9a8af3d217bcb0bacfaed4c30dd5f42e",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.lib": "6d10ca306f60d66efb4942636e4955d6",
"build/prefab/lib/windows/Debug_Win32/BallisticaKitHeadlessPlus.pdb": "1c65d36e4420ed79380dc8c041c94a8b",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.lib": "9b1b72f3d41c89a6b06288be63e8f40a",
"build/prefab/lib/windows/Release_Win32/BallisticaKitGenericPlus.pdb": "e0f2eb8ea024bc88e999b9dc16317fd4",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.lib": "42be1225757328f432d91de950444ba0",
"build/prefab/lib/windows/Release_Win32/BallisticaKitHeadlessPlus.pdb": "05bc2832cc0c9fba308668fc1a6d3b0f",
"src/assets/ba_data/python/babase/_mgen/__init__.py": "f885fed7f2ed98ff2ba271f9dbe3391c",
"src/assets/ba_data/python/babase/_mgen/enums.py": "28323912b56ec07701eda3d41a6a4101",
"src/ballistica/base/mgen/pyembed/binding_base.inc": "72bfed2cce8ff19741989dec28302f3f",

View File

@ -1,4 +1,4 @@
### 1.7.30 (build 21630, api 8, 2023-11-29)
### 1.7.30 (build 21636, api 8, 2023-11-30)
- Continued work on the big 1.7.28 update.
- Got the Android version back up and running. There's been lots of cleanup and
simplification on the Android layer, cleaning out years of cruft. This should
@ -19,6 +19,11 @@
effects such as the app continuing to play audio when it should not be.
- (build 21626) Fixed a bug where click/tap locations were incorrect on some
builds when tv-border was on (Thanks for the heads-up Loup(Dliwk's fan)!).
- (build 21631) Fixes an issue where '^^^^^^^^^^^^^' lines in stack traces could
get chopped into tiny bits each on their own line in the dev console.
- Fixed a longstanding issue where multiple key presses simultaneously could
cause multiple windows to pop up where only one is expected. Please holler if
you still see this problem happening anywhere.
### 1.7.29 (build 21619, api 8, 2023-11-21)

View File

@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
TARGET_BALLISTICA_BUILD = 21630
TARGET_BALLISTICA_BUILD = 21636
TARGET_BALLISTICA_VERSION = '1.7.30'

View File

@ -311,8 +311,8 @@ class MainMenuWindow(bui.Window):
else self._confirm_end_game
),
)
# Assume we're in a client-session.
else:
# Assume we're in a client-session.
bui.buttonwidget(
parent=self._root_widget,
position=(h - self._button_width * 0.5 * scale, v),
@ -360,7 +360,6 @@ class MainMenuWindow(bui.Window):
tilt_scale=0.0,
draw_controller=store_button,
)
self._tdelay += self._t_delay_inc
else:
self._store_button = None

View File

@ -615,7 +615,7 @@ void Graphics::FadeScreen(bool to, millisecs_t time, PyObject* endcall) {
Log(LogLevel::kWarning,
"2 fades overlapping; running first fade-end-call early.");
}
fade_end_call_->Schedule();
fade_end_call_->ScheduleOnce();
fade_end_call_.Clear();
}
set_fade_start_on_next_draw_ = true;
@ -1021,7 +1021,7 @@ void Graphics::DrawFades(FrameDef* frame_def) {
} else {
fade_ = 0;
if (!was_done && fade_end_call_.Exists()) {
fade_end_call_->Schedule();
fade_end_call_->ScheduleOnce();
fade_end_call_.Clear();
}
}

View File

@ -279,7 +279,7 @@ static auto PyPushCall(PyObject* self, PyObject* args, PyObject* keywds)
if (!g_base->InLogicThread()) {
throw Exception("You must use from_other_thread mode.");
}
Object::New<PythonContextCall>(call_obj)->Schedule();
Object::New<PythonContextCall>(call_obj)->ScheduleOnce();
}
Py_RETURN_NONE;
BA_PYTHON_CATCH;

View File

@ -125,45 +125,83 @@ void PythonContextCall::Schedule() {
Object::Ref<PythonContextCall> ref(this);
assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref] {
assert(ref.Exists());
ref->schedule_count_--;
assert(ref->schedule_count_ >= 0);
ref->Run();
});
}
void PythonContextCall::ScheduleOnce() {
if (schedule_count_ > 0) {
return;
}
Schedule();
}
void PythonContextCall::Schedule(const PythonRef& args) {
// Since we're mucking with Object::Refs, need to limit to logic thread.
BA_PRECONDITION(g_base->InLogicThread());
Object::Ref<PythonContextCall> ref(this);
assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref, args] {
assert(ref.Exists());
ref->schedule_count_--;
assert(ref->schedule_count_ >= 0);
ref->Run(args);
});
}
void PythonContextCall::ScheduleOnce(const PythonRef& args) {
if (schedule_count_ > 0) {
return;
}
Schedule(args);
}
void PythonContextCall::ScheduleWeak() {
// Since we're mucking with Object::WeakRefs, need to limit to logic thread.
BA_PRECONDITION(g_base->InLogicThread());
Object::WeakRef<PythonContextCall> ref(this);
assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref] {
if (auto* call = ref.Get()) {
call->schedule_count_--;
assert(call->schedule_count_ >= 0);
call->Run();
}
});
}
void PythonContextCall::ScheduleWeakOnce() {
if (schedule_count_ > 0) {
return;
}
ScheduleWeak();
}
void PythonContextCall::ScheduleWeak(const PythonRef& args) {
// Since we're mucking with Object::WeakRefs, need to limit to logic thread.
BA_PRECONDITION(g_base->InLogicThread());
Object::WeakRef<PythonContextCall> ref(this);
assert(base::g_base);
schedule_count_++;
base::g_base->logic->event_loop()->PushCall([ref, args] {
if (auto* call = ref.Get()) {
call->schedule_count_--;
assert(call->schedule_count_ >= 0);
call->Run(args);
}
});
}
void PythonContextCall::ScheduleWeakOnce(const PythonRef& args) {
if (schedule_count_ > 0) {
return;
}
ScheduleWeak(args);
}
} // namespace ballistica::base

View File

@ -11,10 +11,10 @@
namespace ballistica::base {
// A callable and ballistica context-state wrapped up in a convenient package.
// Handy for use with user-submitted callbacks, as it restores context
// state from when it was created and prints various useful bits of context
// info on exceptions.
// A callable and ballistica context-state wrapped up in a convenient
// package. Handy for use with user-submitted callbacks, as it restores
// context state from when it was created and prints various useful bits of
// context info on exceptions.
class PythonContextCall : public Object {
public:
static auto current_call() -> PythonContextCall* { return current_call_; }
@ -37,35 +37,65 @@ class PythonContextCall : public Object {
auto file_loc() const -> const std::string& { return file_loc_; }
void PrintContext();
/// Run in an upcoming cycle of the logic thread.
/// Must be called from the logic thread.
/// This form creates a strong-reference so the context_ref-call is guaranteed
/// to exist until run.
/// Run in an upcoming cycle of the logic thread. Must be called from the
/// logic thread. This form creates a strong-reference so the
/// context_ref-call is guaranteed to exist until run.
void Schedule();
/// Run in an upcoming cycle of the logic thread with provided args.
/// Must be called from the logic thread.
/// This form creates a strong-reference so the context_ref-call is guaranteed
/// to exist until run.
/// Schedule only if this instance is not already scheduled. Generally a
/// good idea unless you know you need multiple runs scheduled. Avoids
/// problems such as UIs expecting to be activated only once getting
/// activated twice due to two simultenous key presses.
void ScheduleOnce();
/// Run in an upcoming cycle of the logic thread with provided args. Must
/// be called from the logic thread. This form creates a strong-reference
/// so the context_ref-call is guaranteed to exist until run.
void Schedule(const PythonRef& args);
/// Run in an upcoming cycle of the logic thread.
/// Must be called from the logic thread.
/// This form creates a weak-reference and is a no-op if the context_ref-call
/// is destroyed before its scheduled run.
/// Schedule only if this instance is not already scheduled. Generally a
/// good idea unless you know you need multiple runs scheduled. Avoids
/// problems such as UIs expecting to be activated only once getting
/// activated twice due to two simultenous key presses.
void ScheduleOnce(const PythonRef& args);
/// Run in an upcoming cycle of the logic thread. Must be called from the
/// logic thread. This form creates a weak-reference and is a no-op if the
/// context_ref-call is destroyed before its scheduled run.
void ScheduleWeak();
/// Run in an upcoming cycle of the logic thread with provided args.
/// Must be called from the logic thread.
/// This form creates a weak-reference and is a no-op if the context_ref-call
/// is destroyed before its scheduled run.
/// Schedule weakly only if this instance is not already scheduled.
/// Generally a good idea unless you know you need multiple runs
/// scheduled. Avoids problems such as UIs expecting to be activated only
/// once getting activated twice due to two simultenous key presses.
void ScheduleWeakOnce();
/// Run in an upcoming cycle of the logic thread with provided args. Must
/// be called from the logic thread. This form creates a weak-reference
/// and is a no-op if the context_ref-call is destroyed before its
/// scheduled run.
void ScheduleWeak(const PythonRef& args);
/// Schedule weakly only if this instance is not already scheduled.
/// Generally a good idea unless you know you need multiple runs
/// scheduled. Avoids problems such as UIs expecting to be activated only
/// once getting activated twice due to two simultenous key presses.
void ScheduleWeakOnce(const PythonRef& args);
auto IsScheduled() const {
assert(g_base->InLogicThread());
return schedule_count_ > 0;
}
private:
void GetTrace(); // we try to grab basic trace info
std::string file_loc_;
int line_{};
bool dead_ = false;
int schedule_count_{};
bool dead_{};
std::string file_loc_;
PythonRef object_;
base::ContextRef context_state_;
// base::Context* context_target_sanity_test_{};
static PythonContextCall* current_call_;
};

View File

@ -39,7 +39,7 @@ auto main(int argc, char** argv) -> int {
namespace ballistica {
// These are set automatically via script; don't modify them here.
const int kEngineBuildNumber = 21630;
const int kEngineBuildNumber = 21636;
const char* kEngineVersion = "1.7.30";
const int kEngineApiVersion = 8;

View File

@ -115,7 +115,7 @@ void UIV1Python::InvokeStringEditor(PyObject* string_edit_adapter_instance) {
PythonRef::kSteal);
Object::New<base::PythonContextCall>(
objs().Get(ObjID::kOnScreenKeyboardClass))
->Schedule(args);
->ScheduleOnce(args);
}
void UIV1Python::LaunchStringEditOld(TextWidget* w) {
@ -131,7 +131,7 @@ void UIV1Python::LaunchStringEditOld(TextWidget* w) {
PythonRef::kSteal);
Object::New<base::PythonContextCall>(
objs().Get(ObjID::kOnScreenKeyboardClass))
->Schedule(args);
->ScheduleOnce(args);
}
void UIV1Python::InvokeQuitWindow(QuitType quit_type) {

View File

@ -562,7 +562,7 @@ void ButtonWidget::DoActivate(bool is_repeat) {
if (auto* call = on_activate_call_.Get()) {
// Call this in the next cycle (don't want to risk mucking with UI from
// within a UI loop.)
call->ScheduleWeak();
call->ScheduleWeakOnce();
return;
}
}

View File

@ -247,7 +247,7 @@ void CheckBoxWidget::Activate() {
// Call this in the next cycle (don't want to risk mucking with UI from
// within a UI loop)
call->ScheduleWeak(args);
call->ScheduleWeakOnce(args);
}
}

View File

@ -347,7 +347,7 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
// Call this in the next cycle (don't wanna risk mucking with UI from
// within a UI loop).
call->ScheduleWeak();
call->ScheduleWeakOnce();
} else {
OnCancelCustom();
}
@ -631,7 +631,7 @@ auto ContainerWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
if (!claimed && on_outside_click_call_.Exists()) {
// Call this in the next cycle (don't wanna risk mucking with UI from
// within a UI loop).
on_outside_click_call_->ScheduleWeak();
on_outside_click_call_->ScheduleWeakOnce();
}
// Always claim if they want.
@ -1071,7 +1071,7 @@ void ContainerWidget::Activate() {
if (auto* call = on_activate_call_.Get()) {
// Call this in the next cycle (don't wanna risk mucking with UI from within
// a UI loop).
call->ScheduleWeak();
call->ScheduleWeakOnce();
}
}
@ -1182,6 +1182,7 @@ void ContainerWidget::SetTransition(TransitionType t) {
dynamics_update_time_millisecs_ = display_time_millisecs;
transitioning_ = true;
transitioning_out_ = true;
ignore_input_ = true;
} else {
// Calculate the screen size in our own local space - we'll
// animate an offset to slide on/off screen.

View File

@ -592,7 +592,7 @@ void TextWidget::Activate() {
if (auto* call = on_activate_call_.Get()) {
// Call this in the next cycle (don't wanna risk mucking with UI from
// within a UI loop).
call->ScheduleWeak();
call->ScheduleWeakOnce();
}
// Bring up an editor if applicable.
@ -720,7 +720,7 @@ auto TextWidget::HandleMessage(const base::WidgetMessage& m) -> bool {
claimed = true;
// Call this in the next cycle (don't wanna risk mucking with UI
// from within a UI loop)
call->ScheduleWeak();
call->ScheduleWeakOnce();
}
}
break;

View File

@ -88,7 +88,7 @@ void Widget::SetSelected(bool s, SelectionCause cause) {
if (selected_ && on_select_call_.Exists()) {
// Call this in the next cycle (don't wanna risk mucking
// with UI from within a UI loop).
on_select_call_->ScheduleWeak();
on_select_call_->ScheduleWeakOnce();
}
}

View File

@ -450,6 +450,11 @@ class LogHandler(logging.Handler):
def file_write(self, name: str, output: str) -> None:
"""Send raw stdout/stderr output to the logger to be collated."""
# Note to self: it turns out that things like '^^^^^^^^^^^^^^'
# lines in stack traces get written as lots of individual '^'
# writes. It feels a bit dirty to be pushing a deferred call to
# another thread for each character. Perhaps should do some sort
# of basic accumulation here?
self._event_loop.call_soon_threadsafe(
tpartial(self._file_write_in_thread, name, output)
)
@ -509,12 +514,18 @@ class LogHandler(logging.Handler):
traceback.print_exc(file=self._echofile)
async def _ship_chunks_task(self, name: str) -> None:
# Note: it's important we sleep here for a moment. Otherwise,
# things like '^^^^^^^^^^^^' lines in stack traces, which come
# through as lots of individual '^' writes, tend to get broken
# into lots of tiny little lines by us.
await asyncio.sleep(0.01)
self._ship_file_chunks(name, cancel_ship_task=False)
def _ship_file_chunks(self, name: str, cancel_ship_task: bool) -> None:
# Note: Raw print input generally ends in a newline, but that is
# redundant when we break things into log entries and results
# in extra empty lines. So strip off a single trailing newline.
# redundant when we break things into log entries and results in
# extra empty lines. So strip off a single trailing newline if
# one is present.
text = ''.join(self._file_chunks[name]).removesuffix('\n')
self._emit_entry(