Skip to content

Commit

Permalink
feat: Timeline debugger
Browse files Browse the repository at this point in the history
  • Loading branch information
Losses committed May 26, 2024
1 parent ec5fcc1 commit 4bfdd44
Show file tree
Hide file tree
Showing 18 changed files with 199 additions and 57 deletions.
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@
</div>
</div>
</div>
<div class="story-visualize-container">
<div id="story-visualize"></div>
</div>
<script src="src/index.ts" type="module"></script>
</body>

Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
"@web-media/event-target": "^0.0.2",
"@web-media/phonograph": "2.3.2",
"debug": "^4.3.4",
"moment": "^2.30.1",
"standardized-audio-context": "^25.3.72",
"stats.js": "^0.17.0",
"three": "0.138.3",
"tslib": "^2.3.1"
"tslib": "^2.3.1",
"vis-data": "^7.1.9",
"vis-timeline": "^7.7.3"
},
"devDependencies": {
"@biomejs/biome": "1.7.3",
Expand Down
2 changes: 1 addition & 1 deletion src/components/Grass.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as THREE from 'three';
import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';
import { THEME_VALUE } from '../manager/ColorManager';
import { timeManager } from '../manager/TimeManager';
import { VISUAL_LOAD } from '../stores/settings';
Expand Down
2 changes: 1 addition & 1 deletion src/components/Ground2.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as THREE from 'three';

import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';
import { CylinderGeometry2 } from './CylinderGeometry2';

export const RADIUS = 120;
Expand Down
2 changes: 1 addition & 1 deletion src/components/GroundObject.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as THREE from 'three';
import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils';
import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';
import { timeManager } from '../manager/TimeManager';
import { GROUND_Y_OFFSET, RADIUS, SCALE_Z } from './Ground2';

Expand Down
2 changes: 1 addition & 1 deletion src/components/SkyBox.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as THREE from 'three';
import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';

export const SkyBox = (tracker: ResourceTracker) => {
const geometry = new THREE.SphereGeometry(500, 20, 20);
Expand Down
2 changes: 1 addition & 1 deletion src/initializeThreeCanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { SepiaShader } from 'three/examples/jsm/shaders/SepiaShader';
import { VignetteShader } from 'three/examples/jsm/shaders/VignetteShader';
import { CANVAS_SIZE, updateCanvasSize } from './stores/settings';

import { ResourceTracker } from './ResourceTracker';
import { ResourceTracker } from './utils/ResourceTracker';
import { timeManager } from './manager/TimeManager';
import { FrameRateLevel } from './utils/TimeMagic';
import { GlitchShader } from './utils/shaders/GlitchPass';
Expand Down
52 changes: 52 additions & 0 deletions src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -607,4 +607,56 @@ button {
.disconnected {
font-size: 1.3em;
font-weight: 800;
}

/** Other debugging tools **/
.story-visualize-container {
left: 0;
bottom: 0;
width: 100%;
height: 30vh;
position: fixed;
background: rgba(0, 0, 0, 0.24);
backdrop-filter: blur(6px);
}

.story-visualize-container canvas {
height: 100%;
}

.vis-time-axis .vis-text {
color: white;
font-weight: 400;
}

.vis-item-content {
font-size: 14px;
font-weight: 400;
}

.vis-timeline {
border-color: rgba(255, 255, 255, 0.3);
}

.vis-time-axis .vis-grid.vis-minor {
border-color: rgba(255, 255, 255, 0.3);
}

.vis-panel.vis-center, .vis-panel.vis-left, .vis-panel.vis-right, .vis-panel.vis-top, .vis-panel.vis-bottom {
border-color: rgba(255, 255, 255, 0.3);
}

.vis-item {
border-radius: 0;
background: rgba(0, 0, 0, 0.24);
border-image: linear-gradient(60deg, rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.6)) 10%;
box-shadow: 0 0 0 rgba(255, 255, 255, 0.0), inset 0 0 0 rgba(255, 255, 255, 0);
color: white;
}

.vis-item.vis-selected {
background-color: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.3);
box-shadow: 0 0 4px rgba(255, 255, 255, 0.5), inset 0 0 4px rgba(255, 255, 255, 0.5);
border-image: linear-gradient(60deg, rgba(255, 255, 255, 1), rgba(255, 255, 255, 0.6), rgba(255, 255, 255, 1)) 10%;
}
2 changes: 1 addition & 1 deletion src/manager/DebugManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type * as THREE from 'three';

import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';

export const DebugManager = (
camera: THREE.Camera,
Expand Down
2 changes: 1 addition & 1 deletion src/manager/GrassManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type * as THREE from 'three';

import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';
import {
GRID_HEIGHT,
GRID_WIDTH,
Expand Down
2 changes: 1 addition & 1 deletion src/manager/GroundManager2.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as THREE from 'three';

import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';
import type { CylinderGeometry2 } from '../components/CylinderGeometry2';
import { Ground } from '../components/Ground2';
import { STEP_ANGLE } from '../constants/ground';
Expand Down
2 changes: 1 addition & 1 deletion src/manager/GroundObjectManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type * as THREE from 'three';

import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';
import { GroundObject } from '../components/GroundObject';
import { STEP_ANGLE } from '../constants/ground';
import { CompressedTexture } from '../utils/CompressedTexture';
Expand Down
2 changes: 1 addition & 1 deletion src/manager/SkyBoxManager.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type * as THREE from 'three';

import type { ResourceTracker } from '../ResourceTracker';
import type { ResourceTracker } from '../utils/ResourceTracker';
import { SkyBox } from '../components/SkyBox';
import { THEME_VALUE } from './ColorManager';

Expand Down
132 changes: 86 additions & 46 deletions src/manager/StoryManager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import debug from 'debug';
import { Clip, Mp3DeMuxAdapter } from '@web-media/phonograph';
import { type DataItem, Timeline, type DataItemCollectionType, type TimelineOptions } from 'vis-timeline';
import 'vis-timeline/dist/vis-timeline-graph2d.css';

import { THEME_ID } from './ColorManager';

Expand All @@ -13,6 +15,7 @@ import { QUERY_PARAMETER, ROUTER_ID, isStory } from '../stores/router';
import { type ITimelineEvent, TimelineManager } from '../utils/TimeLine';

import { timeManager } from './TimeManager';
import { forceSelect } from '../utils/forceSelect';

export const STORY_AUDIO_URL_BASE = 'https://resource.alice.is.not.ci/';

Expand All @@ -22,70 +25,107 @@ const logEnd = log.extend('end');
const logTheme = log.extend('theme');
const logLowRpm = log.extend('low-rpm');

export const timeLine = new TimelineManager(
stories,
{
audio: (x: ITimelineEvent<'audio', IPlayAudioStoryEvent>) => {
const clip = new Clip({
context: globalAudioContext,
url: STORY_AUDIO_URL_BASE + x.detail.url,
adapter: new Mp3DeMuxAdapter(),
});
export const timeLine = new TimelineManager(stories, {
audio: (x: ITimelineEvent<'audio', IPlayAudioStoryEvent>) => {
const clip = new Clip({
context: globalAudioContext,
url: STORY_AUDIO_URL_BASE + x.detail.url,
adapter: new Mp3DeMuxAdapter(),
});

const id = x.detail.url;
const id = x.detail.url;

logAudio(`[load] [start] ${id}`);
clip.canPlayThough.then((x) => {
logAudio(`[play] [start] ${id}`);
clip.play().then((x) => {
logAudio(`[play] [ end ] ${id}`);
});
logAudio(`[load] [start] ${id}`);
clip.canPlayThough.then((x) => {
logAudio(`[play] [start] ${id}`);
clip.play().then((x) => {
logAudio(`[play] [ end ] ${id}`);
});
});

clip.buffer().then(async () => {
logAudio(`[load] [ end ] ${id}`);
});
clip.buffer().then(async () => {
logAudio(`[load] [ end ] ${id}`);
});

return () => {
clip.dispose();
};
},
end: (x: ITimelineEvent<'end', null>) => {
logEnd('Session finished');
const $finishTraining = document.querySelector('.finish-training') as HTMLDivElement | null;
if ($finishTraining) {
$finishTraining.click();
}
},
theme: (x: ITimelineEvent<'theme', string>) => {
logTheme(x.detail);
THEME_ID.value = x.detail;
},
lowRpm: (x: ITimelineEvent<'lowRpm', number>) => {
logLowRpm(x.detail);
const d = DIFFICULTY.value;
LOW_LIMIT.value = x.detail + ((d > 0) ? (d * (-1/120 * d + 5 / 2)) : d);
},
debugAlert: (x: ITimelineEvent<'debugAlert', string>) => {
alert(x.detail);
},
return () => {
clip.dispose();
};
},
end: (x: ITimelineEvent<'end', null>) => {
logEnd('Session finished');
const $finishTraining = document.querySelector(
'.finish-training',
) as HTMLDivElement | null;
if ($finishTraining) {
$finishTraining.click();
}
},
theme: (x: ITimelineEvent<'theme', string>) => {
logTheme(x.detail);
THEME_ID.value = x.detail;
},
);
lowRpm: (x: ITimelineEvent<'lowRpm', number>) => {
logLowRpm(x.detail);
const d = DIFFICULTY.value;
LOW_LIMIT.value = x.detail + (d > 0 ? d * ((-1 / 120) * d + 5 / 2) : d);
},
debugAlert: (x: ITimelineEvent<'debugAlert', string>) => {
alert(x.detail);
},
});

// @ts-ignore
window.nextEvent = timeLine.nextEvent;

export const StoryManager = () => {
ROUTER_ID.subscribe(() => {
ROUTER_ID.subscribe(() => {
if (isStory()) {
const episode = Math.floor(Number.parseFloat(QUERY_PARAMETER.value.get('episode') ?? '0'));
const episode = Math.floor(
Number.parseFloat(QUERY_PARAMETER.value.get('episode') ?? '0'),
);

timeLine.storyId = episode;

timeManager.addFn(timeLine.tick, FrameRateLevel.D0);
} else {
timeManager.removeFn(timeLine.tick);
timeLine.reset();
}
});
};

const convertTime = (totalMilliseconds: number) => {
const milliseconds = totalMilliseconds % 1000;
const totalSeconds = Math.floor(totalMilliseconds / 1000);
const seconds = totalSeconds % 60;
const totalMinutes = Math.floor(totalSeconds / 60);
const minutes = totalMinutes % 60;
const hours = Math.floor(totalMinutes / 60);

return new Date(0, 0, 0, hours, minutes, seconds, milliseconds);
};

const convertStory = (x: ITimelineEvent<string, unknown>[]): DataItem[] => x.map((x, index) => ({
id: index,
content: x.label,
start: convertTime(x.time),
className: x.type,
}));

export const visualizeStory = (index = 0) => {
const container = forceSelect<HTMLDivElement>('#story-visualize');

const items: DataItemCollectionType = convertStory(stories[index]);

const options: TimelineOptions = {
height: '30vh',
timeAxis: { scale: 'minute', step: 2 },
showMajorLabels: false,
};

// Create a Timeline
const timeline = new Timeline(container, items, options);
};

// @ts-ignore
window.visualizeStory = visualizeStory;
5 changes: 5 additions & 0 deletions src/stories/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export const AudioEvent = (
): ITimelineEvent<"audio", IPlayAudioStoryEvent> => ({
time,
type: "audio",
label: url,
detail: {
url,
},
Expand All @@ -22,6 +23,7 @@ export const AudioEvent = (
export const EndEvent = (time: number): ITimelineEvent<"end", null> => ({
time,
type: "end",
label: "end",
detail: null,
});

Expand All @@ -31,6 +33,7 @@ export const ThemeEvent = (
): ITimelineEvent<"theme", string> => ({
time,
type: "theme",
label: `theme: ${theme}`,
detail: theme,
});

Expand All @@ -40,6 +43,7 @@ export const LowRpmLimitEvent = (
): ITimelineEvent<"lowRpm", number> => ({
time,
type: "lowRpm",
label: `low-rpm: ${rpm}`,
detail: rpm,
});

Expand All @@ -48,6 +52,7 @@ export const DebugAlertEvent = (
text: string
): ITimelineEvent<"debugAlert", string> => ({
time,
label: `alert: ${text}`,
type: "debugAlert",
detail: text,
});
1 change: 1 addition & 0 deletions src/ResourceTracker.ts → src/utils/ResourceTracker.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// biome-ignore lint/suspicious/noExplicitAny: This is safe
type Any = any;

interface IDisposable extends Any {
Expand Down
1 change: 1 addition & 0 deletions src/utils/TimeLine.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface ITimelineEvent<Type extends string, Detail> {
time: number;
type: Type;
label: string;
detail: Detail;
}

Expand Down
Loading

0 comments on commit 4bfdd44

Please sign in to comment.