add 3d to srebot (#1350)
This commit is contained in:
@@ -53,6 +53,9 @@ class ReplayCanvas {
|
||||
this._teamNames = (data.teamNames && typeof data.teamNames === 'object') ? data.teamNames : {};
|
||||
this._winnerSlot = Number(data.winnerSlot) || 0; // winning team slot (1/2)
|
||||
this._mode = 'ground';
|
||||
this._viewMode = '2d';
|
||||
this.view3d = null;
|
||||
this.supports3d = false;
|
||||
const hasAircraft = data.entities.some(e => e.type === 'aircraft');
|
||||
this.hasAirMode = !!(this._airCoords && this._fullMapLevel && hasAircraft);
|
||||
|
||||
@@ -166,6 +169,9 @@ class ReplayCanvas {
|
||||
async init() {
|
||||
this._buildDOM();
|
||||
await Promise.all([this._loadMap(), this._loadEntityIcons()]);
|
||||
this._initView3d();
|
||||
this._onResize = () => { if (this._viewMode === '3d') this.view3d?.resize(); };
|
||||
window.addEventListener('resize', this._onResize);
|
||||
this.playing = true;
|
||||
this.playBtn.innerHTML = '<i class="fas fa-pause"></i>';
|
||||
this.lastFrameTime = performance.now();
|
||||
@@ -173,6 +179,42 @@ class ReplayCanvas {
|
||||
this.animFrameId = requestAnimationFrame(this._tick);
|
||||
}
|
||||
|
||||
_initView3d() {
|
||||
try {
|
||||
if (typeof window.ReplayCanvas3D !== 'function') return;
|
||||
this.view3d = new window.ReplayCanvas3D(this.view3dContainer, this.data);
|
||||
this.supports3d = true;
|
||||
} catch (e) {
|
||||
this.view3d = null;
|
||||
this.supports3d = false;
|
||||
}
|
||||
}
|
||||
|
||||
_renderActive() {
|
||||
if (this._viewMode === '3d') { this.view3d?.setTime(this.currentTime); }
|
||||
else { this.render(); }
|
||||
}
|
||||
|
||||
setViewMode(mode) {
|
||||
const next = mode === '3d' && this.view3d ? '3d' : '2d';
|
||||
if (next === this._viewMode) return;
|
||||
this._viewMode = next;
|
||||
const is3d = next === '3d';
|
||||
this.canvas.classList.toggle('rc-hidden', is3d);
|
||||
this.view3dContainer.classList.toggle('rc-hidden', !is3d);
|
||||
if (is3d) {
|
||||
this.view3d.setMode(this._mode);
|
||||
this.view3d.resize();
|
||||
this.view3d.setTime(this.currentTime);
|
||||
} else {
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
focus(playerId) {
|
||||
if (this._viewMode === '3d') this.view3d?.focus(playerId);
|
||||
}
|
||||
|
||||
_buildDOM() {
|
||||
this.container.innerHTML = '';
|
||||
const layout = document.createElement('div');
|
||||
@@ -190,12 +232,18 @@ class ReplayCanvas {
|
||||
// Tickets meter above the battle view (its top aligns with the team panels)
|
||||
this._buildTicketsBar(center);
|
||||
|
||||
const stage = document.createElement('div');
|
||||
stage.className = 'rc-stage';
|
||||
this.canvas = document.createElement('canvas');
|
||||
this.canvas.width = this.canvasSize;
|
||||
this.canvas.height = this.canvasSize;
|
||||
this.canvas.className = 'rc-canvas';
|
||||
this.ctx = this.canvas.getContext('2d');
|
||||
center.appendChild(this.canvas);
|
||||
stage.appendChild(this.canvas);
|
||||
this.view3dContainer = document.createElement('div');
|
||||
this.view3dContainer.className = 'rc-3d-container rc-hidden';
|
||||
stage.appendChild(this.view3dContainer);
|
||||
center.appendChild(stage);
|
||||
|
||||
// Controls
|
||||
const controls = document.createElement('div');
|
||||
@@ -243,7 +291,7 @@ class ReplayCanvas {
|
||||
this.currentTime = this.tStart + (this.scrubber.value / 1000) * (this.tEnd - this.tStart);
|
||||
this._updatePanelDeathStates();
|
||||
this._updateBattleLog();
|
||||
this.render();
|
||||
this._renderActive();
|
||||
this._updateTicketsBar(this.currentTime);
|
||||
});
|
||||
controls.querySelectorAll('.rc-sp').forEach(btn => {
|
||||
@@ -331,6 +379,7 @@ class ReplayCanvas {
|
||||
}
|
||||
});
|
||||
row.addEventListener('mouseleave', () => this._setHighlight(null));
|
||||
row.addEventListener('click', () => this.focus(parseInt(row.dataset.playerId)));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -873,8 +922,9 @@ class ReplayCanvas {
|
||||
this._drawMapToCanvas();
|
||||
// Recompute death positions in new coordinate space
|
||||
this._computeDeaths();
|
||||
this.view3d?.setMode(mode);
|
||||
// Render immediately
|
||||
this.render();
|
||||
this._renderActive();
|
||||
}
|
||||
|
||||
_togglePlay() {
|
||||
@@ -897,7 +947,7 @@ class ReplayCanvas {
|
||||
this.playBtn.innerHTML = '<i class="fas fa-play"></i>';
|
||||
}
|
||||
}
|
||||
this.render();
|
||||
this._renderActive();
|
||||
this._updateTicketsBar(this.currentTime);
|
||||
this._updateControls();
|
||||
// Update panel death states + battle log every ~250ms
|
||||
@@ -1145,6 +1195,9 @@ class ReplayCanvas {
|
||||
|
||||
destroy() {
|
||||
if (this.animFrameId) { cancelAnimationFrame(this.animFrameId); this.animFrameId = null; }
|
||||
if (this._onResize) window.removeEventListener('resize', this._onResize);
|
||||
this.view3d?.dispose();
|
||||
this.view3d = null;
|
||||
this.container.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user