@bloopjs/web 0.0.55 → 0.0.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/App.d.ts.map +1 -1
- package/dist/debugui/DebugUi.d.ts.map +1 -1
- package/dist/debugui/components/BottomBar.d.ts +8 -0
- package/dist/debugui/components/BottomBar.d.ts.map +1 -0
- package/dist/debugui/components/DebugToggle.d.ts.map +1 -1
- package/dist/debugui/components/Root.d.ts.map +1 -1
- package/dist/debugui/components/TopBar.d.ts +7 -0
- package/dist/debugui/components/TopBar.d.ts.map +1 -0
- package/dist/debugui/components/VerticalBar.d.ts +9 -0
- package/dist/debugui/components/VerticalBar.d.ts.map +1 -0
- package/dist/debugui/state.d.ts +9 -1
- package/dist/debugui/state.d.ts.map +1 -1
- package/dist/debugui/styles.d.ts +1 -1
- package/dist/debugui/styles.d.ts.map +1 -1
- package/dist/mod.js +586 -28
- package/dist/mod.js.map +13 -10
- package/package.json +3 -3
- package/src/App.ts +32 -1
- package/src/debugui/DebugUi.ts +7 -7
- package/src/debugui/components/BottomBar.tsx +68 -0
- package/src/debugui/components/DebugToggle.tsx +2 -6
- package/src/debugui/components/Root.tsx +81 -17
- package/src/debugui/components/TopBar.tsx +36 -0
- package/src/debugui/components/VerticalBar.tsx +26 -0
- package/src/debugui/state.ts +42 -5
- package/src/debugui/styles.ts +232 -2
package/dist/mod.js
CHANGED
|
@@ -1441,8 +1441,21 @@ async function mount(opts, options) {
|
|
|
1441
1441
|
}
|
|
1442
1442
|
},
|
|
1443
1443
|
__on_tape_full: function(_ctxPtr) {
|
|
1444
|
-
if (sim
|
|
1445
|
-
|
|
1444
|
+
if (!sim) {
|
|
1445
|
+
throw new Error("Sim not initialized in on_tape_full");
|
|
1446
|
+
}
|
|
1447
|
+
const tapeBytes = sim.saveTape();
|
|
1448
|
+
if (sim.onTapeFull) {
|
|
1449
|
+
sim.onTapeFull(tapeBytes);
|
|
1450
|
+
} else {
|
|
1451
|
+
const size = tapeBytes.length / 1024;
|
|
1452
|
+
const duration = sim.time.time;
|
|
1453
|
+
const kbPerSecond = size / duration;
|
|
1454
|
+
console.warn("Tape full. Recording stopped", {
|
|
1455
|
+
size: `${(tapeBytes.length / 1024).toFixed(0)}kb`,
|
|
1456
|
+
duration: `${sim.time.time.toFixed(2)}s`,
|
|
1457
|
+
kbPerSecond: `${kbPerSecond.toFixed(2)} kb/s`
|
|
1458
|
+
});
|
|
1446
1459
|
}
|
|
1447
1460
|
},
|
|
1448
1461
|
console_log: function(ptr, len) {
|
|
@@ -3427,6 +3440,7 @@ __export(exports_mod, {
|
|
|
3427
3440
|
resetState: () => resetState,
|
|
3428
3441
|
removePeer: () => removePeer,
|
|
3429
3442
|
debugState: () => debugState,
|
|
3443
|
+
cycleLayout: () => cycleLayout,
|
|
3430
3444
|
clearLogs: () => clearLogs,
|
|
3431
3445
|
addPeer: () => addPeer,
|
|
3432
3446
|
addLog: () => addLog,
|
|
@@ -4458,7 +4472,7 @@ function useSignalEffect(i4) {
|
|
|
4458
4472
|
}
|
|
4459
4473
|
|
|
4460
4474
|
// src/debugui/state.ts
|
|
4461
|
-
var
|
|
4475
|
+
var layoutMode = d2("off");
|
|
4462
4476
|
var netStatus = d2({
|
|
4463
4477
|
ourId: null,
|
|
4464
4478
|
remoteId: null,
|
|
@@ -4466,16 +4480,35 @@ var netStatus = d2({
|
|
|
4466
4480
|
peers: []
|
|
4467
4481
|
});
|
|
4468
4482
|
var logs = d2([]);
|
|
4483
|
+
var fps = d2(0);
|
|
4484
|
+
var frameTime = d2(0);
|
|
4485
|
+
var snapshotSize = d2(0);
|
|
4486
|
+
var frameNumber = d2(0);
|
|
4469
4487
|
var debugState = {
|
|
4470
|
-
|
|
4488
|
+
layoutMode,
|
|
4489
|
+
isVisible: w3(() => layoutMode.value !== "off"),
|
|
4471
4490
|
netStatus,
|
|
4472
4491
|
logs,
|
|
4473
4492
|
peer: w3(() => netStatus.value.peers[0] ?? null),
|
|
4474
4493
|
advantage: w3(() => {
|
|
4475
4494
|
const peer = netStatus.value.peers[0];
|
|
4476
4495
|
return peer ? peer.seq - peer.ack : null;
|
|
4477
|
-
})
|
|
4496
|
+
}),
|
|
4497
|
+
fps,
|
|
4498
|
+
frameTime,
|
|
4499
|
+
snapshotSize,
|
|
4500
|
+
frameNumber
|
|
4478
4501
|
};
|
|
4502
|
+
function cycleLayout() {
|
|
4503
|
+
const current = layoutMode.value;
|
|
4504
|
+
if (current === "off") {
|
|
4505
|
+
layoutMode.value = "letterboxed";
|
|
4506
|
+
} else if (current === "letterboxed") {
|
|
4507
|
+
layoutMode.value = "full";
|
|
4508
|
+
} else {
|
|
4509
|
+
layoutMode.value = "off";
|
|
4510
|
+
}
|
|
4511
|
+
}
|
|
4479
4512
|
function addLog(log) {
|
|
4480
4513
|
debugState.logs.value = [...debugState.logs.value, log];
|
|
4481
4514
|
}
|
|
@@ -4525,7 +4558,7 @@ function clearLogs() {
|
|
|
4525
4558
|
debugState.logs.value = [];
|
|
4526
4559
|
}
|
|
4527
4560
|
function resetState() {
|
|
4528
|
-
debugState.
|
|
4561
|
+
debugState.layoutMode.value = "off";
|
|
4529
4562
|
debugState.logs.value = [];
|
|
4530
4563
|
debugState.netStatus.value = {
|
|
4531
4564
|
ourId: null,
|
|
@@ -4533,6 +4566,10 @@ function resetState() {
|
|
|
4533
4566
|
rtt: null,
|
|
4534
4567
|
peers: []
|
|
4535
4568
|
};
|
|
4569
|
+
debugState.fps.value = 0;
|
|
4570
|
+
debugState.frameTime.value = 0;
|
|
4571
|
+
debugState.snapshotSize.value = 0;
|
|
4572
|
+
debugState.frameNumber.value = 0;
|
|
4536
4573
|
}
|
|
4537
4574
|
// ../../node_modules/preact/jsx-runtime/dist/jsxRuntime.module.js
|
|
4538
4575
|
var f4 = 0;
|
|
@@ -4795,26 +4832,257 @@ function LogEntry({ log }) {
|
|
|
4795
4832
|
|
|
4796
4833
|
// src/debugui/components/DebugToggle.tsx
|
|
4797
4834
|
function DebugToggle({ hotkey = "Escape" }) {
|
|
4798
|
-
const
|
|
4799
|
-
const toggle = () => {
|
|
4800
|
-
debugState.isVisible.value = !debugState.isVisible.value;
|
|
4801
|
-
};
|
|
4835
|
+
const isVisible = debugState.isVisible.value;
|
|
4802
4836
|
return /* @__PURE__ */ u4("button", {
|
|
4803
4837
|
className: "debug-toggle",
|
|
4804
|
-
onClick:
|
|
4838
|
+
onClick: cycleLayout,
|
|
4805
4839
|
onMouseDown: (e4) => e4.stopPropagation(),
|
|
4806
4840
|
onMouseUp: (e4) => e4.stopPropagation(),
|
|
4807
|
-
title:
|
|
4808
|
-
children:
|
|
4841
|
+
title: isVisible ? `Hide debug (${hotkey})` : `Show debug (${hotkey})`,
|
|
4842
|
+
children: isVisible ? "✕" : "⚙"
|
|
4809
4843
|
}, undefined, false, undefined, this);
|
|
4810
4844
|
}
|
|
4811
4845
|
|
|
4846
|
+
// src/debugui/components/TopBar.tsx
|
|
4847
|
+
function TopBar({ leftLabel, rightLabel }) {
|
|
4848
|
+
const fps2 = debugState.fps.value;
|
|
4849
|
+
const frameNumber2 = debugState.frameNumber.value;
|
|
4850
|
+
const rtt = debugState.netStatus.value.rtt;
|
|
4851
|
+
const isOnline = debugState.netStatus.value.peers.length > 0;
|
|
4852
|
+
return /* @__PURE__ */ u4("div", {
|
|
4853
|
+
className: "top-bar",
|
|
4854
|
+
children: [
|
|
4855
|
+
/* @__PURE__ */ u4("span", {
|
|
4856
|
+
className: "top-bar-side-label",
|
|
4857
|
+
children: leftLabel
|
|
4858
|
+
}, undefined, false, undefined, this),
|
|
4859
|
+
/* @__PURE__ */ u4("div", {
|
|
4860
|
+
className: "top-bar-center",
|
|
4861
|
+
children: [
|
|
4862
|
+
/* @__PURE__ */ u4("div", {
|
|
4863
|
+
className: "top-bar-item",
|
|
4864
|
+
children: [
|
|
4865
|
+
/* @__PURE__ */ u4("span", {
|
|
4866
|
+
className: "top-bar-label",
|
|
4867
|
+
children: "FPS"
|
|
4868
|
+
}, undefined, false, undefined, this),
|
|
4869
|
+
/* @__PURE__ */ u4("span", {
|
|
4870
|
+
className: "top-bar-value",
|
|
4871
|
+
children: fps2
|
|
4872
|
+
}, undefined, false, undefined, this)
|
|
4873
|
+
]
|
|
4874
|
+
}, undefined, true, undefined, this),
|
|
4875
|
+
/* @__PURE__ */ u4("div", {
|
|
4876
|
+
className: "top-bar-item",
|
|
4877
|
+
children: [
|
|
4878
|
+
/* @__PURE__ */ u4("span", {
|
|
4879
|
+
className: "top-bar-label",
|
|
4880
|
+
children: "Frame"
|
|
4881
|
+
}, undefined, false, undefined, this),
|
|
4882
|
+
/* @__PURE__ */ u4("span", {
|
|
4883
|
+
className: "top-bar-value",
|
|
4884
|
+
children: frameNumber2
|
|
4885
|
+
}, undefined, false, undefined, this)
|
|
4886
|
+
]
|
|
4887
|
+
}, undefined, true, undefined, this),
|
|
4888
|
+
isOnline && rtt !== null && /* @__PURE__ */ u4("div", {
|
|
4889
|
+
className: "top-bar-item",
|
|
4890
|
+
children: [
|
|
4891
|
+
/* @__PURE__ */ u4("span", {
|
|
4892
|
+
className: "top-bar-label",
|
|
4893
|
+
children: "Ping"
|
|
4894
|
+
}, undefined, false, undefined, this),
|
|
4895
|
+
/* @__PURE__ */ u4("span", {
|
|
4896
|
+
className: "top-bar-value",
|
|
4897
|
+
children: [
|
|
4898
|
+
rtt,
|
|
4899
|
+
"ms"
|
|
4900
|
+
]
|
|
4901
|
+
}, undefined, true, undefined, this)
|
|
4902
|
+
]
|
|
4903
|
+
}, undefined, true, undefined, this)
|
|
4904
|
+
]
|
|
4905
|
+
}, undefined, true, undefined, this),
|
|
4906
|
+
/* @__PURE__ */ u4("span", {
|
|
4907
|
+
className: "top-bar-side-label",
|
|
4908
|
+
children: rightLabel
|
|
4909
|
+
}, undefined, false, undefined, this)
|
|
4910
|
+
]
|
|
4911
|
+
}, undefined, true, undefined, this);
|
|
4912
|
+
}
|
|
4913
|
+
|
|
4914
|
+
// src/debugui/components/VerticalBar.tsx
|
|
4915
|
+
function VerticalBar({
|
|
4916
|
+
value,
|
|
4917
|
+
max,
|
|
4918
|
+
side,
|
|
4919
|
+
color = "#4a9eff"
|
|
4920
|
+
}) {
|
|
4921
|
+
const percentage = max > 0 ? Math.min(100, value / max * 100) : 0;
|
|
4922
|
+
return /* @__PURE__ */ u4("div", {
|
|
4923
|
+
className: `${side}-bar`,
|
|
4924
|
+
children: /* @__PURE__ */ u4("div", {
|
|
4925
|
+
className: "vertical-bar",
|
|
4926
|
+
children: /* @__PURE__ */ u4("div", {
|
|
4927
|
+
className: "vertical-bar-fill",
|
|
4928
|
+
style: { height: `${percentage}%`, background: color }
|
|
4929
|
+
}, undefined, false, undefined, this)
|
|
4930
|
+
}, undefined, false, undefined, this)
|
|
4931
|
+
}, undefined, false, undefined, this);
|
|
4932
|
+
}
|
|
4933
|
+
|
|
4934
|
+
// src/debugui/components/BottomBar.tsx
|
|
4935
|
+
function BottomBar({
|
|
4936
|
+
tapeUtilization = 0,
|
|
4937
|
+
playheadPosition = 0,
|
|
4938
|
+
isPlaying = true
|
|
4939
|
+
}) {
|
|
4940
|
+
const handleJumpBack = () => {};
|
|
4941
|
+
const handleStepBack = () => {};
|
|
4942
|
+
const handlePlayPause = () => {};
|
|
4943
|
+
const handleStepForward = () => {};
|
|
4944
|
+
const handleJumpForward = () => {};
|
|
4945
|
+
const handleSeek = () => {};
|
|
4946
|
+
return /* @__PURE__ */ u4("div", {
|
|
4947
|
+
className: "bottom-bar",
|
|
4948
|
+
children: [
|
|
4949
|
+
/* @__PURE__ */ u4("div", {
|
|
4950
|
+
className: "playbar-controls",
|
|
4951
|
+
children: [
|
|
4952
|
+
/* @__PURE__ */ u4("button", {
|
|
4953
|
+
className: "playbar-btn",
|
|
4954
|
+
onClick: handleJumpBack,
|
|
4955
|
+
children: [
|
|
4956
|
+
"<<",
|
|
4957
|
+
/* @__PURE__ */ u4("span", {
|
|
4958
|
+
className: "tooltip tooltip-left",
|
|
4959
|
+
children: [
|
|
4960
|
+
"Jump back ",
|
|
4961
|
+
/* @__PURE__ */ u4("kbd", {
|
|
4962
|
+
children: "4"
|
|
4963
|
+
}, undefined, false, undefined, this)
|
|
4964
|
+
]
|
|
4965
|
+
}, undefined, true, undefined, this)
|
|
4966
|
+
]
|
|
4967
|
+
}, undefined, true, undefined, this),
|
|
4968
|
+
/* @__PURE__ */ u4("button", {
|
|
4969
|
+
className: "playbar-btn",
|
|
4970
|
+
onClick: handleStepBack,
|
|
4971
|
+
children: [
|
|
4972
|
+
"<",
|
|
4973
|
+
/* @__PURE__ */ u4("span", {
|
|
4974
|
+
className: "tooltip",
|
|
4975
|
+
children: [
|
|
4976
|
+
"Step back ",
|
|
4977
|
+
/* @__PURE__ */ u4("kbd", {
|
|
4978
|
+
children: "5"
|
|
4979
|
+
}, undefined, false, undefined, this)
|
|
4980
|
+
]
|
|
4981
|
+
}, undefined, true, undefined, this)
|
|
4982
|
+
]
|
|
4983
|
+
}, undefined, true, undefined, this),
|
|
4984
|
+
/* @__PURE__ */ u4("button", {
|
|
4985
|
+
className: "playbar-btn",
|
|
4986
|
+
onClick: handlePlayPause,
|
|
4987
|
+
children: [
|
|
4988
|
+
isPlaying ? "||" : ">",
|
|
4989
|
+
/* @__PURE__ */ u4("span", {
|
|
4990
|
+
className: "tooltip",
|
|
4991
|
+
children: [
|
|
4992
|
+
isPlaying ? "Pause" : "Play",
|
|
4993
|
+
" ",
|
|
4994
|
+
/* @__PURE__ */ u4("kbd", {
|
|
4995
|
+
children: "6"
|
|
4996
|
+
}, undefined, false, undefined, this)
|
|
4997
|
+
]
|
|
4998
|
+
}, undefined, true, undefined, this)
|
|
4999
|
+
]
|
|
5000
|
+
}, undefined, true, undefined, this),
|
|
5001
|
+
/* @__PURE__ */ u4("button", {
|
|
5002
|
+
className: "playbar-btn",
|
|
5003
|
+
onClick: handleStepForward,
|
|
5004
|
+
children: [
|
|
5005
|
+
">",
|
|
5006
|
+
/* @__PURE__ */ u4("span", {
|
|
5007
|
+
className: "tooltip",
|
|
5008
|
+
children: [
|
|
5009
|
+
"Step forward ",
|
|
5010
|
+
/* @__PURE__ */ u4("kbd", {
|
|
5011
|
+
children: "7"
|
|
5012
|
+
}, undefined, false, undefined, this)
|
|
5013
|
+
]
|
|
5014
|
+
}, undefined, true, undefined, this)
|
|
5015
|
+
]
|
|
5016
|
+
}, undefined, true, undefined, this),
|
|
5017
|
+
/* @__PURE__ */ u4("button", {
|
|
5018
|
+
className: "playbar-btn",
|
|
5019
|
+
onClick: handleJumpForward,
|
|
5020
|
+
children: [
|
|
5021
|
+
">>",
|
|
5022
|
+
/* @__PURE__ */ u4("span", {
|
|
5023
|
+
className: "tooltip",
|
|
5024
|
+
children: [
|
|
5025
|
+
"Jump forward ",
|
|
5026
|
+
/* @__PURE__ */ u4("kbd", {
|
|
5027
|
+
children: "8"
|
|
5028
|
+
}, undefined, false, undefined, this)
|
|
5029
|
+
]
|
|
5030
|
+
}, undefined, true, undefined, this)
|
|
5031
|
+
]
|
|
5032
|
+
}, undefined, true, undefined, this)
|
|
5033
|
+
]
|
|
5034
|
+
}, undefined, true, undefined, this),
|
|
5035
|
+
/* @__PURE__ */ u4("div", {
|
|
5036
|
+
className: "seek-bar",
|
|
5037
|
+
onClick: handleSeek,
|
|
5038
|
+
children: [
|
|
5039
|
+
/* @__PURE__ */ u4("div", {
|
|
5040
|
+
className: "seek-bar-fill",
|
|
5041
|
+
style: { width: `${tapeUtilization * 100}%` }
|
|
5042
|
+
}, undefined, false, undefined, this),
|
|
5043
|
+
tapeUtilization > 0 && /* @__PURE__ */ u4("div", {
|
|
5044
|
+
className: "seek-bar-position",
|
|
5045
|
+
style: { left: `${playheadPosition * tapeUtilization * 100}%` }
|
|
5046
|
+
}, undefined, false, undefined, this)
|
|
5047
|
+
]
|
|
5048
|
+
}, undefined, true, undefined, this)
|
|
5049
|
+
]
|
|
5050
|
+
}, undefined, true, undefined, this);
|
|
5051
|
+
}
|
|
5052
|
+
|
|
4812
5053
|
// src/debugui/components/Root.tsx
|
|
4813
5054
|
function Root({ canvas, hotkey = "Escape" }) {
|
|
4814
|
-
const
|
|
5055
|
+
const layoutMode2 = debugState.layoutMode.value;
|
|
5056
|
+
if (layoutMode2 === "off") {
|
|
5057
|
+
return /* @__PURE__ */ u4(k, {
|
|
5058
|
+
children: [
|
|
5059
|
+
/* @__PURE__ */ u4("main", {
|
|
5060
|
+
className: "fullscreen",
|
|
5061
|
+
children: /* @__PURE__ */ u4(GameCanvas, {
|
|
5062
|
+
canvas
|
|
5063
|
+
}, undefined, false, undefined, this)
|
|
5064
|
+
}, undefined, false, undefined, this),
|
|
5065
|
+
/* @__PURE__ */ u4(DebugToggle, {
|
|
5066
|
+
hotkey
|
|
5067
|
+
}, undefined, false, undefined, this)
|
|
5068
|
+
]
|
|
5069
|
+
}, undefined, true, undefined, this);
|
|
5070
|
+
}
|
|
5071
|
+
if (layoutMode2 === "letterboxed") {
|
|
5072
|
+
return /* @__PURE__ */ u4(k, {
|
|
5073
|
+
children: [
|
|
5074
|
+
/* @__PURE__ */ u4(LetterboxedLayout, {
|
|
5075
|
+
canvas
|
|
5076
|
+
}, undefined, false, undefined, this),
|
|
5077
|
+
/* @__PURE__ */ u4(DebugToggle, {
|
|
5078
|
+
hotkey
|
|
5079
|
+
}, undefined, false, undefined, this)
|
|
5080
|
+
]
|
|
5081
|
+
}, undefined, true, undefined, this);
|
|
5082
|
+
}
|
|
4815
5083
|
return /* @__PURE__ */ u4(k, {
|
|
4816
5084
|
children: [
|
|
4817
|
-
|
|
5085
|
+
/* @__PURE__ */ u4("main", {
|
|
4818
5086
|
className: "layout",
|
|
4819
5087
|
children: [
|
|
4820
5088
|
/* @__PURE__ */ u4("section", {
|
|
@@ -4832,14 +5100,53 @@ function Root({ canvas, hotkey = "Escape" }) {
|
|
|
4832
5100
|
children: /* @__PURE__ */ u4(Logs, {}, undefined, false, undefined, this)
|
|
4833
5101
|
}, undefined, false, undefined, this)
|
|
4834
5102
|
]
|
|
4835
|
-
}, undefined, true, undefined, this)
|
|
4836
|
-
|
|
5103
|
+
}, undefined, true, undefined, this),
|
|
5104
|
+
/* @__PURE__ */ u4(DebugToggle, {
|
|
5105
|
+
hotkey
|
|
5106
|
+
}, undefined, false, undefined, this)
|
|
5107
|
+
]
|
|
5108
|
+
}, undefined, true, undefined, this);
|
|
5109
|
+
}
|
|
5110
|
+
function LetterboxedLayout({ canvas }) {
|
|
5111
|
+
const isOnline = debugState.netStatus.value.peers.length > 0;
|
|
5112
|
+
const advantage = debugState.advantage.value ?? 0;
|
|
5113
|
+
const frameTime2 = debugState.frameTime.value;
|
|
5114
|
+
const snapshotSize2 = debugState.snapshotSize.value;
|
|
5115
|
+
const leftValue = isOnline ? Math.abs(advantage) : frameTime2;
|
|
5116
|
+
const leftMax = isOnline ? 10 : 16.67;
|
|
5117
|
+
const leftLabel = isOnline ? "ADV" : "MS";
|
|
5118
|
+
const leftColor = isOnline ? advantage >= 0 ? "#4a9eff" : "#ff4a4a" : frameTime2 > 16.67 ? "#ff4a4a" : "#4aff4a";
|
|
5119
|
+
const rightValue = isOnline ? 0 : snapshotSize2;
|
|
5120
|
+
const rightMax = isOnline ? 10 : 1e4;
|
|
5121
|
+
const rightLabel = isOnline ? "RB" : "KB";
|
|
5122
|
+
return /* @__PURE__ */ u4("main", {
|
|
5123
|
+
className: "layout-letterboxed",
|
|
5124
|
+
children: [
|
|
5125
|
+
/* @__PURE__ */ u4(TopBar, {
|
|
5126
|
+
leftLabel,
|
|
5127
|
+
rightLabel
|
|
5128
|
+
}, undefined, false, undefined, this),
|
|
5129
|
+
/* @__PURE__ */ u4(VerticalBar, {
|
|
5130
|
+
value: leftValue,
|
|
5131
|
+
max: leftMax,
|
|
5132
|
+
side: "left",
|
|
5133
|
+
color: leftColor
|
|
5134
|
+
}, undefined, false, undefined, this),
|
|
5135
|
+
/* @__PURE__ */ u4("div", {
|
|
5136
|
+
className: "letterboxed-game",
|
|
4837
5137
|
children: /* @__PURE__ */ u4(GameCanvas, {
|
|
4838
5138
|
canvas
|
|
4839
5139
|
}, undefined, false, undefined, this)
|
|
4840
5140
|
}, undefined, false, undefined, this),
|
|
4841
|
-
/* @__PURE__ */ u4(
|
|
4842
|
-
|
|
5141
|
+
/* @__PURE__ */ u4(VerticalBar, {
|
|
5142
|
+
value: rightValue,
|
|
5143
|
+
max: rightMax,
|
|
5144
|
+
side: "right"
|
|
5145
|
+
}, undefined, false, undefined, this),
|
|
5146
|
+
/* @__PURE__ */ u4(BottomBar, {
|
|
5147
|
+
tapeUtilization: 0.67,
|
|
5148
|
+
playheadPosition: 0.8,
|
|
5149
|
+
isPlaying: true
|
|
4843
5150
|
}, undefined, false, undefined, this)
|
|
4844
5151
|
]
|
|
4845
5152
|
}, undefined, true, undefined, this);
|
|
@@ -4868,13 +5175,24 @@ var styles = `
|
|
|
4868
5175
|
|
|
4869
5176
|
/* Layout */
|
|
4870
5177
|
.fullscreen {
|
|
4871
|
-
width:
|
|
4872
|
-
height:
|
|
5178
|
+
width: 100vw;
|
|
5179
|
+
height: 100vh;
|
|
4873
5180
|
margin: 0;
|
|
4874
5181
|
padding: 0;
|
|
4875
5182
|
overflow: hidden;
|
|
4876
5183
|
}
|
|
4877
5184
|
|
|
5185
|
+
.fullscreen .canvas-container {
|
|
5186
|
+
width: 100%;
|
|
5187
|
+
height: 100%;
|
|
5188
|
+
}
|
|
5189
|
+
|
|
5190
|
+
.fullscreen canvas {
|
|
5191
|
+
width: 100%;
|
|
5192
|
+
height: 100%;
|
|
5193
|
+
display: block;
|
|
5194
|
+
}
|
|
5195
|
+
|
|
4878
5196
|
.layout {
|
|
4879
5197
|
display: grid;
|
|
4880
5198
|
grid-template-areas:
|
|
@@ -4888,6 +5206,225 @@ var styles = `
|
|
|
4888
5206
|
padding: 1rem;
|
|
4889
5207
|
}
|
|
4890
5208
|
|
|
5209
|
+
/* Letterboxed layout - using equal vw/vh percentages keeps game at viewport aspect ratio */
|
|
5210
|
+
.layout-letterboxed {
|
|
5211
|
+
display: grid;
|
|
5212
|
+
grid-template-areas:
|
|
5213
|
+
"top-bar top-bar top-bar"
|
|
5214
|
+
"left-bar game right-bar"
|
|
5215
|
+
"bottom-bar bottom-bar bottom-bar";
|
|
5216
|
+
grid-template-columns: 2vw 1fr 2vw;
|
|
5217
|
+
grid-template-rows: 2vh 1fr 2vh;
|
|
5218
|
+
width: 100vw;
|
|
5219
|
+
height: 100vh;
|
|
5220
|
+
background: #1a1a1a;
|
|
5221
|
+
overflow: hidden;
|
|
5222
|
+
overscroll-behavior: none;
|
|
5223
|
+
}
|
|
5224
|
+
|
|
5225
|
+
.top-bar {
|
|
5226
|
+
grid-area: top-bar;
|
|
5227
|
+
display: flex;
|
|
5228
|
+
align-items: center;
|
|
5229
|
+
justify-content: space-between;
|
|
5230
|
+
background: #111;
|
|
5231
|
+
color: #aaa;
|
|
5232
|
+
font-family: monospace;
|
|
5233
|
+
font-size: 12px;
|
|
5234
|
+
padding: 0;
|
|
5235
|
+
}
|
|
5236
|
+
|
|
5237
|
+
.top-bar-side-label {
|
|
5238
|
+
width: 2vw;
|
|
5239
|
+
text-align: center;
|
|
5240
|
+
font-size: 9px;
|
|
5241
|
+
text-transform: uppercase;
|
|
5242
|
+
letter-spacing: 0.5px;
|
|
5243
|
+
color: #666;
|
|
5244
|
+
}
|
|
5245
|
+
|
|
5246
|
+
.top-bar-center {
|
|
5247
|
+
display: flex;
|
|
5248
|
+
align-items: center;
|
|
5249
|
+
justify-content: center;
|
|
5250
|
+
gap: 24px;
|
|
5251
|
+
flex: 1;
|
|
5252
|
+
}
|
|
5253
|
+
|
|
5254
|
+
.top-bar-item {
|
|
5255
|
+
display: flex;
|
|
5256
|
+
align-items: center;
|
|
5257
|
+
gap: 6px;
|
|
5258
|
+
}
|
|
5259
|
+
|
|
5260
|
+
.top-bar-label {
|
|
5261
|
+
opacity: 0.6;
|
|
5262
|
+
}
|
|
5263
|
+
|
|
5264
|
+
.top-bar-value {
|
|
5265
|
+
color: #fff;
|
|
5266
|
+
font-weight: 500;
|
|
5267
|
+
}
|
|
5268
|
+
|
|
5269
|
+
.left-bar {
|
|
5270
|
+
grid-area: left-bar;
|
|
5271
|
+
display: flex;
|
|
5272
|
+
flex-direction: column;
|
|
5273
|
+
align-items: center;
|
|
5274
|
+
justify-content: flex-end;
|
|
5275
|
+
background: #111;
|
|
5276
|
+
padding: 4px 0;
|
|
5277
|
+
}
|
|
5278
|
+
|
|
5279
|
+
.right-bar {
|
|
5280
|
+
grid-area: right-bar;
|
|
5281
|
+
display: flex;
|
|
5282
|
+
flex-direction: column;
|
|
5283
|
+
align-items: center;
|
|
5284
|
+
justify-content: flex-end;
|
|
5285
|
+
background: #111;
|
|
5286
|
+
padding: 4px 0;
|
|
5287
|
+
}
|
|
5288
|
+
|
|
5289
|
+
.vertical-bar {
|
|
5290
|
+
width: 12px;
|
|
5291
|
+
flex: 1;
|
|
5292
|
+
background: #333;
|
|
5293
|
+
border-radius: 2px;
|
|
5294
|
+
position: relative;
|
|
5295
|
+
overflow: hidden;
|
|
5296
|
+
}
|
|
5297
|
+
|
|
5298
|
+
.vertical-bar-fill {
|
|
5299
|
+
position: absolute;
|
|
5300
|
+
bottom: 0;
|
|
5301
|
+
left: 0;
|
|
5302
|
+
right: 0;
|
|
5303
|
+
background: #4a9eff;
|
|
5304
|
+
border-radius: 2px;
|
|
5305
|
+
transition: height 0.1s ease-out;
|
|
5306
|
+
}
|
|
5307
|
+
|
|
5308
|
+
|
|
5309
|
+
.bottom-bar {
|
|
5310
|
+
grid-area: bottom-bar;
|
|
5311
|
+
display: flex;
|
|
5312
|
+
align-items: center;
|
|
5313
|
+
background: #111;
|
|
5314
|
+
padding: 0 8px;
|
|
5315
|
+
gap: 8px;
|
|
5316
|
+
}
|
|
5317
|
+
|
|
5318
|
+
.playbar-controls {
|
|
5319
|
+
display: flex;
|
|
5320
|
+
align-items: center;
|
|
5321
|
+
gap: 2px;
|
|
5322
|
+
flex-shrink: 0;
|
|
5323
|
+
}
|
|
5324
|
+
|
|
5325
|
+
.playbar-btn {
|
|
5326
|
+
width: 1.5vh;
|
|
5327
|
+
height: 1.5vh;
|
|
5328
|
+
min-width: 18px;
|
|
5329
|
+
min-height: 18px;
|
|
5330
|
+
border: none;
|
|
5331
|
+
background: transparent;
|
|
5332
|
+
color: #888;
|
|
5333
|
+
font-size: 10px;
|
|
5334
|
+
cursor: pointer;
|
|
5335
|
+
border-radius: 2px;
|
|
5336
|
+
display: flex;
|
|
5337
|
+
align-items: center;
|
|
5338
|
+
justify-content: center;
|
|
5339
|
+
transition: background 0.15s, color 0.15s;
|
|
5340
|
+
position: relative;
|
|
5341
|
+
}
|
|
5342
|
+
|
|
5343
|
+
.playbar-btn:hover {
|
|
5344
|
+
background: #333;
|
|
5345
|
+
color: #fff;
|
|
5346
|
+
}
|
|
5347
|
+
|
|
5348
|
+
.playbar-btn:hover .tooltip {
|
|
5349
|
+
opacity: 1;
|
|
5350
|
+
visibility: visible;
|
|
5351
|
+
}
|
|
5352
|
+
|
|
5353
|
+
.tooltip {
|
|
5354
|
+
position: absolute;
|
|
5355
|
+
bottom: calc(100% + 4px);
|
|
5356
|
+
left: 50%;
|
|
5357
|
+
transform: translateX(-50%);
|
|
5358
|
+
background: #222;
|
|
5359
|
+
color: #ccc;
|
|
5360
|
+
padding: 4px 8px;
|
|
5361
|
+
border-radius: 4px;
|
|
5362
|
+
font-size: 10px;
|
|
5363
|
+
white-space: nowrap;
|
|
5364
|
+
opacity: 0;
|
|
5365
|
+
visibility: hidden;
|
|
5366
|
+
transition: opacity 0.15s;
|
|
5367
|
+
pointer-events: none;
|
|
5368
|
+
z-index: 10;
|
|
5369
|
+
}
|
|
5370
|
+
|
|
5371
|
+
.tooltip-left {
|
|
5372
|
+
left: 0;
|
|
5373
|
+
transform: none;
|
|
5374
|
+
}
|
|
5375
|
+
|
|
5376
|
+
.tooltip kbd {
|
|
5377
|
+
background: #444;
|
|
5378
|
+
padding: 1px 4px;
|
|
5379
|
+
border-radius: 2px;
|
|
5380
|
+
margin-left: 4px;
|
|
5381
|
+
font-family: monospace;
|
|
5382
|
+
}
|
|
5383
|
+
|
|
5384
|
+
.seek-bar {
|
|
5385
|
+
flex: 1;
|
|
5386
|
+
height: 16px;
|
|
5387
|
+
background: #222;
|
|
5388
|
+
border-radius: 4px;
|
|
5389
|
+
position: relative;
|
|
5390
|
+
cursor: pointer;
|
|
5391
|
+
overflow: hidden;
|
|
5392
|
+
}
|
|
5393
|
+
|
|
5394
|
+
.seek-bar-fill {
|
|
5395
|
+
position: absolute;
|
|
5396
|
+
top: 0;
|
|
5397
|
+
left: 0;
|
|
5398
|
+
bottom: 0;
|
|
5399
|
+
background: linear-gradient(to right, #4a2070, #7b3fa0);
|
|
5400
|
+
border-radius: 4px;
|
|
5401
|
+
transition: width 0.1s ease-out;
|
|
5402
|
+
}
|
|
5403
|
+
|
|
5404
|
+
.seek-bar-position {
|
|
5405
|
+
position: absolute;
|
|
5406
|
+
top: 0;
|
|
5407
|
+
bottom: 0;
|
|
5408
|
+
width: 2px;
|
|
5409
|
+
background: #fff;
|
|
5410
|
+
}
|
|
5411
|
+
|
|
5412
|
+
.letterboxed-game {
|
|
5413
|
+
grid-area: game;
|
|
5414
|
+
overflow: hidden;
|
|
5415
|
+
}
|
|
5416
|
+
|
|
5417
|
+
.letterboxed-game .canvas-container {
|
|
5418
|
+
width: 100%;
|
|
5419
|
+
height: 100%;
|
|
5420
|
+
}
|
|
5421
|
+
|
|
5422
|
+
.letterboxed-game canvas {
|
|
5423
|
+
width: 100%;
|
|
5424
|
+
height: 100%;
|
|
5425
|
+
display: block;
|
|
5426
|
+
}
|
|
5427
|
+
|
|
4891
5428
|
.game {
|
|
4892
5429
|
grid-area: game;
|
|
4893
5430
|
border-radius: 8px;
|
|
@@ -5074,7 +5611,7 @@ class DebugUi {
|
|
|
5074
5611
|
const container = options.container ?? document.body;
|
|
5075
5612
|
const initiallyVisible = options.initiallyVisible ?? new URLSearchParams(window.location.search).has("debug");
|
|
5076
5613
|
this.#host = document.createElement("bloop-debug-ui");
|
|
5077
|
-
this.#host.style.cssText = "display:block;width:100%;height:100%;position:absolute;top:0;left:0;";
|
|
5614
|
+
this.#host.style.cssText = "display:block;width:100%;height:100%;position:absolute;top:0;left:0;overflow:hidden;overscroll-behavior:none;";
|
|
5078
5615
|
this.#shadow = this.#host.attachShadow({ mode: "open" });
|
|
5079
5616
|
const styleEl = document.createElement("style");
|
|
5080
5617
|
styleEl.textContent = styles;
|
|
@@ -5083,12 +5620,12 @@ class DebugUi {
|
|
|
5083
5620
|
this.#mountPoint.id = "debug-root";
|
|
5084
5621
|
this.#mountPoint.style.cssText = "width:100%;height:100%;";
|
|
5085
5622
|
this.#shadow.appendChild(this.#mountPoint);
|
|
5086
|
-
debugState.
|
|
5623
|
+
debugState.layoutMode.value = initiallyVisible ? "letterboxed" : "off";
|
|
5087
5624
|
this.#canvas = document.createElement("canvas");
|
|
5088
5625
|
this.#render();
|
|
5089
5626
|
container.appendChild(this.#host);
|
|
5090
5627
|
this.#cleanup = this.#setupHotkey();
|
|
5091
|
-
debugState.
|
|
5628
|
+
debugState.layoutMode.subscribe(() => {
|
|
5092
5629
|
this.#render();
|
|
5093
5630
|
});
|
|
5094
5631
|
}
|
|
@@ -5098,7 +5635,7 @@ class DebugUi {
|
|
|
5098
5635
|
#setupHotkey() {
|
|
5099
5636
|
const handler = (e4) => {
|
|
5100
5637
|
if (e4.key === this.#hotkey) {
|
|
5101
|
-
|
|
5638
|
+
cycleLayout();
|
|
5102
5639
|
}
|
|
5103
5640
|
};
|
|
5104
5641
|
window.addEventListener("keydown", handler);
|
|
@@ -5114,7 +5651,7 @@ class DebugUi {
|
|
|
5114
5651
|
return debugState.isVisible.value;
|
|
5115
5652
|
}
|
|
5116
5653
|
set isVisible(value) {
|
|
5117
|
-
debugState.
|
|
5654
|
+
debugState.layoutMode.value = value ? "letterboxed" : "off";
|
|
5118
5655
|
}
|
|
5119
5656
|
unmount() {
|
|
5120
5657
|
this.#cleanup?.();
|
|
@@ -5246,8 +5783,29 @@ class App {
|
|
|
5246
5783
|
}
|
|
5247
5784
|
};
|
|
5248
5785
|
window.addEventListener("keydown", playbarHotkeys);
|
|
5786
|
+
let fpsFrames = 0;
|
|
5787
|
+
let fpsLastTime = performance.now();
|
|
5249
5788
|
const frame = () => {
|
|
5250
|
-
|
|
5789
|
+
const stepStart = performance.now();
|
|
5790
|
+
const ticks = this.sim.step(stepStart - this.#now);
|
|
5791
|
+
if (ticks > 0) {
|
|
5792
|
+
const stepEnd = performance.now();
|
|
5793
|
+
debugState.frameTime.value = stepEnd - stepStart;
|
|
5794
|
+
debugState.frameNumber.value = this.sim.time.frame;
|
|
5795
|
+
if (debugState.layoutMode.value === "letterboxed") {
|
|
5796
|
+
const bag = this.game.bag;
|
|
5797
|
+
if (bag) {
|
|
5798
|
+
debugState.snapshotSize.value = JSON.stringify(bag).length;
|
|
5799
|
+
}
|
|
5800
|
+
}
|
|
5801
|
+
fpsFrames++;
|
|
5802
|
+
const elapsed = stepEnd - fpsLastTime;
|
|
5803
|
+
if (elapsed >= 1000) {
|
|
5804
|
+
debugState.fps.value = Math.round(fpsFrames * 1000 / elapsed);
|
|
5805
|
+
fpsFrames = 0;
|
|
5806
|
+
fpsLastTime = stepEnd;
|
|
5807
|
+
}
|
|
5808
|
+
}
|
|
5251
5809
|
if (!this.sim.isPaused) {
|
|
5252
5810
|
try {
|
|
5253
5811
|
this.afterFrame.notify(this.sim.time.frame);
|
|
@@ -5453,5 +6011,5 @@ export {
|
|
|
5453
6011
|
App
|
|
5454
6012
|
};
|
|
5455
6013
|
|
|
5456
|
-
//# debugId=
|
|
6014
|
+
//# debugId=97C22D9653CE8DB864756E2164756E21
|
|
5457
6015
|
//# sourceMappingURL=mod.js.map
|