Skip to content

Commit

Permalink
Merge branch 'main' into cmk/rayclick
Browse files Browse the repository at this point in the history
  • Loading branch information
brentyi authored Oct 11, 2023
2 parents 081b7c9 + a6c5542 commit 5a4cb21
Show file tree
Hide file tree
Showing 24 changed files with 349 additions and 280 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: docs
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

jobs:
docs:
Expand All @@ -14,7 +17,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.8
python-version: "3.10"

# Build documentation
- name: Building documentation
Expand All @@ -31,3 +34,4 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/build
cname: viser.studio
if: github.event_name != 'pull_request'
2 changes: 1 addition & 1 deletion .github/workflows/typescript-compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 19
node-version: 20
- name: Run tsc
run: |
cd src/viser/client
Expand Down
11 changes: 5 additions & 6 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
sphinx==5.2.0
furo==2023.03.27
docutils==0.17.1
sphinx-autoapi==2.1.0
m2r2==0.3.2
sphinx==7.2.6
furo==2023.9.10
docutils==0.20.1
sphinx-autoapi==3.0.0
m2r2==0.3.3.post2
git+https://github.com/brentyi/sphinxcontrib-programoutput.git
git+https://github.com/brentyi/ansi.git
setuptools
1 change: 1 addition & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@
# -- Options for autoapi extension --------------------------------------------
autoapi_dirs = ["../../src/viser"]
autoapi_root = "api"
autoapi_ignore = ["**/client/**/*.py"]
autoapi_options = [
"members",
"inherited-members",
Expand Down
10 changes: 0 additions & 10 deletions docs/source/examples/15_gui_in_scene.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ performed on them.
rng = onp.random.default_rng(0)
displayed_3d_container: Optional[viser.Gui3dContainerHandle] = None
displayed_index: Optional[int] = None
def make_frame(i: int) -> None:
# Sample a random orientation + position.
Expand All @@ -52,18 +51,11 @@ performed on them.
@frame.on_click
def _(_):
nonlocal displayed_3d_container
nonlocal displayed_index
# Close previously opened GUI.
if displayed_3d_container is not None:
displayed_3d_container.remove()
# Don't re-show the same GUI element.
if displayed_index == i:
return
displayed_index = i
displayed_3d_container = client.add_3d_gui_container(f"/frame_{i}/gui")
with displayed_3d_container:
go_to = client.add_gui_button("Go to")
Expand Down Expand Up @@ -105,12 +97,10 @@ performed on them.
@close.on_click
def _(_) -> None:
nonlocal displayed_3d_container
nonlocal displayed_index
if displayed_3d_container is None:
return
displayed_3d_container.remove()
displayed_3d_container = None
displayed_index = None
for i in range(num_frames):
make_frame(i)
Expand Down
36 changes: 22 additions & 14 deletions examples/14_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,32 @@
server = viser.ViserServer()
server.world_axes.visible = True

markdown_counter = server.add_gui_markdown("Counter: 0")

@server.on_client_connect
def _(client: viser.ClientHandle) -> None:
here = Path(__file__).absolute().parent
markdown_source = (here / "./assets/mdx_example.mdx").read_text()
markdown = client.add_gui_markdown(markdown=markdown_source, image_root=here)
here = Path(__file__).absolute().parent

button = client.add_gui_button("Remove Markdown")
checkbox = client.add_gui_checkbox("Visibility", initial_value=True)
button = server.add_gui_button("Remove blurb")
checkbox = server.add_gui_checkbox("Visibility", initial_value=True)

@button.on_click
def _(_):
markdown.remove()
markdown_source = (here / "./assets/mdx_example.mdx").read_text()
markdown_blurb = server.add_gui_markdown(
content=markdown_source,
image_root=here,
)

@checkbox.on_update
def _(_):
markdown.visible = checkbox.value

@button.on_click
def _(_):
markdown_blurb.remove()


@checkbox.on_update
def _(_):
markdown_blurb.visible = checkbox.value


counter = 0
while True:
time.sleep(10.0)
markdown_counter.content = f"Counter: {counter}"
counter += 1
time.sleep(0.1)
10 changes: 0 additions & 10 deletions examples/15_gui_in_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def _(client: viser.ClientHandle) -> None:
rng = onp.random.default_rng(0)

displayed_3d_container: Optional[viser.Gui3dContainerHandle] = None
displayed_index: Optional[int] = None

def make_frame(i: int) -> None:
# Sample a random orientation + position.
Expand All @@ -47,18 +46,11 @@ def make_frame(i: int) -> None:
@frame.on_click
def _(_):
nonlocal displayed_3d_container
nonlocal displayed_index

# Close previously opened GUI.
if displayed_3d_container is not None:
displayed_3d_container.remove()

# Don't re-show the same GUI element.
if displayed_index == i:
return

displayed_index = i

displayed_3d_container = client.add_3d_gui_container(f"/frame_{i}/gui")
with displayed_3d_container:
go_to = client.add_gui_button("Go to")
Expand Down Expand Up @@ -100,12 +92,10 @@ def _(_) -> None:
@close.on_click
def _(_) -> None:
nonlocal displayed_3d_container
nonlocal displayed_index
if displayed_3d_container is None:
return
displayed_3d_container.remove()
displayed_3d_container = None
displayed_index = None

for i in range(num_frames):
make_frame(i)
Expand Down
1 change: 0 additions & 1 deletion examples/17_background_composite.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# mypy: disable-error-code="var-annotated"
"""Depth compositing
In this example, we show how to use a background image with depth compositing. This can
Expand Down
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.1.5"
version = "0.1.6"
description = "3D visualization + Python"
readme = "README.md"
license = { text="MIT" }
Expand Down Expand Up @@ -67,6 +67,7 @@ python_version = "3.8"
ignore_missing_imports = true
warn_unused_configs = true
exclude="viser/client/.nodeenv"
disable_error_code="var-annotated" # Common source of mypy + numpy false positives.

[tool.pyright]
exclude = ["./docs/**/*", "./examples/assets/**/*", "./src/viser/client/.nodeenv", "./build"]
Expand Down
62 changes: 11 additions & 51 deletions src/viser/_gui_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

import abc
import dataclasses
import re
import threading
import time
import urllib.parse
import warnings
from pathlib import Path
from typing import (
Expand All @@ -24,7 +22,6 @@
overload,
)

import imageio.v3 as iio
import numpy as onp
from typing_extensions import Literal, LiteralString

Expand All @@ -47,7 +44,7 @@
)
from ._icons import base64_from_icon
from ._icons_enum import Icon
from ._message_api import MessageApi, _encode_image_base64, cast_vector
from ._message_api import MessageApi, cast_vector

if TYPE_CHECKING:
from .infra import ClientId
Expand Down Expand Up @@ -87,38 +84,6 @@ def _compute_precision_digits(x: float) -> int:
return digits


def _get_data_url(url: str, image_root: Optional[Path]) -> str:
if not url.startswith("http") and not image_root:
warnings.warn(
"No `image_root` provided. All relative paths will be scoped to viser's installation path.",
stacklevel=2,
)
if url.startswith("http"):
return url
if image_root is None:
image_root = Path(__file__).parent
try:
image = iio.imread(image_root / url)
data_uri = _encode_image_base64(image, "png")
url = urllib.parse.quote(f"{data_uri[1]}")
return f"data:{data_uri[0]};base64,{url}"
except (IOError, FileNotFoundError):
warnings.warn(
f"Failed to read image {url}, with image_root set to {image_root}.",
stacklevel=2,
)
return url


def _parse_markdown(markdown: str, image_root: Optional[Path]) -> str:
markdown = re.sub(
r"\!\[([^]]*)\]\(([^]]*)\)",
lambda match: f"![{match.group(1)}]({_get_data_url(match.group(2), image_root)})",
markdown,
)
return markdown


@dataclasses.dataclass
class _RootGuiContainer:
_children: Dict[str, SupportsRemoveProtocol]
Expand Down Expand Up @@ -277,30 +242,25 @@ def add_gui_tab_group(

def add_gui_markdown(
self,
markdown: str,
content: str,
image_root: Optional[Path] = None,
order: Optional[float] = None,
) -> GuiMarkdownHandle:
"""Add markdown to the GUI."""
markdown = _parse_markdown(markdown, image_root)
markdown_id = _make_unique_id()
order = _apply_default_order(order)
self._get_api()._queue(
_messages.GuiAddMarkdownMessage(
order=order,
id=markdown_id,
markdown=markdown,
container_id=self._get_container_id(),
)
)
return GuiMarkdownHandle(
handle = GuiMarkdownHandle(
_gui_api=self,
_id=markdown_id,
_id=_make_unique_id(),
_visible=True,
_container_id=self._get_container_id(),
_order=order,
_order=_apply_default_order(order),
_image_root=image_root,
_content=None,
)

# Assigning content will send a GuiAddMarkdownMessage.
handle.content = content
return handle

def add_gui_button(
self,
label: str,
Expand Down
Loading

0 comments on commit 5a4cb21

Please sign in to comment.