Skip to content

Commit

Permalink
Merge branch 'main' into abhik/splines
Browse files Browse the repository at this point in the history
  • Loading branch information
brentyi authored Aug 28, 2023
2 parents 3b04bf1 + 30aa5a9 commit 27be24b
Show file tree
Hide file tree
Showing 31 changed files with 1,166 additions and 582 deletions.
2 changes: 1 addition & 1 deletion docs/source/gui_handles.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ clients. When a GUI element is added to a client (for example, via

<!-- prettier-ignore-start -->

.. autoapiclass:: viser.GuiHandle
.. autoapiclass:: viser.GuiInputHandle
:members:
:undoc-members:
:inherited-members:
Expand Down
2 changes: 1 addition & 1 deletion examples/03_gui_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def draw_points() -> None:
gui_num_points.on_update(lambda _: draw_points())

@gui_reset_scene.on_click
def _(_: viser.GuiButtonHandle) -> None:
def _(_) -> None:
"""Reset the scene when the reset button is clicked."""
gui_show.value = True
gui_location.value = 0.0
Expand Down
11 changes: 6 additions & 5 deletions examples/08_smplx_visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def main(
ext: Literal["npz", "pkl"] = "npz",
) -> None:
server = viser.ViserServer()
server.configure_theme(control_layout="collapsible", dark_mode=True)
model = smplx.create(
model_path=str(model_path),
model_type=model_type,
Expand Down Expand Up @@ -114,10 +115,10 @@ def main(
class GuiElements:
"""Structure containing handles for reading from GUI elements."""

gui_rgb: viser.GuiHandle[Tuple[int, int, int]]
gui_wireframe: viser.GuiHandle[bool]
gui_betas: List[viser.GuiHandle[float]]
gui_joints: List[viser.GuiHandle[Tuple[float, float, float]]]
gui_rgb: viser.GuiInputHandle[Tuple[int, int, int]]
gui_wireframe: viser.GuiInputHandle[bool]
gui_betas: List[viser.GuiInputHandle[float]]
gui_joints: List[viser.GuiInputHandle[Tuple[float, float, float]]]

changed: bool
"""This flag will be flipped to True whenever the mesh needs to be re-generated."""
Expand Down Expand Up @@ -197,7 +198,7 @@ def _(_):
joint.value = tf.SO3(wxyz=quat).log()
sync_transform_controls()

gui_joints: List[viser.GuiHandle[Tuple[float, float, float]]] = []
gui_joints: List[viser.GuiInputHandle[Tuple[float, float, float]]] = []
for i in range(num_body_joints + 1):
gui_joint = server.add_gui_vector3(
label=smplx.joint_names.JOINT_NAMES[i],
Expand Down
2 changes: 1 addition & 1 deletion examples/09_urdf_visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def main(urdf_path: Path) -> None:
urdf = ViserUrdf(server, urdf_path)

# Create joint angle sliders.
gui_joints: List[viser.GuiHandle[float]] = []
gui_joints: List[viser.GuiInputHandle[float]] = []
initial_angles: List[float] = []
for joint_name, (lower, upper) in urdf.get_actuated_joint_limits().items():
lower = lower if lower is not None else -onp.pi
Expand Down
35 changes: 28 additions & 7 deletions examples/13_theming.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# mypy: disable-error-code="arg-type"
#
# Waiting on PEP 675 support in mypy. https://github.com/python/mypy/issues/12554
"""Theming
Viser is adding support for theming. Work-in-progress.
Viser includes support for light theming.
"""

import time
Expand Down Expand Up @@ -33,16 +36,34 @@
image_alt="NerfStudio Logo",
href="https://docs.nerf.studio/",
)

# image = None

titlebar_theme = TitlebarConfig(buttons=buttons, image=image)

server.configure_theme(
dark_mode=True, titlebar_content=titlebar_theme, control_layout="fixed"
server.add_gui_markdown(
"Viser includes support for light theming via the `.configure_theme()` method."
)

# GUI elements for controllable values.
titlebar = server.add_gui_checkbox("Titlebar", initial_value=True)
dark_mode = server.add_gui_checkbox("Dark mode", initial_value=True)
control_layout = server.add_gui_dropdown(
"Control layout", ("floating", "fixed", "collapsible")
)
brand_color = server.add_gui_rgb("Brand color", (230, 180, 30))
synchronize = server.add_gui_button("Apply theme")


def synchronize_theme() -> None:
server.configure_theme(
dark_mode=dark_mode.value,
titlebar_content=titlebar_theme if titlebar.value else None,
control_layout=control_layout.value,
brand_color=brand_color.value,
)
server.world_axes.visible = True


server.world_axes.visible = True
synchronize.on_click(lambda _: synchronize_theme())
synchronize_theme()

while True:
time.sleep(10.0)
19 changes: 8 additions & 11 deletions examples/16_modal.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,21 @@ def main():
def _(client: viser.ClientHandle) -> None:
with client.add_gui_modal("Modal example"):
client.add_gui_markdown(
markdown="**The slider below determines how many modals will appear...**"
"**The input below determines the title of the modal...**"
)

gui_slider = client.add_gui_slider(
"Slider",
min=1,
max=10,
step=1,
initial_value=1,
gui_title = client.add_gui_text(
"Title",
initial_value="My Modal",
)

modal_button = client.add_gui_button("Show more modals")

@modal_button.on_click
def _(_: viser.GuiButtonHandle) -> None:
for i in range(gui_slider.value):
with client.add_gui_modal(f"Modal #{i}"):
client.add_gui_markdown("This is a modal!")
def _(_) -> None:
with client.add_gui_modal(gui_title.value) as modal:
client.add_gui_markdown("This is content inside the modal!")
client.add_gui_button("Close").on_click(lambda _: modal.close())

while True:
time.sleep(0.15)
Expand Down
36 changes: 36 additions & 0 deletions examples/17_background_composite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# mypy: disable-error-code="var-annotated"
"""Background image example with depth compositing.
In this example, we show how to use a background image with depth compositing. This can
be useful when we want a 2D image to occlude 3D geometry, such as for NeRF rendering.
"""

import time

import numpy as onp
import trimesh
import trimesh.creation

import viser

server = viser.ViserServer()


img = onp.random.randint(0, 255, size=(1000, 1000, 3), dtype=onp.uint8)
depth = onp.ones((1000, 1000, 1), dtype=onp.float32)

# Make a square middle portal.
depth[250:750, 250:750, :] = 10.0
img[250:750, 250:750, :] = 255

mesh = trimesh.creation.box((0.5, 0.5, 0.5))
server.add_mesh_trimesh(
name="/cube",
mesh=mesh,
position=(0, 0, 0.0),
)
server.set_background_image(img, depth=depth)


while True:
time.sleep(1.0)
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "viser"
version = "0.0.17"
version = "0.1.0"
description = "3D visualization + Python"
readme = "README.md"
license = { text="MIT" }
Expand Down Expand Up @@ -91,6 +91,7 @@ select = [
"PLW", # Pylint warnings.
]
ignore = [
"E741", # Ambiguous variable name. (l, O, or I)
"E501", # Line too long.
"F722", # Forward annotation false positive from jaxtyping. Should be caught by pyright.
"F821", # Forward annotation false positive from jaxtyping. Should be caught by pyright.
Expand Down
10 changes: 9 additions & 1 deletion viser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
from typing import TYPE_CHECKING

from ._gui_handles import GuiButtonGroupHandle as GuiButtonGroupHandle
from ._gui_handles import GuiButtonHandle as GuiButtonHandle
from ._gui_handles import GuiDropdownHandle as GuiDropdownHandle
from ._gui_handles import GuiEvent as GuiEvent
from ._gui_handles import GuiFolderHandle as GuiFolderHandle
from ._gui_handles import GuiHandle as GuiHandle
from ._gui_handles import GuiInputHandle as GuiInputHandle
from ._gui_handles import GuiMarkdownHandle as GuiMarkdownHandle
from ._gui_handles import GuiTabGroupHandle as GuiTabGroupHandle
from ._gui_handles import GuiTabHandle as GuiTabHandle
from ._icons_enum import Icon as Icon
from ._scene_handles import CameraFrustumHandle as CameraFrustumHandle
from ._scene_handles import ClickEvent as ClickEvent
from ._scene_handles import FrameHandle as FrameHandle
from ._scene_handles import Gui3dContainerHandle as Gui3dContainerHandle
from ._scene_handles import ImageHandle as ImageHandle
Expand All @@ -19,3 +23,7 @@
from ._viser import CameraHandle as CameraHandle
from ._viser import ClientHandle as ClientHandle
from ._viser import ViserServer as ViserServer

if not TYPE_CHECKING:
# Backwards compatibility.
GuiHandle = GuiInputHandle
29 changes: 17 additions & 12 deletions viser/_client_autobuild.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@
build_dir = client_dir / "build"


def _check_process(process_name: str) -> bool:
"""
Check if a process is running
"""
def _check_viser_yarn_running() -> bool:
"""Returns True if the viewer client has been launched via `yarn start`."""
for process in psutil.process_iter():
if process_name == process.name():
return True
try:
if Path(process.cwd()).as_posix().endswith("viser/client") and any(
[part.endswith("yarn") for part in process.cmdline()]
):
return True
except (psutil.AccessDenied, psutil.ZombieProcess):
pass
return False


def ensure_client_is_built() -> None:
"""Ensure that the client is built."""
"""Ensure that the client is built or already running."""

if not (client_dir / "src").exists():
# Can't build client.
assert (build_dir / "index.html").exists(), (
"Something went wrong! At least one of the client source or build"
" directories should be present."
Expand All @@ -31,14 +35,15 @@ def ensure_client_is_built() -> None:

# Do we need to re-trigger a build?
build = False
if not (build_dir / "index.html").exists():
rich.print("[bold](viser)[/bold] No client build found. Building now...")
build = True
elif _check_process("Viser Viewer"):
if _check_viser_yarn_running():
# Don't run `yarn build` if `yarn start` is already running.
rich.print(
"[bold](viser)[/bold] A Viser viewer is already running. Skipping build check..."
"[bold](viser)[/bold] The Viser viewer looks like it has been launched via `yarn start`. Skipping build check..."
)
build = False
elif not (build_dir / "index.html").exists():
rich.print("[bold](viser)[/bold] No client build found. Building now...")
build = True
elif _modified_time_recursive(client_dir / "src") > _modified_time_recursive(
build_dir
):
Expand Down
Loading

0 comments on commit 27be24b

Please sign in to comment.