13 #include <pybind11/detail/common.h>
14 #include <pybind11/functional.h>
56 namespace visualization {
68 void unlock() { unlocker_ =
new py::gil_scoped_release(); }
75 py::gil_scoped_release *unlocker_;
82 explicit PyWindow(
const std::string &title,
int flags = 0)
83 :
Super(title, flags) {}
138 if (resource_path.empty()) {
144 py::object cv3d = py::module::import(
"cloudViewer");
145 auto cv3d_init_path = cv3d.attr(
"__file__").cast<std::string>();
148 resource_path = module_path +
"/resources";
169 bool z_in_view_space ) {
190 std::shared_ptr<cloudViewer::t::geometry::Image>
image)
201 :
Super(texture_id, u0, v0, u1, v1) {}
251 std::function<int(
const MouseEvent &)> on_mouse_;
252 std::function<int(
const KeyEvent &)> on_key_;
305 std::function<int(
const MouseEvent &)> on_mouse_;
306 std::function<int(
const KeyEvent &)> on_key_;
311 py::native_enum<FontStyle>(m_gui,
"FontStyle",
"enum.Enum",
"Font style")
319 py::class_<FontDescription> fd(m_gui,
"FontDescription",
320 "Class to describe a custom font");
322 "Name of the default sans-serif font that comes "
324 .def_readonly_static(
326 "Name of the default monospace font that comes "
328 .def(py::init<const char *, FontStyle, int>(),
331 "Creates a FontDescription. 'typeface' is a path to a "
332 "TrueType (.ttf), TrueType Collection (.ttc), or "
333 "OpenType (.otf) file, or it is the name of the font, "
334 "in which case the system font paths will be searched "
335 "to find the font file. This typeface will be used for "
336 "roman characters (Extended Latin, that is, European "
338 .def(
"add_typeface_for_language",
340 "Adds code points outside Extended Latin from the specified "
341 "typeface. Supported languages are:\n"
345 " 'vi' (Vietnamese)\n"
346 " 'zh' (Chinese, 2500 most common characters, 50 MB per "
348 " 'zh_all' (Chinese, all characters, ~200 MB per window)\n"
349 "All other languages will be assumed to be Cyrillic. "
350 "Note that generally fonts do not have CJK glyphs unless they "
351 "are specifically a CJK font, although operating systems "
352 "generally use a CJK font for you. We do not have the "
353 "information necessary to do this, so you will need to "
354 "provide a font that has the glyphs you need. In particular, "
355 "common fonts like 'Arial', 'Helvetica', and SANS_SERIF do "
356 "not contain CJK glyphs.")
357 .def(
"add_typeface_for_code_points",
359 "Adds specific code points from the typeface. This is useful "
360 "for selectively adding glyphs, for example, from an icon "
364 py::class_<Application> application(m_gui,
"Application",
365 "Global application singleton. This "
366 "owns the menubar, windows, and event "
369 .def_readonly_static(
"DEFAULT_FONT_ID",
373 return std::string(
"Application singleton instance");
375 .def_property_readonly_static(
385 py::return_value_policy::reference,
386 "Gets the Application singleton (read-only)")
390 "Initializes the application, using the resources included "
391 "in the wheel. One of the `initialize` functions _must_ be "
392 "called prior to using anything in the gui module")
395 [](
Application &instance,
const char *resource_dir) {
398 "Initializes the application with location of the "
400 "provided by the caller. One of the `initialize` functions "
401 "_must_ be called prior to using anything in the gui "
404 "Adds a font. Must be called after initialize() and before "
405 "a window is created. Returns the font id, which can be used "
406 "to change the font in widgets such as Label which support "
409 "Changes the contents of an existing font, for instance, the "
413 [](
Application &instance,
const std::string &title,
415 std::shared_ptr<PyWindow> w;
417 w.reset(
new PyWindow(title, flags));
418 }
else if (x < 0 && y < 0) {
427 "title"_a = std::string(),
"width"_a = -1,
"height"_a = -1,
428 "x"_a = -1,
"y"_a = -1,
"flags"_a = 0,
429 "Creates a window and adds it to the application. "
430 "To programmatically destroy the window do window.close()."
431 "Usage: create_window(title, width, height, x, y, flags). "
432 "x, y, and flags are optional.")
447 while (instance.
RunOneTick(unlocker,
false)) {
449 if (PyErr_CheckSignals() != 0) {
450 throw py::error_already_set();
454 "Runs the event loop. After this finishes, all windows and "
455 "widgets should be considered uninitialized, even if they "
456 "are still held by Python variables. Using them is unsafe, "
457 "even if run() is called again.")
464 if (PyErr_CheckSignals() != 0) {
465 throw py::error_already_set();
469 "Runs the event loop once, returns True if the app is "
470 "still running, or False if all the windows have closed "
471 "or quit() has been called.")
479 "Renders a scene to an image and returns the image. If you "
480 "are rendering without a visible window you should use "
481 "cloudViewer.visualization.rendering.RenderToImage instead")
484 "Closes all the windows, exiting as a result")
496 "Adds a window to the application. This is only necessary "
498 "creating object that is a Window directly, rather than "
502 "Runs function in a separate thread. Do not call GUI "
503 "functions on this thread, call post_to_main_thread() if "
504 "this thread needs to change the GUI.")
506 py::call_guard<py::gil_scoped_release>(),
507 "Runs the provided function on the main thread. This can "
508 "be used to execute UI-related code at a safe point in "
509 "time. If the UI changes, you will need to manually "
510 "request a redraw of the window with w.post_redraw()")
513 "The Menu for the application (initially None)")
515 "Returns current time in seconds")
517 .def_property_readonly(
"resource_path",
519 "Returns a string with the path to the "
520 "resources directory");
523 py::class_<LayoutContext> lc(
524 m_gui,
"LayoutContext",
525 "Context passed to Window's on_layout callback");
529 lc.def_property_readonly(
"theme",
538 py::class_<Window, UnownedPointer<Window>> window_base(
539 m_gui,
"WindowBase",
"Application window");
540 py::class_<PyWindow, UnownedPointer<PyWindow>,
Window> window(
542 "Application window. Create with "
543 "Application.instance.create_window().");
544 window.def(
"__repr__",
545 [](
const PyWindow &w) {
return "Application window"; })
549 w.
AddChild(TakeOwnership<Widget>(widget));
551 "Adds a widget to the window")
554 "Window rect in OS coords, not device pixels")
556 "Returns the title of the window")
558 "Sets the width and height of window to its preferred size")
560 "The size of the window in device pixels, including "
561 "menubar (except on macOS)")
562 .def_property_readonly(
564 "Returns the frame in device pixels, relative "
565 " to the window, which is available for widgets "
567 .def_property_readonly(
569 "Returns the scaling factor between OS pixels "
570 "and device pixels (read-only)")
572 "True if window is visible (read-only)")
574 "Sets a callback for key events. This callback is passed "
575 "a KeyEvent object. The callback must return "
576 "True to stop more dispatching or False to dispatch"
580 "Closes the window and destroys it, unless an on_close "
581 "callback cancels the close.")
583 "Flags window to re-layout")
585 "Sends a redraw message to the OS message queue")
586 .def_property_readonly(
"is_active_window",
588 "True if the window is currently the active "
589 "window (read-only)")
591 "Makes specified widget have text focus")
592 .def(
"set_on_menu_item_activated",
594 "Sets callback function for menu item: callback()")
596 "Sets callback for tick event. Callback takes no arguments "
597 "and must return True if a redraw is needed (that is, if "
598 "any widget has changed in any fashion) or False if nothing "
601 "Sets a callback that will be called when the window is "
602 "closed. The callback is given no arguments and should return "
603 "True to continue closing the window or False to cancel the "
611 "Sets a callback function that manually sets the frames of "
612 "children of the window. Callback function will be called "
613 "with one argument: gui.LayoutContext")
615 "Get's window's theme info")
621 "Displays the dialog")
623 "Closes the current dialog")
625 "Displays a simple dialog with a title and message and okay "
628 "show_menu(show): shows or hides the menu in the window, "
629 "except on macOS since the menubar is not in the window "
630 "and all applications must have a menubar.")
631 .def_property_readonly(
633 "Gets the rendering.Renderer object for the Window");
636 py::class_<Menu, UnownedPointer<Menu>> menu(m_gui,
"Menu",
637 "A menu, possibly a menu tree");
638 menu.def(py::init<>())
642 int item_id) { menu->AddItem(text, item_id); },
643 "Adds a menu item with id to the menu")
648 menu->AddMenu(text, TakeOwnership<Menu>(submenu));
650 "Adds a submenu to the menu")
652 "Adds a separator to the menu")
656 menu->SetEnabled(item_id, enabled);
658 "Sets menu item enabled or disabled")
662 return menu->IsChecked(item_id);
664 "Returns True if menu item is checked")
668 menu->SetChecked(item_id, checked);
670 "Sets menu item (un)checked");
673 py::class_<Color>
color(m_gui,
"Color",
"Stores color for gui classes");
674 color.def(py::init([](
float r,
float g,
float b,
float a) {
675 return new Color(r, g, b, a);
677 "r"_a = 1.0,
"g"_a = 1.0,
"b"_a = 1.0,
"a"_a = 1.0)
678 .def_property_readonly(
680 "Returns red channel in the range [0.0, 1.0] "
682 .def_property_readonly(
684 "Returns green channel in the range [0.0, 1.0] "
686 .def_property_readonly(
688 "Returns blue channel in the range [0.0, 1.0] "
690 .def_property_readonly(
692 "Returns alpha channel in the range [0.0, 1.0] "
695 "Sets red, green, blue, and alpha channels, (range: [0.0, "
697 "r"_a,
"g"_a,
"b"_a,
"a"_a = 1.0);
701 py::class_<Theme>
theme(m_gui,
"Theme",
702 "Theme parameters such as colors used for drawing "
703 "widgets (read-only)");
705 "Font size (which is also the conventional size of the "
706 "em unit) (read-only)")
708 "Good default value for margins, useful for layouts "
710 .def_readonly(
"default_layout_spacing",
712 "Good value for the spacing parameter in layouts "
716 py::class_<Rect>
rect(m_gui,
"Rect",
"Represents a widget frame");
717 rect.def(py::init<>())
718 .def(py::init<int, int, int, int>())
719 .def(py::init([](
float x,
float y,
float w,
float h) {
720 return Rect(
int(std::round(x)),
int(std::round(y)),
721 int(std::round(w)),
int(std::round(h)));
726 s <<
"Rect (" << r.x <<
", " << r.y <<
"), " << r.width
727 <<
" x " << r.height;
740 py::class_<Size>
size(m_gui,
"Size",
"Size object");
741 size.def(py::init<>())
742 .def(py::init<int, int>())
743 .def(py::init([](
float w,
float h) {
744 return Size(
int(std::round(w)),
int(std::round(h)));
749 s <<
"Size (" << sz.
width <<
", " << sz.
height <<
")";
764 py::class_<Widget, UnownedPointer<Widget>> widget(m_gui,
"Widget",
765 "Base widget class");
767 py::native_enum<EventCallbackResult> widget_event_callback_result(
768 widget,
"EventCallbackResult",
"enum.IntEnum",
769 "Returned by event handlers.");
770 widget_event_callback_result
772 "Event handler ignored the event, widget will "
773 "handle event normally")
775 "Event handler handled the event, but widget "
776 "will still handle the event normally. This is "
777 "useful when you are augmenting base "
780 "Event handler consumed the event, event "
781 "handling stops, widget will not handle the "
782 "event. This is useful when you are replacing "
787 py::class_<Widget::Constraints> constraints(
788 widget,
"Constraints",
789 "Constraints object for Widget.calc_preferred_size()");
790 constraints.def(py::init<>())
794 widget.def(py::init<>())
798 s <<
"Widget (" << w.GetFrame().x <<
", " << w.GetFrame().y
799 <<
"), " << w.GetFrame().width <<
" x "
800 << w.GetFrame().height;
806 w.
AddChild(TakeOwnership<Widget>(child));
808 "Adds a child widget")
810 "Returns the array of children. Do not modify.")
812 "The widget's frame. Setting this value will be "
813 "overridden if the frame is within a layout.")
815 "True if widget is visible, False otherwise")
817 "True if widget is enabled, False if disabled")
820 "Background color of the widget")
822 "Widget's tooltip that is displayed on mouseover")
824 "Returns the preferred size of the widget. This is intended "
825 "to be called only during layout, although it will also work "
826 "during drawing. Calling it at other times will not work, as "
827 "it requires some internal setup in order to function "
831 py::class_<WidgetProxy, UnownedPointer<WidgetProxy>,
Widget> widgetProxy(
832 m_gui,
"WidgetProxy",
833 "Widget container to delegate any widget dynamically."
834 " Widget can not be managed dynamically. Although it is allowed"
835 " to add more child widgets, it's impossible to replace some child"
836 " with new on or remove children. WidgetProxy is designed to solve"
838 " When WidgetProxy is created, it's invisible and disabled, so it"
839 " won't be drawn or layout, seeming like it does not exist. When"
840 " a widget is set by set_widget, all Widget's APIs will be"
841 " conducted to that child widget. It looks like WidgetProxy is"
843 " At any time, a new widget could be set, to replace the old one."
844 " and the old widget will be destroyed."
845 " Due to the content changing after a new widget is set or cleared,"
846 " a relayout of Window might be called after set_widget."
847 " The delegated widget could be retrieved by get_widget in case"
848 " you need to access it directly, like get check status of a"
849 " CheckBox. API other than set_widget and get_widget has"
850 " completely same functions as Widget.");
851 widgetProxy.def(py::init<>(),
"Creates a widget proxy")
863 w.SetWidget(TakeOwnership<Widget>(proxy));
865 "set a new widget to be delegated by this one."
866 " After set_widget, the previously delegated widget ,"
867 " will be abandon all calls to Widget's API will be "
868 " conducted to widget. Before any set_widget call, "
869 " this widget is invisible and disabled, seems it "
870 " does not exist because it won't be drawn or in a "
873 "Retrieve current delegated widget."
874 "return instance of current delegated widget set by "
875 "set_widget. An empty pointer will be returned "
876 "if there is none.");
879 py::class_<WidgetStack, UnownedPointer<WidgetStack>,
WidgetProxy>
880 widget_stack(m_gui,
"WidgetStack",
881 "A widget stack saves all widgets pushed into by "
882 "push_widget and always shows the top one. The "
883 "WidgetStack is a subclass of WidgetProxy, in other"
884 "words, the topmost widget will delegate itself to "
885 "WidgetStack. pop_widget will remove the topmost "
886 "widget and callback set by set_on_top taking the "
887 "new topmost widget will be called. The WidgetStack "
888 "disappears in GUI if there is no widget in stack.");
891 "Creates a widget stack. The widget stack without any"
892 "widget will not be shown in GUI until set_widget is"
893 "called to push a widget.")
903 "push a new widget onto the WidgetStack's stack, hiding "
904 "whatever widget was there before and making the new widget "
907 "pop the topmost widget in the stack. The new topmost widget"
908 "of stack will be the widget on the show in GUI.")
910 "Callable[[widget] -> None], called while a widget "
911 "becomes the topmost of stack after some widget is popped"
912 "out. It won't be called if a widget is pushed into stack"
916 py::class_<Button, UnownedPointer<Button>,
Widget> button(m_gui,
"Button",
918 button.def(py::init<const char *>(),
"Creates a button with the given text")
922 s <<
"Button (" << b.GetFrame().x <<
", " << b.GetFrame().y
923 <<
"), " << b.GetFrame().width <<
" x "
924 << b.GetFrame().height;
928 "Gets/sets the button text.")
932 "True if button is toggleable, False if a push button")
935 "True if the button is toggleable and in the on state")
944 auto vert = b->GetVerticalPaddingEm();
946 b->SetPaddingEm(em.cast<
float>(), vert);
947 }
catch (
const py::cast_error &) {
949 "cloudViewer.visualization.gui.Button."
950 "horizontal_padding_em can only be "
951 "assigned a numeric type");
954 "Horizontal padding in em units")
958 auto horiz = b->GetHorizontalPaddingEm();
960 b->SetPaddingEm(horiz, em.cast<
float>());
961 }
catch (
const py::cast_error &) {
963 "cloudViewer.visualization.gui.Button."
964 "vertical_padding_em can only be "
965 "assigned a numeric type");
968 "Vertical padding in em units")
970 "Calls passed function when button is pressed");
973 py::class_<Checkbox, UnownedPointer<Checkbox>,
Widget> checkbox(
974 m_gui,
"Checkbox",
"Checkbox");
975 checkbox.def(py::init<const char *>(),
976 "Creates a checkbox with the given text")
980 s <<
"Checkbox (" << c.
GetFrame().x <<
", "
987 "True if checked, False otherwise")
989 "Calls passed function when checkbox changes state");
992 py::class_<ColorEdit, UnownedPointer<ColorEdit>,
Widget> coloredit(
993 m_gui,
"ColorEdit",
"Color picker");
994 coloredit.def(py::init<>())
997 auto &
color = c.GetValue();
999 s <<
"ColorEdit [" <<
color.GetRed() <<
", "
1000 <<
color.GetGreen() <<
", " <<
color.GetBlue() <<
", "
1009 "Color value (gui.Color)")
1011 "Calls f(Color) when color changes by user input");
1014 py::class_<Combobox, UnownedPointer<Combobox>,
Widget> combobox(
1015 m_gui,
"Combobox",
"Exclusive selection from a pull-down menu");
1016 combobox.def(py::init<>(),
1017 "Creates an empty combobox. Use add_item() to add items")
1022 "Changes the text of the item at index: "
1023 "change_item(index, newtext)")
1025 (
void(
Combobox::*)(
const char *,
const char *)) &
1027 "Changes the text of the matching item: "
1028 "change_item(text, newtext)")
1031 "Removes the first item of the given text")
1033 "Removes the item at the index")
1035 "Returns the item at the given index. Index must be valid.")
1036 .def_property_readonly(
"number_of_items",
1038 "The number of items (read-only)")
1041 "The index of the currently selected item")
1044 "The index of the currently selected item")
1046 "Calls f(str, int) when user selects item from combobox. "
1047 "Arguments are the selected text and selected index, "
1051 py::class_<RadioButton, UnownedPointer<RadioButton>,
Widget> radiobtn(
1052 m_gui,
"RadioButton",
"Exclusive selection from radio button list");
1053 py::native_enum<RadioButton::Type>(radiobtn,
"Type",
"enum.Enum",
1054 "Enum class for RadioButton types.")
1055 .value(
"VERT", RadioButton::Type::VERT)
1056 .value(
"HORIZ", RadioButton::Type::HORIZ)
1059 radiobtn.def(py::init<RadioButton::Type>(),
1060 "Creates an empty radio buttons. Use set_items() to add items")
1062 "Set radio items, each item is a radio button.")
1065 "The index of the currently selected item")
1066 .def_property_readonly(
"selected_value",
1068 "The text of the currently selected item")
1069 .def(
"set_on_selection_changed",
1071 "Calls f(new_idx) when user changes selection");
1074 py::class_<UIImage, UnownedPointer<UIImage>> uiimage(
1076 "A bitmap suitable for displaying with ImageWidget");
1078 py::native_enum<UIImage::Scaling> uiimage_scaling(
1079 uiimage,
"Scaling",
"enum.Enum",
"UIImage::Scaling.");
1085 uiimage.def(py::init<>([](
const char *
path) {
return new UIImage(
path); }),
1086 "Creates a UIImage from the image at the specified path")
1087 .def(py::init<>([](std::shared_ptr<geometry::Image>
image) {
1090 "Creates a UIImage from the provided image")
1091 .def(
"__repr__", [](
const UIImage &il) {
return "UIImage"; })
1093 "Sets how the image is scaled:\n"
1094 "gui.UIImage.Scaling.NONE: no scaling\n"
1095 "gui.UIImage.Scaling.ANY: scaled to fit\n"
1096 "gui.UIImage.Scaling.ASPECT: scaled to fit but "
1097 "keeping the image's aspect ratio");
1098 py::class_<PyImageWidget, UnownedPointer<PyImageWidget>,
Widget>
1099 imagewidget(m_gui,
"ImageWidget",
"Displays a bitmap");
1102 "Creates an ImageWidget with no image")
1103 .def(py::init<>([](
const char *
path) {
1106 "Creates an ImageWidget from the image at the specified path")
1107 .def(py::init<>([](std::shared_ptr<geometry::Image>
image) {
1110 "Creates an ImageWidget from the provided image")
1111 .def(py::init<>([](std::shared_ptr<t::geometry::Image>
image) {
1114 "Creates an ImageWidget from the provided tgeometry image")
1117 std::stringstream s;
1118 s <<
"ImageWidget (" << il.GetFrame().x <<
", "
1119 << il.GetFrame().y <<
"), " << il.GetFrame().width
1120 <<
" x " << il.GetFrame().height;
1123 .def(
"update_image",
1124 py::overload_cast<std::shared_ptr<geometry::Image>>(
1126 "Mostly a convenience function for ui_image.update_image(). "
1127 "If 'image' is the same size as the current image, will "
1128 "update the texture with the contents of 'image'. This is "
1129 "the fastest path for setting an image, and is recommended "
1130 "if you are displaying video. If 'image' is a different size, "
1131 "it will allocate a new texture, which is essentially the "
1132 "same as creating a new UIImage and calling SetUIImage(). "
1133 "This is the slow path, and may eventually exhaust internal "
1134 "texture resources.")
1135 .def(
"update_image",
1136 py::overload_cast<std::shared_ptr<t::geometry::Image>>(
1138 "Mostly a convenience function for ui_image.update_image(). "
1139 "If 'image' is the same size as the current image, will "
1140 "update the texture with the contents of 'image'. This is "
1141 "the fastest path for setting an image, and is recommended "
1142 "if you are displaying video. If 'image' is a different size, "
1143 "it will allocate a new texture, which is essentially the "
1144 "same as creating a new UIImage and calling SetUIImage(). "
1145 "This is the slow path, and may eventually exhaust internal "
1146 "texture resources.")
1148 "Sets a callback for mouse events. This callback is passed "
1149 "a MouseEvent object. The callback must return "
1150 "EventCallbackResult.IGNORED, EventCallbackResult.HANDLED, "
1151 "or EventCallbackResult.CONSUMED.")
1153 "Sets a callback for key events. This callback is passed "
1154 "a KeyEvent object. The callback must return "
1155 "EventCallbackResult.IGNORED, EventCallbackResult.HANDLED, "
1156 "or EventCallackResult.CONSUMED.")
1159 "Replaces the texture with a new texture. This is "
1160 "not a fast path, and is not recommended for video "
1161 "as you will exhaust internal texture resources.");
1164 py::class_<Label, UnownedPointer<Label>,
Widget> label(m_gui,
"Label",
1166 label.def(py::init([](
const char *title =
"") {
return new Label(title); }),
1167 "Creates a Label with the given text")
1169 [](
const Label &lbl) {
1170 std::stringstream s;
1171 s <<
"Label [" << lbl.
GetText() <<
"] ("
1178 "The text of the label. Newlines will be treated as "
1182 "The color of the text (gui.Color)")
1184 "Set the font using the FontId returned from "
1185 "Application.add_font()");
1188 py::class_<Label3D, UnownedPointer<Label3D>> label3d(
1189 m_gui,
"Label3D",
"Displays text in a 3D scene");
1190 label3d.def(py::init([](
const char *text =
"",
1191 const Eigen::Vector3f &pos = {0.f, 0.f, 0.f}) {
1192 return new Label3D(pos, text);
1194 "Create a 3D Label with given text and position")
1196 "The text to display with this label.")
1199 "The position of the text in 3D coordinates")
1202 "The color of the text (gui.Color)");
1205 py::class_<ListView, UnownedPointer<ListView>,
Widget> listview(
1206 m_gui,
"ListView",
"Displays a list of text");
1207 listview.def(py::init<>(),
"Creates an empty list")
1210 std::stringstream s;
1211 s <<
"Label (" << lv.
GetFrame().x <<
", "
1217 "Sets the list to display the list of items provided")
1219 "Limit the max visible items shown to user. "
1220 "Set to negative number will make list extends vertically "
1221 "as much as possible, otherwise the list will at least show "
1222 "3 items and at most show num items.")
1225 "The index of the currently selected item")
1226 .def_property_readonly(
"selected_value",
1228 "The text of the currently selected item")
1230 "Calls f(new_val, is_double_click) when user changes "
1234 py::class_<NumberEdit, UnownedPointer<NumberEdit>,
Widget> numedit(
1235 m_gui,
"NumberEdit",
"Allows the user to enter a number.");
1237 py::native_enum<NumberEdit::Type> numedit_type(
1238 numedit,
"Type",
"enum.Enum",
"Enum class for NumberEdit types.");
1239 numedit_type.value(
"INT", NumberEdit::Type::INT)
1240 .value(
"DOUBLE", NumberEdit::Type::DOUBLE)
1244 numedit.def(py::init<NumberEdit::Type>(),
1245 "Creates a NumberEdit that is either integers (INT) or "
1246 "floating point (DOUBLE). The initial value is 0 and the "
1247 "limits are +/- max integer (roughly).")
1251 std::stringstream s;
1252 s <<
"NumberEdit [" << val <<
"] (" << ne.
GetFrame().x
1262 "Current value (int)")
1268 "Number of fractional digits shown")
1269 .def_property_readonly(
"minimum_value",
1271 "The minimum value number can contain "
1272 "(read-only, use set_limits() to set)")
1273 .def_property_readonly(
"maximum_value",
1275 "The maximum value number can contain "
1276 "(read-only, use set_limits() to set)")
1278 "Sets the minimum and maximum values for the number")
1280 "Sets f(new_value) which is called with a Float when user "
1281 "changes widget's value")
1283 "Sets the preferred width of the NumberEdit")
1285 "set_preferred_width",
1287 ne.NumberEdit::SetPreferredWidth(
int(
width));
1289 "Sets the preferred width of the NumberEdit");
1292 py::class_<ProgressBar, UnownedPointer<ProgressBar>,
Widget> progress(
1293 m_gui,
"ProgressBar",
"Displays a progress bar");
1294 progress.def(py::init<>())
1297 std::stringstream s;
1298 s <<
"ProgressBar [" << pb.
GetValue() <<
"] ("
1305 "The value of the progress bar, ranges from 0.0 to 1.0");
1360 std::function<int(
const MouseEvent &)> on_mouse_;
1361 std::function<int(
const KeyEvent &)> on_key_;
1364 py::class_<PySceneWidget, UnownedPointer<PySceneWidget>,
Widget> scene(
1365 m_gui,
"SceneWidget",
"Displays 3D content");
1367 py::native_enum<SceneWidget::Controls> scene_ctrl(
1368 scene,
"Controls",
"enum.Enum",
1369 "Enum class describing mouse interaction.");
1370 scene_ctrl.value(
"ROTATE_CAMERA", SceneWidget::Controls::ROTATE_CAMERA)
1371 .value(
"ROTATE_CAMERA_SPHERE",
1372 SceneWidget::Controls::ROTATE_CAMERA_SPHERE)
1373 .value(
"FLY", SceneWidget::Controls::FLY)
1374 .value(
"ROTATE_SUN", SceneWidget::Controls::ROTATE_SUN)
1375 .value(
"ROTATE_IBL", SceneWidget::Controls::ROTATE_IBL)
1376 .value(
"ROTATE_MODEL", SceneWidget::Controls::ROTATE_MODEL)
1377 .value(
"PICK_POINTS", SceneWidget::Controls::PICK_POINTS)
1381 scene.def(py::init<>(),
1382 "Creates an empty SceneWidget. Assign a Scene with the 'scene' "
1386 "The rendering.CloudViewerScene that the SceneWidget "
1388 .def_property(
"center_of_rotation",
1391 "Current center of rotation (for ROTATE_CAMERA and "
1392 "ROTATE_CAMERA_SPHERE)")
1394 "Enable/Disable caching of scene content when the view or "
1395 "model is not changing. Scene caching can help improve UI "
1396 "responsiveness for large models and point clouds")
1398 "Ensures scene redraws even when scene caching is enabled.")
1400 "Sets mouse interaction, e.g. ROTATE_OBJ")
1401 .def(
"setup_camera",
1402 py::overload_cast<
float,
const ccBBox &,
1403 const Eigen::Vector3f &>(
1405 "Configure the camera: setup_camera(field_of_view, "
1406 "model_bounds, center_of_rotation)")
1407 .def(
"setup_camera",
1409 const Eigen::Matrix4d &,
const ccBBox &>(
1411 "setup_camera(intrinsics, extrinsic_matrix, model_bounds): "
1412 "sets the camera view")
1413 .def(
"setup_camera",
1414 py::overload_cast<
const Eigen::Matrix3d &,
1415 const Eigen::Matrix4d &,
int,
int,
1417 "setup_camera(intrinsic_matrix, extrinsic_matrix, "
1418 "intrinsic_width_px, intrinsic_height_px, model_bounds): "
1419 "sets the camera view")
1421 "look_at(center, eye, up): sets the "
1422 "camera view so that the camera is located at 'eye', pointing "
1423 "towards 'center', and oriented so that the up vector is 'up'")
1425 "Sets a callback for mouse events. This callback is passed "
1426 "a MouseEvent object. The callback must return "
1427 "EventCallbackResult.IGNORED, EventCallbackResult.HANDLED, "
1428 "or EventCallackResult.CONSUMED.")
1430 "Sets a callback for key events. This callback is passed "
1431 "a KeyEvent object. The callback must return "
1432 "EventCallbackResult.IGNORED, EventCallbackResult.HANDLED, "
1433 "or EventCallackResult.CONSUMED.")
1434 .def(
"set_on_sun_direction_changed",
1436 "Callback when user changes sun direction (only called in "
1437 "ROTATE_SUN control mode). Called with one argument, the "
1438 "[i, j, k] vector of the new sun direction")
1440 "Add a 3D text label to the scene. The label will be anchored "
1441 "at the specified 3D point.")
1443 "Removes the 3D text label from the scene");
1446 py::class_<Slider, UnownedPointer<Slider>,
Widget> slider(
1447 m_gui,
"Slider",
"A slider widget for visually selecting numbers");
1449 py::native_enum<Slider::Type> slider_type(slider,
"Type",
"enum.Enum",
1450 "Enum class for Slider types.");
1451 slider_type.value(
"INT", Slider::Type::INT)
1452 .value(
"DOUBLE", Slider::Type::DOUBLE)
1456 slider.def(py::init<Slider::Type>(),
1457 "Creates a NumberEdit that is either integers (INT) or "
1458 "floating point (DOUBLE). The initial value is 0 and the limits "
1459 "are +/- infinity.")
1463 std::stringstream s;
1464 s <<
"TextEdit [" << val <<
"] (" << sl.
GetFrame().x
1474 "Slider value (int)")
1477 .def_property_readonly(
"get_minimum_value",
1479 "The minimum value number can contain "
1480 "(read-only, use set_limits() to set)")
1481 .def_property_readonly(
"get_maximum_value",
1483 "The maximum value number can contain "
1484 "(read-only, use set_limits() to set)")
1486 "Sets the minimum and maximum values for the slider")
1488 "Sets f(new_value) which is called with a Float when user "
1489 "changes widget's value");
1492 py::class_<StackedWidget, UnownedPointer<StackedWidget>,
Widget> stacked(
1493 m_gui,
"StackedWidget",
"Like a TabControl but without the tabs");
1494 stacked.def(py::init<>())
1497 "Selects the index of the child to display");
1500 py::class_<TabControl, UnownedPointer<TabControl>,
Widget> tabctrl(
1501 m_gui,
"TabControl",
"Tab control");
1502 tabctrl.def(py::init<>())
1507 tabs.
AddTab(
name, TakeOwnership<Widget>(panel));
1509 "Adds a tab. The first parameter is the title of the tab, "
1510 "and the second parameter is a widget--normally this is a "
1512 .def(
"set_on_selected_tab_changed",
1514 "Calls the provided callback function with the index of the "
1515 "currently selected tab whenever the user clicks on a "
1519 py::class_<TextEdit, UnownedPointer<TextEdit>,
Widget> textedit(
1520 m_gui,
"TextEdit",
"Allows the user to enter or modify text");
1521 textedit.def(py::init<>(),
1522 "Creates a TextEdit widget with an initial value of an empty "
1527 std::stringstream s;
1528 s <<
"TextEdit [" << val <<
"] (" << te.
GetFrame().x
1534 "The value of text")
1538 "The placeholder text displayed when text value is empty")
1540 "Sets f(new_text) which is called whenever the the user makes "
1541 "a change to the text")
1543 "Sets f(new_text) which is called with the new text when the "
1544 "user completes text editing");
1547 py::class_<ToggleSwitch, UnownedPointer<ToggleSwitch>,
Widget> toggle(
1548 m_gui,
"ToggleSwitch",
"ToggleSwitch");
1549 toggle.def(py::init<const char *>(),
1550 "Creates a toggle switch with the given text")
1553 std::stringstream s;
1554 s <<
"ToggleSwitch (" << ts.
GetFrame().x <<
", "
1560 "True if is one, False otherwise")
1562 "Sets f(is_on) which is called when the switch changes "
1566 py::class_<TreeView, UnownedPointer<TreeView>,
Widget> treeview(
1567 m_gui,
"TreeView",
"Hierarchical list");
1568 treeview.def(py::init<>(),
"Creates an empty TreeView widget")
1571 std::stringstream s;
1572 s <<
"TreeView (" << tv.
GetFrame().x <<
", "
1578 "Returns the root item. This item is invisible, so its child "
1579 "are the top-level items")
1584 return tree.
AddItem(parent_id,
1585 TakeOwnership<Widget>(item));
1587 "Adds a child item to the parent. add_item(parent, widget)")
1589 "Adds a child item to the parent. add_text_item(parent, text)")
1591 "Removes an item and all its children (if any)")
1594 "Returns the widget associated with the provided Item ID. For "
1595 "example, to manipulate the widget of the currently selected "
1596 "item you would use the ItemID of the selected_item property "
1597 "with get_item to get the widget.")
1599 "can_select_items_with_children",
1602 "If set to False, clicking anywhere on an item with "
1603 "will toggle the item open or closed; the item cannot be "
1604 "selected. If set to True, items with children can be "
1605 "selected, and to toggle open/closed requires clicking "
1606 "the arrow or double-clicking the item")
1609 "The currently selected item")
1611 "Sets f(new_item_id) which is called when the user "
1612 "changes the selection.");
1615 py::class_<CheckableTextTreeCell, UnownedPointer<CheckableTextTreeCell>,
1617 checkable_cell(m_gui,
"CheckableTextTreeCell",
1618 "TreeView cell with a checkbox and text");
1620 .def(py::init<>([](
const char *text,
bool checked,
1621 std::function<
void(
bool)> on_toggled) {
1625 "Creates a TreeView cell with a checkbox and text. "
1626 "CheckableTextTreeCell(text, is_checked, on_toggled): "
1627 "on_toggled takes a boolean and returns None")
1628 .def_property_readonly(
"checkbox",
1630 "Returns the checkbox widget "
1631 "(property is read-only)")
1633 "Returns the label widget "
1634 "(property is read-only)");
1636 py::class_<LUTTreeCell, UnownedPointer<LUTTreeCell>,
Widget> lut_cell(
1637 m_gui,
"LUTTreeCell",
1638 "TreeView cell with checkbox, text, and color edit");
1639 lut_cell.def(py::init<>([](
const char *text,
bool checked,
1641 std::function<
void(
bool)> on_enabled,
1642 std::function<
void(
const Color &)> on_color) {
1646 "Creates a TreeView cell with a checkbox, text, and "
1647 "a color editor. LUTTreeCell(text, is_checked, color, "
1648 "on_enabled, on_color): on_enabled is called when the "
1649 "checkbox toggles, and takes a boolean and returns None"
1650 "; on_color is called when the user changes the color "
1651 "and it takes a gui.Color and returns None.")
1653 "Returns the checkbox widget "
1654 "(property is read-only)")
1656 "Returns the label widget "
1657 "(property is read-only)")
1659 "Returns the ColorEdit widget "
1660 "(property is read-only)");
1662 py::class_<ColormapTreeCell, UnownedPointer<ColormapTreeCell>,
Widget>
1663 colormap_cell(m_gui,
"ColormapTreeCell",
1664 "TreeView cell with a number edit and color edit");
1666 .def(py::init<>([](
float value,
const Color &
color,
1667 std::function<
void(
double)> on_value_changed,
1668 std::function<
void(
const Color &)>
1673 "Creates a TreeView cell with a number and a color edit. "
1674 "ColormapTreeCell(value, color, on_value_changed, "
1675 "on_color_changed): on_value_changed takes a double "
1676 "and returns None; on_color_changed takes a "
1677 "gui.Color and returns None")
1678 .def_property_readonly(
"number_edit",
1680 "Returns the NumberEdit widget "
1681 "(property is read-only)")
1682 .def_property_readonly(
"color_edit",
1684 "Returns the ColorEdit widget "
1685 "(property is read-only)");
1688 py::class_<VectorEdit, UnownedPointer<VectorEdit>,
Widget> vectoredit(
1689 m_gui,
"VectorEdit",
"Allows the user to edit a 3-space vector");
1690 vectoredit.def(py::init<>())
1694 std::stringstream s;
1695 s <<
"VectorEdit [" << val.x() <<
", " << val.y() <<
", "
1696 << val.z() <<
"] (" << ve.
GetFrame().
x <<
", "
1704 "Sets f([x, y, z]) which is called whenever the user "
1705 "changes the value of a component");
1708 py::class_<Margins, UnownedPointer<Margins>> margins(m_gui,
"Margins",
1709 "Margins for layouts");
1710 margins.def(py::init([](
int left,
int top,
int right,
int bottom) {
1711 return new Margins(left, top, right, bottom);
1713 "left"_a = 0,
"top"_a = 0,
"right"_a = 0,
"bottom"_a = 0,
1714 "Creates margins. Arguments are left, top, right, bottom. "
1715 "Use the em-size (window.theme.font_size) rather than pixels "
1716 "for more consistency across platforms and monitors. Margins "
1717 "are the spacing from the edge of the widget's frame to its "
1718 "content area. They act similar to the 'padding' property in "
1720 .def(py::init([](
float left,
float top,
float right,
float bottom) {
1722 int(std::round(left)),
int(std::round(top)),
1723 int(std::round(right)),
int(std::round(bottom)));
1725 "left"_a = 0.0f,
"top"_a = 0.0f,
"right"_a = 0.0f,
1727 "Creates margins. Arguments are left, top, right, bottom. "
1728 "Use the em-size (window.theme.font_size) rather than pixels "
1729 "for more consistency across platforms and monitors. Margins "
1730 "are the spacing from the edge of the widget's frame to its "
1731 "content area. They act similar to the 'padding' property in "
1741 py::class_<Layout1D, UnownedPointer<Layout1D>,
Widget> layout1d(
1742 m_gui,
"Layout1D",
"Layout base class");
1748 "Adds a fixed amount of empty space to the layout")
1752 layout->AddFixed(
int(std::round(px)));
1754 "Adds a fixed amount of empty space to the layout")
1756 "Adds empty space to the layout that will take up as much "
1757 "extra space as there is available in the layout");
1760 py::class_<Vert, UnownedPointer<Vert>,
Layout1D> vlayout(m_gui,
"Vert",
1762 vlayout.def(py::init([](
int spacing,
const Margins &margins) {
1763 return new Vert(spacing, margins);
1765 "spacing"_a = 0,
"margins"_a =
Margins(),
1766 "Creates a layout that arranges widgets vertically, top to "
1767 "bottom, making their width equal to the layout's width. First "
1768 "argument is the spacing between widgets, the second is the "
1769 "margins. Both default to 0.")
1770 .def(py::init([](
float spacing,
const Margins &margins) {
1771 return new Vert(
int(std::round(spacing)), margins);
1773 "spacing"_a = 0.0f,
"margins"_a =
Margins(),
1774 "Creates a layout that arranges widgets vertically, top to "
1775 "bottom, making their width equal to the layout's width. "
1776 "First argument is the spacing between widgets, the second "
1777 "is the margins. Both default to 0.")
1780 "Sets the preferred width of the layout");
1783 py::class_<CollapsableVert, UnownedPointer<CollapsableVert>,
Vert>
1784 collapsable(m_gui,
"CollapsableVert",
1785 "Vertical layout with title, whose contents are "
1788 .def(py::init([](
const char *text,
int spacing,
1792 "text"_a,
"spacing"_a = 0,
"margins"_a =
Margins(),
1793 "Creates a layout that arranges widgets vertically, top to "
1794 "bottom, making their width equal to the layout's width. "
1795 "First argument is the heading text, the second is the "
1796 "spacing between widgets, and the third is the margins. "
1797 "Both the spacing and the margins default to 0.")
1798 .def(py::init([](
const char *text,
float spacing,
1803 "text"_a,
"spacing"_a = 0.0f,
"margins"_a =
Margins(),
1804 "Creates a layout that arranges widgets vertically, top to "
1805 "bottom, making their width equal to the layout's width. "
1806 "First argument is the heading text, the second is the "
1807 "spacing between widgets, and the third is the margins. "
1808 "Both the spacing and the margins default to 0.")
1810 "Sets to collapsed (False) or open (True). Requires a call to "
1811 "Window.SetNeedsLayout() afterwards, unless calling before "
1812 "window is visible")
1814 "Check if widget is open.")
1816 "Sets the text for the CollapsableVert")
1818 "Gets the text for the CollapsableVert")
1821 "Set the font using the FontId returned from "
1822 "Application.add_font()");
1825 py::class_<ScrollableVert, UnownedPointer<ScrollableVert>,
Vert> slayout(
1826 m_gui,
"ScrollableVert",
"Scrollable vertical layout");
1827 slayout.def(py::init([](
int spacing,
const Margins &margins) {
1830 "spacing"_a = 0,
"margins"_a =
Margins(),
1831 "Creates a layout that arranges widgets vertically, top to "
1832 "bottom, making their width equal to the layout's width. First "
1833 "argument is the spacing between widgets, the second is the "
1834 "margins. Both default to 0.")
1835 .def(py::init([](
float spacing,
const Margins &margins) {
1839 "spacing"_a = 0.0f,
"margins"_a =
Margins(),
1840 "Creates a layout that arranges widgets vertically, top to "
1841 "bottom, making their width equal to the layout's width. "
1842 "First argument is the spacing between widgets, the second "
1843 "is the margins. Both default to 0.");
1846 py::class_<Horiz, UnownedPointer<Horiz>,
Layout1D> hlayout(
1847 m_gui,
"Horiz",
"Horizontal layout");
1848 hlayout.def(py::init([](
int spacing,
const Margins &margins) {
1849 return new Horiz(spacing, margins);
1851 "spacing"_a = 0,
"margins"_a =
Margins(),
1852 "Creates a layout that arranges widgets vertically, left to "
1853 "right, making their height equal to the layout's height "
1854 "(which will generally be the largest height of the items). "
1855 "First argument is the spacing between widgets, the second "
1856 "is the margins. Both default to 0.")
1857 .def(py::init([](
float spacing,
const Margins &margins) {
1858 return new Horiz(
int(std::round(spacing)), margins);
1860 "spacing"_a = 0.0f,
"margins"_a =
Margins(),
1861 "Creates a layout that arranges widgets vertically, left to "
1862 "right, making their height equal to the layout's height "
1863 "(which will generally be the largest height of the items). "
1864 "First argument is the spacing between widgets, the second "
1865 "is the margins. Both default to 0.")
1868 "Sets the preferred height of the layout");
1871 py::class_<VGrid, UnownedPointer<VGrid>,
Widget> vgrid(m_gui,
"VGrid",
1873 vgrid.def(py::init([](
int n_cols,
int spacing,
const Margins &margins) {
1874 return new VGrid(n_cols, spacing, margins);
1876 "cols"_a,
"spacing"_a = 0,
"margins"_a =
Margins(),
1877 "Creates a layout that orders its children in a grid, left to "
1878 "right, top to bottom, according to the number of columns. "
1879 "The first argument is the number of columns, the second is the "
1880 "spacing between items (both vertically and horizontally), and "
1881 "third is the margins. Both spacing and margins default to zero.")
1883 [](
int n_cols,
float spacing,
const Margins &margins) {
1884 return new VGrid(n_cols,
int(std::round(spacing)),
1887 "cols"_a,
"spacing"_a = 0.0f,
"margins"_a =
Margins(),
1888 "Creates a layout that orders its children in a grid, left to "
1889 "right, top to bottom, according to the number of columns. "
1890 "The first argument is the number of columns, the second is "
1892 "spacing between items (both vertically and horizontally), "
1894 "third is the margins. Both spacing and margins default to "
1896 .def_property_readonly(
1898 "Returns the spacing between rows and columns")
1900 "Returns the margins")
1903 "Sets the preferred width of the layout");
1906 py::class_<Dialog, UnownedPointer<Dialog>,
Widget> dialog(m_gui,
"Dialog",
1908 dialog.def(py::init<const char *>(),
1909 "Creates a dialog with the given title");
1912 py::class_<FileDialog, UnownedPointer<FileDialog>,
Dialog> filedlg(
1913 m_gui,
"FileDialog",
"File picker dialog");
1915 py::native_enum<FileDialog::Mode> filedlg_mode(
1916 filedlg,
"Mode",
"enum.Enum",
"Enum class for FileDialog modes.");
1921 filedlg.def(py::init<FileDialog::Mode, const char *, const Theme &>(),
1922 "Creates either an open or save file dialog. The first "
1923 "parameter is either FileDialog.OPEN or FileDialog.SAVE. The "
1924 "second is the title of the dialog, and the third is the "
1926 "which is used internally by the dialog for layout. The theme "
1927 "should normally be retrieved from window.theme.")
1929 "Sets the initial path path of the dialog")
1931 "Adds a selectable file-type filter: "
1932 "add_filter('.stl', 'Stereolithography mesh'")
1934 "Cancel callback; required")
1936 "Done callback; required");
1940 py::module m_gui = m.def_submodule(
"gui");
std::shared_ptr< core::Tensor > image
Contains the pinhole camera intrinsic parameters.
void SetMenubar(std::shared_ptr< Menu > menubar)
std::shared_ptr< geometry::Image > RenderToImage(rendering::Renderer &renderer, rendering::View *view, rendering::Scene *scene, int width, int height)
static Application & GetInstance()
static constexpr FontId DEFAULT_FONT_ID
Identifier for font used by default for all UI elements.
void SetFont(FontId id, const FontDescription &fd)
std::shared_ptr< Menu > GetMenubar() const
const char * GetResourcePath() const
void RunInThread(std::function< void()> f)
FontId AddFont(const FontDescription &fd)
void AddWindow(std::shared_ptr< Window > window)
Must be called on the same thread that calls Run()
void Quit()
Closes all the windows, which exits as a result.
void PostToMainThread(Window *window, std::function< void()> f)
std::shared_ptr< geometry::Image > RenderToDepthImage(rendering::Renderer &renderer, rendering::View *view, rendering::Scene *scene, int width, int height, bool z_in_view_space=false)
bool RunOneTick(EnvUnlocker &unlocker, bool cleanup_if_no_windows=true)
std::shared_ptr< Checkbox > GetCheckbox()
std::shared_ptr< Label > GetLabel()
void SetChecked(bool checked)
void SetOnChecked(std::function< void(bool)> on_checked)
std::string GetText() const
void SetIsOpen(bool is_open)
void SetFontId(FontId font_id)
bool GetIsOpen()
Returns true if open and false if collapsed.
void SetText(const char *text)
void SetValue(const Color &color)
void SetOnValueChanged(std::function< void(const Color &)> on_value_changed)
const Color & GetValue() const
void SetColor(float r, float g, float b, float a=1.0)
std::shared_ptr< NumberEdit > GetNumberEdit()
std::shared_ptr< ColorEdit > GetColorEdit()
int GetNumberOfItems() const
void RemoveItem(const char *name)
Removes the first item matching the given text.
int GetSelectedIndex() const
const char * GetSelectedValue() const
Returns the text of the selected value, or "" if nothing is selected.
int AddItem(const char *name)
bool SetSelectedValue(const char *value)
void ChangeItem(int index, const char *name)
const char * GetItem(int index) const
void SetOnValueChanged(std::function< void(const char *, int)> on_value_changed)
void SetSelectedIndex(int index)
void SetPath(const char *path)
void SetOnCancel(std::function< void()> on_cancel)
The OnCancel and OnDone callbacks must be specified.
void SetOnDone(std::function< void(const char *)> on_done)
The OnCancel and OnDone callbacks must be specified.
void AddFilter(const char *filter, const char *description)
constexpr static const char * MONOSPACE
void AddTypefaceForCodePoints(const char *typeface, const std::vector< uint32_t > &code_points)
void AddTypefaceForLanguage(const char *typeface, const char *lang)
constexpr static const char * SANS_SERIF
Lays out widgets horizontally.
void SetPreferredHeight(int h)
int GetPreferredHeight() const
std::shared_ptr< Label > GetLabel()
std::shared_ptr< ColorEdit > GetColorEdit()
std::shared_ptr< Checkbox > GetCheckbox()
void SetText(const char *text)
Sets the text of the label (copies text)
void SetPosition(const Eigen::Vector3f &pos)
Color GetTextColor() const
void SetTextColor(const Color &color)
Eigen::Vector3f GetPosition() const
const char * GetText() const
const char * GetText() const
void SetText(const char *text)
Sets the text of the label (copies text)
void SetTextColor(const Color &color)
Color GetTextColor() const
void SetFontId(const FontId font_id)
void AddFixed(int size)
Adds a fixed number of pixels after the previously added widget.
void SetOnValueChanged(std::function< void(const char *, bool)> on_value_changed)
const char * GetSelectedValue() const
Returns the value of the currently selected item in the list.
int GetSelectedIndex() const
Returns the currently selected item in the list.
void SetMaxVisibleItems(int num)
void SetItems(const std::vector< std::string > &items)
void SetSelectedIndex(int index)
Selects the indicated row of the list. Does not call onValueChanged.
double GetMinimumValue() const
int GetDecimalPrecision()
void SetPreferredWidth(int width)
void SetLimits(double min_value, double max_value)
void SetDecimalPrecision(int num_digits)
void SetOnValueChanged(std::function< void(double)> on_changed)
double GetMaximumValue() const
double GetDoubleValue() const
void SetValue(double val)
void SetValue(float value)
ProgressBar values ranges from 0.0 (incomplete) to 1.0 (complete)
PyWindow(const std::string &title, int width, int height, int flags=0)
void Layout(const LayoutContext &context) override
PyWindow(const std::string &title, int flags=0)
std::function< void(const LayoutContext &)> on_layout_
PyWindow(const std::string &title, int x, int y, int width, int height, int flags=0)
void SetValue(double val)
int GetIntValue() const
Returns the value of the control as an integer.
double GetMinimumValue() const
double GetMaximumValue() const
void SetLimits(double min_value, double max_value)
double GetDoubleValue() const
Returns the value of the control as a double.
void SetOnValueChanged(std::function< void(double)> on_value_changed)
Sets a function to call when the value changes because of user action.
void AddTab(const char *name, std::shared_ptr< Widget > panel)
void SetOnSelectedTabChanged(std::function< void(int)> on_changed)
const char * GetText() const
Returns the current text value displayed.
void SetPlaceholderText(const char *text)
Sets the text to display if the text value is empty.
void SetOnValueChanged(std::function< void(const char *)> on_value_changed)
const char * GetPlaceholderText() const
Returns the text displayed if the text value is empty.
void SetText(const char *text)
void SetOnTextChanged(std::function< void(const char *)> on_text_changed)
void SetOnClicked(std::function< void(bool)> on_clicked)
std::shared_ptr< Widget > GetItem(ItemId item_id) const
Returns item, or nullptr if item_id cannot be found.
void Clear()
Clears all the items.
void SetOnSelectionChanged(std::function< void(ItemId)> on_selection_changed)
void SetSelectedItemId(ItemId item_id)
Selects the indicated item of the list. Does not call onValueChanged.
ItemId AddTextItem(ItemId parent_id, const char *text)
Adds a text item to the tree.
void SetCanSelectItemsWithChildren(bool can_select)
void RemoveItem(ItemId item_id)
Removes an item an all its children (if any) from the tree.
ItemId GetRootItem() const
bool GetCanSelectItemsWithChildren() const
ItemId GetSelectedItemId() const
Returns the currently selected item id in the tree.
ItemId AddItem(ItemId parent_id, std::shared_ptr< Widget > item)
Adds an item to the tree.
@ ASPECT
Scales to any size and aspect ratio.
@ ANY
No scaling, fixed size.
Scaling GetScaling() const
void SetScaling(Scaling scaling)
void SetPreferredWidth(int w)
const Margins & GetMargins() const
int GetPreferredWidth() const
Eigen::Vector3f GetValue() const
void SetValue(const Eigen::Vector3f &val)
Sets the value of the widget. Does not call onValueChanged.
void SetOnValueChanged(std::function< void(const Eigen::Vector3f &)> on_changed)
Lays out widgets vertically.
int GetPreferredWidth() const
void SetPreferredWidth(int w)
void SetFocusWidget(Widget *w)
Sets.
const std::vector< std::shared_ptr< Widget > > & GetChildren() const
bool IsActiveWindow() const
void SetNeedsLayout()
Instructs the window to relayout before the next draw.
const Theme & GetTheme() const
Window(const std::string &title, int flags=0)
void SetSize(const Size &size)
Sets the size of the window in pixels. Includes menubar on Linux.
const char * GetTitle() const
void AddChild(std::shared_ptr< Widget > w)
void SetOnMenuItemActivated(Menu::ItemId item_id, std::function< void()> callback)
Rect GetContentRect() const
void SetOnKeyEvent(std::function< bool(const KeyEvent &)> callback)
visualization::rendering::Renderer & GetRenderer() const
void SetTitle(const char *title)
virtual void Layout(const LayoutContext &context)
void SetOSFrame(const Rect &r)
void ShowDialog(std::shared_ptr< Dialog > dlg)
void SetOnTickEvent(std::function< bool()> callback)
void CloseDialog()
Closes the dialog.
void ShowMessageBox(const char *title, const char *message)
float GetScaling() const
Returns the scaling factor from OS pixels to device pixels.
void SetOnClose(std::function< bool()> callback)
Renderer & GetRenderer() const
static const std::string path
std::string GetFileParentDirectory(const std::string &filename)
void pybind_gui_events(py::module &m)
void install_cleanup_atexit()
std::shared_ptr< geometry::Image > RenderToImageWithoutWindow(rendering::CloudViewerScene *scene, int width, int height)
void cleanup_filament_atexit()
void pybind_gui(py::module &m)
std::shared_ptr< geometry::Image > RenderToDepthImageWithoutWindow(rendering::CloudViewerScene *scene, int width, int height, bool z_in_view_space)
void pybind_gui_classes(py::module &m_gui)
void InitializeForPython(std::string resource_path, bool headless)
std::shared_ptr< T > TakeOwnership(UnownedPointer< T > x)
Generic file read and write utility for python interface.
int GetVert() const
Convenience function that returns top + bottom.
int GetHoriz() const
Convenience function that returns left + right.
int default_layout_spacing