Skip to content

Commit 345ebf1

Browse files
authored
refactor(voxel-map): implement new features (#255)
feat(voxel-map): implement minimal LocalStorage persistence refactor(voxel-map): replace window.prompt with a PromptDialog component feat(voxel-map): pixel-draw texture editing chore: add transparent material chore: remove old code
1 parent 09c7b05 commit 345ebf1

22 files changed

+1572
-424
lines changed

packages/editors/voxel-map/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"type": "module",
55
"scripts": {
66
"prepublish": "rimraf ./dist && tsc -b",
7-
"test": "node --test test/**/*.test.ts",
87
"check:ts": "tsc --noEmit",
98
"dev": "vite",
109
"build": "vite build",
@@ -28,11 +27,13 @@
2827
"dependencies": {
2928
"@jolly-pixel/engine": "^2.0.0",
3029
"@jolly-pixel/fs-tree": "^1.0.0",
30+
"@jolly-pixel/pixel-draw.renderer": "1.0.0",
3131
"@jolly-pixel/resize-handle": "1.0.0",
3232
"@jolly-pixel/runtime": "^3.0.0",
3333
"@jolly-pixel/voxel.renderer": "1.4.0",
3434
"lit": "3.3.2",
35-
"three": "^0.183.1"
35+
"three": "^0.183.1",
36+
"vanilla-picker": "2.12.3"
3637
},
3738
"devDependencies": {
3839
"@types/three": "^0.182.0"

packages/editors/voxel-map/src/EditorState.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export class EditorState extends EventTarget {
1717
#selectedBlockId: number = 1;
1818
#brushSize: number = 1;
1919
#rotationMode: RotationMode = "auto";
20+
#flipY: boolean = false;
2021
#activeSidebarTab: SidebarTab = "general";
2122
#isGizmoDragging = false;
2223
#gizmoLayer: string | null = null;
@@ -41,6 +42,10 @@ export class EditorState extends EventTarget {
4142
return this.#rotationMode;
4243
}
4344

45+
get flipY(): boolean {
46+
return this.#flipY;
47+
}
48+
4449
get activeSidebarTab(): SidebarTab {
4550
return this.#activeSidebarTab;
4651
}
@@ -151,6 +156,19 @@ export class EditorState extends EventTarget {
151156
this.dispatchEvent(new CustomEvent("change"));
152157
}
153158

159+
setFlipY(
160+
val: boolean
161+
): void {
162+
if (this.#flipY === val) {
163+
return;
164+
}
165+
this.#flipY = val;
166+
this.dispatchEvent(
167+
new CustomEvent("flipYChange", { detail: val })
168+
);
169+
this.dispatchEvent(new CustomEvent("change"));
170+
}
171+
154172
setActiveSidebarTab(
155173
tab: SidebarTab
156174
): void {

packages/editors/voxel-map/src/components/FreeFlyCamera.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class FreeFlyCamera extends CameraComponent {
5252
moveSpeed = 12,
5353
mouseSensitivity = 0.003,
5454
maxPitch = Math.PI / 2 - 0.01,
55-
scrollSpeed = 8,
55+
scrollSpeed = 2.5,
5656
yaw = 0,
5757
pitch = -0.2,
5858
friction = 0.24
@@ -109,7 +109,6 @@ export class FreeFlyCamera extends CameraComponent {
109109
this.camera.getWorldDirection(this.#forward);
110110
this.#forward.y = 0;
111111
this.#forward.normalize();
112-
113112
this.#right.crossVectors(this.#forward, this.#up).normalize();
114113

115114
// --- Accumulate movement intent ---

packages/editors/voxel-map/src/components/GridRenderer.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,15 @@ export class GridRenderer extends ActorComponent {
146146
}
147147

148148
#buildGrid(): void {
149-
const e = this.#extent;
150-
const bs = this.#blockSize;
149+
const extent = this.#extent;
150+
const blockSize = this.#blockSize;
151151
const positions: number[] = [];
152152

153-
for (let i = -e; i <= e; i += bs) {
153+
for (let i = -extent; i <= extent; i += blockSize) {
154154
// Line parallel to X axis
155-
positions.push(-e, 0, i, e, 0, i);
155+
positions.push(-extent, 0, i, extent, 0, i);
156156
// Line parallel to Z axis
157-
positions.push(i, 0, -e, i, 0, e);
157+
positions.push(i, 0, -extent, i, 0, extent);
158158
}
159159

160160
const geo = new LineSegmentsGeometry();
Lines changed: 19 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
// Import Third-party Dependencies
22
import * as THREE from "three";
3-
import { Actor, ActorComponent } from "@jolly-pixel/engine";
4-
import { TransformControls } from "three/addons/controls/TransformControls.js";
5-
import type { VoxelRenderer, VoxelLayerHookEvent } from "@jolly-pixel/voxel.renderer";
3+
import { type Actor } from "@jolly-pixel/engine";
4+
import type {
5+
VoxelRenderer,
6+
VoxelLayerHookEvent
7+
} from "@jolly-pixel/voxel.renderer";
68

79
// Import Internal Dependencies
810
import { editorState } from "../EditorState.ts";
11+
import { TransformGizmoBase } from "./TransformGizmoBase.ts";
912

1013
export interface LayerGizmoOptions {
1114
vr: VoxelRenderer;
@@ -17,48 +20,33 @@ export interface LayerGizmoOptions {
1720
* Uses THREE.js TransformControls
1821
* Activate by calling setActiveLayer(name) from the Layer panel.
1922
*/
20-
export class LayerGizmo extends ActorComponent {
21-
#controls: TransformControls | null = null;
22-
#helper: THREE.Object3D | null = null;
23+
export class LayerGizmo extends TransformGizmoBase {
2324
#pivot = new THREE.Object3D();
2425
#pivotOffset = new THREE.Vector3();
2526
#activeLayer: string | null = null;
2627
#vr: VoxelRenderer;
27-
#camera: THREE.PerspectiveCamera;
2828

2929
constructor(
3030
actor: Actor,
3131
options: LayerGizmoOptions
3232
) {
33-
super({
34-
actor,
35-
typeName: "LayerGizmo"
36-
});
37-
33+
super(actor, options, "LayerGizmo");
3834
this.#vr = options.vr;
39-
this.#camera = options.camera;
4035
}
4136

42-
awake() {
43-
const canvas = this.actor.world.renderer.canvas;
44-
const scene = this.actor.world.sceneManager.getSource();
45-
46-
// Pivot is the object TransformControls manipulates.
47-
scene.add(this.#pivot);
37+
override awake(): void {
38+
super.awake();
4839

49-
this.#controls = new TransformControls(this.#camera, canvas);
50-
this.#controls.setMode("translate");
51-
this.#controls.setSpace("world");
52-
this.#controls.setTranslationSnap(1);
40+
this.controls!.setSpace("world");
41+
this.controls!.setTranslationSnap(1);
5342

54-
// getHelper() returns the Object3D that must live in the scene.
55-
this.#helper = this.#controls.getHelper();
56-
scene.add(this.#helper);
43+
// Pivot is the object TransformControls manipulates.
44+
this.actor.addChildren(this.#pivot);
5745

5846
// Apply offset when pivot is dragged.
5947
// The pivot sits at the voxel-content center, so subtract #pivotOffset
6048
// (center − original offset) to recover the true layer offset.
61-
this.#controls.addEventListener("objectChange", () => {
49+
this.controls!.addEventListener("objectChange", () => {
6250
if (!this.#activeLayer) {
6351
return;
6452
}
@@ -70,13 +58,6 @@ export class LayerGizmo extends ActorComponent {
7058
});
7159
});
7260

73-
// Block voxel painting while a handle is being dragged.
74-
this.#controls.addEventListener("dragging-changed", (event) => {
75-
editorState.setGizmoDragging(
76-
(event as THREE.Event & { value: boolean; }).value
77-
);
78-
});
79-
8061
// Show/hide the gizmo when the user toggles it from the layer list.
8162
editorState.addEventListener("gizmoLayerChange", () => {
8263
this.setActiveLayer(editorState.gizmoLayer);
@@ -104,24 +85,24 @@ export class LayerGizmo extends ActorComponent {
10485
): void {
10586
this.#activeLayer = name;
10687

107-
if (!this.#controls) {
88+
if (!this.controls) {
10889
return;
10990
}
11091

11192
if (!name) {
112-
this.#controls.detach();
93+
this.controls.detach();
11394

11495
return;
11596
}
11697

11798
if (!this.#vr.getLayer(name)) {
118-
this.#controls.detach();
99+
this.controls.detach();
119100

120101
return;
121102
}
122103

123104
this.#repositionPivot();
124-
this.#controls.attach(this.#pivot);
105+
this.controls.attach(this.#pivot);
125106
}
126107

127108
#repositionPivot(): void {
@@ -142,20 +123,4 @@ export class LayerGizmo extends ActorComponent {
142123
);
143124
this.#pivot.position.copy(center);
144125
}
145-
146-
override destroy(): void {
147-
const scene = this.actor.world.sceneManager.getSource();
148-
if (this.#helper) {
149-
scene.remove(this.#helper);
150-
}
151-
152-
if (this.#controls) {
153-
this.#controls.detach();
154-
this.#controls.dispose();
155-
this.#controls = null;
156-
}
157-
scene.remove(this.#pivot);
158-
159-
super.destroy();
160-
}
161126
}

0 commit comments

Comments
 (0)