Giter Site home page Giter Site logo

maxxfrazer / realityui Goto Github PK

View Code? Open in Web Editor NEW
631.0 10.0 34.0 15.27 MB

A Swift Package for creating familiar UI Elements and animations in RealityKit. For both Augmented Reality or Virtual Reality scenes. Now with visionOS support.

Home Page: https://maxxfrazer.github.io/RealityUI/

License: MIT License

Swift 100.00%
augmented-reality ux ar arkit virtual-reality swift swiftpm mixed-reality macos ios

realityui's Introduction

RealityUI

RealityUI is a collection of utilities and UI objects for RealityKit. The UI objects included in RealityUI aim to offer familiar User Interface standards, but in a 3D setting for Augmented and Virtual Reality through RealityKit.

RealityUI also has a collection of components for interfacing with any Entity through touch or drag interactions.



RealityUI Elements in a RealityKit VR space

Requirements

  • iOS 13, macOS 10.15 or visionOS 1.0
  • Swift 5.8
  • Xcode 13

Content

Installation

Swift Package Manager

Add the URL of this repository to your Xcode 11+ Project under Project > Swift Packages.

https://github.com/maxxfrazer/RealityUI.git

Usage

Add import RealityUI to the top of your swift file to start.

Registering RealityUI Components

All components used in RealityUI must be registered before they are used, simply call RealityUI.registerComponents() anywhere in your app before any classes starting with RUI are initialised to avoid issues with that. For more information on what is meant by registering components see Apple's documentation here.

Activating Gestures

visionOS

With visionOS, gestures can be enabled on a RealityView using View/addRUIDragGesture() or View/addRUITapGesture() modifiers, or by adding the gestures directly with .gesture(RUIDragGesture()) or .gesture(RUITapGesture()). The RealityView might look something like this:

RealityView { content in
    let swtch = RUISwitch()
    swtch.scale = .init(repeating: 0.1)
    content.add(swtch)
}.addRUIDragGesture()

The above snippet adds an interactive switch/toggle to the scene.

This gesture works for any entity with RUIDragComponent, for example:

RealityView { content in
    let movable = try! await ModelEntity(named: "toy_biplane")
    movable.generateCollisionShapes(recursive: false)

    movable.components.set(RUIDragComponent(type: .move(nil)))
    movable.components.set(InputTargetComponent())

    content.add(movable)
}.addRUIDragGesture()

moving a biplane around in vision pro simulator

iOS/macOS

Enabling RealityUI gestures can be doen by calling RealityUI.enableGestures(.all, on: ARView), with ARView being your instance of an ARView object.

RUISlider, RUISwitch, RUIStepper and RUIButton all use RUIDragComponent, which requires .ruiDrag. If you are adding elements that use the component RUITapComponent you can use the gesture .tap. I would just recommend using .all when enabling gestures, as these will inevitably move around as RealityUI develops.

RealityUI.enableGestures(.all, on: arView)


Control Entities

By default all RealityUI Entities are quite large. This is used to standardize the sizes so that you always know what to expect. For example, all UI thumbs are spheres with a diameter of 1 meter, which is 1 unit in RealityKit, ± any padding adjustments. All RealityUI Entities face [0, 0, -1] by default. To have them point at the user camera, or .zero, you can use the .look(at:,from:,relativeTo:) method like so: .look(at: .zero, from: [0, 0, 1]). Or if you want it to turn around straight away if you've positioned it at [0, 0, -1], set the orientation to simd_quatf(angle: .pi, axis: [0, 1, 0]). Using the .look() method works here by setting the at: value to the direction the button should be used from.

RUISwitch

RUISwitch is a 3D toggle switch with an on and off state. Default bounding box is 2x1x1m

RUISwitches with and without light responsiveness

More details

RUIStepper

RUIStepper is used to increment or decrement a value. Default bounding box is 2x1x0.25m

RUIStepper with light responsiveness

More details

RUISlider

An interactive track to represent an interpolated value. Default bounding box is 10x1x1m including thumb.

RUISlider with light responsiveness

More details

RUIButton

RUIButton is used to initiate a specified action. The action here will only trigger if the gesture begins on a button, and also ends on the same button. This is similar to the touchUpInside UIControl Event. Default button bounding box before depressing the button into the base is [1, 1, 0.3]

RUIButton with light responsiveness

More details


Gestures

All of the RealityUI Control Entities use custom gestures that aren't standard in RealityKit, but some of them have been isolated so anyone can use them to manipulate their own RealityKit scene.

Drag

Drag objects anywhere in space with 3 degrees of freedom with RUIDragComponent, using the .move type.

Dragging Cubes

This type has an optional constraint, to fix the movement within certain criteria:

  1. Box Constraint: Restricts movement within a specified BoundingBox, providing a defined area where the entity can move.

  2. Points Constraint: Limits movement to a set of predefined points, represented as an array of SIMD3<Float>.

  3. Clamp Constraint: Uses a custom clamping function to control the movement. This function takes a SIMD3<Float> as input and returns a modified SIMD3<Float> to determine the new position.

Turn

Unlock the ability to rotate a RealityKit entity with just one finger.

Turning key

More details

Tap

Create an object in your RealityKit scene with an action, and it will automatically be picked up whenever the user taps on it!

No Gif for this one, but check out RUITapComponent to see how to add this to an entity in your application.

If you instead wanted to use something similar to a "touch up inside" tap, you can use RUIDragComponentType/click.

touch-up-inside example with a button


Animations

There aren't many animations added by default to RealityKit, especially none that you can set to repeat. See the wiki page on how to use these animations.

Spin

Spin an Entity around an axis easily using ruiSpin.

Spinning Star More details

Shake

Shake an entity to attract attention, or signal something was incorrect.

Shaking Phone Icon More details


Text

It's already possible to place text in RealityKit, but I felt it needed a little upgrade.

With RUIText you can easily create an Entity with the specified text placed with its bounding box centre at the middle of your entity.

Hello Text Hello Text More details


More

More information on everything provided in this Swift Package in the documentation.

Also see the Example Project for iOS in this repository.

realityui's People

Contributors

maxxfrazer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

realityui's Issues

Move to Components

Some of the features in this project can/should be moved from protocols to components, such as HasClick.

Tasks

  • Find all pieces which can/should be migrated to components, left in the comments here.
  • Issues for each component piece linked to this one.
  • PR's for each component added to staging branch, with tests added.
  • Update documentation for all before merging to main.

Note: This will require a major version bump to 2.0.0

Reasoning

  • Adherence to Entity-Component System (ECS): RealityKit is built on top of an Entity-Component System architecture. Using components instead of protocols embraces the architectural foundations of RealityKit, ensuring your code leverages the framework's inherent design patterns for more seamless integration.
  • Modularity and Flexibility: Components promote modular design. By separating the click action into its component, you can easily attach, modify, or remove functionalities without altering the core entity or other unrelated components. It also allows you to attach the same functionality to various entities regardless of their other functionalities or hierarchies.

Another important factor is future-proofing this library. RealityKit is at it's core an ECS, and will likely play nicer with classes that adhere to that in the future.

Contributions

Contributions are more than welcome for this update, please let me know if you'd like to help!
This will be the first major update of RealityUI, so input such as suggested components or their names would be greatly appreciated.
As this is a breaking change, I want it to be something really worth upgrading.

Bad conversion in macOS

Hi, under mac OS (not catalyst) I experience problems with translation. It seems that the Y coordinates is reversed.
I've made a quick and dirty test with RUISwitch scale 0.5, rotation 0, translation (0, 0.5, 0) and I have the button animation if I click between the middle and the bottom of the view while the button is drawn between the middle and the top.
I've tried to replace the conversion by event.locationInWindow on the "let touchInView =" lines for macOS, it seems to work better.
I believe it can't be so simple (I didn't test with rotations for example), so I hope you have enough information if you need to investigate.
Regards
Thanks for this code.

Animation Tests Failing

New animation tests fail with Xcode 15. The callback at the end of the animation never calls in the tests, but does call when used in full application.

HasClick to Component

New component name: TapActionComponent

Usage:

let entity: Entity = ...
entity.components.set(TapActionComponent { tappedEntity, worldPosition in
    print("Entity \(tappedEntity) was tapped at \(worldPosition ?? .zero)!")
})

See: #18

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.