create-shallot 0.3.9 → 0.5.0

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.
Files changed (2) hide show
  1. package/index.ts +80 -15
  2. package/package.json +1 -1
package/index.ts CHANGED
@@ -42,6 +42,14 @@ writeFileSync(
42
42
  `,
43
43
  );
44
44
 
45
+ writeFileSync(
46
+ join(dir, ".gitignore"),
47
+ `node_modules/
48
+ dist/
49
+ build/
50
+ `,
51
+ );
52
+
45
53
  writeFileSync(
46
54
  join(dir, "package.json"),
47
55
  JSON.stringify(
@@ -50,9 +58,34 @@ writeFileSync(
50
58
  version: "0.0.0",
51
59
  private: true,
52
60
  type: "module",
53
- scripts: { dev: "vite" },
61
+ scripts: {
62
+ dev: "vite",
63
+ build: "vite build",
64
+ preview: "vite preview",
65
+ },
54
66
  dependencies: { "@dylanebert/shallot": "latest" },
55
- devDependencies: { vite: "^8.0.0" },
67
+ devDependencies: { typescript: "^5.9.3", vite: "^8.0.0" },
68
+ },
69
+ null,
70
+ 2,
71
+ ) + "\n",
72
+ );
73
+
74
+ writeFileSync(
75
+ join(dir, "tsconfig.json"),
76
+ JSON.stringify(
77
+ {
78
+ compilerOptions: {
79
+ target: "ESNext",
80
+ module: "ESNext",
81
+ moduleResolution: "bundler",
82
+ lib: ["ESNext", "DOM", "DOM.Iterable"],
83
+ types: ["@webgpu/types", "vite/client"],
84
+ strict: true,
85
+ noEmit: true,
86
+ skipLibCheck: true,
87
+ },
88
+ include: ["src"],
56
89
  },
57
90
  null,
58
91
  2,
@@ -66,11 +99,11 @@ writeFileSync(
66
99
  <head>
67
100
  <meta charset="UTF-8" />
68
101
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
69
- <link rel="icon" type="image/svg+xml" href="/icon.svg" />
102
+ <link rel="icon" type="image/svg+xml" href="./icon.svg" />
70
103
  <title>${name}</title>
71
104
  <style>
72
105
  * { box-sizing: border-box; margin: 0; padding: 0; }
73
- body { background: #0a0a0a; overflow: hidden; }
106
+ body { background: #0c0a09; overflow: hidden; }
74
107
  canvas { display: block; width: 100vw; height: 100vh; }
75
108
  </style>
76
109
  </head>
@@ -87,19 +120,44 @@ writeFileSync(
87
120
  `import { defineConfig } from "vite";
88
121
 
89
122
  export default defineConfig({
123
+ base: "./",
90
124
  server: { port: 3000 },
91
- build: { target: "esnext" },
125
+ build: {
126
+ target: "esnext",
127
+ outDir: "dist",
128
+ emptyOutDir: true,
129
+ },
92
130
  });
93
131
  `,
94
132
  );
95
133
 
96
134
  writeFileSync(
97
135
  join(dir, "src/lib.ts"),
98
- `import { OrbitPlugin, type Config } from "@dylanebert/shallot";
136
+ `import { type Config, Part, quat, type State, type System, Transform } from "@dylanebert/shallot";
137
+
138
+ // A system is plain data: an \`update\` the engine runs each frame. This one spins
139
+ // every Part around Y. It runs in the standalone app but not the editor — \`shallot .\`
140
+ // builds in edit mode, where unannotated systems are skipped, so the cube stays put
141
+ // and editable there. Delete it (and the plugin entry below) for a static scene.
142
+ let angle = 0;
143
+ const SpinSystem: System = {
144
+ group: "simulation",
145
+ update(state: State) {
146
+ angle = (angle + state.time.deltaTime * 45) % 360;
147
+ const q = quat(0, angle, 0);
148
+ for (const eid of state.query([Part, Transform])) {
149
+ Transform.rot.set(eid, q.x, q.y, q.z, q.w);
150
+ }
151
+ },
152
+ };
99
153
 
154
+ // The project definition, shared by the standalone app (src/main.ts) and the shallot
155
+ // editor (\`shallot .\`). The default plugins (render, lit surface, orbit camera) stay
156
+ // on; the spin plugin adds our one system. The scene lives here too, so main.ts stays
157
+ // untouched as the project grows.
100
158
  export const config: Config = {
101
- plugins: [OrbitPlugin],
102
- scene: "/scenes/demo.scene",
159
+ plugins: [{ name: "spin", systems: [SpinSystem] }],
160
+ scene: "scenes/scene.scene",
103
161
  };
104
162
  `,
105
163
  );
@@ -109,21 +167,28 @@ writeFileSync(
109
167
  `import { run } from "@dylanebert/shallot";
110
168
  import { config } from "./lib";
111
169
 
112
- const state = await run(config);
170
+ // One config source (src/lib.ts) drives both this standalone build and the editor. The camera
171
+ // auto-binds to the page's <canvas>.
172
+ const { dispose } = await run(config);
113
173
 
174
+ // HMR re-runs this module — dispose the old State + RAF loop or each reload stacks another.
114
175
  if (import.meta.hot) {
115
- import.meta.hot.dispose(() => state.dispose());
176
+ import.meta.hot.dispose(() => dispose());
116
177
  }
117
178
  `,
118
179
  );
119
180
 
120
181
  writeFileSync(
121
- join(dir, "public/scenes/demo.scene"),
182
+ join(dir, "public/scenes/scene.scene"),
122
183
  `<scene>
123
- <a id="camera" camera fxaa orbit tonemap transform />
124
- <a ambient-light />
125
- <a directional-light />
126
- <a id="cube" part="shape: box; color: 0xc77b58" transform />
184
+ <a ambient-light="color: 0xd0dcec; intensity: 0.5" />
185
+ <a directional-light="direction: -0.4 -1 -0.55; color: 0xfff4e0; intensity: 1.1" />
186
+
187
+ <!-- the camera auto-binds to the page's <canvas>; drag to orbit, scroll to zoom -->
188
+ <a camera sear orbit="distance: 5; yaw: 0.6; pitch: 0.25" transform />
189
+
190
+ <!-- a Part is the engine's drop-in renderable: a mesh (default "cube") wearing a surface (default "default", lit) -->
191
+ <a part transform="pos: 0 0 0" color="rgba: 0.85 0.55 0.35 1" />
127
192
  </scene>
128
193
  `,
129
194
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-shallot",
3
- "version": "0.3.9",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "bin": "./index.ts",
6
6
  "files": ["index.ts"],