Spaces:
Running
Running
Resize Pixi canvases on tab select (tabs start hidden at 0x0)
Browse filesCo-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- __pycache__/app.cpython-313.pyc +0 -0
- app.py +5 -2
- web/tiny.js +16 -0
__pycache__/app.cpython-313.pyc
CHANGED
|
Binary files a/__pycache__/app.cpython-313.pyc and b/__pycache__/app.cpython-313.pyc differ
|
|
|
app.py
CHANGED
|
@@ -41,15 +41,18 @@ with gr.Blocks(title="Tiny Army") as demo:
|
|
| 41 |
"legend is true.* Built on Gradio; sprites + engine reused from "
|
| 42 |
"auto-battler, rendered with Pixi.")
|
| 43 |
with gr.Tabs():
|
| 44 |
-
with gr.Tab("Battle"):
|
| 45 |
gr.HTML(f'<div id="battle-stage" style="{STAGE}"></div>')
|
| 46 |
-
with gr.Tab("Sprite Animations"):
|
| 47 |
with gr.Row():
|
| 48 |
char = gr.Dropdown(CHARACTERS, value=CHARACTERS[0][1], label="Character")
|
| 49 |
anim = gr.Dropdown(ANIMS, value="idle", label="Animation")
|
| 50 |
gr.HTML(f'<div id="sprite-stage" style="{STAGE.replace("56vh", "48vh")}"></div>')
|
| 51 |
char.change(None, [char, anim], None, js="(c,a)=>window.tinyShowSprite(c,a)")
|
| 52 |
anim.change(None, [char, anim], None, js="(c,a)=>window.tinyShowSprite(c,a)")
|
|
|
|
|
|
|
|
|
|
| 53 |
with gr.Tab("Barracks"):
|
| 54 |
with gr.Row():
|
| 55 |
unit = gr.Textbox("Bram the Warrior", label="Unit")
|
|
|
|
| 41 |
"legend is true.* Built on Gradio; sprites + engine reused from "
|
| 42 |
"auto-battler, rendered with Pixi.")
|
| 43 |
with gr.Tabs():
|
| 44 |
+
with gr.Tab("Battle") as battle_tab:
|
| 45 |
gr.HTML(f'<div id="battle-stage" style="{STAGE}"></div>')
|
| 46 |
+
with gr.Tab("Sprite Animations") as sprite_tab:
|
| 47 |
with gr.Row():
|
| 48 |
char = gr.Dropdown(CHARACTERS, value=CHARACTERS[0][1], label="Character")
|
| 49 |
anim = gr.Dropdown(ANIMS, value="idle", label="Animation")
|
| 50 |
gr.HTML(f'<div id="sprite-stage" style="{STAGE.replace("56vh", "48vh")}"></div>')
|
| 51 |
char.change(None, [char, anim], None, js="(c,a)=>window.tinyShowSprite(c,a)")
|
| 52 |
anim.change(None, [char, anim], None, js="(c,a)=>window.tinyShowSprite(c,a)")
|
| 53 |
+
# Pixi canvases start hidden (0×0); re-measure them when a tab is shown.
|
| 54 |
+
battle_tab.select(None, None, None, js="()=>window.tinyResize&&window.tinyResize()")
|
| 55 |
+
sprite_tab.select(None, None, None, js="()=>window.tinyResize&&window.tinyResize()")
|
| 56 |
with gr.Tab("Barracks"):
|
| 57 |
with gr.Row():
|
| 58 |
unit = gr.Textbox("Bram the Warrior", label="Unit")
|
web/tiny.js
CHANGED
|
@@ -16,6 +16,19 @@ function whenEl(id, cb) {
|
|
| 16 |
o.observe(document.body, { childList: true, subtree: true })
|
| 17 |
}
|
| 18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
// ── Sprite Animations tab ────────────────────────────────────────────────────
|
| 20 |
let charMap = null
|
| 21 |
async function loadChars() {
|
|
@@ -34,6 +47,7 @@ whenEl('sprite-stage', async (el) => {
|
|
| 34 |
const app = new PIXI.Application()
|
| 35 |
await app.init({ background: 0x10151b, resizeTo: el, antialias: false })
|
| 36 |
el.appendChild(app.canvas)
|
|
|
|
| 37 |
let sprite = null
|
| 38 |
window.tinyShowSprite = async (slug, anim) => {
|
| 39 |
const map = await loadChars()
|
|
@@ -51,6 +65,7 @@ whenEl('sprite-stage', async (el) => {
|
|
| 51 |
sprite.scale.set(sc)
|
| 52 |
sprite.position.set(app.screen.width / 2, app.screen.height * 0.6)
|
| 53 |
app.stage.addChild(sprite); sprite.play()
|
|
|
|
| 54 |
}
|
| 55 |
if (pending) window.tinyShowSprite(...pending)
|
| 56 |
})
|
|
@@ -70,6 +85,7 @@ whenEl('battle-stage', async (el) => {
|
|
| 70 |
const app = new PIXI.Application()
|
| 71 |
await app.init({ background: 0x0b0e12, resizeTo: el, antialias: true })
|
| 72 |
el.appendChild(app.canvas)
|
|
|
|
| 73 |
const g = new PIXI.Graphics(); app.stage.addChild(g)
|
| 74 |
let battle, seed = 1, overAt = 0
|
| 75 |
const fresh = () => { battle = makeTeamBattle({ seed: seed++, players: PLAYERS, enemies: ENEMIES }); overAt = 0 }
|
|
|
|
| 16 |
o.observe(document.body, { childList: true, subtree: true })
|
| 17 |
}
|
| 18 |
|
| 19 |
+
// Pixi apps live in tabs that start hidden (0×0); Gradio fires a tab `select`
|
| 20 |
+
// event wired to window.tinyResize so the canvas re-measures when shown.
|
| 21 |
+
let spriteApp = null, battleApp = null, spriteObj = null
|
| 22 |
+
function centerSprite() {
|
| 23 |
+
if (!spriteApp || !spriteObj) return
|
| 24 |
+
spriteObj.position.set(spriteApp.screen.width / 2, spriteApp.screen.height * 0.6)
|
| 25 |
+
}
|
| 26 |
+
window.tinyResize = () => {
|
| 27 |
+
try { spriteApp && spriteApp.resize() } catch {}
|
| 28 |
+
try { battleApp && battleApp.resize() } catch {}
|
| 29 |
+
centerSprite()
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
// ── Sprite Animations tab ────────────────────────────────────────────────────
|
| 33 |
let charMap = null
|
| 34 |
async function loadChars() {
|
|
|
|
| 47 |
const app = new PIXI.Application()
|
| 48 |
await app.init({ background: 0x10151b, resizeTo: el, antialias: false })
|
| 49 |
el.appendChild(app.canvas)
|
| 50 |
+
spriteApp = app
|
| 51 |
let sprite = null
|
| 52 |
window.tinyShowSprite = async (slug, anim) => {
|
| 53 |
const map = await loadChars()
|
|
|
|
| 65 |
sprite.scale.set(sc)
|
| 66 |
sprite.position.set(app.screen.width / 2, app.screen.height * 0.6)
|
| 67 |
app.stage.addChild(sprite); sprite.play()
|
| 68 |
+
spriteObj = sprite
|
| 69 |
}
|
| 70 |
if (pending) window.tinyShowSprite(...pending)
|
| 71 |
})
|
|
|
|
| 85 |
const app = new PIXI.Application()
|
| 86 |
await app.init({ background: 0x0b0e12, resizeTo: el, antialias: true })
|
| 87 |
el.appendChild(app.canvas)
|
| 88 |
+
battleApp = app
|
| 89 |
const g = new PIXI.Graphics(); app.stage.addChild(g)
|
| 90 |
let battle, seed = 1, overAt = 0
|
| 91 |
const fresh = () => { battle = makeTeamBattle({ seed: seed++, players: PLAYERS, enemies: ENEMIES }); overAt = 0 }
|