mirror of
https://github.com/isledecomp/isle.pizza.git
synced 2026-03-01 06:17:38 +00:00
Add zoom, pan, and camera reset to 3D editors
Enable zoom (scroll/pinch) and pan (right-click/two-finger drag) on all OrbitControls. Add resetView() to BaseRenderer that restores initial camera state and auto-rotate via OrbitControls.saveState/reset. Add reset camera button to EditorTooltip with mobile-friendly touch targets and hover-only highlight to avoid sticky state on touch.
This commit is contained in:
parent
57b1c31305
commit
cf23e22931
@ -96,6 +96,7 @@ export class ActorRenderer extends BaseRenderer {
|
|||||||
|
|
||||||
this.setupControls(new THREE.Vector3(0, 0.2, 0));
|
this.setupControls(new THREE.Vector3(0, 0.2, 0));
|
||||||
this.controls.autoRotate = false;
|
this.controls.autoRotate = false;
|
||||||
|
this._initialAutoRotate = false;
|
||||||
|
|
||||||
this.raycaster = new THREE.Raycaster();
|
this.raycaster = new THREE.Raycaster();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,8 +41,8 @@ export class BaseRenderer {
|
|||||||
|
|
||||||
setupControls(target) {
|
setupControls(target) {
|
||||||
this.controls = new OrbitControls(this.camera, this.canvas);
|
this.controls = new OrbitControls(this.camera, this.canvas);
|
||||||
this.controls.enableZoom = false;
|
this.controls.enableZoom = true;
|
||||||
this.controls.enablePan = false;
|
this.controls.enablePan = true;
|
||||||
this.controls.enableDamping = true;
|
this.controls.enableDamping = true;
|
||||||
this.controls.dampingFactor = 0.1;
|
this.controls.dampingFactor = 0.1;
|
||||||
this.controls.autoRotate = true;
|
this.controls.autoRotate = true;
|
||||||
@ -66,6 +66,15 @@ export class BaseRenderer {
|
|||||||
|
|
||||||
this.canvas.addEventListener('pointerdown', this._onPointerDown);
|
this.canvas.addEventListener('pointerdown', this._onPointerDown);
|
||||||
this.canvas.addEventListener('pointermove', this._onPointerMove);
|
this.canvas.addEventListener('pointermove', this._onPointerMove);
|
||||||
|
|
||||||
|
this._initialAutoRotate = this.controls.autoRotate;
|
||||||
|
this.controls.saveState();
|
||||||
|
}
|
||||||
|
|
||||||
|
resetView() {
|
||||||
|
if (!this.controls) return;
|
||||||
|
this.controls.reset();
|
||||||
|
this.controls.autoRotate = this._initialAutoRotate;
|
||||||
}
|
}
|
||||||
|
|
||||||
wasDragged() {
|
wasDragged() {
|
||||||
|
|||||||
@ -1,11 +1,26 @@
|
|||||||
<script>
|
<script>
|
||||||
export let text = '';
|
export let text = '';
|
||||||
|
export let onResetCamera = null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="editor-tooltip-wrapper">
|
<div class="editor-tooltip-wrapper">
|
||||||
<span class="tooltip-trigger">?
|
<div class="tooltip-icons">
|
||||||
<span class="tooltip-content">{text}</span>
|
{#if onResetCamera}
|
||||||
</span>
|
<button
|
||||||
|
type="button"
|
||||||
|
class="reset-camera-btn"
|
||||||
|
onclick={onResetCamera}
|
||||||
|
title="Reset camera"
|
||||||
|
>
|
||||||
|
<svg width="12" height="12" viewBox="0 0 16 16" fill="currentColor">
|
||||||
|
<path d="M8 1a7 7 0 0 0-7 7h2a5 5 0 0 1 9.17-2.74L10 7h5V2l-1.87 1.87A7 7 0 0 0 8 1z"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<span class="tooltip-trigger">?
|
||||||
|
<span class="tooltip-content">{text}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div class="editor-tooltip-content">
|
<div class="editor-tooltip-content">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
@ -17,11 +32,51 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tooltip-trigger {
|
.tooltip-icons {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reset-camera-btn {
|
||||||
|
position: relative;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: var(--color-border-medium);
|
||||||
|
color: #eee;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Expand touch target on mobile */
|
||||||
|
@media (pointer: coarse) {
|
||||||
|
.reset-camera-btn::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
inset: -10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (hover: hover) {
|
||||||
|
.reset-camera-btn:hover {
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
color: var(--color-bg-panel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.reset-camera-btn:active {
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
color: var(--color-bg-panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-tooltip-content {
|
.editor-tooltip-content {
|
||||||
|
|||||||
@ -333,7 +333,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<EditorTooltip text="Click to customize based on your current character. Navigate between all 66 game actors using the arrows. Changes are automatically saved.">
|
<EditorTooltip text="Click to customize based on your current character. Navigate between all 66 game actors using the arrows. Changes are automatically saved." onResetCamera={() => renderer?.resetView()}>
|
||||||
<div class="preview-container">
|
<div class="preview-container">
|
||||||
<canvas
|
<canvas
|
||||||
bind:this={canvas}
|
bind:this={canvas}
|
||||||
|
|||||||
@ -122,7 +122,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<EditorTooltip text="Click on the cube to cycle high scores. Changes are automatically saved.">
|
<EditorTooltip text="Click on the cube to cycle high scores. Changes are automatically saved." onResetCamera={() => renderer?.resetView()}>
|
||||||
<div class="score-cube-container">
|
<div class="score-cube-container">
|
||||||
<canvas
|
<canvas
|
||||||
bind:this={canvas}
|
bind:this={canvas}
|
||||||
|
|||||||
@ -323,7 +323,7 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<EditorTooltip text="Click on the part to cycle through colors. Use the texture button to customize textures on supported parts (vehicle must be fully built first). Changes are automatically saved.">
|
<EditorTooltip text="Click on the part to cycle through colors. Use the texture button to customize textures on supported parts (vehicle must be fully built first). Changes are automatically saved." onResetCamera={() => renderer?.resetView()}>
|
||||||
<!-- 3D Preview (clickable to cycle color) -->
|
<!-- 3D Preview (clickable to cycle color) -->
|
||||||
<div class="preview-container">
|
<div class="preview-container">
|
||||||
<canvas
|
<canvas
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user