Skip to content

Commit 98ba48b

Browse files
authored
Small improvements (#42)
* add euler to lib * quick scene navigate
1 parent 4ce5792 commit 98ba48b

11 files changed

Lines changed: 78 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ All notable changes to this project will be documented in this file, following t
1111
- User quota management (100 sessions/states per user)
1212
- Docker containerization with production deployment configuration
1313
- Comprehensive test suite with pytest coverage
14-
- `Vec3`, `Mat3`, `Mat4`, `Quat` accessible in the code editor
14+
- `Vec3`, `Mat3`, `Mat4`, `Quat`, `Euler` accessible in the code editor
1515

1616
### Changed
1717
- **Session Upload Optimization**: Replaced base64 encoding with native FormData uploads

scripts/process-mvs-types.mjs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import fs from 'fs';
33
let data = fs.readFileSync('./tmp/mvs.d.ts', 'utf-8');
44
data = data.replaceAll('`', '\\`').replaceAll('${', '\\${').replaceAll(/(\r\n|\n|\r)/g, '\n');
55

6+
const lib = ['Vec3', 'Mat3', 'Mat4', 'Quat', 'Euler'];
7+
68
const lines = data.split('\n'); // .filter(line => !line.startsWith('export '));
79
const final = [
810
'// Automatically generated file. Do not edit manually.',
@@ -14,10 +16,7 @@ const final = [
1416
'}',
1517
'',
1618
'declare const builder: _.Builder;',
17-
'declare const Vec3: typeof _.Vec3;',
18-
'declare const Mat3: typeof _.Mat3;',
19-
'declare const Mat4: typeof _.Mat4;',
20-
'declare const Quat: typeof _.Quat;',
19+
...lib.map(name => `declare const ${name}: typeof _.${name};`),
2120
'`;',
2221
];
2322

scripts/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as _ from '../node_modules/molstar/lib/extensions/mvs/mvs-data.d.ts';
22
export { Vec3, Mat3, Mat4, Quat } from '../node_modules/molstar/lib/mol-math/linear-algebra.d.ts';
3+
export { Euler } from '../node_modules/molstar/lib/mol-math/linear-algebra/3d/euler.d.ts';
34

45
export type Builder = ReturnType<typeof _.MVSData.createBuilder>;

src/app/examples/empty.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { UUID } from 'molstar/lib/mol-util';
22
import { Story } from '../state/types';
3+
import { BuilderLibNamespaces } from '../state/actions';
34

4-
const LibraryFns = `// Mol* library functions: Vec3, Mat3, Mat4, Quat`;
5+
const LibraryFns = `// Mol* library functions: ${BuilderLibNamespaces.join(', ')}\n`;
56

67
export const EmptyStory: Story = {
78
metadata: { title: 'New Story' },

src/app/state/actions.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { MVSData, Snapshot } from 'molstar/lib/extensions/mvs/mvs-data';
3333
import { Mat3, Mat4, Quat, Vec3 } from 'molstar/lib/mol-math/linear-algebra';
3434
import { tryFindIfStoryIsShared } from '@/lib/data-utils';
3535
import { toast } from 'sonner';
36+
import { Euler } from 'molstar/lib/mol-math/linear-algebra/3d/euler';
3637

3738
// Extended session interface that may include story data
3839
export interface SessionWithData extends SessionItem {
@@ -91,21 +92,33 @@ export function newStory() {
9192
setSessionIdUrl(undefined);
9293
}
9394

95+
// Should be sync with typing generation in the scripts directory
96+
const BuilderLib = {
97+
Vec3,
98+
Mat3,
99+
Mat4,
100+
Quat,
101+
Euler,
102+
};
103+
104+
export const BuilderLibNamespaces = Object.keys(BuilderLib);
105+
94106
const createStateProvider = (code: string) => {
95-
return new Function('builder', 'index', 'Vec3', 'Mat3', 'Mat4', 'Quat', code);
107+
return new Function('builder', 'index', '__lib__', code);
96108
};
97109

98110
async function getMVSSnapshot(story: Story, scene: SceneData, index: number) {
99111
try {
100112
const stateProvider = createStateProvider(`
113+
const { ${Object.keys(BuilderLib).join(', ')} } = __lib__;
101114
async function _run_builder() {
102115
${story.javascript}\n\n${scene.javascript}
103116
}
104117
return _run_builder();
105118
`);
106119
const builder = MVSData.createBuilder();
107120
toast.dismiss('state-build-error');
108-
await stateProvider(builder, index, Vec3, Mat3, Mat4, Quat);
121+
await stateProvider(builder, index, BuilderLib);
109122
if (scene.camera) {
110123
builder.camera({
111124
position: adjustedCameraPosition(scene.camera),

src/app/version.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export const APP_VERSION = '1.0.0-beta.6';
1+
export const APP_VERSION = '1.0.0-beta.7';

src/components/story-builder/Toolbar.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import { Menubar } from '@/components/ui/menubar';
44
import { Separator } from '@/components/ui/separator';
55
import { SceneMenu, StoryPreview, StoryOptions, SceneSelector } from './menus';
6+
import { Button } from '../ui/button';
7+
import { ChevronLeft, ChevronRight } from 'lucide-react';
8+
import { useAtom, useAtomValue } from 'jotai';
9+
import { ActiveSceneAtom, CurrentViewAtom, StoryAtom } from '@/app/appstate';
610

711
export function StoriesToolBar() {
812
return (
@@ -30,6 +34,8 @@ export function StoriesToolBar() {
3034
<SceneMenu />
3135
<Separator orientation='vertical' className='h-6' />
3236
<SceneSelector />
37+
<NextScene dir={-1} />
38+
<NextScene dir={1} />
3339
</Menubar>
3440
</div>
3541
</div>
@@ -49,3 +55,34 @@ export function StoriesToolBar() {
4955
</>
5056
);
5157
}
58+
59+
function NextScene({ dir }: { dir: -1 | 1 }) {
60+
const [currentView, setCurrentView] = useAtom(CurrentViewAtom);
61+
const story = useAtomValue(StoryAtom);
62+
const activeScene = useAtomValue(ActiveSceneAtom);
63+
64+
const Icon = dir < 0 ? ChevronLeft : ChevronRight;
65+
const onClick = () => {
66+
if (currentView.type !== 'scene') {
67+
setCurrentView({ type: 'scene', id: story.scenes[0].id.toString(), subview: 'scene-options' });
68+
return;
69+
}
70+
71+
let idx = story.scenes.findIndex((s) => s.id === activeScene.id);
72+
idx += dir;
73+
if (idx < 0) idx = story.scenes.length - 1;
74+
if (idx >= story.scenes.length) idx = 0;
75+
76+
setCurrentView({ type: 'scene', id: story.scenes[idx].id.toString(), subview: 'scene-options' });
77+
};
78+
return (
79+
<Button
80+
className='text-sm has-[>svg]:px-1 cursor-pointer rounded-none'
81+
variant='link'
82+
onClick={onClick}
83+
title={dir < 0 ? 'Previous Scene' : 'Next Scene'}
84+
>
85+
<Icon className='size-4' />
86+
</Button>
87+
);
88+
}

src/components/story-builder/editors/StoryCodeEditor.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Editor, { OnMount } from '@monaco-editor/react';
55
import * as monaco from 'monaco-editor';
66
import { useAtom } from 'jotai';
77
import { useEffect, useRef, useState } from 'react';
8+
import { setupMonacoCodeCompletion } from './common';
89

910
export function StoryCodeEditor() {
1011
const [story, setStory] = useAtom(StoryAtom);
@@ -32,6 +33,7 @@ export function StoryCodeEditor() {
3233

3334
const handleEditorDidMount: OnMount = (editor, monaco) => {
3435
editorRef.current = editor;
36+
setupMonacoCodeCompletion(monaco);
3537
editor.layout();
3638

3739
// Add Alt+S keyboard shortcut for saving markdown

src/components/story-builder/editors/common.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import { MVSTypes } from './mvs-typing';
33

44
export function setupMonacoCodeCompletion(monaco: Monaco) {
55
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
6-
monaco.languages.typescript.javascriptDefaults.addExtraLib(MVSTypes, 'ts:mvs.d.ts');
6+
const extraLibs = monaco.languages.typescript.javascriptDefaults.getExtraLibs();
7+
if (!('ts:mvs.d.ts' in extraLibs)) {
8+
monaco.languages.typescript.javascriptDefaults.addExtraLib(MVSTypes, 'ts:mvs.d.ts');
9+
}
710
monaco.languages.typescript.javascriptDefaults.setCompilerOptions({
811
target: monaco.languages.typescript.ScriptTarget.ES2020,
912
allowNonTsExtensions: true,

src/components/story-builder/editors/mvs-typing.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2963,7 +2963,7 @@ namespace _ {
29632963
29642964
type Builder = ReturnType<typeof MVSData.createBuilder>;
29652965
2966-
export { Mat3, Mat4, Quat, Vec3 };
2966+
export { Euler, Mat3, Mat4, Quat, Vec3 };
29672967
export type { Builder };
29682968
29692969
}
@@ -2973,4 +2973,5 @@ declare const Vec3: typeof _.Vec3;
29732973
declare const Mat3: typeof _.Mat3;
29742974
declare const Mat4: typeof _.Mat4;
29752975
declare const Quat: typeof _.Quat;
2976+
declare const Euler: typeof _.Euler;
29762977
`;

0 commit comments

Comments
 (0)