added text widgets to dev-console tabs python api

This commit is contained in:
Eric 2023-10-02 19:12:41 -07:00
parent d85ac6a160
commit 9fcc313b0b
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
9 changed files with 321 additions and 124 deletions

40
.efrocachemap generated
View File

@ -4056,26 +4056,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": "5979fc1374865abb96a8ff2e3f44c166",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "b389b9d4d3cac1d18dc6c04d266d444e",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "9446081855fe37326f970d0ab43e2e59",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "1527bc05d69edeb8af30c6ab25b928f0",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "c57b7f45564dd7cbb3f25c28266a5a3a",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "54911f2b25836bf38f8a33e306dcdee2",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "9f887dfab9eb196ee8a9ff5d7f876139",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "7f89a9b77feb1cde4ba611f4dd8bb444",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "b52a34026a36769640de84ae94ac94d3",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "3c90aa7a5828921da6fa2d1b0242c76a",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "f057fa1a420d0d23e6a5ccfa29a5cd2b",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "24ca0d3ddbe3c45870de1167cd92459a",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "eddb8691d13480b147baf732428139ca",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "9b276bef34a259e05c23391fa3d372a6",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "789d66ae2c844d81f3d4929cc6caf950",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "9fe031c292167461bd8790f11c1b78c6",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "461d3623b1d047a81000bf91f2b5095d",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "57fa8e653ccd0625fa6a95ba7cbcc089",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "7c9ef4e375fcfa593ea8ebdb2cb59f8e",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "d6e492d84f592d0547878c7de8b60e35",
"build/prefab/full/linux_arm64_gui/debug/ballisticakit": "53125d7d6bd34fdfe78880773272237b",
"build/prefab/full/linux_arm64_gui/release/ballisticakit": "804a8aa64c159a3812a31be3df3584b1",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "655d8bc1d591917d7bbec7ffed98a5a7",
"build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "9830f4dac6f35121b19db8e2f332d87c",
"build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "7a360065ea427f2d44f1db6d550becfb",
"build/prefab/full/linux_x86_64_gui/release/ballisticakit": "dd5b6769d2e95c93aae7126c8bdd3ffe",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "791b43e652365874eb136b7ec147f9e8",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "8d3fe48c1a1b601aa97ce33e892f5163",
"build/prefab/full/mac_arm64_gui/debug/ballisticakit": "12d92655438f34e912e1525991df1f73",
"build/prefab/full/mac_arm64_gui/release/ballisticakit": "e39556a0047b65919b61c740e096e967",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "ae3a622c7fe0bddc6badba38402284fd",
"build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "1e744c3641f603e22b55882f96fb0a86",
"build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "bcbb650a041317c7788a31525a7c2d02",
"build/prefab/full/mac_x86_64_gui/release/ballisticakit": "a84d2e36cb685224749f556d5ba857a5",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "beeecfee397c12e4c7193391973873f7",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "f186772de8396573ca7daa4f765ac63a",
"build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "ada072c442da241991d2de9ad35abf79",
"build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "52a2e2a3bd751f941069d4d007d7bc59",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "82d428e93227eafc8c8ffcb6e24d1ec0",
"build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "567cac9a0ba532234fedb35a9bdd51a3",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "6ce4983e76e1cc2d2803fe306d08ad58",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "4ea0cf78901f994215f215aebb0af1dc",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "6ce4983e76e1cc2d2803fe306d08ad58",

View File

@ -1,4 +1,4 @@
### 1.7.28 (build 21406, api 8, 2023-10-02)
### 1.7.28 (build 21407, api 8, 2023-10-02)
- Massively cleaned up code related to rendering and window systems (OpenGL,
SDL, etc). This code had been growing into a nasty tangle for 15 years
@ -37,6 +37,9 @@
etc.)
- The in-app Python console text is now sized up on phone and tablet devices,
and is generally a bit larger everywhere.
- Added an API to define DevConsole tabs via Python. Currently it supports basic
buttons and text, but should be easy to expand to whatever we need. See
`babase/_devconsole.py`. It should be easy to define new tabs via plugins/etc.
- Cleaned up onscreen keyboard support and generalized it to make it possible to
support other things besides widgets and to make it easier to implement on
other platforms.

View File

@ -49,6 +49,21 @@ class DevConsoleTab:
style,
)
def text(
self,
text: str,
pos: tuple[float, float],
h_anchor: Literal['left', 'center', 'right'] = 'center',
h_align: Literal['left', 'center', 'right'] = 'center',
v_align: Literal['top', 'center', 'bottom', 'none'] = 'center',
scale: float = 1.0,
) -> None:
"""Add a button to the tab being refreshed."""
assert _babase.app.devconsole.is_refreshing
_babase.dev_console_add_text(
text, pos[0], pos[1], h_anchor, h_align, v_align, scale
)
def python_terminal(self) -> None:
"""Add a Python Terminal to the tab being refreshed."""
assert _babase.app.devconsole.is_refreshing
@ -95,6 +110,7 @@ class DevConsoleTabTest(DevConsoleTab):
pos=(10, 10),
size=(100, 30),
h_anchor='left',
label_scale=0.6,
call=self.request_refresh,
)
self.button(
@ -102,8 +118,17 @@ class DevConsoleTabTest(DevConsoleTab):
pos=(120, 10),
size=(100, 30),
h_anchor='left',
label_scale=0.6,
style='dark',
)
self.text(
'TestText',
scale=0.8,
pos=(15, 50),
h_anchor='left',
h_align='left',
v_align='none',
)
@dataclass
@ -115,7 +140,15 @@ class DevConsoleTabEntry:
class DevConsoleSubsystem:
"""Wrangles the dev console."""
"""Subsystem for wrangling the dev console.
The single instance of this class can be found at
babase.app.devconsole. The dev-console is a simple always-available
UI intended for use by developers; not end users. Traditionally it
is available by typing a backtick (`) key on a keyboard, but now can
be accessed via an on-screen button (see settings/advanced to enable
said button).
"""
def __init__(self) -> None:
# All tabs in the dev-console. Add your own stuff here via

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 = 21406
TARGET_BALLISTICA_BUILD = 21407
TARGET_BALLISTICA_VERSION = '1.7.28'

View File

@ -1501,6 +1501,48 @@ static PyMethodDef PyDevConsoleAddButtonDef = {
"(internal)",
};
// ------------------------- dev_console_add_text ------------------------------
static auto PyDevConsoleAddText(PyObject* self, PyObject* args) -> PyObject* {
BA_PYTHON_TRY;
BA_PRECONDITION(g_base->InLogicThread());
auto* dev_console = g_base->ui->dev_console();
BA_PRECONDITION(dev_console);
BA_PRECONDITION(dev_console->IsActive());
const char* text;
float x;
float y;
const char* h_anchor;
const char* h_align;
const char* v_align;
float scale;
if (!PyArg_ParseTuple(args, "sffsssf", &text, &x, &y, &h_anchor, &h_align,
&v_align, &scale)) {
return nullptr;
}
dev_console->AddText(text, x, y, h_anchor, h_align, v_align, scale);
Py_RETURN_NONE;
BA_PYTHON_CATCH;
}
static PyMethodDef PyDevConsoleAddTextDef = {
"dev_console_add_text", // name
(PyCFunction)PyDevConsoleAddText, // method
METH_VARARGS, // flags
"dev_console_add_text(\n"
" text: str,\n"
" x: float,\n"
" y: float,\n"
" h_anchor: str,\n"
" h_align: str,\n"
" v_align: str,\n"
" scale: float,\n"
") -> None\n"
"\n"
"(internal)",
};
// -------------------- dev_console_add_python_terminal ------------------------
static auto PyDevConsoleAddPythonTerminal(PyObject* self, PyObject* args)
@ -1673,6 +1715,7 @@ auto PythonMethodsMisc::GetMethods() -> std::vector<PyMethodDef> {
PyOpenDirExternallyDef,
PyFatalErrorDef,
PyDevConsoleAddButtonDef,
PyDevConsoleAddTextDef,
PyDevConsoleAddPythonTerminalDef,
PyDevConsoleTabWidthDef,
PyDevConsoleTabHeightDef,

View File

@ -31,44 +31,102 @@ const int kDevConsoleActivateKey1 = SDLK_BACKQUOTE;
const int kDevConsoleActivateKey2 = SDLK_F2;
const float kDevConsoleTabButtonCornerRadius{16.0f};
const double kTransitionSeconds = 0.1;
const double kTransitionSeconds = 0.15;
enum class DevButtonAttach_ { kLeft, kCenter, kRight };
enum class DevConsoleHAnchor_ { kLeft, kCenter, kRight };
enum class DevButtonStyle_ { kNormal, kDark };
static auto XOffs(DevButtonAttach_ attach) -> float {
static auto DevButtonStyleFromStr_(const char* strval) {
if (!strcmp(strval, "dark")) {
return DevButtonStyle_::kDark;
}
assert(!strcmp(strval, "normal"));
return DevButtonStyle_::kNormal;
}
static auto DevConsoleHAttachFromStr_(const char* strval) {
if (!strcmp(strval, "left")) {
return DevConsoleHAnchor_::kLeft;
} else if (!strcmp(strval, "right")) {
return DevConsoleHAnchor_::kRight;
}
assert(!strcmp(strval, "center"));
return DevConsoleHAnchor_::kCenter;
}
static auto TextMeshHAlignFromStr_(const char* strval) {
if (!strcmp(strval, "left")) {
return TextMesh::HAlign::kLeft;
} else if (!strcmp(strval, "right")) {
return TextMesh::HAlign::kRight;
}
assert(!strcmp(strval, "center"));
return TextMesh::HAlign::kCenter;
}
static auto TextMeshVAlignFromStr_(const char* strval) {
if (!strcmp(strval, "top")) {
return TextMesh::VAlign::kTop;
} else if (!strcmp(strval, "bottom")) {
return TextMesh::VAlign::kBottom;
} else if (!strcmp(strval, "none")) {
return TextMesh::VAlign::kNone;
}
assert(!strcmp(strval, "center"));
return TextMesh::VAlign::kCenter;
}
static auto XOffs(DevConsoleHAnchor_ attach) -> float {
switch (attach) {
case DevButtonAttach_::kLeft:
case DevConsoleHAnchor_::kLeft:
return 0.0f;
case DevButtonAttach_::kRight:
case DevConsoleHAnchor_::kRight:
return g_base->graphics->screen_virtual_width();
case DevButtonAttach_::kCenter:
case DevConsoleHAnchor_::kCenter:
return g_base->graphics->screen_virtual_width() * 0.5f;
}
assert(false);
return 0.0f;
}
static void DrawBasicButton(RenderPass* pass, Mesh* mesh, TextGroup* tgrp,
float tscale, float bottom, float x, float y,
float width, float height, const Vector3f& fgcolor,
const Vector3f& bgcolor) {
static void DrawRect(RenderPass* pass, Mesh* mesh, float bottom, float x,
float y, float width, float height,
const Vector3f& bgcolor) {
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetColor(bgcolor.x, bgcolor.y, bgcolor.z, 1.0f);
c.SetTexture(g_base->assets->SysTexture(SysTextureID::kCircle));
{
// Draw mesh bg.
if (mesh) {
auto xf = c.ScopedTransform();
c.Translate(x, y + bottom, kDevConsoleZDepth);
c.DrawMesh(mesh);
}
// Draw our text.
// Draw text.
// {
// auto xf = c.ScopedTransform();
// c.Translate(x + width * 0.5f, y + bottom + height * 0.5f,
// kDevConsoleZDepth);
// c.Scale(tscale, tscale, 1.0f);
// int elem_count = tgrp->GetElementCount();
// c.SetColor(fgcolor.x, fgcolor.y, fgcolor.z, 1.0f);
// c.SetFlatness(1.0f);
// for (int e = 0; e < elem_count; e++) {
// c.SetTexture(tgrp->GetElementTexture(e));
// c.DrawMesh(tgrp->GetElementMesh(e));
// }
// }
}
static void DrawText(RenderPass* pass, TextGroup* tgrp, float tscale,
float bottom, float x, float y, const Vector3f& fgcolor) {
SimpleComponent c(pass);
c.SetTransparent(true);
// Draw text.
{
auto xf = c.ScopedTransform();
c.Translate(x + width * 0.5f, y + bottom + height * 0.5f,
kDevConsoleZDepth);
float sc{0.6f * tscale};
c.Scale(sc, sc, 1.0f);
c.Translate(x, y + bottom, kDevConsoleZDepth);
c.Scale(tscale, tscale, 1.0f);
int elem_count = tgrp->GetElementCount();
c.SetColor(fgcolor.x, fgcolor.y, fgcolor.z, 1.0f);
c.SetFlatness(1.0f);
@ -84,14 +142,46 @@ static void DrawBasicButton(RenderPass* pass, Mesh* mesh, TextGroup* tgrp,
class DevConsole::Widget_ {
public:
virtual ~Widget_() = default;
virtual auto HandleMouseDown(float mx, float my) -> bool = 0;
virtual void HandleMouseUp(float mx, float my) = 0;
virtual auto HandleMouseDown(float mx, float my) -> bool { return false; }
virtual void HandleMouseUp(float mx, float my) {}
virtual void Draw(RenderPass* pass, float bottom) = 0;
};
class DevConsole::Text_ : public DevConsole::Widget_ {
public:
DevConsoleHAnchor_ h_attach;
TextMesh::HAlign h_align;
TextMesh::VAlign v_align;
float x;
float y;
float scale;
TextGroup text_group;
DevButtonStyle_ style;
Text_(const std::string& text, float x, float y, DevConsoleHAnchor_ h_attach,
TextMesh::HAlign h_align, TextMesh::VAlign v_align, float scale)
: h_attach{h_attach},
h_align(h_align),
v_align(v_align),
x{x},
y{y},
scale{scale} {
text_group.SetText(text, h_align, v_align);
}
void Draw(RenderPass* pass, float bottom) override {
Vector3f fgcolor;
Vector3f bgcolor;
fgcolor = Vector3f{0.8f, 0.7f, 0.8f};
bgcolor = Vector3f{0.25, 0.2f, 0.3f};
DrawText(pass, &text_group, scale, bottom, x + XOffs(h_attach), y, fgcolor);
}
};
class DevConsole::Button_ : public DevConsole::Widget_ {
public:
DevButtonAttach_ attach;
DevConsoleHAnchor_ attach;
float x;
float y;
float width;
@ -104,7 +194,7 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
DevButtonStyle_ style;
template <typename F>
Button_(const std::string& label, float text_scale, DevButtonAttach_ attach,
Button_(const std::string& label, float text_scale, DevConsoleHAnchor_ attach,
float x, float y, float width, float height, float corner_radius,
DevButtonStyle_ style, const F& lambda)
: attach{attach},
@ -165,14 +255,15 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
bgcolor =
pressed ? Vector3f{0.8f, 0.7f, 0.8f} : Vector3f{0.25, 0.2f, 0.3f};
}
DrawBasicButton(pass, &mesh, &text_group, text_scale, bottom,
x + XOffs(attach), y, width, height, fgcolor, bgcolor);
DrawRect(pass, &mesh, bottom, x + XOffs(attach), y, width, height, bgcolor);
DrawText(pass, &text_group, text_scale, bottom,
x + XOffs(attach) + width * 0.5f, y + height * 0.5f, fgcolor);
}
};
class DevConsole::ToggleButton_ : public DevConsole::Widget_ {
public:
DevButtonAttach_ attach;
DevConsoleHAnchor_ attach;
float x;
float y;
float width;
@ -187,7 +278,7 @@ class DevConsole::ToggleButton_ : public DevConsole::Widget_ {
template <typename F, typename G>
ToggleButton_(const std::string& label, float text_scale,
DevButtonAttach_ attach, float x, float y, float width,
DevConsoleHAnchor_ attach, float x, float y, float width,
float height, float corner_radius, const F& on_call,
const G& off_call)
: attach{attach},
@ -234,20 +325,22 @@ class DevConsole::ToggleButton_ : public DevConsole::Widget_ {
}
void Draw(RenderPass* pass, float bottom) override {
DrawBasicButton(pass, &mesh, &text_group, text_scale, bottom,
x + XOffs(attach), y, width, height,
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
: on ? Vector3f{1.0f, 1.0f, 1.0f}
: Vector3f{0.8f, 0.7f, 0.8f},
pressed ? Vector3f{0.5f, 0.2f, 1.0f}
: on ? Vector3f{0.5f, 0.4f, 0.6f}
: Vector3f{0.25, 0.2f, 0.3f});
DrawRect(pass, &mesh, bottom, x + XOffs(attach), y, width, height,
pressed ? Vector3f{0.5f, 0.2f, 1.0f}
: on ? Vector3f{0.5f, 0.4f, 0.6f}
: Vector3f{0.25, 0.2f, 0.3f});
DrawText(pass, &text_group, text_scale, bottom,
x + XOffs(attach) + width * 0.5f, y + height * 0.5f,
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
: on ? Vector3f{1.0f, 1.0f, 1.0f}
: Vector3f{0.8f, 0.7f, 0.8f});
}
};
class DevConsole::TabButton_ : public DevConsole::Widget_ {
public:
DevButtonAttach_ attach;
DevConsoleHAnchor_ attach;
float x;
float y;
float width;
@ -261,7 +354,7 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
template <typename F>
TabButton_(const std::string& label, bool selected, float text_scale,
DevButtonAttach_ attach, float x, float y, float width,
DevConsoleHAnchor_ attach, float x, float y, float width,
float height, const F& call)
: attach{attach},
x{x},
@ -308,15 +401,15 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
}
void Draw(RenderPass* pass, float bottom) override {
DrawBasicButton(pass, &mesh, &text_group, text_scale, bottom,
x + XOffs(attach), y, width, height,
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
: selected ? Vector3f{1.0f, 1.0f, 1.0f}
: Vector3f{0.6f, 0.5f, 0.6f},
pressed ? Vector3f{0.4f, 0.2f, 0.8f}
: selected ? Vector3f{0.4f, 0.3f, 0.4f}
// : selected ? Vector3f{0.5f, 0.4f, 0.6f}
: Vector3f{0.25, 0.2f, 0.3f});
DrawRect(pass, &mesh, bottom, x + XOffs(attach), y, width, height,
pressed ? Vector3f{0.4f, 0.2f, 0.8f}
: selected ? Vector3f{0.4f, 0.3f, 0.4f}
: Vector3f{0.25, 0.2f, 0.3f});
DrawText(pass, &text_group, text_scale, bottom,
x + XOffs(attach) + width * 0.5f, y + height * 0.5f,
pressed ? Vector3f{1.0f, 1.0f, 1.0f}
: selected ? Vector3f{1.0f, 1.0f, 1.0f}
: Vector3f{0.6f, 0.5f, 0.6f});
}
};
@ -381,13 +474,13 @@ void DevConsole::RefreshTabButtons_() {
float bs = BaseScale();
float bwidth = 90.0f * bs;
float bheight = 26.0f * bs;
float bscale = 0.8f * bs;
float bscale = 0.6f * bs;
float total_width = tabs_.size() * bwidth;
float x = total_width * -0.5f;
for (auto&& tab : tabs_) {
tab_buttons_.emplace_back(std::make_unique<TabButton_>(
tab, active_tab_ == tab, bscale, DevButtonAttach_::kCenter, x, -bheight,
bwidth, bheight, [this, tab] {
tab, active_tab_ == tab, bscale, DevConsoleHAnchor_::kCenter, x,
-bheight, bwidth, bheight, [this, tab] {
active_tab_ = tab;
RefreshTabButtons_();
RefreshTabContents_();
@ -404,7 +497,7 @@ void DevConsole::RefreshTabContents_() {
refresh_pending_ = false;
// Clear to an empty slate.
buttons_.clear();
widgets_.clear();
python_terminal_visible_ = false;
// Now ask the Python layer to fill this tab in.
@ -414,43 +507,39 @@ void DevConsole::RefreshTabContents_() {
.Call(args);
}
void DevConsole::AddText(const char* text, float x, float y,
const char* h_anchor_str, const char* h_align_str,
const char* v_align_str, float scale) {
auto h_anchor = DevConsoleHAttachFromStr_(h_anchor_str);
auto h_align = TextMeshHAlignFromStr_(h_align_str);
auto v_align = TextMeshVAlignFromStr_(v_align_str);
widgets_.emplace_back(
std::make_unique<Text_>(text, x, y, h_anchor, h_align, v_align, scale));
}
void DevConsole::AddButton(const char* label, float x, float y, float width,
float height, PyObject* call, const char* h_anchor,
float label_scale, float corner_radius,
const char* style) {
float height, PyObject* call,
const char* h_anchor_str, float label_scale,
float corner_radius, const char* style_str) {
assert(g_base->InLogicThread());
DevButtonStyle_ style_val;
if (!strcmp(style, "dark")) {
style_val = DevButtonStyle_::kDark;
} else {
style_val = DevButtonStyle_::kNormal;
}
auto style = DevButtonStyleFromStr_(style_str);
auto h_anchor = DevConsoleHAttachFromStr_(h_anchor_str);
DevButtonAttach_ anchor;
if (!strcmp(h_anchor, "left")) {
anchor = DevButtonAttach_::kLeft;
} else if (!strcmp(h_anchor, "right")) {
anchor = DevButtonAttach_::kRight;
} else {
assert(!strcmp(h_anchor, "center"));
anchor = DevButtonAttach_::kCenter;
}
// auto call_obj = PythonRef::Acquired(call);
buttons_.emplace_back(std::make_unique<Button_>(
label, label_scale, anchor, x, y, width, height, corner_radius, style_val,
[this, call_obj = PythonRef::Acquired(call)] {
if (call_obj.Get() != Py_None) {
call_obj.Call();
widgets_.emplace_back(std::make_unique<Button_>(
label, label_scale, h_anchor, x, y, width, height, corner_radius, style,
[this, callref = PythonRef::Acquired(call)] {
if (callref.Get() != Py_None) {
callref.Call();
}
}));
}
void DevConsole::AddPythonTerminal() {
float bs = BaseScale();
buttons_.emplace_back(std::make_unique<Button_>(
"Exec", 0.75f * bs, DevButtonAttach_::kRight, -33.0f * bs, 15.95f * bs,
widgets_.emplace_back(std::make_unique<Button_>(
"Exec", 0.5f * bs, DevConsoleHAnchor_::kRight, -33.0f * bs, 15.95f * bs,
32.0f * bs, 13.0f * bs, 2.0 * bs, DevButtonStyle_::kNormal,
[this] { Exec(); }));
python_terminal_visible_ = true;
@ -483,7 +572,7 @@ auto DevConsole::HandleMouseDown(int button, float x, float y) -> bool {
return true;
}
}
for (auto&& button : buttons_) {
for (auto&& button : widgets_) {
if (button->HandleMouseDown(x, y - bottom)) {
return true;
}
@ -517,7 +606,7 @@ void DevConsole::HandleMouseUp(int button, float x, float y) {
for (auto&& button : tab_buttons_) {
button->HandleMouseUp(x, y - bottom);
}
for (auto&& button : buttons_) {
for (auto&& button : widgets_) {
button->HandleMouseUp(x, y - bottom);
}
}
@ -800,6 +889,10 @@ auto DevConsole::Bottom_() const -> float {
// more important for them to be able to be written to a known hard-coded
// mini-size.
float mini_size = 100.0f;
// Now that we have tabs and drop-shadows hanging down, we have to
// overshoot the top of the screen when transitioning out.
float top_buffer = 100.0f;
if (state_ == State_::kMini) {
bottom = vh - mini_size;
} else {
@ -812,7 +905,7 @@ auto DevConsole::Bottom_() const -> float {
} else if (state_prev_ == State_::kFull) {
from_height = vh - vh * kDevConsoleSize;
} else {
from_height = vh;
from_height = vh + top_buffer;
}
float to_height;
if (state_ == State_::kMini) {
@ -820,7 +913,7 @@ auto DevConsole::Bottom_() const -> float {
} else if (state_ == State_::kFull) {
to_height = vh - vh * kDevConsoleSize;
} else {
to_height = vh;
to_height = vh + top_buffer;
}
bottom = to_height * ratio + from_height * (1.0 - ratio);
}
@ -852,19 +945,20 @@ void DevConsole::Draw(FrameDef* frame_def) {
border_mesh_.SetPositionAndSize(0, bottom - border_height * bs,
kDevConsoleZDepth, pass->virtual_width(),
border_height * bs);
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetColor(0, 0, 0.1f, 0.9f);
c.DrawMesh(&bg_mesh_);
c.Submit();
if (python_terminal_visible_) {
c.SetColor(1.0f, 1.0f, 1.0f, 0.1f);
c.DrawMesh(&stripe_mesh_);
{
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetColor(0, 0, 0.1f, 0.9f);
c.DrawMesh(&bg_mesh_);
c.Submit();
if (python_terminal_visible_) {
c.SetColor(1.0f, 1.0f, 1.0f, 0.1f);
c.DrawMesh(&stripe_mesh_);
c.Submit();
}
c.SetColor(0.25f, 0.2f, 0.3f, 1.0f);
c.DrawMesh(&border_mesh_);
}
c.SetColor(0.25f, 0.2f, 0.3f, 1.0f);
c.DrawMesh(&border_mesh_);
c.Submit();
}
// Drop shadow.
@ -936,7 +1030,6 @@ void DevConsole::Draw(FrameDef* frame_def) {
c.DrawMesh(input_text_group_.GetElementMesh(e));
}
}
c.Submit();
}
// Carat.
@ -956,17 +1049,16 @@ void DevConsole::Draw(FrameDef* frame_def) {
c.Scale(6.0f * bs, 12.0f * bs, 1.0f);
c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
}
c.Submit();
}
// Draw output lines.
// Output lines.
{
float draw_scale = 0.6f;
float v_inc = 18.0f;
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetColor(1, 1, 1, 1);
c.SetFlatness(1.0f);
float draw_scale = 0.6f;
float v_inc = 18.0f;
float h = 0.5f
* (g_base->graphics->screen_virtual_width()
- (kDevConsoleStringBreakUpSize * draw_scale));
@ -1007,7 +1099,6 @@ void DevConsole::Draw(FrameDef* frame_def) {
break;
}
}
c.Submit();
}
}
@ -1020,7 +1111,7 @@ void DevConsole::Draw(FrameDef* frame_def) {
// Buttons.
{
for (auto&& button : buttons_) {
for (auto&& button : widgets_) {
button->Draw(pass, bottom);
}
}
@ -1040,4 +1131,21 @@ auto DevConsole::BaseScale() const -> float {
return 1.0f;
}
void DevConsole::StepDisplayTime() {
assert(g_base->InLogicThread());
// If we're inactive, blow away all our stuff once we transition fully
// off screen. This will kill any Python stuff attached to our widgets
// so things can clean themselves up.
if (state_ == State_::kInactive && !tab_buttons_.empty()) {
if ((g_base->logic->display_time() - transition_start_)
>= kTransitionSeconds) {
// Reset to a blank slate but *don't refresh anything (that will
// happen once we get vis'ed again).
tab_buttons_.clear();
widgets_.clear();
python_terminal_visible_ = false;
}
}
}
} // namespace ballistica::base

View File

@ -37,6 +37,8 @@ class DevConsole {
void Print(const std::string& s_in);
void Draw(FrameDef* frame_def);
void StepDisplayTime();
/// Called when the console should start accepting Python command input.
void EnableInput();
@ -53,8 +55,10 @@ class DevConsole {
void Exec();
void AddButton(const char* label, float x, float y, float width, float height,
PyObject* call, const char* h_anchor, float label_scale,
float corner_radius, const char* style);
PyObject* call, const char* h_anchor_str, float label_scale,
float corner_radius, const char* style_str);
void AddText(const char* text, float x, float y, const char* h_anchor_str,
const char* h_align_str, const char* v_align_str, float scale);
void AddPythonTerminal();
auto Width() -> float;
@ -65,6 +69,7 @@ class DevConsole {
private:
class Widget_;
class Button_;
class Text_;
class ToggleButton_;
class TabButton_;
class OutputLine_;
@ -103,7 +108,7 @@ class DevConsole {
Object::Ref<TextGroup> last_line_mesh_group_;
std::list<std::string> input_history_;
std::list<OutputLine_> output_lines_;
std::vector<std::unique_ptr<Widget_> > buttons_;
std::vector<std::unique_ptr<Widget_> > widgets_;
std::vector<std::unique_ptr<Widget_> > tab_buttons_;
};

View File

@ -49,7 +49,12 @@ UI::UI() {
}
}
void UI::StepDisplayTime() { assert(g_base->InLogicThread()); }
void UI::StepDisplayTime() {
assert(g_base->InLogicThread());
if (dev_console_) {
dev_console_->StepDisplayTime();
}
}
void UI::OnAppStart() {
assert(g_base->InLogicThread());

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 = 21406;
const int kEngineBuildNumber = 21407;
const char* kEngineVersion = "1.7.28";
const int kEngineApiVersion = 8;