mirror of
https://github.com/brunopostle/ifcurl.git
synced 2026-07-12 10:18:14 +00:00
viewer.html: fix toolbar input focus blocked by camera controls
- Shrink viewer div to start below toolbar (CSS var --toolbar-h via ResizeObserver) so the canvas never overlaps the input area - Disable camera controls on input focus, re-enable on blur - Stop pointer event propagation from input to prevent camera-controls capture Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
81f022d4af
commit
7370776ed6
2 changed files with 27 additions and 5 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{"id":"ifcurl-1sh","title":"viewer.html: place camera from ifc:// URL camera= param on load","description":"When viewer.html loads with a camera= param in the ifc:// URL (9 comma-separated floats: position, direction, up in IFC world coordinates), apply the IFC→Three.js coordinate transform (Y/Z swap, one negated) and set the Three.js camera position, direction and up vector accordingly. Depends on the syncCameraUrl fix (ifcurl-j2s) so the forward and inverse transforms are consistent.","status":"in_progress","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T20:05:57Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:09:26Z","started_at":"2026-04-23T20:09:26Z","dependencies":[{"issue_id":"ifcurl-1sh","depends_on_id":"ifcurl-j2s","type":"blocks","created_at":"2026-04-23T21:06:08Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||
{"id":"ifcurl-940","title":"viewer.html: URL input box and drag-and-drop target","description":"Add a text entry box and a drag-and-drop target to viewer.html so any ifc:// URL can be loaded without navigating from a Forgejo page. The input should accept a pasted ifc:// URL and immediately load it into the viewer. Drag-and-drop should accept a dropped ifc:// URL or a .ifc file URL. This makes the viewer usable as a standalone tool.","status":"in_progress","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T20:05:43Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:09:23Z","started_at":"2026-04-23T20:09:23Z","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||
{"id":"ifcurl-cmd","title":"Apply forward IFC→Three.js transform when setting camera from URL params","description":"When the viewer page loads with a camera= param in the ifc:// URL, the 9 floats are in IFC world coordinates. Apply the IFC→Three.js transform to convert them before passing them to the Three.js camera / camera-controls. This is the forward direction of the same transform used in the inverse task.","status":"in_progress","priority":2,"issue_type":"bug","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:38Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:09:25Z","started_at":"2026-04-23T20:09:25Z","dependencies":[{"issue_id":"ifcurl-cmd","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:10Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||
{"id":"ifcurl-j2s","title":"Apply inverse IFC↔Three.js transform in syncCameraUrl","description":"Using the transform found in the research task, apply its inverse to camera.position, the direction vector, and camera.up before serialising them as the ifc:// camera param in syncCameraUrl. The result should be in IFC world coordinates (Z-up, matching BCF viewpoint conventions) not Three.js scene space.","status":"in_progress","priority":2,"issue_type":"bug","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:37Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:09:25Z","started_at":"2026-04-23T20:09:25Z","dependencies":[{"issue_id":"ifcurl-j2s","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:09Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||
{"id":"ifcurl-1sh","title":"viewer.html: place camera from ifc:// URL camera= param on load","description":"When viewer.html loads with a camera= param in the ifc:// URL (9 comma-separated floats: position, direction, up in IFC world coordinates), apply the IFC→Three.js coordinate transform (Y/Z swap, one negated) and set the Three.js camera position, direction and up vector accordingly. Depends on the syncCameraUrl fix (ifcurl-j2s) so the forward and inverse transforms are consistent.","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T20:05:57Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:15:45Z","started_at":"2026-04-23T20:09:26Z","closed_at":"2026-04-23T20:15:45Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-1sh","depends_on_id":"ifcurl-j2s","type":"blocks","created_at":"2026-04-23T21:06:08Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||
{"id":"ifcurl-940","title":"viewer.html: URL input box and drag-and-drop target","description":"Add a text entry box and a drag-and-drop target to viewer.html so any ifc:// URL can be loaded without navigating from a Forgejo page. The input should accept a pasted ifc:// URL and immediately load it into the viewer. Drag-and-drop should accept a dropped ifc:// URL or a .ifc file URL. This makes the viewer usable as a standalone tool.","status":"closed","priority":2,"issue_type":"feature","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T20:05:43Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:15:43Z","started_at":"2026-04-23T20:09:23Z","closed_at":"2026-04-23T20:15:43Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0}
|
||||
{"id":"ifcurl-cmd","title":"Apply forward IFC→Three.js transform when setting camera from URL params","description":"When the viewer page loads with a camera= param in the ifc:// URL, the 9 floats are in IFC world coordinates. Apply the IFC→Three.js transform to convert them before passing them to the Three.js camera / camera-controls. This is the forward direction of the same transform used in the inverse task.","status":"closed","priority":2,"issue_type":"bug","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:38Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:15:44Z","started_at":"2026-04-23T20:09:25Z","closed_at":"2026-04-23T20:15:44Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-cmd","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:10Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0}
|
||||
{"id":"ifcurl-j2s","title":"Apply inverse IFC↔Three.js transform in syncCameraUrl","description":"Using the transform found in the research task, apply its inverse to camera.position, the direction vector, and camera.up before serialising them as the ifc:// camera param in syncCameraUrl. The result should be in IFC world coordinates (Z-up, matching BCF viewpoint conventions) not Three.js scene space.","status":"closed","priority":2,"issue_type":"bug","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:37Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:15:44Z","started_at":"2026-04-23T20:09:25Z","closed_at":"2026-04-23T20:15:44Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-j2s","depends_on_id":"ifcurl-ldk","type":"blocks","created_at":"2026-04-23T07:14:09Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||
{"id":"ifcurl-ldk","title":"Find IFC↔Three.js coordinate transform in @thatopen/components source","description":"Grep ~/src/engine_components and ~/src/engine_fragment for the matrix or transform applied when an IFC model is loaded into Three.js scene space. IFC uses Z-up; Three.js uses Y-up. @thatopen/components almost certainly applies a 90° X-axis rotation (and possibly a scale) when constructing the Three.Group from IFC geometry. Record the exact transform so the inverse can be applied in syncCameraUrl.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:36Z","created_by":"Bruno Postle","updated_at":"2026-04-23T20:05:29Z","started_at":"2026-04-23T06:19:35Z","closed_at":"2026-04-23T20:05:29Z","close_reason":"Transform identified: IFC→Three.js is a Y/Z swap with one axis negated (Z-up to Y-up). Unblocks j2s and cmd.","dependency_count":0,"dependent_count":2,"comment_count":0}
|
||||
{"id":"ifcurl-49o","title":"Deploy footer.tmpl to Forgejo custom templates directory","description":"Copy forgejo/templates/custom/footer.tmpl from the repo to /etc/forgejo/templates/custom/footer.tmpl on the Forgejo server. No Forgejo restart needed — custom templates are loaded dynamically. Verify the View in 3D button appears on an .ifc file page.","status":"closed","priority":2,"issue_type":"task","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:22Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:16Z","closed_at":"2026-04-23T19:47:16Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-49o","depends_on_id":"ifcurl-ohq","type":"blocks","created_at":"2026-04-23T07:14:08Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||
{"id":"ifcurl-ohq","title":"Update footer.tmpl: point viewer button to Forgejo static file URL","description":"Change the VIEWER_BASE URL in forgejo/templates/custom/footer.tmpl from http://localhost:8000/viewer to the Forgejo static file URL determined by the research task (ifcurl-5t3). The button href should become something like /assets/viewer.html?url=ifc://... rather than the ifcurl service URL.","status":"closed","priority":2,"issue_type":"task","assignee":"Bruno Postle","owner":"bruno@postle.net","created_at":"2026-04-23T06:12:21Z","created_by":"Bruno Postle","updated_at":"2026-04-23T19:47:15Z","started_at":"2026-04-23T18:48:37Z","closed_at":"2026-04-23T19:47:15Z","close_reason":"Closed","dependencies":[{"issue_id":"ifcurl-ohq","depends_on_id":"ifcurl-5t3","type":"blocks","created_at":"2026-04-23T07:14:07Z","created_by":"Bruno Postle","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
body { background: #1c1c1e; color: #f0f0f0;
|
||||
font-family: system-ui, sans-serif; overflow: hidden; }
|
||||
#viewer { position: fixed; inset: 0; }
|
||||
#viewer { position: fixed; inset: 0; top: var(--toolbar-h, 40px); }
|
||||
#toolbar {
|
||||
position: fixed; top: 0; left: 0; right: 0; z-index: 10;
|
||||
display: flex; align-items: center; gap: 8px; padding: 8px 12px;
|
||||
|
|
@ -67,9 +67,30 @@
|
|||
const ifcUrl = params.get("url") ?? "";
|
||||
const statusEl = document.getElementById("status");
|
||||
const urlInput = document.getElementById("url-input");
|
||||
const toolbar = document.getElementById("toolbar");
|
||||
|
||||
// Keep viewer below the toolbar so the toolbar never overlaps the canvas.
|
||||
const resizeObs = new ResizeObserver(() => {
|
||||
document.documentElement.style.setProperty("--toolbar-h", toolbar.offsetHeight + "px");
|
||||
});
|
||||
resizeObs.observe(toolbar);
|
||||
|
||||
// Module-level reference so event handlers can reach camera controls.
|
||||
let cameraControls = null;
|
||||
|
||||
urlInput.value = ifcUrl;
|
||||
|
||||
// Disable camera controls while the input has focus so keystrokes are not
|
||||
// swallowed by the camera-controls library.
|
||||
urlInput.addEventListener("focus", () => {
|
||||
if (cameraControls) cameraControls.enabled = false;
|
||||
});
|
||||
urlInput.addEventListener("blur", () => {
|
||||
if (cameraControls) cameraControls.enabled = true;
|
||||
});
|
||||
urlInput.addEventListener("pointerdown", e => e.stopPropagation());
|
||||
urlInput.addEventListener("mousedown", e => e.stopPropagation());
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Navigate to the viewer with a different ifc:// URL.
|
||||
// -----------------------------------------------------------------------
|
||||
|
|
@ -235,6 +256,7 @@
|
|||
world.camera = new OBC.OrthoPerspectiveCamera(components);
|
||||
world.scene.setup();
|
||||
components.init();
|
||||
cameraControls = world.camera.controls;
|
||||
|
||||
// --- FragmentsManager ---
|
||||
// Firefox blocks cross-origin module workers; wrap in a blob URL so the
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue