Project Graveyard – Devlog 004

Revamping the gravestone options and editing controls.

A big part of the update this summer is moving features from a utility window into the main volume. This weekend I worked on the gravestone options that will appear in Edit Mode. When Edit Mode is active, a user can tap on one of the gravestones. Using the Presentation Component, a SwiftUI view is presented above that item. This view will start with a list of options.

  • Customize (most common) – select material and color
  • Text – Edit the text that appears on the gravestone
  • Accessories – more info on this new feature coming soon
  • Delete – permanently delete a gravestone and related data

Most of this is pretty basic SwiftUI. I spent most of my time one the Customize screen. The previous version had too much space and padding between elements. It also showed the material options rendered as spheres. I decided to replace the sphere with small preview versions of the gravestone. The labels that used to appear below each preview are now rendered as attachments on each gravestone. I also changed the selection indicator from a rounded rectangle to a simple capsule underneath the current value. Lastly, I reduced the padding around the tint color options. The result is a more compact layout that better represents how the entities will appear in the scene.

I thought about using Model3D and spatialOverlay for the material stone preview items. What tipped the scale is that these previews don’t just display the material. They also render the selected tint color. If I wanted to use Model3D I’d either have to have 144 models to load or 4 models with 24 color configurations. Bad idea! So I stuck to using small RealityViews for the gravestones. Each one is using .realityViewLayoutBehavior(.fixedSize) to resize the view fit and focus the viewable content.

A small issue I ran into was the alert I was using for deletion confirmation. It worked well in the utility window, but when used in a popover in a volume it was confusing. visionOS would anchor the alert at the very front of the volume, often pretty far from where the item I was deleting. I decided to hack something together for now. The Delete button on the options page navigates to a second view. This view has buttons to confirm deletion or cancel. Not ideal, but it works.

Delete confirmation view

Another huge change is how the UI updates the correct entity in the volume. In the previous version I used several bit of shared state from an @Observable ViewModel. I could set one of these values and trigger the RealityView to update, reaching into the entity graph to change materials or colors. I pulled all of that out. When the user taps on a gravestone, the app passes a weak reference to the entity to the root view of the popover. From there, each of the features above can access the entity to make changes.

    .onEnded({ [weak entity] _ in
        if let selection = entity?.findEntity(named: "selection") {
            selection.components[PresentationComponent.self]?.isPresented.toggle()
        }
    })

A handful of features I used in this update

Video Demo

Questions or feedback?