Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ARENAUI classes #162

Merged
merged 4 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arena/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .torus import Torus
from .torus_knot import TorusKnot
from .triangle import Triangle
from .ui import *

OBJECT_TYPE_MAP = {
"box": Box,
Expand Down
90 changes: 90 additions & 0 deletions arena/objects/ui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from .arena_object import Object


class Button:
"""
Buttons of a ButtonPanel in the ARENA UI.

:param str name: Button Name
:param str img: Image URl for image buttons (optional)
:param float size: Size of image button (optional)
:param float height: Height of image button, overrides size (optional)
:param float: Width of image button, overrides size (optional)
:param float borderRadius: Border radius of image button (optional)
"""

def __init__(self, name="Button", **kwargs):
self.name = name
self.__dict__.update(kwargs)


class ButtonPanel(Object):
"""
Button Panel in the ARENA UI.

:param list[Button] buttons: List of Button objects
:param str title: Title of Button Panel (optional)
:param bool vertical: Whether to display buttons vertically (optional)
:param str font: Font of button panel ['Roboto', 'Roboto-Mono'] (optional)
"""

object_type = "arenaui-button-panel"

def __init__(self, **kwargs):
super().__init__(object_type=ButtonPanel.object_type, **kwargs)

def json_preprocess(self, **kwargs):
# kwargs are for additional param to add to json, like "action":"create"
skipped_keys = [
"evt_handler",
"update_handler",
"animations",
"delayed_prop_tasks",
]
json_payload = {k: v for k, v in vars(self).items() if k not in skipped_keys}
json_payload["data"]["buttons"] = [
vars(button) if hasattr(button, "__dict__") else button
for button in json_payload["data"]["buttons"]
]
json_payload.update(kwargs)
return json_payload


class Prompt(Object):
"""
Popup Prompt in the ARENA UI.

:param str title: Title of Prompt (optional)
:param str description: Additional desc text of prompt (optional)
:param list[str] buttons: List of button name strings (optional)
:param str width: Width of prompt (optional)
:param str font: Font of button panel ['Roboto', 'Roboto-Mono'] (optional)
"""

object_type = "arenaui-prompt"

def __init__(self, **kwargs):
super().__init__(object_type=Prompt.object_type, **kwargs)


class Card(Object):
"""
Text/Image Card in the ARENA UI.

:param str title: Title of Card (optional)
:param str body: Body text of Card (optional)
:param str bodyAlign: Text alignment of body text ['center', 'left', 'right', 'justify'] (optional)
:param str img: Image URL of Card (optional)
:param str imgCaption: Image caption (optional)
:param str imgDirection: Left or Right image placement vs body text [ 'left', 'right'] (optional)
:param str imgSize: Container size fitting of image ['cover', 'contain'] (optional)
:param float fontSize: Font size of card, scales both title and body (optional)
:param float widthScale: Width of card as a factor of the default (optional)
:param bool closeButton: Whether to display a close button (optional)
:param str font: Font of card ['Roboto', 'Roboto-Mono'] (optional)
"""

object_type = "arenaui-card"

def __init__(self, **kwargs):
super().__init__(object_type=Card.object_type, **kwargs)
85 changes: 85 additions & 0 deletions examples/objects/ui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from arena import *

scene = Scene(host="arenaxr.org", scene="example")

prompt = None


@scene.run_once
def setup_scene():
# Add a simple info card with text and image
intro_card = Card(
object_id="intro-card",
persist=True,
title="Welcome to ARENA",
body="ARENA is a framework designed to both simplify and host collaborative "
"multi-user XR applications. It makes it easy to combine virtual and "
"physical components like sensors, actuators, and digital interfaces in "
"an immersive 3D environment.",
bodyAlign="left",
imgDirection="left",
img="/static/landing/images/xr-logo-v8.png",
imgSize="contain",
position=Position(0, 2, -2.5),
)
scene.add_object(intro_card)

hello_card = Card(
object_id="hello_card",
persist=True,
title="Hello World",
body="Please applaud",
bodyAlign="center",
position=Position(-2, 2, -2.5),
widthScale=0.25,
look_at="#my-camera"
)
scene.add_object(hello_card)

# Add a popup prompt with single button

def prompt_handler(_scene, evt, _msg):
if evt.type == "buttonClick":
if evt.data.buttonName == "OK":
print("OK clicked!")
scene.delete_object(prompt)

# Add a button panel, with two sets of buttons

first_buttonset = [Button(name="Prompt A"), Button(name="Option B"), Button("More")]
second_buttonset = [Button("D"), Button("E"), Button("F"), Button("Back")]

def button_handler(_scene, evt, _msg):
global prompt
if evt.type == "buttonClick":
if evt.data.buttonName in ["Option B", "D", "E", "F"]: # Compare buttonName
print(f"{evt.data.buttonName} clicked!")
elif evt.data.buttonName == "Prompt A": # Show prompt
prompt = Prompt(
object_id="promptA",
title="Prompt A",
description="This is a prompt with a description.",
buttons=["OK"],
position=Position(2, 2, -2),
evt_handler=prompt_handler,
)
scene.add_object(prompt)
elif evt.data.buttonName == "More": # switch to second button set
scene.update_object(button_panel, buttons=second_buttonset)
elif evt.data.buttonIndex == 3: # compare buttonIndex, switch 1st set
scene.update_object(button_panel, buttons=first_buttonset)

button_panel = ButtonPanel(
object_id="button-panel",
persist=True,
title="Option Buttons",
buttons=first_buttonset,
vertical=True,
font="Roboto-Mono",
position=Position(2, 2, -2.5),
evt_handler=button_handler,
)
scene.add_object(button_panel)


scene.run_tasks()