Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/editors/voxel-map/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"type": "module",
"scripts": {
"prepublish": "rimraf ./dist && tsc -b",
"test": "node --test test/**/*.test.ts",
"check:ts": "tsc --noEmit",
"dev": "vite",
"build": "vite build",
Expand All @@ -28,11 +27,13 @@
"dependencies": {
"@jolly-pixel/engine": "^2.0.0",
"@jolly-pixel/fs-tree": "^1.0.0",
"@jolly-pixel/pixel-draw.renderer": "1.0.0",
"@jolly-pixel/resize-handle": "1.0.0",
"@jolly-pixel/runtime": "^3.0.0",
"@jolly-pixel/voxel.renderer": "1.4.0",
"lit": "3.3.2",
"three": "^0.183.1"
"three": "^0.183.1",
"vanilla-picker": "2.12.3"
},
"devDependencies": {
"@types/three": "^0.182.0"
Expand Down
18 changes: 18 additions & 0 deletions packages/editors/voxel-map/src/EditorState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class EditorState extends EventTarget {
#selectedBlockId: number = 1;
#brushSize: number = 1;
#rotationMode: RotationMode = "auto";
#flipY: boolean = false;
#activeSidebarTab: SidebarTab = "general";
#isGizmoDragging = false;
#gizmoLayer: string | null = null;
Expand All @@ -41,6 +42,10 @@ export class EditorState extends EventTarget {
return this.#rotationMode;
}

get flipY(): boolean {
return this.#flipY;
}

get activeSidebarTab(): SidebarTab {
return this.#activeSidebarTab;
}
Expand Down Expand Up @@ -151,6 +156,19 @@ export class EditorState extends EventTarget {
this.dispatchEvent(new CustomEvent("change"));
}

setFlipY(
val: boolean
): void {
if (this.#flipY === val) {
return;
}
this.#flipY = val;
this.dispatchEvent(
new CustomEvent("flipYChange", { detail: val })
);
this.dispatchEvent(new CustomEvent("change"));
}

setActiveSidebarTab(
tab: SidebarTab
): void {
Expand Down
3 changes: 1 addition & 2 deletions packages/editors/voxel-map/src/components/FreeFlyCamera.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export class FreeFlyCamera extends CameraComponent {
moveSpeed = 12,
mouseSensitivity = 0.003,
maxPitch = Math.PI / 2 - 0.01,
scrollSpeed = 8,
scrollSpeed = 2.5,
yaw = 0,
pitch = -0.2,
friction = 0.24
Expand Down Expand Up @@ -109,7 +109,6 @@ export class FreeFlyCamera extends CameraComponent {
this.camera.getWorldDirection(this.#forward);
this.#forward.y = 0;
this.#forward.normalize();

this.#right.crossVectors(this.#forward, this.#up).normalize();

// --- Accumulate movement intent ---
Expand Down
10 changes: 5 additions & 5 deletions packages/editors/voxel-map/src/components/GridRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,15 +146,15 @@ export class GridRenderer extends ActorComponent {
}

#buildGrid(): void {
const e = this.#extent;
const bs = this.#blockSize;
const extent = this.#extent;
const blockSize = this.#blockSize;
const positions: number[] = [];

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

const geo = new LineSegmentsGeometry();
Expand Down
73 changes: 19 additions & 54 deletions packages/editors/voxel-map/src/components/LayerGizmo.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
// Import Third-party Dependencies
import * as THREE from "three";
import { Actor, ActorComponent } from "@jolly-pixel/engine";
import { TransformControls } from "three/addons/controls/TransformControls.js";
import type { VoxelRenderer, VoxelLayerHookEvent } from "@jolly-pixel/voxel.renderer";
import { type Actor } from "@jolly-pixel/engine";
import type {
VoxelRenderer,
VoxelLayerHookEvent
} from "@jolly-pixel/voxel.renderer";

// Import Internal Dependencies
import { editorState } from "../EditorState.ts";
import { TransformGizmoBase } from "./TransformGizmoBase.ts";

export interface LayerGizmoOptions {
vr: VoxelRenderer;
Expand All @@ -17,48 +20,33 @@ export interface LayerGizmoOptions {
* Uses THREE.js TransformControls
* Activate by calling setActiveLayer(name) from the Layer panel.
*/
export class LayerGizmo extends ActorComponent {
#controls: TransformControls | null = null;
#helper: THREE.Object3D | null = null;
export class LayerGizmo extends TransformGizmoBase {
#pivot = new THREE.Object3D();
#pivotOffset = new THREE.Vector3();
#activeLayer: string | null = null;
#vr: VoxelRenderer;
#camera: THREE.PerspectiveCamera;

constructor(
actor: Actor,
options: LayerGizmoOptions
) {
super({
actor,
typeName: "LayerGizmo"
});

super(actor, options, "LayerGizmo");
this.#vr = options.vr;
this.#camera = options.camera;
}

awake() {
const canvas = this.actor.world.renderer.canvas;
const scene = this.actor.world.sceneManager.getSource();

// Pivot is the object TransformControls manipulates.
scene.add(this.#pivot);
override awake(): void {
super.awake();

this.#controls = new TransformControls(this.#camera, canvas);
this.#controls.setMode("translate");
this.#controls.setSpace("world");
this.#controls.setTranslationSnap(1);
this.controls!.setSpace("world");
this.controls!.setTranslationSnap(1);

// getHelper() returns the Object3D that must live in the scene.
this.#helper = this.#controls.getHelper();
scene.add(this.#helper);
// Pivot is the object TransformControls manipulates.
this.actor.addChildren(this.#pivot);

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

// Block voxel painting while a handle is being dragged.
this.#controls.addEventListener("dragging-changed", (event) => {
editorState.setGizmoDragging(
(event as THREE.Event & { value: boolean; }).value
);
});

// Show/hide the gizmo when the user toggles it from the layer list.
editorState.addEventListener("gizmoLayerChange", () => {
this.setActiveLayer(editorState.gizmoLayer);
Expand Down Expand Up @@ -104,24 +85,24 @@ export class LayerGizmo extends ActorComponent {
): void {
this.#activeLayer = name;

if (!this.#controls) {
if (!this.controls) {
return;
}

if (!name) {
this.#controls.detach();
this.controls.detach();

return;
}

if (!this.#vr.getLayer(name)) {
this.#controls.detach();
this.controls.detach();

return;
}

this.#repositionPivot();
this.#controls.attach(this.#pivot);
this.controls.attach(this.#pivot);
}

#repositionPivot(): void {
Expand All @@ -142,20 +123,4 @@ export class LayerGizmo extends ActorComponent {
);
this.#pivot.position.copy(center);
}

override destroy(): void {
const scene = this.actor.world.sceneManager.getSource();
if (this.#helper) {
scene.remove(this.#helper);
}

if (this.#controls) {
this.#controls.detach();
this.#controls.dispose();
this.#controls = null;
}
scene.remove(this.#pivot);

super.destroy();
}
}
Loading
Loading