Due to Unity's pricing changes, I made the decision to discontinue the development of this app, as I am no longer comfortable with spending significant time building on top of a foundation that could be pulled from under you at any point in time.
Some of the code and design decisions inside this repository might help someone develop something similar, which is why I have decided to publish the source code under the MIT license. Note that the project depends on one paid asset, Shapes by Freya HolmΓ©r. Luckily, this dependency could be replaced fairly trivially by something else.
Cuboid allows you to design for the real world, in the real world. Import high quality assets, and place and manipulate them at world-scale in your environment. Reimagine your living room, your house, or an entire city!
- Meta Quest 2
- Meta Quest Pro
- Import any Unity Prefab or 3D model into the application via com.cuboid.unity-plugin (custom MonoBehaviour scripts excluded)
- Place 3D objects in your environment on world-scale augmented reality using Passthrough.
- Built-in asset library.
- Cuboid is a local, standalone application. It does not require an internet connection or creating an account.
- Translate, rotate and scale objects using gizmos and intuitive scale bounds handles, from a distance!
- Select, cut, copy, paste, duplicate and delete objects via a context menu.
- Full undo / redo support.
- Save and load scenes to and from a local .json file.
- Draw primitive shapes and change corner radius or their color via a full RGB / HSV color picker.
Unity Editor version: 2021.3.27f1
Notable packages:
com.unity.nuget.newtonsoft-json
3.2.1
com.gwiazdorrr.betterstreamingassets
See Packages/manifest.json
for all packages. Other than those above, it only contains packages created and maintained by Unity.
These are free and paid plugins retrieved from the Unity AssetStore and should be installed to the Plugins
directory.
- DOTween by Demigiant
> 1.2.000
(free) - Shapes by Freya HolmΓ©r
4.2.1
(β οΈ paid)
The project depends on the Oculus Integration
package > 57.0.0
Only the VR
subdirectory of the package needs to be installed to the Oculus
subdirectory.
There are two main Unity Scenes that compose the app. These are the main entrypoints of the application:
AppEditor
The main scene for testing the application directly inside the Editor with theXR Device Simulator
.AppRuntime
The main scene that gets run on the XR device, which does not contain the simulator.
Both scenes contain the App
prefab, which contain prefabs for each controller described below (e.g. UndoRedoController
, RealitySceneController
and ToolController
).
The only difference is that the AppEditor
scene contains the EditorXRRig
, and AppRuntime
contains the RuntimeXRRig
.
All code is located in the following directories:
π app/
βββ π Assets/
βββ π Scripts/
βββ π Editor/
βββ π Runtime/
βββ π Commands/
βββ π Document/
βββ π Input/
βββ π Rendering/
βββ π SpatialUI/
βββ π Tools/
βββ π UI/
βββ π Utils/
Top level scripts inside π Runtime
:
Binding.cs
Utility class for binding a value to a UI element to keep the UI and data model in sync.CacheController.cs
Enables the user to clear the cache and to inspect its sizeColorsController.cs
Global controller for changing the color of all selected objects
For storing the editing history to enable fully undoing and redoing all edits made by the user. This employs the command pattern. Commands can be nested and/or combined to create compound commands, e.g. for selecting and moving objects on click and drag.
AddCommand.cs
Add RealityObject to the sceneRemoveCommand.cs
Remove RealityObject from the sceneSelectCommand.cs
Select or deselect a set of RealityObjectsSetPropertyCommand.cs
Set a property of a set of RealityObjects that have the same typeTransformCommand.cs
Transform a set of objects using a TRS matrix transform
Serializable and editable data model of a 3D scene. A RealityDocument
is the data model that gets saved and loaded to and from disk. A RealityDocument
contains a RealityScene
, which in its turn contains a set of RealityObject
s. These RealityObject
s can have different types, such as a 3D asset, or a primitive shape.
3D assets are not stored inside the RealityDocument
but stored as a reference to a RealityAssetCollection
, which wraps a Unity AssetBundle. These RealityAssetCollection
s are created with com.cuboid.unity-plugin
.
RealityDocument.cs
Main data model of the applicationTransformData.cs
3D TRS Transform of aRealityObject
RealityObject.cs
A selectable object inside theRealityDocument
RealityAsset.cs
A fully textured, animated and shaded 3D model, stored inside aRealityAssetCollection
RealityAssetCollection.cs
A collection of 3D models stored inside a Unity AssetBundle on diskRealityShape.cs
A primitive shape with editable propertiesRoundedCuboidRenderer.cs
Renders a cuboid, used byRealityShape
if the primitive type isCuboid
Selection.cs
A hashset of objects that represents the current selection
RealityAssetsController.cs
Loading 3D models from diskClipboardController.cs
Storing cut or copied objectsPropertiesController.cs
Rendering reflected property fields in the UI for objects that are selected in the sceneRealityDocumentController.cs
Storing and loading aRealityDocument
from diskRealitySceneController
Rendering a scene and instantiating RealityObjects when loadedSelectionController.cs
Selection, transform updates and bounds of selected objectsThumbnailProvider.cs
Cache layer to avoid retrieving thumbnails from the AssetBundle each time
Handling of spatial input events from XR controllers. Part of this is adopted and modified from the XR Interaction Toolkit, as the XR Interaction Toolkit proved insufficient for achieving the exact interactions expected in a design application.
There are three different types of interactables in the scene. They are interacted with in the following order: UI is always on top of SpatialUI, which on its turn is always above the scene.
UI
2D UI such as buttons and a colorpickerSpatialUI
3D handles and UI elements that should be moved in 3D space to perform the action, e.g. a translate along axis handleOutsideUI
Anywhere outside UI or SpatialUI, can be digital objects or the physical world
Handedness.cs
Handle left- and right-handednessRayInteractor.cs
Replacement forXRRayInteractor
in XR Interaction ToolkitSpatialGraphicRaycaster.cs
Raycasting with UISpatialInputModule.cs
Handling of input events that retains focus for either UI interactions or 3D scene interactions. Handles stabilization and smoothing of the spatial pointer.SpatialPhysicsRaycaster.cs
Raycasting with the 3D sceneSpatialPointerConfiguration.cs
Dictates how the spatial pointer should be moved when the user interacts with a specific Spatial UI element.SpatialPointerEvents.cs
Events that spatial UI can listen to to create interactable spatial UISpatialPointerReticle.cs
Rendering of the spatial pointer
Custom VR keyboard implementation with numeric support.
Handling buttons and rendering of controller.
Mapping buttons to high level actions.
Not much to see here, as Unity handles all rendering.
PassthroughController.cs
Turning Passthrough on or offScreenshotController.cs
For capturing thumbnails of the scene when saving a documentSelectionOutlineRendererFeature.cs
Custom URP render feature that renders selected objects' outlines
The handles defined in SpatialUI purely contain data and implement the interfaces defined in SpatialPointerEvents.cs
in π Input
.
Calculating the new position of the handle on moving the spatial pointer is performed by the tools in π Tools
. These tools are also responsible for instantiating these handles.
Handle.cs
Base class that implements the interfaces defined inSpatialPointerEvents.cs
AxisHandle.cs
Contains additional data for which axis (x, y or z) this handle would editTranslateHandle.cs
Contains additional data for whether the handle is a plane or axis handleSelectionBoundsHandle.cs
Handle for the corner, edge or face of a selection bounds
SpatialContextMenu.cs
A floating menu that rotates towards the user.Visuals.cs
Show origin and grid in scene
ToolController.cs
Instantiates the tool prefab based on the selected toolToolSwitcher.cs
A quick switcher that enables the user to switch with the joystick between the most commonly used tools.ModifiersController.cs
Listens to buttons on the non-dominant hand to activate theShift
orOption
modifiersOutsideUIBehaviour.cs
Registers listening to events (e.g. when the user clicks or drags) for outside the UI and outside spatial UI.
DefaultSelectBehaviour.cs
Behaviour for selecting and moving objects when clicking and dragging an object. Depends onOutsideUIBehaviour
. All handle tools use this behaviour.SelectTool.cs
UsesDefaultSelectBehaviour
.
AxisHandleTool.cs
Base class for a tool that instantiates handles. UsesDefaultSelectBehaviour
TranslateTool.cs
Translate the selected objects along their local x, y or z axis, or their x, y or z plane.RotateTool.cs
Rotate the selected objects around their local x, y or z axis.ScaleTool.cs
Scale the selected objects along their local x, y or z axisSelectionBoundsTool.cs
Scale the selected objects by dragging the corners, edges or faces of the selection bounds, similar to how Adobe Photoshop or Adobe Illustrator has a selection box around the selected items.
DrawShapeTool.cs
Depends onOutsideUIBehaviour
. For drawing a primitive shape (seeRealityShape.cs
inπ Document
) in 3D space.
Contains UI components that are bound to specific data or data types inside the application. Ideally, only the generic versions of these UI Binding classes exist, but as UI is still sometimes defined inside Prefabs, specialized versions need to exist. These are ommitted for brevity.
Contains custom UI components that are data driven and better than Unity UI's built in components, such as scroll views, sliders and more.
Button.cs
A data driven buttonPopupButton.cs
A button for an enum value that on press shows a list of all enum values to pick from.Slider.cs
A data driven sliderSlider2D.cs
A data driven 2D slider (used by the color picker)Toggle.cs
A data driven toggleInputField.cs
An input field, adapted from TextMeshPro as that one was broken with text selection and editing in VR. Instantiates the correct keyboard popup based on its value type (e.g. numeric or text).ValueField.cs
Depends onInputField
, binds to a binding that contains a float value.Vector2Field.cs
Contains twoValueField
sVector3Field.cs
Contains threeValueField
s
NavigationStack.cs
A stack of views similar to UIKit's NavigationStack.ScrollView.cs
A scroll view that keeps focus during dragging, even when the pointer exits the scroll view bounds.ScrollViewPool.cs
A performant data driven grid or list view that pools UI elements and only renders the amount of UI elements that are visible.
ContextMenu.cs
A data driven context menu that contains a set of actions that can be performed.DialogBox.cs
Similar to a ContextMenu, but with a description and icon for the actions that are to be performed (used for a save file dialog for example)
ColorPicker.cs
ColorPicker with HSV and RGB sliders with value field and and a 2D area for setting for example Hue and Value at the same time.LoadingSpinner.cs
A rotating spinner for indicating that something is loadingNotification.cs
A notification that hides after a set durationTooltip.cs
A tooltip that shows when hovering over a UI element. Hides after a set duration.
Contains property UI elements. Property UI elements get instantiated by the PropertiesController
(see π Document/PropertiesController.cs
).
The state of the UI elements referenced by the property UI elements reflects the state of the document. Changes are propagated to the document when changed in the UI, and when the document changes, the UI changes (e.g. when performing Undo or Redo).
Another unique property of properties (he), is that they can update the document live while for example dragging the slider, but only register the set property command on release.
In addition, it works with multiple objects selected at the same time.
Property.cs
Base class for a propertyFloatProperty.cs
Contains aSlider
and aValueField
IntProperty.cs
Contains aSlider
and aValueField
StringProperty.cs
Contains aInputField
BooleanProperty.cs
Contains aToggle
ColorProperty.cs
Creates aColorPicker
popup on clicking on the propertyEnumProperty.cs
Contains aPopupButton
Vector2Property.cs
Contains aVector2Field
Vector3Property.cs
Contains aVector3Field
Contains implementation for the UI for each specific view (i.e. panel). These panels can be selected in the interface via the panel buttons.
π AssetsView
Display asset collections and handle dragging and dropping RealityAssets into the sceneπ DocumentsView
Display the currently opened document, and other documents that the user has created that they could open, rename or delete.ColorsViewController.cs
Display a colors panel with the currently activeCreditsViewController.cs
Display credits and links to license and websitePropertiesViewController.cs
Display properties of the currently selected objectsSettingsViewController.cs
Display settingsToolsViewController.cs
Display tools, and the properties of the selected tool, if any.TransformProperties.cs
Display transform properties of selected objects (translation, rotation and scale) using Vector3Fields
General utility functions that extend Unity's classes or mitigate some ommision in Unity.