diff --git a/.efrocachemap b/.efrocachemap
index c1e1e508..c2891745 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -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": "879f9ae6e9feb73e78f485b651cd34c7",
- "build/prefab/full/linux_arm64_gui/release/ballisticakit": "ff1fa0221ac83f4d531134b9a9a87356",
- "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "4d4fd7114044126319142a4668456bd5",
- "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "2d7d1d66d4d39aa312b973118b970851",
- "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "2b42e72406fb0c54bfd5c3dcdeca0a89",
- "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "977c9fc76d955ce30c709d97127d2b3d",
- "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "15d20411f5c80701a78e08d5bf832e94",
- "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "dce80ee691257accb0a87f41ff4f673e",
- "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "a84e2b62b91d6cf6d9ec20b28af5c629",
- "build/prefab/full/mac_arm64_gui/release/ballisticakit": "477bf924c8d9f9e2d646dee4006ce1d9",
- "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "79b4e2cd534ec0adec870d54c47e4e17",
- "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "4e2caa995f9d806124c4d715105606a3",
- "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "4b7878086aa663c03679d568109d0dc6",
- "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "457020313456fd2e255bd25588fc87d8",
- "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "dec55597731654d412ff2756c9e574c6",
- "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "0a0c061db51c8bfed9eabd085e3978a7",
- "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "1724f00d6acffd249a01b85482ae322c",
- "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "5626611d504dd205ea318d720a134816",
- "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "ea6804ac87fe463666deeeb6bc1a2dc1",
- "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "bfaf973230af195bfd9ec18cff3db17a",
+ "build/prefab/full/linux_arm64_gui/debug/ballisticakit": "a5196028d865c1da423e3b44f322f0b4",
+ "build/prefab/full/linux_arm64_gui/release/ballisticakit": "0eb477fffc094aa13e5c89176cc0f588",
+ "build/prefab/full/linux_arm64_server/debug/dist/ballisticakit_headless": "2a83c1baf22d8bf356fcc27f1471f957",
+ "build/prefab/full/linux_arm64_server/release/dist/ballisticakit_headless": "8c102382876ec9b3bf5157c2e692eb83",
+ "build/prefab/full/linux_x86_64_gui/debug/ballisticakit": "fb64489102c92ecfe2824c3044987f8a",
+ "build/prefab/full/linux_x86_64_gui/release/ballisticakit": "4e4a1a0187bfaf6133a59d245b2d1bbc",
+ "build/prefab/full/linux_x86_64_server/debug/dist/ballisticakit_headless": "fd2476f5995fd19dd50ef49e84cb797b",
+ "build/prefab/full/linux_x86_64_server/release/dist/ballisticakit_headless": "c6d32394a7420aa0d8a32c72df24de17",
+ "build/prefab/full/mac_arm64_gui/debug/ballisticakit": "4e1302cc8907bd2814df01cd61fc03ad",
+ "build/prefab/full/mac_arm64_gui/release/ballisticakit": "bde2ee121f12001e5b1d0e8a727dd4df",
+ "build/prefab/full/mac_arm64_server/debug/dist/ballisticakit_headless": "e956c21f24bbf0291b1d0eef980a0f71",
+ "build/prefab/full/mac_arm64_server/release/dist/ballisticakit_headless": "6bc7ba87119a7ba3d4a21ceda731311e",
+ "build/prefab/full/mac_x86_64_gui/debug/ballisticakit": "0f7e7ec2068443eb3cba3bd87d98b700",
+ "build/prefab/full/mac_x86_64_gui/release/ballisticakit": "43fe6217db63f5e1f471ec3bc926589f",
+ "build/prefab/full/mac_x86_64_server/debug/dist/ballisticakit_headless": "25da26e2ebc227d61da7261dff3b22da",
+ "build/prefab/full/mac_x86_64_server/release/dist/ballisticakit_headless": "383df77c017fa93d9abeb60fe6ecc7d3",
+ "build/prefab/full/windows_x86_gui/debug/BallisticaKit.exe": "1059e2cd37f10fe93fd85c06e7679cef",
+ "build/prefab/full/windows_x86_gui/release/BallisticaKit.exe": "6bf2fd565a36d8da031138ae2a593c8e",
+ "build/prefab/full/windows_x86_server/debug/dist/BallisticaKitHeadless.exe": "84363c68b54f2a38b91173600580a1f3",
+ "build/prefab/full/windows_x86_server/release/dist/BallisticaKitHeadless.exe": "44cfae2645b1b865d4965e859ee1d7b6",
"build/prefab/lib/linux_arm64_gui/debug/libballisticaplus.a": "f3d305e647a7f77dd70a48f615cfd750",
"build/prefab/lib/linux_arm64_gui/release/libballisticaplus.a": "931ce8eab9859d20ad86c47d196ba62c",
"build/prefab/lib/linux_arm64_server/debug/libballisticaplus.a": "f3d305e647a7f77dd70a48f615cfd750",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4f05b3a0..941fbe32 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-### 1.7.28 (build 21393, api 8, 2023-09-28)
+### 1.7.28 (build 21395, api 8, 2023-09-28)
- 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
diff --git a/ballisticakit-cmake/CMakeLists.txt b/ballisticakit-cmake/CMakeLists.txt
index cd0abc3d..de4a7282 100644
--- a/ballisticakit-cmake/CMakeLists.txt
+++ b/ballisticakit-cmake/CMakeLists.txt
@@ -341,6 +341,8 @@ set(BALLISTICA_SOURCES
${BA_SRC_ROOT}/ballistica/base/graphics/mesh/mesh_indexed_static_dynamic.h
${BA_SRC_ROOT}/ballistica/base/graphics/mesh/mesh_non_indexed.h
${BA_SRC_ROOT}/ballistica/base/graphics/mesh/mesh_renderer_data.h
+ ${BA_SRC_ROOT}/ballistica/base/graphics/mesh/nine_patch_mesh.cc
+ ${BA_SRC_ROOT}/ballistica/base/graphics/mesh/nine_patch_mesh.h
${BA_SRC_ROOT}/ballistica/base/graphics/mesh/sprite_mesh.h
${BA_SRC_ROOT}/ballistica/base/graphics/mesh/text_mesh.cc
${BA_SRC_ROOT}/ballistica/base/graphics/mesh/text_mesh.h
diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj
index ed6cfdcc..4f7d8d54 100644
--- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj
+++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj
@@ -327,6 +327,8 @@
+
+
diff --git a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters
index 405c7f97..7cc31a90 100644
--- a/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters
+++ b/ballisticakit-windows/Generic/BallisticaKitGeneric.vcxproj.filters
@@ -415,6 +415,12 @@
ballistica\base\graphics\mesh
+
+ ballistica\base\graphics\mesh
+
+
+ ballistica\base\graphics\mesh
+
ballistica\base\graphics\mesh
diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj
index 0a1d3a3f..a3933aac 100644
--- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj
+++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj
@@ -322,6 +322,8 @@
+
+
diff --git a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters
index 405c7f97..7cc31a90 100644
--- a/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters
+++ b/ballisticakit-windows/Headless/BallisticaKitHeadless.vcxproj.filters
@@ -415,6 +415,12 @@
ballistica\base\graphics\mesh
+
+ ballistica\base\graphics\mesh
+
+
+ ballistica\base\graphics\mesh
+
ballistica\base\graphics\mesh
diff --git a/src/assets/ba_data/python/baenv.py b/src/assets/ba_data/python/baenv.py
index 0248a106..128aa866 100644
--- a/src/assets/ba_data/python/baenv.py
+++ b/src/assets/ba_data/python/baenv.py
@@ -52,7 +52,7 @@ if TYPE_CHECKING:
# Build number and version of the ballistica binary we expect to be
# using.
-TARGET_BALLISTICA_BUILD = 21393
+TARGET_BALLISTICA_BUILD = 21395
TARGET_BALLISTICA_VERSION = '1.7.28'
diff --git a/src/ballistica/base/graphics/mesh/nine_patch_mesh.cc b/src/ballistica/base/graphics/mesh/nine_patch_mesh.cc
new file mode 100644
index 00000000..e2a376ff
--- /dev/null
+++ b/src/ballistica/base/graphics/mesh/nine_patch_mesh.cc
@@ -0,0 +1,112 @@
+// Released under the MIT License. See LICENSE for details.
+
+#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
+
+namespace ballistica::base {
+
+NinePatchMesh::NinePatchMesh(float x, float y, float z, float width,
+ float height, float border_left,
+ float border_bottom, float border_right,
+ float border_top) {
+ // Statically allocate enough for a full 9 patches even though we may
+ // not use them all (in cases of size 0 borders).
+ VertexSimpleFull verts[16]; // 4 vertical * 4 horizontal slices.
+ uint16_t indices[54]; // 9 patches * 2 triangles * 3 verts.
+
+ float y0 = y;
+ float y1 = y + border_bottom * height;
+ float y2 = y + (1.0 - border_top) * height;
+ float y3 = y + height;
+ auto v0 = 65535;
+ auto v1 = 32767;
+ auto v2 = 32767;
+ auto v3 = 0;
+
+ float x0 = x;
+ float x1 = x + border_left * width;
+ float x2 = x + (1.0 - border_right) * width;
+ float x3 = x + width;
+ auto u0 = 0;
+ auto u1 = 32767;
+ auto u2 = 32767;
+ auto u3 = 65535;
+
+ int icount{};
+
+ // Assign all 16 positions and uvs.
+ for (int yi = 0; yi < 4; ++yi) {
+ for (int xi = 0; xi < 4; ++xi) {
+ VertexSimpleFull* v = verts + yi * 4 + xi;
+
+ float xpos, ypos;
+ uint16_t uval, vval;
+ switch (xi) {
+ case 0:
+ xpos = x0;
+ uval = u0;
+ break;
+ case 1:
+ xpos = x1;
+ uval = u1;
+ break;
+ case 2:
+ xpos = x2;
+ uval = u2;
+ break;
+ default:
+ assert(xi == 3);
+ xpos = x3;
+ uval = u3;
+ }
+ switch (yi) {
+ case 0:
+ ypos = y0;
+ vval = v0;
+ break;
+ case 1:
+ ypos = y1;
+ vval = v1;
+ break;
+ case 2:
+ ypos = y2;
+ vval = v2;
+ break;
+ default:
+ assert(yi == 3);
+ ypos = y3;
+ vval = v3;
+ }
+
+ v->position[0] = xpos;
+ v->position[1] = ypos;
+ v->position[2] = z;
+ v->uv[0] = uval;
+ v->uv[1] = vval;
+ }
+ }
+
+ // Now add triangle draws for any of the 9 patches with width/height > 0.
+ for (int yi = 0; yi < 3; ++yi) {
+ for (int xi = 0; xi < 3; ++xi) {
+ VertexSimpleFull* v = verts + yi * 4 + xi;
+ VertexSimpleFull* vright = v + 1;
+ VertexSimpleFull* vtop = v + 4;
+
+ if (vright->position[0] > v->position[0]
+ && vtop->position[1] > v->position[1]) {
+ indices[icount++] = yi * 4 + xi;
+ indices[icount++] = yi * 4 + xi + 1;
+ indices[icount++] = (yi + 1) * 4 + xi + 1;
+
+ indices[icount++] = yi * 4 + xi;
+ indices[icount++] = (yi + 1) * 4 + xi + 1;
+ indices[icount++] = (yi + 1) * 4 + xi;
+ }
+ }
+ }
+ assert(icount <= 54);
+ SetIndexData(Object::New(icount, indices));
+ SetData(Object::New>(16, verts));
+}
+
+} // namespace ballistica::base
diff --git a/src/ballistica/base/graphics/mesh/nine_patch_mesh.h b/src/ballistica/base/graphics/mesh/nine_patch_mesh.h
new file mode 100644
index 00000000..a0934afc
--- /dev/null
+++ b/src/ballistica/base/graphics/mesh/nine_patch_mesh.h
@@ -0,0 +1,20 @@
+// Released under the MIT License. See LICENSE for details.
+
+#ifndef BALLISTICA_BASE_GRAPHICS_MESH_NINE_PATCH_MESH_H_
+#define BALLISTICA_BASE_GRAPHICS_MESH_NINE_PATCH_MESH_H_
+
+#include "ballistica/base/graphics/mesh/mesh_indexed_simple_full.h"
+
+namespace ballistica::base {
+
+// A mesh set up to draw images as 9-patches.
+class NinePatchMesh : public MeshIndexedSimpleFull {
+ public:
+ NinePatchMesh(float x, float y, float z, float width, float height,
+ float border_left, float border_bottom, float border_right,
+ float border_top);
+};
+
+} // namespace ballistica::base
+
+#endif // BALLISTICA_BASE_GRAPHICS_MESH_NINE_PATCH_MESH_H_
diff --git a/src/ballistica/base/ui/dev_console.cc b/src/ballistica/base/ui/dev_console.cc
index a73e0dfc..cfea2af7 100644
--- a/src/ballistica/base/ui/dev_console.cc
+++ b/src/ballistica/base/ui/dev_console.cc
@@ -5,6 +5,7 @@
#include "ballistica/base/app_mode/app_mode.h"
#include "ballistica/base/audio/audio.h"
#include "ballistica/base/graphics/component/simple_component.h"
+#include "ballistica/base/graphics/mesh/nine_patch_mesh.h"
#include "ballistica/base/graphics/text/text_graphics.h"
#include "ballistica/base/input/input.h"
#include "ballistica/base/logic/logic.h"
@@ -45,38 +46,34 @@ static auto XOffs(DevButtonAttach_ attach) -> float {
return 0.0f;
}
-static void DrawBasicButton(RenderPass* pass, TextGroup* tgrp, float tscale,
- float bottom, float x, float y, float width,
- float height, const Vector3f& fgcolor,
+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) {
SimpleComponent c(pass);
c.SetTransparent(true);
c.SetColor(bgcolor.x, bgcolor.y, bgcolor.z, 1.0f);
+ c.SetTexture(g_base->assets->SysTexture(SysTextureID::kCircle));
+ {
+ auto xf = c.ScopedTransform();
+ c.Translate(x, y + bottom, kDevConsoleZDepth);
+ c.DrawMesh(mesh);
+ }
+ // Draw our text.
{
auto xf = c.ScopedTransform();
c.Translate(x + width * 0.5f, y + bottom + height * 0.5f,
kDevConsoleZDepth);
- // Draw our backing.
- {
- auto xf = c.ScopedTransform();
- c.Scale(width, height);
- c.DrawMeshAsset(g_base->assets->SysMesh(SysMeshID::kImage1x1));
- }
- // Draw our text.
+ float sc{0.6f * tscale};
+ c.Scale(sc, sc, 1.0f);
+ int elem_count = tgrp->GetElementCount();
c.SetColor(fgcolor.x, fgcolor.y, fgcolor.z, 1.0f);
c.SetFlatness(1.0f);
- int elem_count = tgrp->GetElementCount();
for (int e = 0; e < elem_count; e++) {
c.SetTexture(tgrp->GetElementTexture(e));
- {
- auto xf = c.ScopedTransform();
- float sc{0.6f * tscale};
- c.Scale(sc, sc, 1.0f);
- c.DrawMesh(tgrp->GetElementMesh(e));
- }
+ c.DrawMesh(tgrp->GetElementMesh(e));
}
}
- c.Submit();
}
/// Super-simple widget type for populating dev-console
@@ -98,6 +95,7 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
float height;
bool pressed{};
Object::Ref call;
+ NinePatchMesh mesh;
TextGroup text_group;
float text_scale;
@@ -110,7 +108,8 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
width{width},
height{height},
call{NewLambdaRunnable(lambda)},
- text_scale{text_scale} {
+ text_scale{text_scale},
+ mesh(0.0f, 0.0f, 0.0f, width, height, 0.1f, 0.3f, 0.1f, 0.3f) {
text_group.SetText(label, TextMesh::HAlign::kCenter,
TextMesh::VAlign::kCenter);
}
@@ -141,8 +140,8 @@ class DevConsole::Button_ : public DevConsole::Widget_ {
void Draw(RenderPass* pass, float bottom) override {
DrawBasicButton(
- pass, &text_group, text_scale, bottom, x + XOffs(attach), y, width,
- height,
+ pass, &mesh, &text_group, text_scale, bottom, x + XOffs(attach), y,
+ width, height,
pressed ? Vector3f{0.0f, 0.0f, 0.0f} : Vector3f{0.8f, 0.7f, 0.8f},
pressed ? Vector3f{0.8f, 0.7f, 0.8f} : Vector3f{0.25, 0.2f, 0.3f});
}
@@ -159,6 +158,7 @@ class DevConsole::ToggleButton_ : public DevConsole::Widget_ {
bool on{};
Object::Ref on_call;
Object::Ref off_call;
+ NinePatchMesh mesh;
TextGroup text_group;
float text_scale;
@@ -173,7 +173,8 @@ class DevConsole::ToggleButton_ : public DevConsole::Widget_ {
height{height},
on_call{NewLambdaRunnable(on_call)},
off_call{NewLambdaRunnable(off_call)},
- text_scale{text_scale} {
+ text_scale{text_scale},
+ mesh(0.0f, 0.0f, 0.0f, width, height, 0.1f, 0.3f, 0.1f, 0.3f) {
text_group.SetText(label, TextMesh::HAlign::kCenter,
TextMesh::VAlign::kCenter);
}
@@ -205,8 +206,8 @@ class DevConsole::ToggleButton_ : public DevConsole::Widget_ {
}
void Draw(RenderPass* pass, float bottom) override {
- DrawBasicButton(pass, &text_group, text_scale, bottom, x + XOffs(attach), y,
- width, height,
+ 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},
@@ -227,6 +228,7 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
bool selected{};
Object::Ref call;
TextGroup text_group;
+ NinePatchMesh mesh;
float text_scale;
template
@@ -240,7 +242,8 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
width{width},
height{height},
call{NewLambdaRunnable(call)},
- text_scale{text_scale} {
+ text_scale{text_scale},
+ mesh(0.0f, 0.0f, 0.0f, width, height, 0.1f, 0.3f, 0.1f, 0.0f) {
text_group.SetText(label, TextMesh::HAlign::kCenter,
TextMesh::VAlign::kCenter);
}
@@ -270,8 +273,8 @@ class DevConsole::TabButton_ : public DevConsole::Widget_ {
}
void Draw(RenderPass* pass, float bottom) override {
- DrawBasicButton(pass, &text_group, text_scale, bottom, x + XOffs(attach), y,
- width, height,
+ 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.8f, 0.7f, 0.8f},
diff --git a/src/ballistica/shared/ballistica.cc b/src/ballistica/shared/ballistica.cc
index 9a2b58c5..7d919d59 100644
--- a/src/ballistica/shared/ballistica.cc
+++ b/src/ballistica/shared/ballistica.cc
@@ -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 = 21393;
+const int kEngineBuildNumber = 21395;
const char* kEngineVersion = "1.7.28";
const int kEngineApiVersion = 8;