Skip to content

Commit

Permalink
Merge pull request #162 from arenaxr/arenaui
Browse files Browse the repository at this point in the history
Add ARENAUI classes
  • Loading branch information
hi-liang authored Aug 31, 2023
2 parents 3eb303f + c44bee8 commit d187935
Show file tree
Hide file tree
Showing 3 changed files with 176 additions and 0 deletions.
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()

0 comments on commit d187935

Please sign in to comment.