From 4acdf8502d084c375bd630eab78bea0f910739d0 Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Tue, 17 May 2022 20:50:31 +0200 Subject: [PATCH] Initial voxel editing functionality for Create App --- scripts/system/create/edit.js | 9 +- scripts/system/create/editModes/editVoxels.js | 236 ++++++++++++++++++ scripts/system/html/gridControls.html | 4 +- 3 files changed, 245 insertions(+), 4 deletions(-) create mode 100644 scripts/system/create/editModes/editVoxels.js diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index 8d206f5586..de572c221e 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EditTools, EntityListTool, Vec3, SelectionManager, +/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EditTools, EditVoxels, EntityListTool, Vec3, SelectionManager, Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow, keyUpEventFromUIWindow:true */ @@ -38,7 +38,8 @@ Script.include([ "entitySelectionTool/entitySelectionTool.js", "audioFeedback/audioFeedback.js", "modules/brokenURLReport.js", - "editModes/editModes.js" + "editModes/editModes.js", + "editModes/editVoxels.js" ]); var CreateWindow = Script.require('./modules/createWindow.js'); @@ -132,6 +133,10 @@ var editTools = new EditTools({ createToolsWindow: createToolsWindow, }); +var editVoxels = new EditVoxels(); + +editTools.addListener(editVoxels.updateEditSettings); + var entityShapeVisualizerSessionName = "SHAPE_VISUALIZER_" + Uuid.generate(); var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js'); diff --git a/scripts/system/create/editModes/editVoxels.js b/scripts/system/create/editModes/editVoxels.js new file mode 100644 index 0000000000..a9ee82e946 --- /dev/null +++ b/scripts/system/create/editModes/editVoxels.js @@ -0,0 +1,236 @@ +// +// editModes.js +// +// Created by Karol Suprynowicz on 2022.05.17. +// Copyright 2022 Overte e.V. +// +// Based on voxels.js +// Created by Seth Alves on 2015-08-25 +// Copyright 2015 High Fidelity, Inc. +// +// This script implements voxel edit mode +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +Script.include([ + "./libraries/utils.js", +]); + +EditVoxels = function() { + var that = {}; + + var controlHeld = false; + var shiftHeld = false; + + var editEnabled = false; + var addingVoxels = false; + var deletingVoxels = false; + var addingSpheres = false; + var deletingSpheres = false; + var addingCubes = false; + var deletingCubes = false; + var continuousPaint = false; + var brushPointer = false; + + var editSphereRadius = 0.15; + var brushLength = 0.5; + + that.updateEditSettings = function(data) { + + if (data.createAppMode) { + if (data.createAppMode === "voxel"){ + editEnabled = true; + } else { + editEnabled = false; + } + } + + if (data.voxelEditMode) { + addingVoxels = false; + deletingVoxels = false; + addingSpheres = false; + deletingSpheres = false; + addingCubes = false; + deletingCubes = false; + if (data.voxelRemove) { + if (data.voxelEditMode === "single") { + deletingVoxels = true; + } else if (data.voxelEditMode === "sphere") { + deletingSpheres = true; + } else if (data.voxelEditMode === "cube") { + deletingCubes = true; + } + } else { + if (data.voxelEditMode === "single") { + addingVoxels = true; + } else if (data.voxelEditMode === "sphere") { + addingSpheres = true; + } else if (data.voxelEditMode === "cube") { + addingCubes = true; + } + } + } + + if (data.voxelSphereSize) { + editSphereRadius = parseFloat(data.voxelSphereSize) / 2.0; + } + + if (data.voxelEditDynamics) { + if (data.voxelEditDynamics === "continuous"){ + continuousPaint = true; + } else { + continuousPaint = false; + } + } + + if (data.voxelPointerMode) { + if (data.voxelPointerMode === "brush") { + brushPointer = true; + } else { + brushPointer = false; + } + } + + if (data.voxelBrushLength) { + voxelBrushLength = parseFloat(data.voxelBrushLength); + } + + } + + function floorVector(v) { + return { + x: Math.floor(v.x), + y: Math.floor(v.y), + z: Math.floor(v.z) + }; + } + + function attemptVoxelChangeForEntity(entityID, pickRayDir, intersectionLocation) { + + var properties = Entities.getEntityProperties(entityID); + if (properties.type != "PolyVox") { + return false; + } + + if (!editEnabled) { + return false; + } + + if (addingVoxels == false && deletingVoxels == false && addingSpheres == false && deletingSpheres == false) { + return false; + } + + var voxelOrigin = Entities.worldCoordsToVoxelCoords(entityID, Vec3.subtract(intersectionLocation, pickRayDir)); + var voxelPosition = Entities.worldCoordsToVoxelCoords(entityID, intersectionLocation); + var pickRayDirInVoxelSpace = Vec3.subtract(voxelPosition, voxelOrigin); + pickRayDirInVoxelSpace = Vec3.normalize(pickRayDirInVoxelSpace); + + var doAdd = addingVoxels; + var doDelete = deletingVoxels; + var doAddSphere = addingSpheres; + var doDeleteSphere = deletingSpheres; + + if (controlHeld) { + if (doAdd) { + doAdd = false; + doDelete = true; + } else if (doDelete) { + doDelete = false; + doAdd = true; + } else if (doAddSphere) { + doAddSphere = false; + doDeleteSphere = true; + } else if (doDeleteSphere) { + doDeleteSphere = false; + doAddSphere = true; + } + } + + if (doDelete) { + var toErasePosition = Vec3.sum(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); + return Entities.setVoxel(entityID, floorVector(toErasePosition), 0); + } + if (doAdd) { + var toDrawPosition = Vec3.subtract(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); + return Entities.setVoxel(entityID, floorVector(toDrawPosition), 255); + } + if (doDeleteSphere) { + var toErasePosition = intersectionLocation; + return Entities.setVoxelSphere(entityID, floorVector(toErasePosition), editSphereRadius, 0); + } + if (doAddSphere) { + var toDrawPosition = intersectionLocation; + return Entities.setVoxelSphere(entityID, floorVector(toDrawPosition), editSphereRadius, 255); + } + } + + function attemptVoxelChange(pickRayDir, intersection) { + + var ids; + + ids = Entities.findEntities(intersection.intersection, editSphereRadius + 1.0); + if (ids.indexOf(intersection.entityID) < 0) { + ids.push(intersection.entityID); + } + + var success = false; + for (var i = 0; i < ids.length; i++) { + var entityID = ids[i]; + success |= attemptVoxelChangeForEntity(entityID, pickRayDir, intersection.intersection) + } + return success; + } + + function mousePressEvent(event) { + if (!event.isLeftButton) { + return; + } + + var pickRay = Camera.computePickRay(event.x, event.y); + var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking + + if (intersection.intersects) { + if (attemptVoxelChange(pickRay.direction, intersection)) { + return; + } + } + + // if the PolyVox entity is empty, we can't pick against its "on" voxels. try picking against its + // bounding box, instead. + intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking + if (intersection.intersects) { + attemptVoxelChange(pickRay.direction, intersection); + } + } + + function keyPressEvent(event) { + if (event.text == "CONTROL") { + controlHeld = true; + } + if (event.text == "SHIFT") { + shiftHeld = true; + } + } + + function keyReleaseEvent(event) { + if (event.text == "CONTROL") { + controlHeld = false; + } + if (event.text == "SHIFT") { + shiftHeld = false; + } + } + + function cleanup() { + toolBar.cleanup(); + } + + Controller.mousePressEvent.connect(mousePressEvent); + Controller.keyPressEvent.connect(keyPressEvent); + Controller.keyReleaseEvent.connect(keyReleaseEvent); + Script.scriptEnding.connect(cleanup); + + return that; +} diff --git a/scripts/system/html/gridControls.html b/scripts/system/html/gridControls.html index 9c21fbdb0d..97213aca39 100644 --- a/scripts/system/html/gridControls.html +++ b/scripts/system/html/gridControls.html @@ -59,8 +59,8 @@