Example #1
0
 def set_clipboard(self,
                   callback=None,
                   object_type=None,
                   scale=Scale(0.05, 0.05, 0.05),
                   position=Position(0, 0, -CLIP_RADIUS/SCL_HUD),
                   color=Color(255, 255, 255),
                   url=None):
     if object_type:
         self.clipboard = Object(  # show item to be created
             object_id=f"{self.camname}_clipboard",
             object_type=object_type,
             position=position,
             parent=self.hud.object_id,
             scale=Scale(scale.x/SCL_HUD, scale.y/SCL_HUD, scale.z/SCL_HUD),
             material=Material(color=color, transparent=True, opacity=0.4),
             url=url,
             clickable=True,
             evt_handler=callback)
         self.scene.add_object(self.clipboard)
     self.cliptarget = Circle(  # add helper target object to find true origin
         object_id=f"{self.camname}_cliptarget",
         position=position,
         parent=self.hud.object_id,
         scale=Scale(0.005/SCL_HUD, 0.005/SCL_HUD, 0.005/SCL_HUD),
         material=Material(color=Color(255, 255, 255),
                           transparent=True, opacity=0.4),
         clickable=True,
         evt_handler=callback)
     self.scene.add_object(self.cliptarget)
Example #2
0
def init_origin(scene: Scene):
    """Origin object, construction cone, so user knows ARB is running."""
    # TODO: migrate to shared-scene setting
    size = [0.2, 0.4, 0.2]
    scene.add_object(Cone(  # 370mm x 370mm # 750mm
        object_id="arb-origin",
        material=Material(
            color=Color(255, 114, 33),
            transparent=True,
            opacity=0.5,
            shader="flat"),
        position=Position(0, size[1] / 2, 0),
        scale=Scale(size[0] / 2, size[1], size[2] / 2)))
    scene.add_object(Cone(
        object_id="arb-origin-hole",
        **{"material-extras": {"transparentOccluder": True}},
        position=Position(0, size[1] - (size[1] / 2 / 15), 0),
        scale=Scale(size[0] / 15, size[1] / 10, size[2] / 15)))
    scene.add_object(Box(
        object_id="arb-origin-base",
        material=Material(
            color=Color(0, 0, 0),
            transparent=True,
            opacity=0.5,
            shader="flat"),
        position=Position(0, size[1] / 20, 0),
        scale=Scale(size[0], size[1] / 10, size[2])))
Example #3
0
def update_dropdown(camname, objid, mode, options, row, callback):
    # show new dropdown
    if USERS[camname].panel[objid].active:
        followname = USERS[camname].follow.object_id
        maxwidth = min(len(options), 10)
        drop_button_offset = -math.floor(maxwidth / 2)
        for i, option in enumerate(options):
            if mode is Mode.COLOR:
                bcolor = Color(option)
            else:
                bcolor = arblib.CLR_SELECT
            dbutton = arblib.Button(scene,
                                    camname,
                                    mode, (i % maxwidth) + drop_button_offset,
                                    row,
                                    label=option,
                                    parent=followname,
                                    color=bcolor,
                                    drop=option,
                                    callback=callback)
            USERS[camname].dbuttons[dbutton.button.object_id] = dbutton
            if (i + 1) % maxwidth == 0:  # next row
                if row < 0:
                    row -= 1
                else:
                    row += 1
        # make default selection
        if mode is Mode.COLOR:
            rcolor = Color(options[0])
        else:
            rcolor = arblib.CLR_HUDTEXT
        USERS[camname].set_textright(options[0], color=rcolor)
        USERS[camname].target_style = options[0]
Example #4
0
def temp_rot_marker(position, rotation):
    return Box(ttl=120,
               rotation=rotation,
               material=Material(color=Color(255, 255, 255)),
               position=position,
               scale=Scale(0.02, 0.01, 0.15),
               clickable=True)
Example #5
0
def color_callback(_scene, event, msg):
    camname, objid, drop = handle_panel_event(event, dropdown=True)
    if not camname or not objid:
        return
    hcolor = drop
    color = Color(hcolor)
    USERS[camname].set_textright(hcolor, color=color)
    USERS[camname].target_style = hcolor
Example #6
0
def do_wall_end(camname):
    # end (green)
    USERS[camname].wloc_end = USERS[camname].position
    USERS[camname].wrot_end = USERS[camname].rotation
    scene.add_object(
        arblib.temp_loc_marker(USERS[camname].wloc_end, Color(0, 255, 0)))
    scene.add_object(
        arblib.temp_rot_marker(USERS[camname].wloc_end,
                               USERS[camname].wrot_end))
Example #7
0
def do_wall_start(camname):
    # start (red)
    USERS[camname].wloc_start = USERS[camname].position
    USERS[camname].wrot_start = USERS[camname].rotation
    scene.add_object(
        arblib.temp_loc_marker(USERS[camname].wloc_start, Color(255, 0, 0)))
    scene.add_object(
        arblib.temp_rot_marker(USERS[camname].wloc_start,
                               USERS[camname].wrot_start))
Example #8
0
 def set_lamp(self, enabled):
     if enabled:
         self.lamp = Light(object_id=f"{self.camname}_lamp",
                           parent=self.hud.object_id,
                           material=Material(color=Color(144, 144, 173)),
                           type="point",
                           intensity=0.75)
         self.scene.add_object(self.lamp)
     elif self.lamp:
         self.scene.delete_object(self.lamp)
Example #9
0
def do_move_select(camname, object_id):
    obj = scene.get_persisted_obj(object_id)
    USERS[camname].target_id = object_id
    object_type = "box"
    if "object_type" in obj.data:
        object_type = obj.data.object_type
    scale = Scale()
    if "scale" in obj.data:
        scale = obj.data.scale
    color = Color()
    if "material" in obj.data and "color" in obj.data.material:
        color = obj.data.material.color
    url = None
    if "url" in obj.data:
        url = obj.data.url
    USERS[camname].set_clipboard(
        callback=clipboard_callback,
        object_type=object_type,
        scale=scale,
        color=color,
        url=url,
    )
Example #10
0
from arena import (Box, Circle, Color, Cone, Cylinder, Dodecahedron,
                   Icosahedron, Light, Material, Object, Octahedron, Plane,
                   Position, Ring, Rotation, Scale, Scene, Sphere, Tetrahedron,
                   Text, Torus, TorusKnot, Triangle)

CLICKLINE_LEN_OBJ = 0.5  # meters
CLICKLINE_LEN_MOD = 0.5  # meters
CLICKLINE_SCL = Scale(1, 1, 1)  # meters
FLOOR_Y = 0.1  # meters
GRIDLEN = 20  # meters
SCL_HUD = 0.1  # meters
PANEL_RADIUS = 1  # meters
CLIP_RADIUS = PANEL_RADIUS + 0.25  # meters
LOCK_XOFF = 0  # quaternion vector
LOCK_YOFF = 0.7  # quaternion vector
CLR_HUDTEXT = Color(128, 128, 128)  # gray
CLR_NUDGE = Color(255, 255, 0)  # yellow
CLR_SCALE = Color(0, 0, 255)  # blue
CLR_STRETCH = Color(255, 0, 0)  # red
CLR_ROTATE = Color(255, 165, 0)  # orange
CLR_SELECT = Color(255, 255, 0)  # yellow
CLR_GRID = Color(0, 255, 0)  # green
CLR_BUTTON = Color(200, 200, 200)  # white-ish
CLR_BUTTON_DISABLED = Color(128, 128, 128)  # gray
CLR_BUTTON_TEXT = Color(0, 0, 0)  # black
OPC_BUTTON = 0.1  # % opacity
OPC_BUTTON_HOVER = 0.25  # % opacity
OPC_CLINE = 0.1  # % opacity
OPC_CLINE_HOVER = 0.9  # % opacity
TTL_TEMP = 30  # seconds
QUAT_VEC_RGTS = [-1, -0.7, -0.5, 0, 0.5, 0.7, 1]
Example #11
0
def show_redpill_scene(enabled):
    # any scene changes must not persist
    # show gridlines
    name = "grid_redpill"
    path = []
    glen = arblib.GRIDLEN
    y = arblib.FLOOR_Y
    for z in range(-glen, glen + 1):
        if (z % 2) == 0:
            path.append(Position(-glen, y, z))
            path.append(Position(glen, y, z))
        else:
            path.append(Position(glen, y, z))
            path.append(Position(-glen, y, z))
    for x in range(-glen, glen + 1):
        if (x % 2) == 0:
            path.append(Position(x, y, glen))
            path.append(Position(x, y, -glen))
        else:
            path.append(Position(x, y, -glen))
            path.append(Position(x, y, glen))

    if enabled:
        scene.add_object(
            ThickLine(object_id=name, path=path, color=arblib.CLR_GRID))
    else:
        arblib.delete_obj(scene, name)

    objs = scene.get_persisted_objs()
    for object_id in objs:
        obj = objs[object_id]
        # show occluded objects
        if "material-extras" in obj.data and "transparentOccluder" in obj.data[
                "material-extras"]:
            name = "redpill_" + obj.object_id
            if enabled:
                object_type = "box"
                if "object_type" in obj.data:
                    object_type = obj.data.object_type
                position = Position()
                if "position" in obj.data:
                    position = obj.data.position
                rotation = Rotation()
                if "rotation" in obj.data:
                    rotation = obj.data.rotation
                scale = Scale()
                if "scale" in obj.data:
                    scale = obj.data.scale
                url = None
                if "url" in obj.data:
                    url = obj.data.url
                color = Color()
                if "material" in obj.data and "color" in obj.data.material:
                    color = obj.data.material.color
                scene.add_object(
                    Object(
                        object_id=name,
                        object_type=object_type,
                        position=position,
                        rotation=rotation,
                        scale=scale,
                        clickable=True,
                        url=url,
                        material=Material(color=color,
                                          transparent=True,
                                          opacity=0.5),
                    ))
                print("Wrapping occlusion " + name)
            else:
                arblib.delete_obj(scene, name)
Example #12
0
def scene_callback(_scene, event, msg):
    # This is the MQTT message callback function for the scene
    object_id = action = msg_type = object_type = None
    if "object_id" in msg:
        object_id = msg["object_id"]
    if "action" in msg:
        action = msg["action"]
    if "type" in msg:
        msg_type = msg["type"]
    if "data" in msg and "object_type" in msg["data"]:
        object_type = msg["data"]["object_type"]
    # print(f'{object_type} {action} {msg_type} {object_id}')

    if object_type == "camera":
        # camera updates define users present
        camname = object_id
        if camname not in USERS:
            USERS[camname] = arblib.User(scene, camname, panel_callback)

        # save camera's attitude in the world
        USERS[camname].position = Position(msg["data"]["position"]["x"],
                                           msg["data"]["position"]["y"],
                                           msg["data"]["position"]["z"])
        USERS[camname].rotation = Rotation(msg["data"]["rotation"]["x"],
                                           msg["data"]["rotation"]["y"],
                                           msg["data"]["rotation"]["z"],
                                           msg["data"]["rotation"]["w"])

        rx = msg["data"]["rotation"]["x"]
        ry = msg["data"]["rotation"]["y"]

        # floating controller
        if not USERS[camname].follow_lock:
            ty = -(ry + USERS[camname].locky) / 0.7 * math.pi / 2
            tx = -(rx + USERS[camname].lockx) / 0.7 * math.pi / 2
            px = arblib.PANEL_RADIUS * -math.cos(ty)
            py = arblib.PANEL_RADIUS * math.sin(tx)
            pz = arblib.PANEL_RADIUS * math.sin(ty)
            scene.update_object(USERS[camname].follow,
                                position=Position(px, py, pz))
        # else: # TODO: panel lock position drop is inaccurate
        # users[camname].lockx = rx + arblib.LOCK_XOFF
        # users[camname].locky = -(ry * math.pi) - arblib.LOCK_YOFF

    # mouse event
    elif action == "clientEvent":
        object_id = msg["object_id"]
        # camera updates define users present
        camname = msg["data"]["source"]
        if camname not in USERS:
            USERS[camname] = arblib.User(scene, camname, panel_callback)

        # show objects with events
        if msg_type == EVT_MOUSEENTER:
            if USERS[camname].redpill:
                show_redpill_obj(camname, object_id)
            else:
                USERS[camname].set_textstatus(object_id)
        elif msg_type == EVT_MOUSELEAVE:
            USERS[camname].set_textstatus("")

        # handle click
        elif msg_type == EVT_MOUSEDOWN:
            # clicked on persisted object to modify
            update_controls(USERS[camname].target_id)
            USERS[camname].target_id = object_id  # always update
            if USERS[camname].mode == Mode.DELETE:
                arblib.delete_obj(scene, object_id)
            elif USERS[camname].mode == Mode.MOVE:
                do_move_select(camname, object_id)
            elif USERS[camname].mode == Mode.NUDGE:
                do_nudge_select(camname, object_id)
            elif USERS[camname].mode == Mode.SCALE:
                do_scale_select(camname, object_id)
            elif USERS[camname].mode == Mode.STRETCH:
                do_stretch_select(camname, object_id)
            elif USERS[camname].mode == Mode.ROTATE:
                do_rotate_select(camname, object_id)
            elif USERS[camname].mode == Mode.COLOR:
                arblib.color_obj(scene, object_id,
                                 Color(USERS[camname].target_style))
            elif USERS[camname].mode == Mode.OCCLUDE:
                arblib.occlude_obj(scene, object_id,
                                   USERS[camname].target_style)
            elif USERS[camname].mode == Mode.RENAME or USERS[
                    camname].mode == Mode.PARENT:
                if len(USERS[camname].typetext) > 0:  # edits already made
                    new_id = USERS[camname].typetext
                    USERS[camname].typetext = ""
                    if USERS[camname].mode == Mode.PARENT:
                        arblib.parent_obj(scene, object_id, new_id)
                    else:
                        do_rename(camname, object_id, new_id)
                else:  # no edits yet, load previous name to change
                    USERS[camname].typetext = object_id
                USERS[camname].set_textright(USERS[camname].typetext)
Example #13
0
def make_wall(camname):
    # Wall theory: capture two poses and use them to place a wall object.
    # Also assumes first corner easier to capture accurate rotation than last.
    # Click 1: Capture the position and rotation.
    # Click 2: Capture the position only.
    sloc = USERS[camname].wloc_start
    eloc = USERS[camname].wloc_end
    srot = USERS[camname].wrot_start
    erot = USERS[camname].wrot_end
    print(f"S POS {str(sloc)}")
    print(f"E POS {str(eloc)}")
    # center point (blue)
    locx = statistics.median([sloc.x, eloc.x])
    locy = statistics.median([sloc.y, eloc.y])
    locz = statistics.median([sloc.z, eloc.z])
    pos = Position(locx, locy, locz)
    scene.add_object(arblib.temp_loc_marker(pos, Color(0, 0, 255)))
    print(f"wall position {str(pos)}")
    # rotation
    print(f"S ROT {str(srot)}")
    print(f"E ROT {str(erot)}")
    rotx = arblib.probable_quat(srot.x)
    roty = arblib.probable_quat(srot.y)
    rotz = arblib.probable_quat(srot.z)
    rotw = arblib.probable_quat(srot.w)
    rot = Rotation(rotx, roty, rotz, rotw)
    gaze = (rotx, roty, rotz, rotw)
    scene.add_object(arblib.temp_rot_marker(pos, rot))
    print(f"wall rotation {str(rot)}")
    # which axis to use for wall? use camera gaze
    # TODO: rotation still off
    if gaze in arblib.GAZES[0]:
        height = abs(sloc.y - eloc.y)
        width = abs(sloc.x - eloc.x)
    elif gaze in arblib.GAZES[1]:
        height = abs(sloc.y - eloc.y)
        width = abs(sloc.z - eloc.z)
    elif gaze in arblib.GAZES[2]:
        height = abs(sloc.z - eloc.z)
        width = abs(sloc.x - eloc.x)
    else:
        # TODO: (placeholder) add direction and hypotenuse
        height = abs(sloc.y - eloc.y)
        width = abs(sloc.x - eloc.x)
        print(f"Non-axis parallel rotation: {str(rot)}")
    # scale
    scax = width
    scay = height
    scaz = arblib.WALL_WIDTH
    sca = Scale(scax, scay, scaz)
    print(f"wall scale {str(sca)}")
    # make wall
    randstr = str(random.randrange(0, 1000000))
    new_wall = Box(
        persist=True,
        clickable=True,
        object_id=f"wall_{randstr}",
        position=pos,
        rotation=rot,
        scale=sca,
        material=Material(color=Color(200, 200, 200),
                          transparent=True,
                          opacity=0.5),
    )
    scene.add_object(new_wall)
    USERS[camname].target_id = new_wall.object_id
    print(f"Created {new_wall.object_id} r{str(rot)} s{str(sca)}")