Disabled external gits

This commit is contained in:
2022-04-07 18:46:57 +02:00
parent 88cb3426ad
commit 15e7120d6d
5316 changed files with 4563444 additions and 6 deletions

View File

@@ -0,0 +1,54 @@
if (NOT NANOGUI_BUILD_SHARED)
# Need PIC code in libnanogui & GLFW even when compiled as a static library
set_target_properties(nanogui PROPERTIES POSITION_INDEPENDENT_CODE ON)
if (NANOGUI_BUILD_GLFW)
set_target_properties(glfw_objects PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
endif()
if (NANOGUI_BUILD_PYTHON AND (APPLE OR CMAKE_SYSTEM MATCHES "Linux"))
# Include coroutine support for running the mainloop in detached mode
add_definitions(-DCORO_SJLJ)
include_directories(../ext/coro)
set(NANOGUI_PYTHON_EXTRA ../ext/coro/coro.c)
endif()
add_definitions(-DNANOGUI_PYTHON)
pybind11_add_module(nanogui-python MODULE THIN_LTO OPT_SIZE
main.cpp
glfw.cpp
icons.cpp
color.cpp
widget.cpp
layout.cpp
basics.cpp
button.cpp
tabs.cpp
textbox.cpp
textarea.cpp
theme.cpp
formhelper.cpp
misc.cpp
canvas.cpp
nanovg.cpp
render.cpp
vector.cpp
python.h
py_doc.h
${NANOGUI_PYTHON_EXTRA})
set_target_properties(nanogui-python PROPERTIES OUTPUT_NAME nanogui)
target_link_libraries(nanogui-python PRIVATE nanogui)
if (CMAKE_COMPILER_IS_GNUCC)
# Quench warnings on GCC
target_compile_options(nanogui-python PRIVATE -Wno-unused-variable)
endif()
if (NANOGUI_INSTALL)
install(TARGETS nanogui-python
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib)
endif()

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,104 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
DECLARE_WIDGET(Label);
DECLARE_WIDGET(Popup);
DECLARE_WIDGET(MessageDialog);
DECLARE_WIDGET(VScrollPanel);
DECLARE_WIDGET(ComboBox);
DECLARE_WIDGET(ProgressBar);
DECLARE_WIDGET(Slider);
void register_basics(py::module &m) {
py::class_<Label, Widget, ref<Label>, PyLabel>(m, "Label", D(Label))
.def(py::init<Widget *, const std::string &, const std::string &, int>(),
"parent"_a, "caption"_a, "font"_a = std::string("sans"),
"font_size"_a = -1,
D(Label, Label))
.def("caption", &Label::caption, D(Label, caption))
.def("set_caption", &Label::set_caption, D(Label, set_caption))
.def("font", &Label::font, D(Label, font))
.def("set_font", &Label::set_font, D(Label, set_font))
.def("color", &Label::color, D(Label, color))
.def("set_color", &Label::set_color, D(Label, set_color));
py::class_<Popup, Window, ref<Popup>, PyPopup> popup(m, "Popup", D(Popup));
popup
.def(py::init<Widget *, Window *>(), "parent"_a, "parent_window"_a, D(Popup, Popup))
.def("anchor_pos", &Popup::anchor_pos, D(Popup, anchor_pos))
.def("set_anchor_pos", &Popup::set_anchor_pos, D(Popup, set_anchor_pos))
.def("anchor_offset", &Popup::anchor_offset, D(Popup, anchor_offset))
.def("set_anchor_offset", &Popup::set_anchor_offset, D(Popup, set_anchor_offset))
.def("anchor_size", &Popup::anchor_size, D(Popup, anchor_size))
.def("set_anchor_size", &Popup::set_anchor_size, D(Popup, set_anchor_size))
.def("parent_window", (Window*(Popup::*)(void)) &Popup::parent_window, D(Popup, parent_window))
.def("side", &Popup::side, D(Popup, side))
.def("set_side", &Popup::set_side, D(Popup, set_side));
py::enum_<Popup::Side>(popup, "Side", D(Popup, Side))
.value("Left", Popup::Side::Left)
.value("Right", Popup::Side::Right)
.export_values();
py::class_<MessageDialog, Window, ref<MessageDialog>, PyMessageDialog> mdlg(m, "MessageDialog", D(MessageDialog));
mdlg
.def(py::init<Widget *, MessageDialog::Type, const std::string&,
const std::string&, const std::string&, const std::string&, bool>(),
"parent"_a, "type"_a, "title"_a = std::string("Untitled"),
"message"_a = std::string("Message"), "button_text"_a = std::string("OK"),
"alt_button_text"_a = std::string("Cancel"), "alt_button"_a = false,
D(MessageDialog, MessageDialog))
.def("message_label", (Label * (MessageDialog::*)()) &MessageDialog::message_label, D(MessageDialog, message_label))
.def("callback", &MessageDialog::callback, D(MessageDialog, callback))
.def("set_callback", &MessageDialog::set_callback, D(MessageDialog, set_callback));
py::enum_<MessageDialog::Type>(mdlg, "Type", D(MessageDialog, Type))
.value("Information", MessageDialog::Type::Information)
.value("Question", MessageDialog::Type::Question)
.value("Warning", MessageDialog::Type::Warning);
py::class_<VScrollPanel, Widget, ref<VScrollPanel>, PyVScrollPanel>(m, "VScrollPanel", D(VScrollPanel))
.def(py::init<Widget *>(), "parent"_a, D(VScrollPanel, VScrollPanel))
.def("scroll", &VScrollPanel::scroll, D(VScrollPanel, scroll))
.def("set_scroll", &VScrollPanel::set_scroll, D(VScrollPanel, set_scroll));
py::class_<ComboBox, Widget, ref<ComboBox>, PyComboBox>(m, "ComboBox", D(ComboBox))
.def(py::init<Widget *>(), "parent"_a, D(ComboBox, ComboBox))
.def(py::init<Widget *, const std::vector<std::string> &>(),
"parent"_a, "items"_a/*, D(ComboBox, ComboBox, 2)*/)
.def(py::init<Widget *, const std::vector<std::string> &,
const std::vector<std::string> &>(),
"parent"_a, "items"_a, "items_short"_a/* ,D(ComboBox, ComboBox, 3)*/)
.def("callback", &ComboBox::callback, D(ComboBox, callback))
.def("set_callback", &ComboBox::set_callback, D(ComboBox, set_callback))
.def("selected_index", &ComboBox::selected_index, D(ComboBox, selected_index))
.def("set_selected_index", &ComboBox::set_selected_index, D(ComboBox, set_selected_index))
.def("set_items", (void(ComboBox::*)(const std::vector<std::string>&)) &ComboBox::set_items, D(ComboBox, set_items))
.def("set_items", (void(ComboBox::*)(const std::vector<std::string>&,
const std::vector<std::string>&)) &ComboBox::set_items/*, D(ComboBox, set_items, 2)*/)
.def("items", &ComboBox::items, D(ComboBox, items))
.def("items_short", &ComboBox::items_short, D(ComboBox, items_short));
py::class_<ProgressBar, Widget, ref<ProgressBar>, PyProgressBar>(m, "ProgressBar", D(ProgressBar))
.def(py::init<Widget *>(), "parent"_a, D(ProgressBar, ProgressBar))
.def("value", &ProgressBar::value, D(ProgressBar, value))
.def("set_value", &ProgressBar::set_value, D(ProgressBar, set_value));
py::class_<Slider, Widget, ref<Slider>, PySlider>(m, "Slider", D(Slider))
.def(py::init<Widget *>(), "parent"_a, D(Slider, Slider))
.def("value", &Slider::value, D(Slider, value))
.def("set_value", &Slider::set_value, D(Slider, set_value))
.def("highlight_color", &Slider::highlight_color, D(Slider, highlight_color))
.def("set_highlight_color", &Slider::set_highlight_color, D(Slider, set_highlight_color))
.def("range", &Slider::range, D(Slider, range))
.def("set_range", &Slider::set_range, D(Slider, set_range))
.def("highlighted_range", &Slider::highlighted_range, D(Slider, highlighted_range))
.def("set_highlighted_range", &Slider::set_highlighted_range, D(Slider, set_highlighted_range))
.def("set_callback", &Slider::set_callback, D(Slider, set_callback))
.def("callback", &Slider::callback, D(Slider, callback))
.def("set_final_callback", &Slider::set_final_callback, D(Slider, set_final_callback))
.def("final_callback", &Slider::final_callback, D(Slider, final_callback));
}
#endif

View File

@@ -0,0 +1,82 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
DECLARE_WIDGET(Button);
DECLARE_WIDGET(ToolButton);
DECLARE_WIDGET(PopupButton);
DECLARE_WIDGET(CheckBox);
void register_button(py::module &m) {
py::class_<Button, Widget, ref<Button>, PyButton> button(m, "Button", D(Button));
button
.def(py::init<Widget *, const std::string &, int>(),
"parent"_a, "caption"_a = std::string("Untitled"), "icon"_a = 0, D(Button, Button))
.def("caption", &Button::caption, D(Button, caption))
.def("set_caption", &Button::set_caption, D(Button, set_caption))
.def("background_color", &Button::background_color, D(Button, background_color))
.def("set_background_color", &Button::set_background_color, D(Button, set_background_color))
.def("text_color", &Button::text_color, D(Button, text_color))
.def("set_text_color", &Button::set_text_color, D(Button, set_text_color))
.def("icon", &Button::icon, D(Button, icon))
.def("set_icon", &Button::set_icon, D(Button, set_icon))
.def("flags", &Button::flags, D(Button, flags))
.def("set_flags", &Button::set_flags, D(Button, set_flags))
.def("icon_position", &Button::icon_position, D(Button, icon_position))
.def("set_icon_position", &Button::set_icon_position, D(Button, set_icon_position))
.def("pushed", &Button::pushed, D(Button, pushed))
.def("set_pushed", &Button::set_pushed, D(Button, set_pushed))
.def("callback", &Button::callback, D(Button, callback))
.def("set_callback", &Button::set_callback, D(Button, set_callback))
.def("change_callback", &Button::change_callback, D(Button, change_callback))
.def("set_change_callback", &Button::set_change_callback, D(Button, set_change_callback))
.def("button_group", &Button::button_group, D(Button, button_group))
.def("set_button_group", &Button::set_button_group, D(Button, set_button_group));
py::enum_<Button::IconPosition>(button, "IconPosition", D(Button, IconPosition))
.value("Left", Button::IconPosition::Left)
.value("LeftCentered", Button::IconPosition::LeftCentered)
.value("RightCentered", Button::IconPosition::RightCentered)
.value("Right", Button::IconPosition::Right);
py::enum_<Button::Flags>(button, "Flags", D(Button, Flags))
.value("NormalButton", Button::Flags::NormalButton)
.value("RadioButton", Button::Flags::RadioButton)
.value("ToggleButton", Button::Flags::ToggleButton)
.value("PopupButton", Button::Flags::PopupButton)
.value("MenuButton", Button::Flags::MenuButton);
py::class_<ToolButton, Button, ref<ToolButton>, PyToolButton>(m, "ToolButton", D(ToolButton))
.def(py::init<Widget *,int, const std::string &>(),
"parent"_a, "icon"_a, "caption"_a = std::string(""),
D(ToolButton, ToolButton));
py::class_<PopupButton, Button, ref<PopupButton>, PyPopupButton> popup_btn(m, "PopupButton", D(PopupButton));
popup_btn
.def(py::init<Widget *, const std::string&, int>(),
"parent"_a, "caption"_a = std::string("Untitled"),
"button_icon"_a = 0, D(PopupButton, PopupButton))
.def("popup", (Popup*(PopupButton::*)(void)) &PopupButton::popup, D(PopupButton, popup))
.def("chevron_icon", &PopupButton::chevron_icon, D(PopupButton, chevron_icon))
.def("set_chevron_icon", &PopupButton::set_chevron_icon, D(PopupButton, set_chevron_icon))
.def("side", &PopupButton::side, D(PopupButton, side))
.def("set_side", &PopupButton::set_side, D(PopupButton, set_side));
py::class_<CheckBox, Widget, ref<CheckBox>, PyCheckBox>(m, "CheckBox", D(CheckBox))
.def(py::init<Widget *, const std::string &>(), "parent"_a,
"caption"_a = std::string("Untitled"),
D(CheckBox, CheckBox))
.def(py::init<Widget *, const std::string &, const std::function<void(bool)>&>(),
"parent"_a, "caption"_a, "callback"_a,
D(CheckBox, CheckBox))
.def("caption", &CheckBox::caption, D(CheckBox, caption))
.def("set_caption", &CheckBox::set_caption, D(CheckBox, set_caption))
.def("checked", &CheckBox::checked, D(CheckBox, checked))
.def("set_checked", &CheckBox::set_checked, D(CheckBox, set_checked))
.def("pushed", &CheckBox::pushed, D(CheckBox, pushed))
.def("set_pushed", &CheckBox::set_pushed, D(CheckBox, set_pushed))
.def("callback", &CheckBox::callback, D(CheckBox, callback))
.def("set_callback", &CheckBox::set_callback, D(CheckBox, set_callback));
}
#endif

View File

@@ -0,0 +1,64 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
class PyCanvas : public Canvas {
public:
using Canvas::Canvas;
NANOGUI_WIDGET_OVERLOADS(Canvas);
void draw_contents() override {
PYBIND11_OVERLOAD(void, Canvas, draw_contents);
}
};
class PyImageView : public ImageView {
public:
using ImageView::ImageView;
NANOGUI_WIDGET_OVERLOADS(ImageView);
void draw_contents() override {
PYBIND11_OVERLOAD(void, ImageView, draw_contents);
}
};
void register_canvas(py::module &m) {
py::class_<Canvas, Widget, ref<Canvas>, PyCanvas>(m, "Canvas", D(Canvas))
.def(py::init<Widget *, uint8_t, bool, bool, bool>(),
"parent"_a, "samples"_a = 4, "has_depth_buffer"_a = true,
"has_stencil_buffer"_a = false,
"clear"_a = true, D(Canvas, Canvas))
.def("render_pass", &Canvas::render_pass, D(Canvas, render_pass))
.def("draw_border", &Canvas::draw_border, D(Canvas, draw_border))
.def("set_draw_border", &Canvas::set_draw_border, D(Canvas, set_draw_border))
.def("border_color", &Canvas::border_color, D(Canvas, border_color))
.def("set_border_color", &Canvas::set_border_color, D(Canvas, set_border_color))
.def("background_color", &Canvas::background_color, D(Canvas, background_color))
.def("set_background_color", &Canvas::set_background_color, D(Canvas, set_background_color))
.def("draw_contents", &Canvas::draw_contents, D(Canvas, draw_contents));
py::class_<ImageView, Canvas, ref<ImageView>, PyImageView>(m, "ImageView", D(ImageView))
.def(py::init<Widget *>(), D(ImageView, ImageView))
.def("image", py::overload_cast<>(&ImageView::image, py::const_), D(ImageView, image))
.def("set_image", &ImageView::set_image, D(ImageView, set_image))
.def("reset", &ImageView::reset, D(ImageView, reset))
.def("center", &ImageView::center, D(ImageView, center))
.def("offset", &ImageView::offset, D(ImageView, offset))
.def("set_offset", &ImageView::set_offset, D(ImageView, set_offset))
.def("scale", &ImageView::scale, D(ImageView, scale))
.def("set_scale", &ImageView::set_scale, D(ImageView, set_scale))
.def("pos_to_pixel", &ImageView::pos_to_pixel, D(ImageView, pos_to_pixel))
.def("pixel_to_pos", &ImageView::pixel_to_pos, D(ImageView, pixel_to_pos))
.def("set_pixel_callback",
[](ImageView &img,
const std::function<std::array<std::string, 4>(const Vector2i &)> &func) {
img.set_pixel_callback([func](const Vector2i &p, char **out, size_t size) {
auto str = func(p);
for (int i = 0; i < 4; ++i)
strncpy(out[i], str[i].c_str(), size);
});
},
D(ImageView, set_pixel_callback));
}
#endif

View File

@@ -0,0 +1,27 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
void register_eigen(py::module &m) {
py::class_<Color>(m, "Color", D(Color))
.def(py::init<int, int, int, int>(), D(Color, Color, 7))
.def(py::init<int, int>(), D(Color, Color, 5))
.def(py::init<float, float, float, float>(), D(Color, Color, 7))
.def(py::init<float, float>(), D(Color, Color, 5))
.def("contrasting_color", &Color::contrasting_color,
D(Color, contrasting_color))
.def_property("r", [](const Color &c) { return c.r(); },
[](Color &c, float v) { c.r() = v; }, D(Color, r))
.def_property("g", [](const Color &c) { return c.g(); },
[](Color &c, float v) { c.g() = v; }, D(Color, g))
.def_property("b", [](const Color &c) { return c.b(); },
[](Color &c, float v) { c.b() = v; }, D(Color, b))
.def_property("w", [](const Color &c) { return c.w(); },
[](Color &c, float v) { c.w() = v; }, "Return a reference to the alpha channel.")
.def("__repr__", [](const Color &c) {
std::ostringstream oss;
oss << c;
return oss.str();
});
}
#endif

View File

@@ -0,0 +1,490 @@
# python/example1.py -- Python version of an example application that shows
# how to use the various widget classes. For a C++ implementation, see
# '../src/example1.cpp'.
#
# NanoGUI was developed by Wenzel Jakob <wenzel@inf.ethz.ch>.
# The widget drawing code is based on the NanoVG demo application
# by Mikko Mononen.
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.txt file.
import nanogui
import math
import time
import gc
import numpy as np
from nanogui import Color, ColorPicker, Screen, Window, GroupLayout, \
BoxLayout, ToolButton, Label, Button, Widget, \
Popup, PopupButton, CheckBox, MessageDialog, \
VScrollPanel, ImagePanel, ImageView, ComboBox, \
ProgressBar, Slider, TextBox, ColorWheel, Graph, \
GridLayout, Alignment, Orientation, TabWidget, \
IntBox, RenderPass, Shader, Texture, Matrix4f
from nanogui import glfw, icons
# A simple counter, used for dynamic tab creation with TabWidget callback
counter = 1
class TestApp(Screen):
def __init__(self):
super(TestApp, self).__init__((1024, 768), "NanoGUI Test")
self.shader = None
window = Window(self, "Button demo")
window.set_position((15, 15))
window.set_layout(GroupLayout())
Label(window, "Push buttons", "sans-bold")
b = Button(window, "Plain button")
def cb():
print("pushed!")
b.set_callback(cb)
b = Button(window, "Styled", icons.FA_ROCKET)
b.set_background_color(Color(0, 0, 1.0, 0.1))
b.set_callback(cb)
Label(window, "Toggle buttons", "sans-bold")
b = Button(window, "Toggle me")
b.set_flags(Button.Flags.ToggleButton)
def change_cb(state):
print("Toggle button state: %s" % str(state))
b.set_change_callback(change_cb)
Label(window, "Radio buttons", "sans-bold")
b = Button(window, "Radio button 1")
b.set_flags(Button.Flags.RadioButton)
b = Button(window, "Radio button 2")
b.set_flags(Button.Flags.RadioButton)
Label(window, "A tool palette", "sans-bold")
tools = Widget(window)
tools.set_layout(BoxLayout(Orientation.Horizontal,
Alignment.Middle, 0, 6))
ToolButton(tools, icons.FA_CLOUD)
ToolButton(tools, icons.FA_FAST_FORWARD)
ToolButton(tools, icons.FA_COMPASS)
ToolButton(tools, icons.FA_UTENSILS)
Label(window, "Popup buttons", "sans-bold")
popup_btn = PopupButton(window, "Popup", icons.FA_FLASK)
popup = popup_btn.popup()
popup.set_layout(GroupLayout())
Label(popup, "Arbitrary widgets can be placed here")
CheckBox(popup, "A check box")
# popup right
popup_btn = PopupButton(popup, "Recursive popup", icons.FA_CHART_PIE)
popup_right = popup_btn.popup()
popup_right.set_layout(GroupLayout())
CheckBox(popup_right, "Another check box")
# popup left
popup_btn = PopupButton(popup, "Recursive popup", icons.FA_DNA)
popup_btn.set_side(Popup.Side.Left)
popup_left = popup_btn.popup()
popup_left.set_layout(GroupLayout())
CheckBox(popup_left, "Another check box")
window = Window(self, "Basic widgets")
window.set_position((200, 15))
window.set_layout(GroupLayout())
Label(window, "Message dialog", "sans-bold")
tools = Widget(window)
tools.set_layout(BoxLayout(Orientation.Horizontal,
Alignment.Middle, 0, 6))
def cb2(result):
print("Dialog result: %i" % result)
b = Button(tools, "Info")
def cb():
dlg = MessageDialog(self, MessageDialog.Type.Information, "Title",
"This is an information message")
dlg.set_callback(cb2)
b.set_callback(cb)
b = Button(tools, "Warn")
def cb():
dlg = MessageDialog(self, MessageDialog.Type.Warning, "Title",
"This is a warning message")
dlg.set_callback(cb2)
b.set_callback(cb)
b = Button(tools, "Ask")
def cb():
dlg = MessageDialog(self, MessageDialog.Type.Warning, "Title",
"This is a question message", "Yes", "No",
True)
dlg.set_callback(cb2)
b.set_callback(cb)
import os
import sys
os.chdir(sys.path[0])
try:
icons_data = nanogui.load_image_directory(self.nvg_context(), "icons")
except:
try:
icons_data = nanogui.load_image_directory(self.nvg_context(), "../icons")
except:
icons_data = nanogui.load_image_directory(self.nvg_context(), "../resources/icons")
Label(window, "Image panel & scroll panel", "sans-bold")
image_panel_btn = PopupButton(window, "Image Panel")
image_panel_btn.set_icon(icons.FA_IMAGES)
popup = image_panel_btn.popup()
vscroll = VScrollPanel(popup)
img_panel = ImagePanel(vscroll)
img_panel.set_images(icons_data)
popup.set_fixed_size((245, 150))
img_window = Window(self, "Selected image")
img_window.set_position((710, 15))
img_window.set_layout(GroupLayout())
img_view = ImageView(img_window)
img_view.set_image(Texture(icons_data[0][1] + ".png",
Texture.InterpolationMode.Trilinear,
Texture.InterpolationMode.Nearest))
img_view.center()
def cb(i):
print("Selected item %i" % i)
img_view.set_image(Texture(icons_data[i][1] + ".png",
Texture.InterpolationMode.Trilinear,
Texture.InterpolationMode.Nearest))
img_panel.set_callback(cb)
Label(window, "File dialog", "sans-bold")
tools = Widget(window)
tools.set_layout(BoxLayout(Orientation.Horizontal,
Alignment.Middle, 0, 6))
b = Button(tools, "Open")
valid = [("png", "Portable Network Graphics"), ("txt", "Text file")]
def cb():
result = nanogui.file_dialog(valid, False)
print("File dialog result = %s" % result)
b.set_callback(cb)
b = Button(tools, "Save")
def cb():
result = nanogui.file_dialog(valid, True)
print("File dialog result = %s" % result)
b.set_callback(cb)
Label(window, "Combo box", "sans-bold")
ComboBox(window, ["Combo box item 1", "Combo box item 2",
"Combo box item 3"])
Label(window, "Check box", "sans-bold")
def cb(state):
print("Check box 1 state: %s" % state)
chb = CheckBox(window, "Flag 1", cb)
chb.set_checked(True)
def cb(state):
print("Check box 2 state: %s" % state)
CheckBox(window, "Flag 2", cb)
Label(window, "Progress bar", "sans-bold")
self.progress = ProgressBar(window)
Label(window, "Slider and text box", "sans-bold")
panel = Widget(window)
panel.set_layout(BoxLayout(Orientation.Horizontal,
Alignment.Middle, 0, 20))
slider = Slider(panel)
slider.set_value(0.5)
slider.set_fixed_width(80)
text_box = TextBox(panel)
text_box.set_fixed_size((60, 25))
text_box.set_value("50")
text_box.set_units("%")
text_box.set_font_size(20)
text_box.set_alignment(TextBox.Alignment.Right)
def cb(value):
text_box.set_value("%i" % int(value * 100))
slider.set_callback(cb)
def cb(value):
print("Final slider value: %i" % int(value * 100))
slider.set_final_callback(cb)
window = Window(self, "Misc. widgets")
window.set_position((425, 15))
window.set_layout(GroupLayout())
tab_widget = TabWidget(window)
layer = Widget(tab_widget)
layer.set_layout(GroupLayout())
tab_widget.append_tab("Color Wheel", layer)
Label(layer, "Color wheel widget", "sans-bold")
ColorWheel(layer)
layer = Widget(tab_widget)
layer.set_layout(GroupLayout())
tab_widget.append_tab("Function Graph", layer)
Label(layer, "Function graph widget", "sans-bold")
graph = Graph(layer, "Some function")
graph.set_header("E = 2.35e-3")
graph.set_footer("Iteration 89")
values = [0.5 * (0.5 * math.sin(i / 10.0) +
0.5 * math.cos(i / 23.0) + 1)
for i in range(100)]
graph.set_values(values)
# Dummy tab used to represent the last tab button.
plus_id = tab_widget.append_tab("+", Widget(tab_widget))
def tab_cb(index):
if index == plus_id:
global counter
# When the "+" tab has been clicked, simply add a new tab.
tab_name = "Dynamic {0}".format(counter)
layer_dyn = Widget(tab_widget)
layer_dyn.set_layout(GroupLayout())
new_id = tab_widget.insert_tab(tab_widget.tab_count() - 1,
tab_name, layer_dyn)
Label(layer_dyn, "Function graph widget", "sans-bold")
graph_dyn = Graph(layer_dyn, "Dynamic function")
graph_dyn.set_header("E = 2.35e-3")
graph_dyn.set_footer("Iteration {0}".format(index*counter))
values_dyn = [0.5 * abs((0.5 * math.sin(i / 10.0 + counter)) +
(0.5 * math.cos(i / 23.0 + 1 + counter)))
for i in range(100)]
graph_dyn.set_values(values_dyn)
counter += 1
# We must invoke the layout manager after adding tabs dynamically
self.perform_layout()
tab_widget.set_selected_id(new_id)
tab_widget.set_callback(tab_cb)
window = Window(self, "Grid of small widgets")
window.set_position((425, 300))
layout = GridLayout(Orientation.Horizontal, 2,
Alignment.Middle, 15, 5)
layout.set_col_alignment(
[Alignment.Maximum, Alignment.Fill])
layout.set_spacing(0, 10)
window.set_layout(layout)
Label(window, "Floating point :", "sans-bold")
float_box = TextBox(window)
float_box.set_editable(True)
float_box.set_fixed_size((100, 20))
float_box.set_value("50")
float_box.set_units("GiB")
float_box.set_default_value("0.0")
float_box.set_font_size(16)
float_box.set_format("[-]?[0-9]*\\.?[0-9]+")
Label(window, "Positive integer :", "sans-bold")
int_box = IntBox(window)
int_box.set_editable(True)
int_box.set_fixed_size((100, 20))
int_box.set_value(50)
int_box.set_units("Mhz")
int_box.set_default_value("0")
int_box.set_font_size(16)
int_box.set_format("[1-9][0-9]*")
int_box.set_spinnable(True)
int_box.set_min_value(1)
int_box.set_value_increment(2)
Label(window, "Checkbox :", "sans-bold")
cb = CheckBox(window, "Check me")
cb.set_font_size(16)
cb.set_checked(True)
Label(window, "Combo box :", "sans-bold")
cobo = ComboBox(window, ["Item 1", "Item 2", "Item 3"])
cobo.set_font_size(16)
cobo.set_fixed_size((100, 20))
Label(window, "Color picker :", "sans-bold")
cp = ColorPicker(window, Color(255, 120, 0, 255))
cp.set_fixed_size((100, 20))
def cp_final_cb(color):
print(
"ColorPicker Final Callback: [{0}, {1}, {2}, {3}]".format(color.r,
color.g,
color.b,
color.w)
)
cp.set_final_callback(cp_final_cb)
# setup a fast callback for the color picker widget on a new window
# for demonstrative purposes
window = Window(self, "Color Picker Fast Callback")
window.set_position((425, 300))
layout = GridLayout(Orientation.Horizontal, 2,
Alignment.Middle, 15, 5)
layout.set_col_alignment(
[Alignment.Maximum, Alignment.Fill])
layout.set_spacing(0, 10)
window.set_layout(layout)
window.set_position((425, 500))
Label(window, "Combined: ")
b = Button(window, "ColorWheel", icons.FA_INFINITY)
Label(window, "Red: ")
red_int_box = IntBox(window)
red_int_box.set_editable(False)
Label(window, "Green: ")
green_int_box = IntBox(window)
green_int_box.set_editable(False)
Label(window, "Blue: ")
blue_int_box = IntBox(window)
blue_int_box.set_editable(False)
Label(window, "Alpha: ")
alpha_int_box = IntBox(window)
def cp_fast_cb(color):
b.set_background_color(color)
b.set_text_color(color.contrasting_color())
red = int(color.r * 255.0)
red_int_box.set_value(red)
green = int(color.g * 255.0)
green_int_box.set_value(green)
blue = int(color.b * 255.0)
blue_int_box.set_value(blue)
alpha = int(color.w * 255.0)
alpha_int_box.set_value(alpha)
cp.set_callback(cp_fast_cb)
self.perform_layout()
self.render_pass = RenderPass([self])
self.render_pass.set_clear_color(0, Color(0.3, 0.3, 0.32, 1.0))
if nanogui.api == 'opengl':
vertex_shader = """
#version 330
uniform mat4 mvp;
in vec3 position;
void main() {
gl_Position = mvp * vec4(position, 1.0);
}"""
fragment_shader = """
#version 330
out vec4 color;
uniform float intensity;
void main() {
color = vec4(vec3(intensity), 1.0);
}"""
elif nanogui.api == 'gles2' or nanogui.api == 'gles3':
vertex_shader = """
precision highp float;
uniform mat4 mvp;
attribute vec3 position;
void main() {
gl_Position = mvp * vec4(position, 1.0);
}"""
fragment_shader = """
precision highp float;
uniform float intensity;
void main() {
gl_FragColor = vec4(vec3(intensity), 1.0);
}"""
elif nanogui.api == 'metal':
vertex_shader = """
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
vertex VertexOut vertex_main(const device packed_float3 *position,
constant float4x4 &mvp,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = mvp * float4(position[id], 1.f);
return vert;
}"""
fragment_shader = """
using namespace metal;
fragment float4 fragment_main(const constant float &intensity) {
return float4(intensity);
}"""
self.shader = Shader(
self.render_pass,
# An identifying name
"A simple shader",
vertex_shader,
fragment_shader
)
self.shader.set_buffer("indices", np.array([0, 1, 2, 2, 3, 0], dtype=np.uint32))
self.shader.set_buffer("position", np.array(
[[-1, -1, 0],
[1, -1, 0],
[1, 1, 0],
[-1, 1, 0]],
dtype=np.float32
))
self.shader.set_buffer("intensity", np.array(0.5, dtype=np.float32))
def draw(self, ctx):
self.progress.set_value(math.fmod(time.time() / 10, 1))
super(TestApp, self).draw(ctx)
def draw_contents(self):
if self.shader is None:
return
self.render_pass.resize(self.framebuffer_size())
s = self.size()
with self.render_pass:
mvp = Matrix4f.scale([s[1] / float(s[0]) * 0.25, 0.25, 0.25]) @ \
Matrix4f.rotate([0, 0, 1], glfw.getTime())
self.shader.set_buffer("mvp", np.float32(mvp).T)
with self.shader:
self.shader.draw_array(Shader.PrimitiveType.Triangle, 0, 6, True)
def keyboard_event(self, key, scancode, action, modifiers):
if super(TestApp, self).keyboard_event(key, scancode,
action, modifiers):
return True
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
self.set_visible(False)
return True
return False
if __name__ == "__main__":
nanogui.init()
test = TestApp()
test.draw_all()
test.set_visible(True)
nanogui.mainloop(refresh=1 / 60.0 * 1000)
del test
gc.collect()
nanogui.shutdown()

View File

@@ -0,0 +1,76 @@
# python/example2.py -- Python version of an example application that shows
# how to use the form helper class. For a C++ implementation, see
# '../src/example2.cpp'.
#
# NanoGUI was developed by Wenzel Jakob <wenzel@inf.ethz.ch>.
# The widget drawing code is based on the NanoVG demo application
# by Mikko Mononen.
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.txt file.
import nanogui
import math
import gc
from nanogui import Screen, FormHelper
bvar = True
ivar = 12345678
dvar = math.pi
strvar = 'A string'
strvar2 = ''
enumvar = 1
colvar = nanogui.Color(.5, .5, .7, 1)
def make_accessors(name):
def setter(value):
globals()[name] = value
def getter():
return globals()[name]
return setter, getter
nanogui.init()
use_gl_4_1 = False # Set to True to create an OpenGL 4.1 context.
if use_gl_4_1:
# NanoGUI presents many options for you to utilize at your discretion.
# See include/nanogui/screen.h for what all of the options are.
screen = Screen((500, 700), 'NanoGUI test [GL 4.1]', gl_major=4, gl_minor=1)
else:
screen = Screen((500, 700), 'NanoGUI test')
gui = FormHelper(screen)
window = gui.add_window((10, 10), 'Form helper example')
gui.add_group('Basic types')
gui.add_bool_variable('bool', *make_accessors('bvar'))
gui.add_string_variable('string', *make_accessors('strvar'))
gui.add_string_variable('placeholder', *make_accessors('strvar2')).set_placeholder('placeholder')
gui.add_group('Validating fields')
gui.add_int_variable('int', *make_accessors('ivar'))
gui.add_double_variable('double', *make_accessors('dvar'))
gui.add_group('Complex types')
gui.add_enum_variable('Enumeration', *make_accessors('enumvar')) \
.set_items(['Item 1', 'Item 2', 'Item 3'])
gui.add_color_variable('Color', *make_accessors('colvar'))
gui.add_group('Other widgets')
def cb():
print('Button pressed.')
gui.add_button('A button', cb)
screen.set_visible(True)
screen.perform_layout()
window.center()
nanogui.mainloop(refresh=0)
screen = gui = window = None
gc.collect()
nanogui.shutdown()

View File

@@ -0,0 +1,57 @@
# python/example3.py -- running NanoGUI in detached mode
# (contributed by Dmitriy Morozov)
#
# NanoGUI was developed by Wenzel Jakob <wenzel@inf.ethz.ch>.
# The widget drawing code is based on the NanoVG demo application
# by Mikko Mononen.
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.txt file.
import nanogui
from nanogui import *
import time
class TestApp(Screen):
def __init__(self):
super(TestApp, self).__init__((190, 170), "NanoGUI Test")
window = Window(self, "Detached mode")
window.set_position((15, 15))
window.set_layout(GroupLayout())
Label(window, "Push buttons", "sans-bold")
b = Button(window, "Plain button")
def cb():
print("pushed!")
b.set_callback(cb)
b = Button(window, "Quit")
def cb2():
self.set_visible(False)
b.set_callback(cb2)
self.perform_layout()
if __name__ == "__main__":
nanogui.init()
test = TestApp()
test.draw_all()
test.set_visible(True)
print("Launching detached mainloop")
h = nanogui.mainloop(detach=test, refresh=0)
print("Back in Python context")
for i in range(10):
print(i)
time.sleep(1)
if not nanogui.active():
break
h.join()
nanogui.shutdown()

View File

@@ -0,0 +1,227 @@
# python/example4.py -- Python version of an example application that
# shows how to use the Canvas widget. For a C++ implementation, see
# '../src/example4.cpp'.
#
# NanoGUI was developed by Wenzel Jakob <wenzel@inf.ethz.ch>.
# The widget drawing code is based on the NanoVG demo application
# by Mikko Mononen.
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.txt file.
import nanogui
import random
import math
import gc
from nanogui import Canvas, Shader, RenderPass, Screen, Window, \
GroupLayout, Color, Widget, BoxLayout, Orientation, Alignment, \
Button, Matrix4f
from nanogui import glfw
class MyCanvas(Canvas):
def __init__(self, parent):
super(MyCanvas, self).__init__(parent, 1)
try:
import numpy as np
if nanogui.api == 'opengl':
vertex_shader = """
#version 330
uniform mat4 mvp;
in vec3 position;
in vec3 color;
out vec4 frag_color;
void main() {
frag_color = vec4(color, 1.0);
gl_Position = mvp * vec4(position, 1.0);
}
"""
fragment_shader = """
#version 330
out vec4 color;
in vec4 frag_color;
void main() {
color = frag_color;
}
"""
elif nanogui.api == 'gles2' or nanogui.api == 'gles3':
vertex_shader = """
precision highp float;
uniform mat4 mvp;
attribute vec3 position;
attribute vec3 color;
varying vec4 frag_color;
void main() {
frag_color = vec4(color, 1.0);
gl_Position = mvp * vec4(position, 1.0);
}
"""
fragment_shader = """
precision highp float;
varying vec4 frag_color;
void main() {
gl_FragColor = frag_color;
}
"""
elif nanogui.api == 'metal':
vertex_shader = """
using namespace metal;
struct VertexOut {
float4 position [[position]];
float4 color;
};
vertex VertexOut vertex_main(const device packed_float3 *position,
const device packed_float3 *color,
constant float4x4 &mvp,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = mvp * float4(position[id], 1.f);
vert.color = float4(color[id], 1.f);
return vert;
}
"""
fragment_shader = """
using namespace metal;
struct VertexOut {
float4 position [[position]];
float4 color;
};
fragment float4 fragment_main(VertexOut vert [[stage_in]]) {
return vert.color;
}
"""
else:
raise Exception("Unknown graphics API!")
self.shader = Shader(
self.render_pass(),
# An identifying name
"a_simple_shader",
vertex_shader,
fragment_shader
)
# Draw a cube
indices = np.array(
[3, 2, 6, 6, 7, 3,
4, 5, 1, 1, 0, 4,
4, 0, 3, 3, 7, 4,
1, 5, 6, 6, 2, 1,
0, 1, 2, 2, 3, 0,
7, 6, 5, 5, 4, 7],
dtype=np.uint32)
positions = np.array(
[[-1, 1, 1], [-1, -1, 1],
[1, -1, 1], [1, 1, 1],
[-1, 1, -1], [-1, -1, -1],
[1, -1, -1], [1, 1, -1]],
dtype=np.float32)
colors = np.array(
[[0, 1, 1], [0, 0, 1],
[1, 0, 1], [1, 1, 1],
[0, 1, 0], [0, 0, 0],
[1, 0, 0], [1, 1, 0]],
dtype=np.float32)
self.shader.set_buffer("indices", indices)
self.shader.set_buffer("position", positions)
self.shader.set_buffer("color", colors)
self.rotation = 0
except ImportError:
self.shader = None
pass
def draw_contents(self):
if self.shader is None:
return
import numpy as np
view = Matrix4f.look_at(
origin=[0, -2, -10],
target=[0, 0, 0],
up=[0, 1, 0]
)
model = Matrix4f.rotate(
[0, 1, 0],
glfw.getTime()
)
model2 = Matrix4f.rotate(
[1, 0, 0],
self.rotation
)
size = self.size()
proj = Matrix4f.perspective(
fov=25 * np.pi / 180,
near=0.1,
far=20,
aspect=size[0] / float(size[1])
)
mvp = proj @ view @ model @ model2
self.shader.set_buffer("mvp", np.float32(mvp).T)
with self.shader:
self.shader.draw_array(Shader.PrimitiveType.Triangle,
0, 36, indexed=True)
class TestApp(Screen):
def __init__(self):
super(TestApp, self).__init__((800, 600), "NanoGUI Test", False)
window = Window(self, "Canvas widget demo")
window.set_position((15, 15))
window.set_layout(GroupLayout())
self.canvas = MyCanvas(window)
self.canvas.set_background_color(Color(0.5, 0.5, 0.5, 1.0))
self.canvas.set_size((400, 400))
tools = Widget(window)
tools.set_layout(BoxLayout(Orientation.Horizontal,
Alignment.Middle, 0, 5))
b0 = Button(tools, "Random Background")
def cb0():
self.canvas.set_background_color(Color(random.random(), random.random(), random.random(), 1.0))
b0.set_callback(cb0)
b1 = Button(tools, "Random Rotation")
def cb1():
self.canvas.rotation = random.random() * math.pi
b1.set_callback(cb1)
self.perform_layout()
def keyboard_event(self, key, scancode, action, modifiers):
if super(TestApp, self).keyboard_event(key, scancode,
action, modifiers):
return True
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
self.set_visible(False)
return True
return False
if __name__ == "__main__":
nanogui.init()
test = TestApp()
test.draw_all()
test.set_visible(True)
nanogui.mainloop(refresh=1 / 60.0 * 1000)
del test
gc.collect()
nanogui.shutdown()

View File

@@ -0,0 +1,62 @@
# python/example_icons.py -- Python version of an example application that shows
# all available Entypo icons as they would appear in NanoGUI itself. For a C++
# implementation, see '../src/example_icons.cpp'.
#
# NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>.
# The widget drawing code is based on the NanoVG demo application
# by Mikko Mononen.
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.txt file.
# Developer note: need to make a change to this file?
# Please raise an Issue on GitHub describing what needs to change. This file
# was generated, so the scripts that generated it needs to update as well.
import gc
import nanogui
from nanogui import Screen, Window, Widget, GridLayout, VScrollPanel, Button
from nanogui import entypo
if __name__ == "__main__":
nanogui.init()
width = 1000
half_width = width // 2
height = 800
# create a fixed size screen with one window
screen = Screen((width, height), "NanoGUI Icons", False)
window = Window(screen, "All Icons")
window.set_position((0, 0))
window.set_fixed_size((width, height))
# attach a vertical scroll panel
vscroll = VScrollPanel(window)
vscroll.set_fixed_size((width, height))
# vscroll should only have *ONE* child. this is what `wrapper` is for
wrapper = Widget(vscroll)
wrapper.set_fixed_size((width, height))
wrapper.set_layout(GridLayout()) # defaults: 2 columns
# NOTE: don't __dict__ crawl in real code!
# this is just because it's more convenient to do this for enumerating all
# of the icons -- see cpp example for alternative...
for key in entypo.__dict__.keys():
if key.startswith("ICON_"):
b = Button(wrapper, "entypo.{0}".format(key), entypo.__dict__[key])
b.set_icon_position(Button.IconPosition.Left)
b.set_fixed_width(half_width)
screen.perform_layout()
screen.draw_all()
screen.set_visible(True)
nanogui.mainloop()
del screen
gc.collect()
nanogui.shutdown()

View File

@@ -0,0 +1,86 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
typedef IntBox<int64_t> Int64Box;
void register_formhelper(py::module &m) {
enum DummyEnum { };
py::class_<FormHelper>(m, "FormHelper", D(FormHelper))
.def(py::init<Screen *>(), D(FormHelper, FormHelper))
.def("add_window", &FormHelper::add_window, "pos"_a,
"title"_a = std::string("Untitled"),
D(FormHelper, add_window))
.def("add_group", &FormHelper::add_group, D(FormHelper, add_group))
.def("add_button", &FormHelper::add_button, "label"_a,
"cb"_a, D(FormHelper, add_group))
.def("add_bool_variable",
[](FormHelper &h, const std::string &label,
const std::function<void(const bool &) > &setter,
const std::function<bool(void) > &getter, bool editable) -> CheckBox* {
return h.add_variable(label, setter, getter, editable);
},
"label"_a, "setter"_a, "getter"_a,
"editable"_a = true)
.def("add_int_variable",
[](FormHelper &h, const std::string &label,
const std::function<void(const int64_t &) > &setter,
const std::function<int64_t(void) > &getter, bool editable) -> Int64Box* {
return h.add_variable(label, setter, getter, editable);
},
"label"_a, "setter"_a, "getter"_a,
"editable"_a = true)
.def("add_double_variable",
[](FormHelper &h, const std::string &label,
const std::function<void(const double &) > &setter,
const std::function<double(void) > &getter, bool editable) -> FloatBox<double>* {
return h.add_variable(label, setter, getter, editable);
},
"label"_a, "setter"_a, "getter"_a,
"editable"_a = true)
.def("add_string_variable",
[](FormHelper &h, const std::string &label,
const std::function<void(const std::string &) > &setter,
const std::function<std::string(void) > &getter, bool editable) -> TextBox* {
return h.add_variable(label, setter, getter, editable);
},
"label"_a, "setter"_a, "getter"_a,
"editable"_a = true)
.def("add_color_variable",
[](FormHelper &h, const std::string &label,
const std::function<void(const Color &) > &setter,
const std::function<Color(void) > &getter, bool editable) -> ColorPicker* {
return h.add_variable(label, setter, getter, editable);
},
"label"_a, "setter"_a, "getter"_a,
"editable"_a = true)
.def("add_enum_variable",
[](FormHelper &h, const std::string &label,
const std::function<void(const int &) > &setter,
const std::function<int(void) > &getter, bool editable) -> ComboBox* {
return h.add_variable(label,
reinterpret_cast<const std::function<void(const DummyEnum &)>&>(setter),
reinterpret_cast<const std::function<DummyEnum(void)>&>(getter),
editable);
},
"label"_a, "setter"_a, "getter"_a,
"editable"_a = true)
.def("add_widget", &FormHelper::add_widget, D(FormHelper, add_widget))
.def("refresh", &FormHelper::refresh, D(FormHelper, refresh))
.def("window", &FormHelper::window, D(FormHelper, window))
.def("set_window", &FormHelper::set_window, D(FormHelper, set_window))
.def("fixed_size", &FormHelper::fixed_size, D(FormHelper, fixed_size))
.def("set_fixed_size", &FormHelper::set_fixed_size, D(FormHelper, set_fixed_size))
.def("group_font_name", &FormHelper::group_font_name, D(FormHelper, group_font_name))
.def("set_group_font_name", &FormHelper::set_group_font_name, D(FormHelper, set_group_font_name))
.def("label_font_name", &FormHelper::label_font_name, D(FormHelper, label_font_name))
.def("set_label_font_name", &FormHelper::set_label_font_name, D(FormHelper, set_label_font_name))
.def("group_font_size", &FormHelper::group_font_size, D(FormHelper, group_font_size))
.def("set_group_font_size", &FormHelper::set_group_font_size, D(FormHelper, set_group_font_size))
.def("label_font_size", &FormHelper::label_font_size, D(FormHelper, label_font_size))
.def("set_label_font_size", &FormHelper::set_label_font_size, D(FormHelper, set_label_font_size))
.def("widget_font_size", &FormHelper::widget_font_size, D(FormHelper, widget_font_size))
.def("set_widget_font_size", &FormHelper::set_widget_font_size, D(FormHelper, set_widget_font_size));
}
#endif

View File

@@ -0,0 +1,47 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
void register_glfw(py::module &m) {
/* GLFW constants + functions */
{
#define C(name) g.attr(#name) = py::int_(GLFW_##name);
py::module g = m.def_submodule("glfw");
C(KEY_UNKNOWN); C(KEY_SPACE); C(KEY_APOSTROPHE); C(KEY_COMMA);
C(KEY_MINUS); C(KEY_PERIOD); C(KEY_SLASH); C(KEY_0); C(KEY_1);
C(KEY_2); C(KEY_3); C(KEY_4); C(KEY_5); C(KEY_6); C(KEY_7); C(KEY_8);
C(KEY_9); C(KEY_SEMICOLON); C(KEY_EQUAL); C(KEY_A); C(KEY_B); C(KEY_C);
C(KEY_D); C(KEY_E); C(KEY_F); C(KEY_G); C(KEY_H); C(KEY_I); C(KEY_J);
C(KEY_K); C(KEY_L); C(KEY_M); C(KEY_N); C(KEY_O); C(KEY_P); C(KEY_Q);
C(KEY_R); C(KEY_S); C(KEY_T); C(KEY_U); C(KEY_V); C(KEY_W); C(KEY_X);
C(KEY_Y); C(KEY_Z); C(KEY_LEFT_BRACKET); C(KEY_BACKSLASH);
C(KEY_RIGHT_BRACKET); C(KEY_GRAVE_ACCENT); C(KEY_WORLD_1);
C(KEY_WORLD_2); C(KEY_ESCAPE); C(KEY_ENTER); C(KEY_TAB);
C(KEY_BACKSPACE); C(KEY_INSERT); C(KEY_DELETE); C(KEY_RIGHT);
C(KEY_LEFT); C(KEY_DOWN); C(KEY_UP); C(KEY_PAGE_UP); C(KEY_PAGE_DOWN);
C(KEY_HOME); C(KEY_END); C(KEY_CAPS_LOCK); C(KEY_SCROLL_LOCK);
C(KEY_NUM_LOCK); C(KEY_PRINT_SCREEN); C(KEY_PAUSE); C(KEY_F1);
C(KEY_F2); C(KEY_F3); C(KEY_F4); C(KEY_F5); C(KEY_F6); C(KEY_F7);
C(KEY_F8); C(KEY_F9); C(KEY_F10); C(KEY_F11); C(KEY_F12); C(KEY_F13);
C(KEY_F14); C(KEY_F15); C(KEY_F16); C(KEY_F17); C(KEY_F18); C(KEY_F19);
C(KEY_F20); C(KEY_F21); C(KEY_F22); C(KEY_F23); C(KEY_F24); C(KEY_F25);
C(KEY_KP_0); C(KEY_KP_1); C(KEY_KP_2); C(KEY_KP_3); C(KEY_KP_4);
C(KEY_KP_5); C(KEY_KP_6); C(KEY_KP_7); C(KEY_KP_8); C(KEY_KP_9);
C(KEY_KP_DECIMAL); C(KEY_KP_DIVIDE); C(KEY_KP_MULTIPLY);
C(KEY_KP_SUBTRACT); C(KEY_KP_ADD); C(KEY_KP_ENTER); C(KEY_KP_EQUAL);
C(KEY_LEFT_SHIFT); C(KEY_LEFT_CONTROL); C(KEY_LEFT_ALT);
C(KEY_LEFT_SUPER); C(KEY_RIGHT_SHIFT); C(KEY_RIGHT_CONTROL);
C(KEY_RIGHT_ALT); C(KEY_RIGHT_SUPER); C(KEY_MENU); C(KEY_LAST);
C(MOD_SHIFT); C(MOD_CONTROL); C(MOD_ALT); C(MOD_SUPER);
C(MOUSE_BUTTON_1); C(MOUSE_BUTTON_2); C(MOUSE_BUTTON_3);
C(MOUSE_BUTTON_4); C(MOUSE_BUTTON_5); C(MOUSE_BUTTON_6);
C(MOUSE_BUTTON_7); C(MOUSE_BUTTON_8); C(MOUSE_BUTTON_LAST);
C(MOUSE_BUTTON_LEFT); C(MOUSE_BUTTON_RIGHT); C(MOUSE_BUTTON_MIDDLE);
C(RELEASE); C(PRESS); C(REPEAT);
#undef C
g.def("getTime", &glfwGetTime);
}
}
#endif

View File

@@ -0,0 +1,976 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
/* Developer note: need to make a change to this file?
* Please raise an Issue on GitHub describing what needs to change. This file
* was generated, so the scripts that generated it needs to update as well.
*/
void register_entypo(py::module &m) {
/* Entypo constants */
{
#define C(name) g.attr(#name) = py::int_(name);
py::module g = m.def_submodule("icons");
C(FA_AD);
C(FA_ADDRESS_BOOK);
C(FA_ADDRESS_CARD);
C(FA_ADJUST);
C(FA_AIR_FRESHENER);
C(FA_ALIGN_CENTER);
C(FA_ALIGN_JUSTIFY);
C(FA_ALIGN_LEFT);
C(FA_ALIGN_RIGHT);
C(FA_ALLERGIES);
C(FA_AMBULANCE);
C(FA_AMERICAN_SIGN_LANGUAGE_INTERPRETING);
C(FA_ANCHOR);
C(FA_ANGLE_DOUBLE_DOWN);
C(FA_ANGLE_DOUBLE_LEFT);
C(FA_ANGLE_DOUBLE_RIGHT);
C(FA_ANGLE_DOUBLE_UP);
C(FA_ANGLE_DOWN);
C(FA_ANGLE_LEFT);
C(FA_ANGLE_RIGHT);
C(FA_ANGLE_UP);
C(FA_ANGRY);
C(FA_ANKH);
C(FA_APPLE_ALT);
C(FA_ARCHIVE);
C(FA_ARCHWAY);
C(FA_ARROW_ALT_CIRCLE_DOWN);
C(FA_ARROW_ALT_CIRCLE_LEFT);
C(FA_ARROW_ALT_CIRCLE_RIGHT);
C(FA_ARROW_ALT_CIRCLE_UP);
C(FA_ARROW_CIRCLE_DOWN);
C(FA_ARROW_CIRCLE_LEFT);
C(FA_ARROW_CIRCLE_RIGHT);
C(FA_ARROW_CIRCLE_UP);
C(FA_ARROW_DOWN);
C(FA_ARROW_LEFT);
C(FA_ARROW_RIGHT);
C(FA_ARROW_UP);
C(FA_ARROWS_ALT);
C(FA_ARROWS_ALT_H);
C(FA_ARROWS_ALT_V);
C(FA_ASSISTIVE_LISTENING_SYSTEMS);
C(FA_ASTERISK);
C(FA_AT);
C(FA_ATLAS);
C(FA_ATOM);
C(FA_AUDIO_DESCRIPTION);
C(FA_AWARD);
C(FA_BABY);
C(FA_BABY_CARRIAGE);
C(FA_BACKSPACE);
C(FA_BACKWARD);
C(FA_BACON);
C(FA_BALANCE_SCALE);
C(FA_BALANCE_SCALE_LEFT);
C(FA_BALANCE_SCALE_RIGHT);
C(FA_BAN);
C(FA_BAND_AID);
C(FA_BARCODE);
C(FA_BARS);
C(FA_BASEBALL_BALL);
C(FA_BASKETBALL_BALL);
C(FA_BATH);
C(FA_BATTERY_EMPTY);
C(FA_BATTERY_FULL);
C(FA_BATTERY_HALF);
C(FA_BATTERY_QUARTER);
C(FA_BATTERY_THREE_QUARTERS);
C(FA_BED);
C(FA_BEER);
C(FA_BELL);
C(FA_BELL_SLASH);
C(FA_BEZIER_CURVE);
C(FA_BIBLE);
C(FA_BICYCLE);
C(FA_BIKING);
C(FA_BINOCULARS);
C(FA_BIOHAZARD);
C(FA_BIRTHDAY_CAKE);
C(FA_BLENDER);
C(FA_BLENDER_PHONE);
C(FA_BLIND);
C(FA_BLOG);
C(FA_BOLD);
C(FA_BOLT);
C(FA_BOMB);
C(FA_BONE);
C(FA_BONG);
C(FA_BOOK);
C(FA_BOOK_DEAD);
C(FA_BOOK_MEDICAL);
C(FA_BOOK_OPEN);
C(FA_BOOK_READER);
C(FA_BOOKMARK);
C(FA_BORDER_ALL);
C(FA_BORDER_NONE);
C(FA_BORDER_STYLE);
C(FA_BOWLING_BALL);
C(FA_BOX);
C(FA_BOX_OPEN);
C(FA_BOXES);
C(FA_BRAILLE);
C(FA_BRAIN);
C(FA_BREAD_SLICE);
C(FA_BRIEFCASE);
C(FA_BRIEFCASE_MEDICAL);
C(FA_BROADCAST_TOWER);
C(FA_BROOM);
C(FA_BRUSH);
C(FA_BUG);
C(FA_BUILDING);
C(FA_BULLHORN);
C(FA_BULLSEYE);
C(FA_BURN);
C(FA_BUS);
C(FA_BUS_ALT);
C(FA_BUSINESS_TIME);
C(FA_CALCULATOR);
C(FA_CALENDAR);
C(FA_CALENDAR_ALT);
C(FA_CALENDAR_CHECK);
C(FA_CALENDAR_DAY);
C(FA_CALENDAR_MINUS);
C(FA_CALENDAR_PLUS);
C(FA_CALENDAR_TIMES);
C(FA_CALENDAR_WEEK);
C(FA_CAMERA);
C(FA_CAMERA_RETRO);
C(FA_CAMPGROUND);
C(FA_CANDY_CANE);
C(FA_CANNABIS);
C(FA_CAPSULES);
C(FA_CAR);
C(FA_CAR_ALT);
C(FA_CAR_BATTERY);
C(FA_CAR_CRASH);
C(FA_CAR_SIDE);
C(FA_CARET_DOWN);
C(FA_CARET_LEFT);
C(FA_CARET_RIGHT);
C(FA_CARET_SQUARE_DOWN);
C(FA_CARET_SQUARE_LEFT);
C(FA_CARET_SQUARE_RIGHT);
C(FA_CARET_SQUARE_UP);
C(FA_CARET_UP);
C(FA_CARROT);
C(FA_CART_ARROW_DOWN);
C(FA_CART_PLUS);
C(FA_CASH_REGISTER);
C(FA_CAT);
C(FA_CERTIFICATE);
C(FA_CHAIR);
C(FA_CHALKBOARD);
C(FA_CHALKBOARD_TEACHER);
C(FA_CHARGING_STATION);
C(FA_CHART_AREA);
C(FA_CHART_BAR);
C(FA_CHART_LINE);
C(FA_CHART_PIE);
C(FA_CHECK);
C(FA_CHECK_CIRCLE);
C(FA_CHECK_DOUBLE);
C(FA_CHECK_SQUARE);
C(FA_CHEESE);
C(FA_CHESS);
C(FA_CHESS_BISHOP);
C(FA_CHESS_BOARD);
C(FA_CHESS_KING);
C(FA_CHESS_KNIGHT);
C(FA_CHESS_PAWN);
C(FA_CHESS_QUEEN);
C(FA_CHESS_ROOK);
C(FA_CHEVRON_CIRCLE_DOWN);
C(FA_CHEVRON_CIRCLE_LEFT);
C(FA_CHEVRON_CIRCLE_RIGHT);
C(FA_CHEVRON_CIRCLE_UP);
C(FA_CHEVRON_DOWN);
C(FA_CHEVRON_LEFT);
C(FA_CHEVRON_RIGHT);
C(FA_CHEVRON_UP);
C(FA_CHILD);
C(FA_CHURCH);
C(FA_CIRCLE);
C(FA_CIRCLE_NOTCH);
C(FA_CITY);
C(FA_CLINIC_MEDICAL);
C(FA_CLIPBOARD);
C(FA_CLIPBOARD_CHECK);
C(FA_CLIPBOARD_LIST);
C(FA_CLOCK);
C(FA_CLONE);
C(FA_CLOSED_CAPTIONING);
C(FA_CLOUD);
C(FA_CLOUD_DOWNLOAD_ALT);
C(FA_CLOUD_MEATBALL);
C(FA_CLOUD_MOON);
C(FA_CLOUD_MOON_RAIN);
C(FA_CLOUD_RAIN);
C(FA_CLOUD_SHOWERS_HEAVY);
C(FA_CLOUD_SUN);
C(FA_CLOUD_SUN_RAIN);
C(FA_CLOUD_UPLOAD_ALT);
C(FA_COCKTAIL);
C(FA_CODE);
C(FA_CODE_BRANCH);
C(FA_COFFEE);
C(FA_COG);
C(FA_COGS);
C(FA_COINS);
C(FA_COLUMNS);
C(FA_COMMENT);
C(FA_COMMENT_ALT);
C(FA_COMMENT_DOLLAR);
C(FA_COMMENT_DOTS);
C(FA_COMMENT_MEDICAL);
C(FA_COMMENT_SLASH);
C(FA_COMMENTS);
C(FA_COMMENTS_DOLLAR);
C(FA_COMPACT_DISC);
C(FA_COMPASS);
C(FA_COMPRESS);
C(FA_COMPRESS_ARROWS_ALT);
C(FA_CONCIERGE_BELL);
C(FA_COOKIE);
C(FA_COOKIE_BITE);
C(FA_COPY);
C(FA_COPYRIGHT);
C(FA_COUCH);
C(FA_CREDIT_CARD);
C(FA_CROP);
C(FA_CROP_ALT);
C(FA_CROSS);
C(FA_CROSSHAIRS);
C(FA_CROW);
C(FA_CROWN);
C(FA_CRUTCH);
C(FA_CUBE);
C(FA_CUBES);
C(FA_CUT);
C(FA_DATABASE);
C(FA_DEAF);
C(FA_DEMOCRAT);
C(FA_DESKTOP);
C(FA_DHARMACHAKRA);
C(FA_DIAGNOSES);
C(FA_DICE);
C(FA_DICE_D20);
C(FA_DICE_D6);
C(FA_DICE_FIVE);
C(FA_DICE_FOUR);
C(FA_DICE_ONE);
C(FA_DICE_SIX);
C(FA_DICE_THREE);
C(FA_DICE_TWO);
C(FA_DIGITAL_TACHOGRAPH);
C(FA_DIRECTIONS);
C(FA_DIVIDE);
C(FA_DIZZY);
C(FA_DNA);
C(FA_DOG);
C(FA_DOLLAR_SIGN);
C(FA_DOLLY);
C(FA_DOLLY_FLATBED);
C(FA_DONATE);
C(FA_DOOR_CLOSED);
C(FA_DOOR_OPEN);
C(FA_DOT_CIRCLE);
C(FA_DOVE);
C(FA_DOWNLOAD);
C(FA_DRAFTING_COMPASS);
C(FA_DRAGON);
C(FA_DRAW_POLYGON);
C(FA_DRUM);
C(FA_DRUM_STEELPAN);
C(FA_DRUMSTICK_BITE);
C(FA_DUMBBELL);
C(FA_DUMPSTER);
C(FA_DUMPSTER_FIRE);
C(FA_DUNGEON);
C(FA_EDIT);
C(FA_EGG);
C(FA_EJECT);
C(FA_ELLIPSIS_H);
C(FA_ELLIPSIS_V);
C(FA_ENVELOPE);
C(FA_ENVELOPE_OPEN);
C(FA_ENVELOPE_OPEN_TEXT);
C(FA_ENVELOPE_SQUARE);
C(FA_EQUALS);
C(FA_ERASER);
C(FA_ETHERNET);
C(FA_EURO_SIGN);
C(FA_EXCHANGE_ALT);
C(FA_EXCLAMATION);
C(FA_EXCLAMATION_CIRCLE);
C(FA_EXCLAMATION_TRIANGLE);
C(FA_EXPAND);
C(FA_EXPAND_ARROWS_ALT);
C(FA_EXTERNAL_LINK_ALT);
C(FA_EXTERNAL_LINK_SQUARE_ALT);
C(FA_EYE);
C(FA_EYE_DROPPER);
C(FA_EYE_SLASH);
C(FA_FAN);
C(FA_FAST_BACKWARD);
C(FA_FAST_FORWARD);
C(FA_FAX);
C(FA_FEATHER);
C(FA_FEATHER_ALT);
C(FA_FEMALE);
C(FA_FIGHTER_JET);
C(FA_FILE);
C(FA_FILE_ALT);
C(FA_FILE_ARCHIVE);
C(FA_FILE_AUDIO);
C(FA_FILE_CODE);
C(FA_FILE_CONTRACT);
C(FA_FILE_CSV);
C(FA_FILE_DOWNLOAD);
C(FA_FILE_EXCEL);
C(FA_FILE_EXPORT);
C(FA_FILE_IMAGE);
C(FA_FILE_IMPORT);
C(FA_FILE_INVOICE);
C(FA_FILE_INVOICE_DOLLAR);
C(FA_FILE_MEDICAL);
C(FA_FILE_MEDICAL_ALT);
C(FA_FILE_PDF);
C(FA_FILE_POWERPOINT);
C(FA_FILE_PRESCRIPTION);
C(FA_FILE_SIGNATURE);
C(FA_FILE_UPLOAD);
C(FA_FILE_VIDEO);
C(FA_FILE_WORD);
C(FA_FILL);
C(FA_FILL_DRIP);
C(FA_FILM);
C(FA_FILTER);
C(FA_FINGERPRINT);
C(FA_FIRE);
C(FA_FIRE_ALT);
C(FA_FIRE_EXTINGUISHER);
C(FA_FIRST_AID);
C(FA_FISH);
C(FA_FIST_RAISED);
C(FA_FLAG);
C(FA_FLAG_CHECKERED);
C(FA_FLAG_USA);
C(FA_FLASK);
C(FA_FLUSHED);
C(FA_FOLDER);
C(FA_FOLDER_MINUS);
C(FA_FOLDER_OPEN);
C(FA_FOLDER_PLUS);
C(FA_FONT);
C(FA_FONT_AWESOME_LOGO_FULL);
C(FA_FOOTBALL_BALL);
C(FA_FORWARD);
C(FA_FROG);
C(FA_FROWN);
C(FA_FROWN_OPEN);
C(FA_FUNNEL_DOLLAR);
C(FA_FUTBOL);
C(FA_GAMEPAD);
C(FA_GAS_PUMP);
C(FA_GAVEL);
C(FA_GEM);
C(FA_GENDERLESS);
C(FA_GHOST);
C(FA_GIFT);
C(FA_GIFTS);
C(FA_GLASS_CHEERS);
C(FA_GLASS_MARTINI);
C(FA_GLASS_MARTINI_ALT);
C(FA_GLASS_WHISKEY);
C(FA_GLASSES);
C(FA_GLOBE);
C(FA_GLOBE_AFRICA);
C(FA_GLOBE_AMERICAS);
C(FA_GLOBE_ASIA);
C(FA_GLOBE_EUROPE);
C(FA_GOLF_BALL);
C(FA_GOPURAM);
C(FA_GRADUATION_CAP);
C(FA_GREATER_THAN);
C(FA_GREATER_THAN_EQUAL);
C(FA_GRIMACE);
C(FA_GRIN);
C(FA_GRIN_ALT);
C(FA_GRIN_BEAM);
C(FA_GRIN_BEAM_SWEAT);
C(FA_GRIN_HEARTS);
C(FA_GRIN_SQUINT);
C(FA_GRIN_SQUINT_TEARS);
C(FA_GRIN_STARS);
C(FA_GRIN_TEARS);
C(FA_GRIN_TONGUE);
C(FA_GRIN_TONGUE_SQUINT);
C(FA_GRIN_TONGUE_WINK);
C(FA_GRIN_WINK);
C(FA_GRIP_HORIZONTAL);
C(FA_GRIP_LINES);
C(FA_GRIP_LINES_VERTICAL);
C(FA_GRIP_VERTICAL);
C(FA_GUITAR);
C(FA_H_SQUARE);
C(FA_HAMBURGER);
C(FA_HAMMER);
C(FA_HAMSA);
C(FA_HAND_HOLDING);
C(FA_HAND_HOLDING_HEART);
C(FA_HAND_HOLDING_USD);
C(FA_HAND_LIZARD);
C(FA_HAND_MIDDLE_FINGER);
C(FA_HAND_PAPER);
C(FA_HAND_PEACE);
C(FA_HAND_POINT_DOWN);
C(FA_HAND_POINT_LEFT);
C(FA_HAND_POINT_RIGHT);
C(FA_HAND_POINT_UP);
C(FA_HAND_POINTER);
C(FA_HAND_ROCK);
C(FA_HAND_SCISSORS);
C(FA_HAND_SPOCK);
C(FA_HANDS);
C(FA_HANDS_HELPING);
C(FA_HANDSHAKE);
C(FA_HANUKIAH);
C(FA_HARD_HAT);
C(FA_HASHTAG);
C(FA_HAT_WIZARD);
C(FA_HAYKAL);
C(FA_HDD);
C(FA_HEADING);
C(FA_HEADPHONES);
C(FA_HEADPHONES_ALT);
C(FA_HEADSET);
C(FA_HEART);
C(FA_HEART_BROKEN);
C(FA_HEARTBEAT);
C(FA_HELICOPTER);
C(FA_HIGHLIGHTER);
C(FA_HIKING);
C(FA_HIPPO);
C(FA_HISTORY);
C(FA_HOCKEY_PUCK);
C(FA_HOLLY_BERRY);
C(FA_HOME);
C(FA_HORSE);
C(FA_HORSE_HEAD);
C(FA_HOSPITAL);
C(FA_HOSPITAL_ALT);
C(FA_HOSPITAL_SYMBOL);
C(FA_HOT_TUB);
C(FA_HOTDOG);
C(FA_HOTEL);
C(FA_HOURGLASS);
C(FA_HOURGLASS_END);
C(FA_HOURGLASS_HALF);
C(FA_HOURGLASS_START);
C(FA_HOUSE_DAMAGE);
C(FA_HRYVNIA);
C(FA_I_CURSOR);
C(FA_ICE_CREAM);
C(FA_ICICLES);
C(FA_ICONS);
C(FA_ID_BADGE);
C(FA_ID_CARD);
C(FA_ID_CARD_ALT);
C(FA_IGLOO);
C(FA_IMAGE);
C(FA_IMAGES);
C(FA_INBOX);
C(FA_INDENT);
C(FA_INDUSTRY);
C(FA_INFINITY);
C(FA_INFO);
C(FA_INFO_CIRCLE);
C(FA_ITALIC);
C(FA_JEDI);
C(FA_JOINT);
C(FA_JOURNAL_WHILLS);
C(FA_KAABA);
C(FA_KEY);
C(FA_KEYBOARD);
C(FA_KHANDA);
C(FA_KISS);
C(FA_KISS_BEAM);
C(FA_KISS_WINK_HEART);
C(FA_KIWI_BIRD);
C(FA_LANDMARK);
C(FA_LANGUAGE);
C(FA_LAPTOP);
C(FA_LAPTOP_CODE);
C(FA_LAPTOP_MEDICAL);
C(FA_LAUGH);
C(FA_LAUGH_BEAM);
C(FA_LAUGH_SQUINT);
C(FA_LAUGH_WINK);
C(FA_LAYER_GROUP);
C(FA_LEAF);
C(FA_LEMON);
C(FA_LESS_THAN);
C(FA_LESS_THAN_EQUAL);
C(FA_LEVEL_DOWN_ALT);
C(FA_LEVEL_UP_ALT);
C(FA_LIFE_RING);
C(FA_LIGHTBULB);
C(FA_LINK);
C(FA_LIRA_SIGN);
C(FA_LIST);
C(FA_LIST_ALT);
C(FA_LIST_OL);
C(FA_LIST_UL);
C(FA_LOCATION_ARROW);
C(FA_LOCK);
C(FA_LOCK_OPEN);
C(FA_LONG_ARROW_ALT_DOWN);
C(FA_LONG_ARROW_ALT_LEFT);
C(FA_LONG_ARROW_ALT_RIGHT);
C(FA_LONG_ARROW_ALT_UP);
C(FA_LOW_VISION);
C(FA_LUGGAGE_CART);
C(FA_MAGIC);
C(FA_MAGNET);
C(FA_MAIL_BULK);
C(FA_MALE);
C(FA_MAP);
C(FA_MAP_MARKED);
C(FA_MAP_MARKED_ALT);
C(FA_MAP_MARKER);
C(FA_MAP_MARKER_ALT);
C(FA_MAP_PIN);
C(FA_MAP_SIGNS);
C(FA_MARKER);
C(FA_MARS);
C(FA_MARS_DOUBLE);
C(FA_MARS_STROKE);
C(FA_MARS_STROKE_H);
C(FA_MARS_STROKE_V);
C(FA_MASK);
C(FA_MEDAL);
C(FA_MEDKIT);
C(FA_MEH);
C(FA_MEH_BLANK);
C(FA_MEH_ROLLING_EYES);
C(FA_MEMORY);
C(FA_MENORAH);
C(FA_MERCURY);
C(FA_METEOR);
C(FA_MICROCHIP);
C(FA_MICROPHONE);
C(FA_MICROPHONE_ALT);
C(FA_MICROPHONE_ALT_SLASH);
C(FA_MICROPHONE_SLASH);
C(FA_MICROSCOPE);
C(FA_MINUS);
C(FA_MINUS_CIRCLE);
C(FA_MINUS_SQUARE);
C(FA_MITTEN);
C(FA_MOBILE);
C(FA_MOBILE_ALT);
C(FA_MONEY_BILL);
C(FA_MONEY_BILL_ALT);
C(FA_MONEY_BILL_WAVE);
C(FA_MONEY_BILL_WAVE_ALT);
C(FA_MONEY_CHECK);
C(FA_MONEY_CHECK_ALT);
C(FA_MONUMENT);
C(FA_MOON);
C(FA_MORTAR_PESTLE);
C(FA_MOSQUE);
C(FA_MOTORCYCLE);
C(FA_MOUNTAIN);
C(FA_MOUSE_POINTER);
C(FA_MUG_HOT);
C(FA_MUSIC);
C(FA_NETWORK_WIRED);
C(FA_NEUTER);
C(FA_NEWSPAPER);
C(FA_NOT_EQUAL);
C(FA_NOTES_MEDICAL);
C(FA_OBJECT_GROUP);
C(FA_OBJECT_UNGROUP);
C(FA_OIL_CAN);
C(FA_OM);
C(FA_OTTER);
C(FA_OUTDENT);
C(FA_PAGER);
C(FA_PAINT_BRUSH);
C(FA_PAINT_ROLLER);
C(FA_PALETTE);
C(FA_PALLET);
C(FA_PAPER_PLANE);
C(FA_PAPERCLIP);
C(FA_PARACHUTE_BOX);
C(FA_PARAGRAPH);
C(FA_PARKING);
C(FA_PASSPORT);
C(FA_PASTAFARIANISM);
C(FA_PASTE);
C(FA_PAUSE);
C(FA_PAUSE_CIRCLE);
C(FA_PAW);
C(FA_PEACE);
C(FA_PEN);
C(FA_PEN_ALT);
C(FA_PEN_FANCY);
C(FA_PEN_NIB);
C(FA_PEN_SQUARE);
C(FA_PENCIL_ALT);
C(FA_PENCIL_RULER);
C(FA_PEOPLE_CARRY);
C(FA_PEPPER_HOT);
C(FA_PERCENT);
C(FA_PERCENTAGE);
C(FA_PERSON_BOOTH);
C(FA_PHONE);
C(FA_PHONE_ALT);
C(FA_PHONE_SLASH);
C(FA_PHONE_SQUARE);
C(FA_PHONE_SQUARE_ALT);
C(FA_PHONE_VOLUME);
C(FA_PHOTO_VIDEO);
C(FA_PIGGY_BANK);
C(FA_PILLS);
C(FA_PIZZA_SLICE);
C(FA_PLACE_OF_WORSHIP);
C(FA_PLANE);
C(FA_PLANE_ARRIVAL);
C(FA_PLANE_DEPARTURE);
C(FA_PLAY);
C(FA_PLAY_CIRCLE);
C(FA_PLUG);
C(FA_PLUS);
C(FA_PLUS_CIRCLE);
C(FA_PLUS_SQUARE);
C(FA_PODCAST);
C(FA_POLL);
C(FA_POLL_H);
C(FA_POO);
C(FA_POO_STORM);
C(FA_POOP);
C(FA_PORTRAIT);
C(FA_POUND_SIGN);
C(FA_POWER_OFF);
C(FA_PRAY);
C(FA_PRAYING_HANDS);
C(FA_PRESCRIPTION);
C(FA_PRESCRIPTION_BOTTLE);
C(FA_PRESCRIPTION_BOTTLE_ALT);
C(FA_PRINT);
C(FA_PROCEDURES);
C(FA_PROJECT_DIAGRAM);
C(FA_PUZZLE_PIECE);
C(FA_QRCODE);
C(FA_QUESTION);
C(FA_QUESTION_CIRCLE);
C(FA_QUIDDITCH);
C(FA_QUOTE_LEFT);
C(FA_QUOTE_RIGHT);
C(FA_QURAN);
C(FA_RADIATION);
C(FA_RADIATION_ALT);
C(FA_RAINBOW);
C(FA_RANDOM);
C(FA_RECEIPT);
C(FA_RECYCLE);
C(FA_REDO);
C(FA_REDO_ALT);
C(FA_REGISTERED);
C(FA_REMOVE_FORMAT);
C(FA_REPLY);
C(FA_REPLY_ALL);
C(FA_REPUBLICAN);
C(FA_RESTROOM);
C(FA_RETWEET);
C(FA_RIBBON);
C(FA_RING);
C(FA_ROAD);
C(FA_ROBOT);
C(FA_ROCKET);
C(FA_ROUTE);
C(FA_RSS);
C(FA_RSS_SQUARE);
C(FA_RUBLE_SIGN);
C(FA_RULER);
C(FA_RULER_COMBINED);
C(FA_RULER_HORIZONTAL);
C(FA_RULER_VERTICAL);
C(FA_RUNNING);
C(FA_RUPEE_SIGN);
C(FA_SAD_CRY);
C(FA_SAD_TEAR);
C(FA_SATELLITE);
C(FA_SATELLITE_DISH);
C(FA_SAVE);
C(FA_SCHOOL);
C(FA_SCREWDRIVER);
C(FA_SCROLL);
C(FA_SD_CARD);
C(FA_SEARCH);
C(FA_SEARCH_DOLLAR);
C(FA_SEARCH_LOCATION);
C(FA_SEARCH_MINUS);
C(FA_SEARCH_PLUS);
C(FA_SEEDLING);
C(FA_SERVER);
C(FA_SHAPES);
C(FA_SHARE);
C(FA_SHARE_ALT);
C(FA_SHARE_ALT_SQUARE);
C(FA_SHARE_SQUARE);
C(FA_SHEKEL_SIGN);
C(FA_SHIELD_ALT);
C(FA_SHIP);
C(FA_SHIPPING_FAST);
C(FA_SHOE_PRINTS);
C(FA_SHOPPING_BAG);
C(FA_SHOPPING_BASKET);
C(FA_SHOPPING_CART);
C(FA_SHOWER);
C(FA_SHUTTLE_VAN);
C(FA_SIGN);
C(FA_SIGN_IN_ALT);
C(FA_SIGN_LANGUAGE);
C(FA_SIGN_OUT_ALT);
C(FA_SIGNAL);
C(FA_SIGNATURE);
C(FA_SIM_CARD);
C(FA_SITEMAP);
C(FA_SKATING);
C(FA_SKIING);
C(FA_SKIING_NORDIC);
C(FA_SKULL);
C(FA_SKULL_CROSSBONES);
C(FA_SLASH);
C(FA_SLEIGH);
C(FA_SLIDERS_H);
C(FA_SMILE);
C(FA_SMILE_BEAM);
C(FA_SMILE_WINK);
C(FA_SMOG);
C(FA_SMOKING);
C(FA_SMOKING_BAN);
C(FA_SMS);
C(FA_SNOWBOARDING);
C(FA_SNOWFLAKE);
C(FA_SNOWMAN);
C(FA_SNOWPLOW);
C(FA_SOCKS);
C(FA_SOLAR_PANEL);
C(FA_SORT);
C(FA_SORT_ALPHA_DOWN);
C(FA_SORT_ALPHA_DOWN_ALT);
C(FA_SORT_ALPHA_UP);
C(FA_SORT_ALPHA_UP_ALT);
C(FA_SORT_AMOUNT_DOWN);
C(FA_SORT_AMOUNT_DOWN_ALT);
C(FA_SORT_AMOUNT_UP);
C(FA_SORT_AMOUNT_UP_ALT);
C(FA_SORT_DOWN);
C(FA_SORT_NUMERIC_DOWN);
C(FA_SORT_NUMERIC_DOWN_ALT);
C(FA_SORT_NUMERIC_UP);
C(FA_SORT_NUMERIC_UP_ALT);
C(FA_SORT_UP);
C(FA_SPA);
C(FA_SPACE_SHUTTLE);
C(FA_SPELL_CHECK);
C(FA_SPIDER);
C(FA_SPINNER);
C(FA_SPLOTCH);
C(FA_SPRAY_CAN);
C(FA_SQUARE);
C(FA_SQUARE_FULL);
C(FA_SQUARE_ROOT_ALT);
C(FA_STAMP);
C(FA_STAR);
C(FA_STAR_AND_CRESCENT);
C(FA_STAR_HALF);
C(FA_STAR_HALF_ALT);
C(FA_STAR_OF_DAVID);
C(FA_STAR_OF_LIFE);
C(FA_STEP_BACKWARD);
C(FA_STEP_FORWARD);
C(FA_STETHOSCOPE);
C(FA_STICKY_NOTE);
C(FA_STOP);
C(FA_STOP_CIRCLE);
C(FA_STOPWATCH);
C(FA_STORE);
C(FA_STORE_ALT);
C(FA_STREAM);
C(FA_STREET_VIEW);
C(FA_STRIKETHROUGH);
C(FA_STROOPWAFEL);
C(FA_SUBSCRIPT);
C(FA_SUBWAY);
C(FA_SUITCASE);
C(FA_SUITCASE_ROLLING);
C(FA_SUN);
C(FA_SUPERSCRIPT);
C(FA_SURPRISE);
C(FA_SWATCHBOOK);
C(FA_SWIMMER);
C(FA_SWIMMING_POOL);
C(FA_SYNAGOGUE);
C(FA_SYNC);
C(FA_SYNC_ALT);
C(FA_SYRINGE);
C(FA_TABLE);
C(FA_TABLE_TENNIS);
C(FA_TABLET);
C(FA_TABLET_ALT);
C(FA_TABLETS);
C(FA_TACHOMETER_ALT);
C(FA_TAG);
C(FA_TAGS);
C(FA_TAPE);
C(FA_TASKS);
C(FA_TAXI);
C(FA_TEETH);
C(FA_TEETH_OPEN);
C(FA_TEMPERATURE_HIGH);
C(FA_TEMPERATURE_LOW);
C(FA_TENGE);
C(FA_TERMINAL);
C(FA_TEXT_HEIGHT);
C(FA_TEXT_WIDTH);
C(FA_TH);
C(FA_TH_LARGE);
C(FA_TH_LIST);
C(FA_THEATER_MASKS);
C(FA_THERMOMETER);
C(FA_THERMOMETER_EMPTY);
C(FA_THERMOMETER_FULL);
C(FA_THERMOMETER_HALF);
C(FA_THERMOMETER_QUARTER);
C(FA_THERMOMETER_THREE_QUARTERS);
C(FA_THUMBS_DOWN);
C(FA_THUMBS_UP);
C(FA_THUMBTACK);
C(FA_TICKET_ALT);
C(FA_TIMES);
C(FA_TIMES_CIRCLE);
C(FA_TINT);
C(FA_TINT_SLASH);
C(FA_TIRED);
C(FA_TOGGLE_OFF);
C(FA_TOGGLE_ON);
C(FA_TOILET);
C(FA_TOILET_PAPER);
C(FA_TOOLBOX);
C(FA_TOOLS);
C(FA_TOOTH);
C(FA_TORAH);
C(FA_TORII_GATE);
C(FA_TRACTOR);
C(FA_TRADEMARK);
C(FA_TRAFFIC_LIGHT);
C(FA_TRAIN);
C(FA_TRAM);
C(FA_TRANSGENDER);
C(FA_TRANSGENDER_ALT);
C(FA_TRASH);
C(FA_TRASH_ALT);
C(FA_TRASH_RESTORE);
C(FA_TRASH_RESTORE_ALT);
C(FA_TREE);
C(FA_TROPHY);
C(FA_TRUCK);
C(FA_TRUCK_LOADING);
C(FA_TRUCK_MONSTER);
C(FA_TRUCK_MOVING);
C(FA_TRUCK_PICKUP);
C(FA_TSHIRT);
C(FA_TTY);
C(FA_TV);
C(FA_UMBRELLA);
C(FA_UMBRELLA_BEACH);
C(FA_UNDERLINE);
C(FA_UNDO);
C(FA_UNDO_ALT);
C(FA_UNIVERSAL_ACCESS);
C(FA_UNIVERSITY);
C(FA_UNLINK);
C(FA_UNLOCK);
C(FA_UNLOCK_ALT);
C(FA_UPLOAD);
C(FA_USER);
C(FA_USER_ALT);
C(FA_USER_ALT_SLASH);
C(FA_USER_ASTRONAUT);
C(FA_USER_CHECK);
C(FA_USER_CIRCLE);
C(FA_USER_CLOCK);
C(FA_USER_COG);
C(FA_USER_EDIT);
C(FA_USER_FRIENDS);
C(FA_USER_GRADUATE);
C(FA_USER_INJURED);
C(FA_USER_LOCK);
C(FA_USER_MD);
C(FA_USER_MINUS);
C(FA_USER_NINJA);
C(FA_USER_NURSE);
C(FA_USER_PLUS);
C(FA_USER_SECRET);
C(FA_USER_SHIELD);
C(FA_USER_SLASH);
C(FA_USER_TAG);
C(FA_USER_TIE);
C(FA_USER_TIMES);
C(FA_USERS);
C(FA_USERS_COG);
C(FA_UTENSIL_SPOON);
C(FA_UTENSILS);
C(FA_VECTOR_SQUARE);
C(FA_VENUS);
C(FA_VENUS_DOUBLE);
C(FA_VENUS_MARS);
C(FA_VIAL);
C(FA_VIALS);
C(FA_VIDEO);
C(FA_VIDEO_SLASH);
C(FA_VIHARA);
C(FA_VOICEMAIL);
C(FA_VOLLEYBALL_BALL);
C(FA_VOLUME_DOWN);
C(FA_VOLUME_MUTE);
C(FA_VOLUME_OFF);
C(FA_VOLUME_UP);
C(FA_VOTE_YEA);
C(FA_VR_CARDBOARD);
C(FA_WALKING);
C(FA_WALLET);
C(FA_WAREHOUSE);
C(FA_WATER);
C(FA_WAVE_SQUARE);
C(FA_WEIGHT);
C(FA_WEIGHT_HANGING);
C(FA_WHEELCHAIR);
C(FA_WIFI);
C(FA_WIND);
C(FA_WINDOW_CLOSE);
C(FA_WINDOW_MAXIMIZE);
C(FA_WINDOW_MINIMIZE);
C(FA_WINDOW_RESTORE);
C(FA_WINE_BOTTLE);
C(FA_WINE_GLASS);
C(FA_WINE_GLASS_ALT);
C(FA_WON_SIGN);
C(FA_WRENCH);
C(FA_X_RAY);
C(FA_YEN_SIGN);
C(FA_YIN_YANG);
#undef C
}
}
#endif

View File

@@ -0,0 +1,98 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
DECLARE_LAYOUT(Layout);
DECLARE_LAYOUT(GroupLayout);
DECLARE_LAYOUT(BoxLayout);
DECLARE_LAYOUT(GridLayout);
DECLARE_LAYOUT(AdvancedGridLayout);
void register_layout(py::module &m) {
py::class_<Layout, ref<Layout>, PyLayout> layout(m, "Layout", D(Layout));
layout
.def("preferred_size", &Layout::preferred_size, D(Layout, preferred_size))
.def("perform_layout", &Layout::perform_layout, D(Layout, perform_layout));
py::class_<BoxLayout, Layout, ref<BoxLayout>, PyBoxLayout>(m, "BoxLayout", D(BoxLayout))
.def(py::init<Orientation, Alignment, int, int>(),
"orientation"_a, "alignment"_a = Alignment::Middle,
"margin"_a = 0, "spacing"_a = 0, D(BoxLayout, BoxLayout))
.def("orientation", &BoxLayout::orientation, D(BoxLayout, orientation))
.def("set_orientation", &BoxLayout::set_orientation, D(BoxLayout, set_orientation))
.def("alignment", &BoxLayout::alignment, D(BoxLayout, alignment))
.def("set_alignment", &BoxLayout::set_alignment, D(BoxLayout, set_alignment))
.def("margin", &BoxLayout::margin, D(BoxLayout, margin))
.def("set_margin", &BoxLayout::set_margin, D(BoxLayout, set_margin))
.def("spacing", &BoxLayout::spacing, D(BoxLayout, spacing))
.def("set_spacing", &BoxLayout::set_spacing, D(BoxLayout, set_spacing));
py::class_<GroupLayout, Layout, ref<GroupLayout>, PyGroupLayout>(m, "GroupLayout", D(GroupLayout))
.def(py::init<int, int, int, int>(),
"margin"_a = 15, "spacing"_a = 6,
"group_spacing"_a = 14, "group_indent"_a = 20,
D(GroupLayout, GroupLayout))
.def("margin", &GroupLayout::margin, D(GroupLayout, margin))
.def("set_margin", &GroupLayout::set_margin, D(GroupLayout, set_margin))
.def("spacing", &GroupLayout::spacing, D(GroupLayout, spacing))
.def("set_spacing", &GroupLayout::set_spacing, D(GroupLayout, set_spacing))
.def("group_indent", &GroupLayout::group_indent, D(GroupLayout, group_indent))
.def("set_group_indent", &GroupLayout::set_group_indent, D(GroupLayout, set_group_indent))
.def("group_spacing", &GroupLayout::group_spacing, D(GroupLayout, group_spacing))
.def("set_group_spacing", &GroupLayout::set_group_spacing, D(GroupLayout, set_group_spacing));
py::class_<GridLayout, Layout, ref<GridLayout>, PyGridLayout>(m, "GridLayout", D(GridLayout))
.def(py::init<Orientation, int, Alignment, int, int>(),
"orientation"_a = Orientation::Horizontal,
"resolution"_a = 2, "alignment"_a = Alignment::Middle,
"margin"_a = 0, "spacing"_a = 0,
D(GridLayout, GridLayout))
.def("orientation", &GridLayout::orientation, D(GridLayout, orientation))
.def("set_orientation", &GridLayout::set_orientation, D(GridLayout, set_orientation))
.def("resolution", &GridLayout::resolution, D(GridLayout, resolution))
.def("set_resolution", &GridLayout::set_resolution, D(GridLayout, set_resolution))
.def("margin", &GridLayout::margin, D(GridLayout, margin))
.def("set_margin", &GridLayout::set_margin, D(GridLayout, set_margin))
.def("spacing", &GridLayout::spacing, D(GridLayout, spacing))
.def("set_spacing", (void(GridLayout::*)(int)) &GridLayout::set_spacing, D(GridLayout, set_spacing))
.def("set_spacing", (void(GridLayout::*)(int, int)) &GridLayout::set_spacing, D(GridLayout, set_spacing, 2))
.def("alignment", &GridLayout::alignment, D(GridLayout, alignment))
.def("set_col_alignment", (void(GridLayout::*)(Alignment)) &GridLayout::set_col_alignment, D(GridLayout, set_col_alignment))
.def("set_row_alignment", (void(GridLayout::*)(Alignment)) &GridLayout::set_row_alignment, D(GridLayout, set_row_alignment))
.def("set_col_alignment", (void(GridLayout::*)(const std::vector<Alignment>&)) &GridLayout::set_col_alignment/*, D(GridLayout, set_col_alignment, 2)*/)
.def("set_row_alignment", (void(GridLayout::*)(const std::vector<Alignment>&)) &GridLayout::set_row_alignment/*, D(GridLayout, set_row_alignment, 2)*/);
py::class_<AdvancedGridLayout, Layout, ref<AdvancedGridLayout>, PyAdvancedGridLayout> adv_grid_layout(
m, "AdvancedGridLayout", D(AdvancedGridLayout));
adv_grid_layout
.def(py::init<const std::vector<int> &, const std::vector<int> &>(),
"widths"_a, "heights"_a,
D(AdvancedGridLayout, AdvancedGridLayout))
.def("row_count", &AdvancedGridLayout::row_count, D(AdvancedGridLayout, row_count))
.def("col_count", &AdvancedGridLayout::col_count, D(AdvancedGridLayout, col_count))
.def("margin", &AdvancedGridLayout::margin, D(AdvancedGridLayout, margin))
.def("set_margin", &AdvancedGridLayout::set_margin, D(AdvancedGridLayout, set_margin))
.def("append_row", &AdvancedGridLayout::append_row, "size"_a,
"stretch"_a = 0, D(AdvancedGridLayout, append_row))
.def("append_col", &AdvancedGridLayout::append_col, "size"_a,
"stretch"_a = 0, D(AdvancedGridLayout, append_col))
.def("set_row_stretch", &AdvancedGridLayout::set_row_stretch, D(AdvancedGridLayout, set_row_stretch))
.def("set_col_stretch", &AdvancedGridLayout::set_col_stretch, D(AdvancedGridLayout, set_col_stretch))
.def("set_anchor", &AdvancedGridLayout::set_anchor, D(AdvancedGridLayout, set_anchor))
.def("anchor", &AdvancedGridLayout::anchor, D(AdvancedGridLayout, anchor));
py::class_<AdvancedGridLayout::Anchor>(adv_grid_layout, "Anchor")
.def(py::init<int, int, Alignment, Alignment>(),
"x"_a, "y"_a,
"horiz"_a = Alignment::Fill,
"vert"_a = Alignment::Fill,
D(AdvancedGridLayout, Anchor, Anchor, 2))
.def(py::init<int, int, int, int, Alignment, Alignment>(),
"x"_a, "y"_a, "w"_a, "h"_a,
"horiz"_a = Alignment::Fill,
"vert"_a = Alignment::Fill,
D(AdvancedGridLayout, Anchor, Anchor, 3));
}
#endif

View File

@@ -0,0 +1,271 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
#include <thread>
#include <mutex>
#include <condition_variable>
#if defined(__APPLE__) || defined(__linux__)
# include <coro.h>
# include <signal.h>
#endif
#if defined(__APPLE__) || defined(__linux__)
namespace {
class semaphore {
public:
semaphore(int count = 0) : count(count) { }
void notify() {
std::unique_lock<std::mutex> lck(mtx);
++count;
cv.notify_one();
}
void wait() {
std::unique_lock<std::mutex> lck(mtx);
while (count == 0)
cv.wait(lck);
--count;
}
private:
std::mutex mtx;
std::condition_variable cv;
int count;
};
}
#endif
extern void register_vector(py::module &m);
extern void register_glfw(py::module &m);
extern void register_entypo(py::module &m);
extern void register_eigen(py::module &m);
extern void register_widget(py::module &m);
extern void register_layout(py::module &m);
extern void register_basics(py::module &m);
extern void register_button(py::module &m);
extern void register_tabs(py::module &m);
extern void register_textbox(py::module &m);
extern void register_textarea(py::module &m);
extern void register_theme(py::module &m);
extern void register_canvas(py::module &m);
extern void register_formhelper(py::module &m);
extern void register_misc(py::module &m);
extern void register_nanovg(py::module &m);
extern void register_render(py::module &m);
class MainloopHandle;
static MainloopHandle *handle = nullptr;
class MainloopHandle {
public:
bool active = false;
bool detached = false;
float refresh = 0;
std::thread thread;
#if defined(__APPLE__) || defined(__linux__)
coro_context ctx_helper, ctx_main, ctx_thread;
coro_stack stack;
semaphore sema;
#endif
~MainloopHandle() {
join();
handle = nullptr;
}
void join() {
if (!detached)
return;
#if defined(__APPLE__) || defined(__linux__)
/* Release GIL and disassociate from thread state (which was originally
associated with the main Python thread) */
py::gil_scoped_release thread_state(true);
coro_transfer(&ctx_main, &ctx_thread);
coro_stack_free(&stack);
/* Destroy the thread state that was created in mainloop() */
{
py::gil_scoped_acquire acquire;
acquire.dec_ref();
}
#endif
thread.join();
detached = false;
#if defined(__APPLE__) || defined(__linux__)
/* Reacquire GIL and reassociate with thread state
[via RAII destructor in 'thread_state'] */
#endif
}
};
#if defined(__APPLE__) || defined(__linux__)
static void (*sigint_handler_prev)(int) = nullptr;
static void sigint_handler(int sig) {
nanogui::leave();
signal(sig, sigint_handler_prev);
raise(sig);
}
#endif
PYBIND11_MODULE(nanogui, m) {
m.attr("__doc__") = "NanoGUI plugin";
#if defined(NANOGUI_USE_OPENGL)
m.attr("api") = "opengl";
#elif defined(NANOGUI_USE_GLES) && NANOGUI_GLES_VERSION == 2
m.attr("api") = "gles2";
#elif defined(NANOGUI_USE_GLES) && NANOGUI_GLES_VERSION == 3
m.attr("api") = "gles3";
#elif defined(NANOGUI_USE_METAL)
m.attr("api") = "metal";
#endif
py::class_<MainloopHandle>(m, "MainloopHandle")
.def("join", &MainloopHandle::join);
m.def("init", &nanogui::init, D(init));
m.def("shutdown", &nanogui::shutdown, D(shutdown));
m.def("mainloop", [](float refresh, py::object detach) -> MainloopHandle* {
if (!detach.is(py::none())) {
if (handle)
throw std::runtime_error("Main loop is already running!");
handle = new MainloopHandle();
handle->detached = true;
handle->refresh = refresh;
#if defined(__APPLE__) || defined(__linux__)
/* Release GIL and completely disassociate the calling thread
from its associated Python thread state data structure */
py::gil_scoped_release thread_state(true);
/* Create a new thread state for the nanogui main loop
and reference it once (to keep it from being constructed and
destructed at every callback invocation) */
{
py::gil_scoped_acquire acquire;
acquire.inc_ref();
}
handle->thread = std::thread([]{
/* Handshake 1: wait for signal from detach_helper */
handle->sema.wait();
/* Swap context with main thread */
coro_transfer(&handle->ctx_thread, &handle->ctx_main);
/* Handshake 2: wait for signal from detach_helper */
handle->sema.notify();
});
void (*detach_helper)(void *) = [](void *ptr) -> void {
MainloopHandle *handle = (MainloopHandle *) ptr;
/* Handshake 1: Send signal to new thread */
handle->sema.notify();
/* Enter main loop */
sigint_handler_prev = signal(SIGINT, sigint_handler);
mainloop(handle->refresh);
signal(SIGINT, sigint_handler_prev);
/* Handshake 2: Wait for signal from new thread */
handle->sema.wait();
/* Return back to Python */
coro_transfer(&handle->ctx_helper, &handle->ctx_main);
};
/* Allocate an 8MB stack and transfer context to the
detach_helper function */
coro_stack_alloc(&handle->stack, 8 * 1024 * 1024);
coro_create(&handle->ctx_helper, detach_helper, handle,
handle->stack.sptr, handle->stack.ssze);
coro_transfer(&handle->ctx_main, &handle->ctx_helper);
#else
handle->thread = std::thread([]{
mainloop(handle->refresh);
});
#endif
#if defined(__APPLE__) || defined(__linux__)
/* Reacquire GIL and reassociate with thread state on newly
created thread [via RAII destructor in 'thread_state'] */
#endif
return handle;
} else {
py::gil_scoped_release release;
#if defined(__APPLE__) || defined(__linux__)
sigint_handler_prev = signal(SIGINT, sigint_handler);
#endif
mainloop(refresh);
#if defined(__APPLE__) || defined(__linux__)
signal(SIGINT, sigint_handler_prev);
#endif
return nullptr;
}
}, "refresh"_a = -1, "detach"_a = py::none(),
D(mainloop), py::keep_alive<0, 2>());
m.def("async", &nanogui::async, D(async));
m.def("leave", &nanogui::leave, D(leave));
m.def("active", &nanogui::active, D(active));
m.def("file_dialog", (std::string(*)(const std::vector<std::pair<std::string, std::string>> &, bool)) &nanogui::file_dialog, D(file_dialog));
m.def("file_dialog", (std::vector<std::string>(*)(const std::vector<std::pair<std::string, std::string>> &, bool, bool)) &nanogui::file_dialog, D(file_dialog, 2));
#if defined(__APPLE__)
m.def("chdir_to_bundle_parent", &nanogui::chdir_to_bundle_parent);
#endif
m.def("utf8", [](int c) { return std::string(utf8(c).data()); }, D(utf8));
m.def("load_image_directory", &nanogui::load_image_directory, D(load_image_directory));
py::enum_<Cursor>(m, "Cursor", D(Cursor))
.value("Arrow", Cursor::Arrow)
.value("IBeam", Cursor::IBeam)
.value("Crosshair", Cursor::Crosshair)
.value("Hand", Cursor::Hand)
.value("HResize", Cursor::HResize)
.value("VResize", Cursor::VResize);
py::enum_<Alignment>(m, "Alignment", D(Alignment))
.value("Minimum", Alignment::Minimum)
.value("Middle", Alignment::Middle)
.value("Maximum", Alignment::Maximum)
.value("Fill", Alignment::Fill);
py::enum_<Orientation>(m, "Orientation", D(Orientation))
.value("Horizontal", Orientation::Horizontal)
.value("Vertical", Orientation::Vertical);
register_vector(m);
register_glfw(m);
register_entypo(m);
register_eigen(m);
register_widget(m);
register_layout(m);
register_basics(m);
register_button(m);
register_tabs(m);
register_textbox(m);
register_textarea(m);
register_theme(m);
register_canvas(m);
register_formhelper(m);
register_misc(m);
register_nanovg(m);
register_render(m);
}
#endif

View File

@@ -0,0 +1,57 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
DECLARE_WIDGET(ColorWheel);
DECLARE_WIDGET(ColorPicker);
DECLARE_WIDGET(Graph);
DECLARE_WIDGET(ImagePanel);
void register_misc(py::module &m) {
py::class_<ColorWheel, Widget, ref<ColorWheel>, PyColorWheel>(m, "ColorWheel", D(ColorWheel))
.def(py::init<Widget *>(), "parent"_a, D(ColorWheel, ColorWheel))
.def(py::init<Widget *, const Color &>(), "parent"_a, "Color"_a)
.def("color", &ColorWheel::color, D(ColorWheel, color))
.def("set_color", &ColorWheel::set_color, D(ColorWheel, set_color))
.def("callback", &ColorWheel::callback, D(ColorWheel, callback))
.def("set_callback", &ColorWheel::set_callback, D(ColorWheel, set_callback));
py::class_<ColorPicker, PopupButton, ref<ColorPicker>, PyColorPicker>(m, "ColorPicker", D(ColorPicker))
.def(py::init<Widget *>(), "parent"_a, D(ColorPicker, ColorPicker))
.def(py::init<Widget *, const Color &>(), "parent"_a, "Color"_a)
.def("color", &ColorPicker::color, D(ColorPicker, color))
.def("set_color", &ColorPicker::set_color, D(ColorPicker, set_color))
.def("callback", &ColorPicker::callback, D(ColorPicker, callback))
.def("set_callback", &ColorPicker::set_callback, D(ColorPicker, set_callback))
.def("final_callback", &ColorPicker::final_callback, D(ColorPicker, final_callback))
.def("set_final_callback", &ColorPicker::set_final_callback, D(ColorPicker, set_final_callback));
py::class_<Graph, Widget, ref<Graph>, PyGraph>(m, "Graph", D(Graph))
.def(py::init<Widget *, const std::string &>(), "parent"_a,
"caption"_a = std::string("Untitled"), D(Graph, Graph))
.def("caption", &Graph::caption, D(Graph, caption))
.def("set_caption", &Graph::set_caption, D(Graph, set_caption))
.def("header", &Graph::header, D(Graph, header))
.def("set_header", &Graph::set_header, D(Graph, set_header))
.def("footer", &Graph::footer, D(Graph, footer))
.def("set_footer", &Graph::set_footer, D(Graph, set_footer))
.def("background_color", &Graph::background_color, D(Graph, background_color))
.def("set_background_color", &Graph::set_background_color, D(Graph, set_background_color))
.def("fill_color", &Graph::fill_color, D(Graph, fill_color))
.def("set_fill_color", &Graph::set_fill_color, D(Graph, set_fill_color))
.def("stroke_color", &Graph::stroke_color, D(Graph, stroke_color))
.def("set_stroke_color", &Graph::set_stroke_color, D(Graph, set_stroke_color))
.def("text_color", &Graph::text_color, D(Graph, text_color))
.def("set_text_color", &Graph::set_text_color, D(Graph, set_text_color))
.def("values", (std::vector<float> &(Graph::*)(void)) &Graph::values, D(Graph, values))
.def("set_values", &Graph::set_values, D(Graph, set_values));
py::class_<ImagePanel, Widget, ref<ImagePanel>, PyImagePanel>(m, "ImagePanel", D(ImagePanel))
.def(py::init<Widget *>(), "parent"_a, D(ImagePanel, ImagePanel))
.def("images", &ImagePanel::images, D(ImagePanel, images))
.def("set_images", &ImagePanel::set_images, D(ImagePanel, set_images))
.def("callback", &ImagePanel::callback, D(ImagePanel, callback))
.def("set_callback", &ImagePanel::set_callback, D(ImagePanel, set_callback));
}
#endif

View File

@@ -0,0 +1,192 @@
#include "python.h"
using namespace pybind11::literals;
void register_nanovg(py::module &m) {
/* NanoVG */
/* To be done: docstrings, functions taking memory arguments (fonts, images) */
py::module nvg = m.def_submodule("nanovg", "NanoVG bindings");
py::enum_<NVGwinding>(nvg, "NVGwinding")
.value("CCW", NVG_CCW)
.value("CW", NVG_CW)
.export_values();
py::enum_<NVGsolidity>(nvg, "NVGsolidity")
.value("SOLID", NVG_SOLID)
.value("HOLE", NVG_HOLE)
.export_values();
py::enum_<NVGlineCap>(nvg, "NVGlineCap")
.value("BUTT", NVG_BUTT)
.value("ROUND", NVG_ROUND)
.value("SQUARE", NVG_SQUARE)
.value("BEVEL", NVG_BEVEL)
.value("MITER", NVG_MITER)
.export_values();
py::enum_<NVGalign>(nvg, "NVGalign")
.value("ALIGN_LEFT", NVG_ALIGN_LEFT)
.value("ALIGN_CENTER", NVG_ALIGN_CENTER)
.value("ALIGN_RIGHT", NVG_ALIGN_RIGHT)
.value("ALIGN_TOP", NVG_ALIGN_TOP)
.value("ALIGN_MIDDLE", NVG_ALIGN_MIDDLE)
.value("ALIGN_BOTTOM", NVG_ALIGN_BOTTOM)
.value("ALIGN_BASELINE", NVG_ALIGN_BASELINE)
.export_values();
py::enum_<NVGblendFactor>(nvg, "NVGblendFactor")
.value("ZERO", NVG_ZERO)
.value("ONE", NVG_ONE)
.value("SRC_COLOR", NVG_SRC_COLOR)
.value("ONE_MINUS_SRC_COLOR", NVG_ONE_MINUS_SRC_COLOR)
.value("DST_COLOR", NVG_DST_COLOR)
.value("ONE_MINUS_DST_COLOR", NVG_ONE_MINUS_DST_COLOR)
.value("SRC_ALPHA", NVG_SRC_ALPHA)
.value("ONE_MINUS_SRC_ALPHA", NVG_ONE_MINUS_SRC_ALPHA)
.value("DST_ALPHA", NVG_DST_ALPHA)
.value("ONE_MINUS_DST_ALPHA", NVG_ONE_MINUS_DST_ALPHA)
.value("SRC_ALPHA_SATURATE", NVG_SRC_ALPHA_SATURATE)
.export_values();
py::enum_<NVGcompositeOperation>(nvg, "NVGcompositeOperation")
.value("SOURCE_OVER", NVG_SOURCE_OVER)
.value("SOURCE_IN", NVG_SOURCE_IN)
.value("SOURCE_OUT", NVG_SOURCE_OUT)
.value("ATOP", NVG_ATOP)
.value("DESTINATION_OVER", NVG_DESTINATION_OVER)
.value("DESTINATION_IN", NVG_DESTINATION_IN)
.value("DESTINATION_OUT", NVG_DESTINATION_OUT)
.value("DESTINATION_ATOP", NVG_DESTINATION_ATOP)
.value("LIGHTER", NVG_LIGHTER)
.value("COPY", NVG_COPY)
.value("XOR", NVG_XOR)
.export_values();
py::class_<NVGpaint>(nvg, "NVGpaint");
py::class_<NVGcolor>(nvg, "NVGcolor")
.def(py::init([](const Color &c) { return new NVGcolor(c); }));
py::implicitly_convertible<Color, NVGcolor>();
nvg.def("RGB", &nvgRGB);
nvg.def("RGBf", &nvgRGBf);
nvg.def("RGBA", &nvgRGBA);
nvg.def("RGBAf", &nvgRGBAf);
nvg.def("LerpRGBA", &nvgLerpRGBA);
nvg.def("TransRGBA", &nvgTransRGBA);
nvg.def("TransRGBAf", &nvgTransRGBAf);
nvg.def("HSL", &nvgHSL);
nvg.def("HSLA", &nvgHSLA);
//nvg.def("TextGlyphPositions", &nvgTextBounds);
//nvg.def("TextGlyphMetrics", &nvgTextBounds);
//nvg.def("TextTextBreakLines", &nvgTextBounds);
py::class_<NVGcontext>(nvg, "NVGcontext")
.def("GlobalCompositeOperation", &nvgGlobalCompositeOperation,
"factor"_a)
.def("GlobalCompositeBlendFunc", &nvgGlobalCompositeBlendFunc,
"sfactor"_a, "dfactor"_a)
.def("GlobalCompositeBlendFuncSeparate",
&nvgGlobalCompositeBlendFuncSeparate, "srcRGB"_a, "dstRGB"_a,
"srcAlpha"_a, "dstAlpha"_a)
.def("Save", &nvgSave)
.def("Restore", &nvgRestore)
.def("Reset", &nvgReset)
.def("StrokeColor", &nvgStrokeColor, "color"_a)
.def("StrokePaint", &nvgStrokePaint, "paint"_a)
.def("FillColor", &nvgFillColor, "color"_a)
.def("FillPaint", &nvgFillPaint, "paint"_a)
.def("MiterLimit", &nvgMiterLimit, "limit"_a)
.def("StrokeWidth", &nvgStrokeWidth, "size"_a)
.def("LineCap", &nvgLineCap, "cap"_a)
.def("LineJoin", &nvgLineJoin, "join"_a)
.def("GlobalAlpha", &nvgGlobalAlpha, "alpha"_a)
.def("ResetTransform", &nvgResetTransform)
.def("Transform", &nvgTransform, "a"_a, "b"_a, "c"_a, "d"_a, "e"_a,
"f"_a)
.def("Translate", &nvgTranslate, "x"_a, "y"_a)
.def("Rotate", &nvgRotate, "angle"_a)
.def("SkewX", &nvgSkewX, "angle"_a)
.def("SkewY", &nvgSkewY, "angle"_a)
.def("Scale", &nvgScale, "x"_a, "y"_a)
.def("CreateImage", &nvgCreateImage, "filename"_a, "imageFlags"_a)
.def("DeleteImage", &nvgDeleteImage, "image"_a)
.def("LinearGradient", &nvgLinearGradient, "sx"_a, "sy"_a, "ex"_a,
"ey"_a, "icol"_a, "ocol"_a)
.def("BoxGradient", &nvgBoxGradient, "x"_a, "y"_a, "w"_a, "h"_a, "r"_a,
"f"_a, "icol"_a, "ocol"_a)
.def("RadialGradient", &nvgRadialGradient, "cx"_a, "cy"_a, "inr"_a,
"outr"_a, "icol"_a, "ocol"_a)
.def("ImagePattern", &nvgImagePattern, "ox"_a, "oy"_a, "ex"_a, "ey"_a,
"angle"_a, "image"_a, "alpha"_a)
.def("Scissor", &nvgScissor, "x"_a, "y"_a, "w"_a, "h"_a)
.def("IntersectScissor", &nvgIntersectScissor, "x"_a, "y"_a, "w"_a,
"h"_a)
.def("ResetScissor", &nvgResetScissor)
.def("BeginPath", &nvgBeginPath)
.def("MoveTo", &nvgMoveTo, "x"_a, "y"_a)
.def("LineTo", &nvgLineTo, "x"_a, "y"_a)
.def("BezierTo", &nvgBezierTo, "c1x"_a, "c1y"_a, "c2x"_a, "c2y"_a,
"x"_a, "y"_a)
.def("QuadTo", &nvgQuadTo, "cx"_a, "cy"_a, "x"_a, "y"_a)
.def("ArcTo", &nvgArcTo, "x1"_a, "y1"_a, "x2"_a, "y2"_a, "radius"_a)
.def("ClosePath", &nvgClosePath)
.def("PathWinding", &nvgPathWinding, "dir"_a)
.def("Arc", &nvgArc, "cx"_a, "cy"_a, "r"_a, "a0"_a, "a1"_a, "dir"_a)
.def("Rect", &nvgRect, "x"_a, "y"_a, "w"_a, "h"_a)
.def("RoundedRect", &nvgRoundedRect, "x"_a, "y"_a, "w"_a, "h"_a, "r"_a)
.def("RoundedRectVarying", &nvgRoundedRectVarying, "x"_a, "y"_a, "w"_a,
"h"_a, "radTopLeft"_a, "radTopRight"_a, "radBottomRight"_a,
"radBottomLeft"_a)
.def("Ellipse", &nvgEllipse, "cx"_a, "cy"_a, "rx"_a, "ry"_a)
.def("Circle", &nvgCircle, "cx"_a, "cy"_a, "r"_a)
.def("Fill", &nvgFill)
.def("Stroke", &nvgStroke)
.def("CreateFont", &nvgCreateFont, "name"_a, "filename"_a)
.def("FindFont", &nvgFindFont, "name"_a)
.def("AddFallbackFontId", &nvgAddFallbackFontId, "baseFont"_a,
"fallbackFont"_a)
.def("AddFallbackFont", &nvgAddFallbackFont, "baseFont"_a,
"fallbackFont"_a)
.def("FontSize", &nvgFontSize, "size"_a)
.def("FontBlur", &nvgFontBlur, "blur"_a)
.def("TextLetterSpacing", &nvgTextLetterSpacing, "spacing"_a)
.def("TextLineHeight", &nvgTextLineHeight, "lineHeight"_a)
.def("TextAlign", &nvgTextAlign, "align"_a)
.def("FontFaceId", &nvgFontFaceId, "font"_a)
.def("FontFace", &nvgFontFace, "font"_a)
.def("Text", [](NVGcontext *ctx, float x, float y,
const char *str) { nvgText(ctx, x, y, str, nullptr); },
"x"_a, "y"_a, "string"_a)
.def("TextBounds",
[](NVGcontext *ctx, float x, float y, const char *str) {
float bounds[4];
nvgTextBounds(ctx, x, y, str, nullptr, bounds);
return std::make_tuple(bounds[0], bounds[1], bounds[2], bounds[3]);
}, "x"_a, "y"_a, "string"_a)
.def("TextBox",
[](NVGcontext *ctx, float x, float y, float breakRowWidth,
const char *str) {
nvgTextBox(ctx, x, y, breakRowWidth, str, nullptr);
},
"x"_a, "y"_a, "breakRowWidth"_a, "string"_a)
.def("TextBoxBounds",
[](NVGcontext *ctx, float x, float y, float breakRowWidth,
const char *str) {
float bounds[4];
nvgTextBoxBounds(ctx, x, y, breakRowWidth, str, nullptr, bounds);
return std::make_tuple(bounds[0], bounds[1], bounds[2], bounds[3]);
},
"x"_a, "y"_a, "breakRowWidth"_a, "string"_a)
.def("BeginFrame", &nvgBeginFrame, "windowWidth"_a, "windowHeight"_a,
"devicePixelRatio"_a)
.def("CancelFrame", &nvgCancelFrame)
.def("EndFrame", &nvgEndFrame);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
#pragma once
#if defined(_MSC_VER)
# pragma warning (disable:5033) // 'register' is no longer a supported storage class
#endif
#include <nanogui/nanogui.h>
#include <nanogui/opengl.h>
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <nanogui/python.h>
#include "py_doc.h"
PYBIND11_MAKE_OPAQUE(nanogui::Color)
#define D(...) DOC(nanogui, __VA_ARGS__ )
#define DECLARE_LAYOUT(Name) \
class Py##Name : public Name { \
public: \
using Name::Name; \
NANOGUI_LAYOUT_OVERLOADS(Name); \
}
#define DECLARE_WIDGET(Name) \
class Py##Name : public Name { \
public: \
using Name::Name; \
NANOGUI_WIDGET_OVERLOADS(Name); \
}
#define DECLARE_SCREEN(Name) \
class Py##Name : public Name { \
public: \
using Name::Name; \
NANOGUI_WIDGET_OVERLOADS(Name); \
NANOGUI_SCREEN_OVERLOADS(Name); \
}
using namespace nanogui;
namespace py = pybind11;
using namespace py::literals;
/// Make pybind aware of the ref-counted wrapper type
PYBIND11_DECLARE_HOLDER_TYPE(T, ref<T>);

View File

@@ -0,0 +1,279 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
#include <pybind11/numpy.h>
static VariableType dtype_to_enoki(const py::dtype &dtype) {
switch (dtype.kind()) {
case 'i':
switch (dtype.itemsize()) {
case 1: return VariableType::Int8;
case 2: return VariableType::Int16;
case 4: return VariableType::Int32;
case 8: return VariableType::Int64;
default: break;
}
break;
case 'u':
switch (dtype.itemsize()) {
case 1: return VariableType::UInt8;
case 2: return VariableType::UInt16;
case 4: return VariableType::UInt32;
case 8: return VariableType::UInt64;
default: break;
}
break;
case 'f':
switch (dtype.itemsize()) {
case 2: return VariableType::Float16;
case 4: return VariableType::Float32;
case 8: return VariableType::Float64;
default: break;
}
break;
default:
break;
}
return VariableType::Invalid;
}
static void shader_set_buffer(Shader &shader, const std::string &name, py::array array) {
if (array.ndim() > 3)
throw py::type_error("Shader::set_buffer(): tensor rank must be < 3!");
array = py::array::ensure(array, py::array::c_style);
VariableType dtype = dtype_to_enoki(array.dtype());
if (dtype == VariableType::Invalid)
throw py::type_error("Shader::set_buffer(): unsupported array dtype!");
size_t dim[3] {
array.ndim() > 0 ? (size_t) array.shape(0) : 1,
array.ndim() > 1 ? (size_t) array.shape(1) : 1,
array.ndim() > 2 ? (size_t) array.shape(2) : 1
};
shader.set_buffer(name, dtype, array.ndim(), dim, array.data());
}
static py::array texture_download(Texture &texture) {
const char *dtype_name;
switch (texture.component_format()) {
case Texture::ComponentFormat::UInt8: dtype_name = "u1"; break;
case Texture::ComponentFormat::Int8: dtype_name = "i1"; break;
case Texture::ComponentFormat::UInt16: dtype_name = "u2"; break;
case Texture::ComponentFormat::Int16: dtype_name = "i2"; break;
case Texture::ComponentFormat::UInt32: dtype_name = "u4"; break;
case Texture::ComponentFormat::Int32: dtype_name = "i4"; break;
case Texture::ComponentFormat::Float16: dtype_name = "f2"; break;
case Texture::ComponentFormat::Float32: dtype_name = "f4"; break;
default:
throw std::runtime_error("Invalid component format");
}
py::array result(
py::dtype(dtype_name),
std::vector<ssize_t> { texture.size().y(), texture.size().x(),
(ssize_t) texture.channels() },
std::vector<ssize_t> { }
);
texture.download((uint8_t *) result.mutable_data());
return result;
}
static void texture_upload(Texture &texture, py::array array) {
size_t n_channels = array.ndim() == 3 ? array.shape(2) : 1;
VariableType dtype = dtype_to_enoki(array.dtype()),
dtype_texture = (VariableType) texture.component_format();
if (array.ndim() != 2 && array.ndim() != 3)
throw std::runtime_error("Texture::upload(): expected a 2 or 3-dimensional array!");
else if (array.shape(0) != texture.size().y() ||
array.shape(1) != texture.size().x())
throw std::runtime_error("Texture::upload(): array size does not match the texture!");
else if (n_channels != texture.channels())
throw std::runtime_error(
std::string("Texture::upload(): number of color channels in array (") +
std::to_string(n_channels) + ") does not match the texture (" +
std::to_string(texture.channels()) + ")!");
else if (dtype != dtype_texture)
throw std::runtime_error(
std::string("Texture::upload(): dtype of array (") +
type_name(dtype) + ") does not match the texture (" +
type_name(dtype_texture) + ")!");
texture.upload((const uint8_t *) array.data());
}
void register_render(py::module &m) {
using PixelFormat = Texture::PixelFormat;
using ComponentFormat = Texture::ComponentFormat;
using InterpolationMode = Texture::InterpolationMode;
using WrapMode = Texture::WrapMode;
using TextureFlags = Texture::TextureFlags;
using PrimitiveType = Shader::PrimitiveType;
using BlendMode = Shader::BlendMode;
using DepthTest = RenderPass::DepthTest;
using CullMode = RenderPass::CullMode;
auto texture = py::class_<Texture, Object, ref<Texture>>(m, "Texture", D(Texture));
py::enum_<PixelFormat>(texture, "PixelFormat", D(Texture, PixelFormat))
.value("R", PixelFormat::R, D(Texture, PixelFormat, R))
.value("RA", PixelFormat::RA, D(Texture, PixelFormat, RA))
.value("RGB", PixelFormat::RGB, D(Texture, PixelFormat, RGB))
.value("RGBA", PixelFormat::RGBA, D(Texture, PixelFormat, RGBA))
.value("BGR", PixelFormat::BGR, D(Texture, PixelFormat, BGR))
.value("BGRA", PixelFormat::BGRA, D(Texture, PixelFormat, BGRA))
.value("Depth", PixelFormat::Depth, D(Texture, PixelFormat, Depth))
.value("DepthStencil", PixelFormat::DepthStencil, D(Texture, PixelFormat, DepthStencil));
py::enum_<ComponentFormat>(texture, "ComponentFormat", D(Texture, ComponentFormat))
.value("UInt8", ComponentFormat::UInt8, D(Texture, ComponentFormat, UInt8))
.value("Int8", ComponentFormat::Int8, D(Texture, ComponentFormat, Int8))
.value("UInt16", ComponentFormat::UInt16, D(Texture, ComponentFormat, UInt16))
.value("Int16", ComponentFormat::Int16, D(Texture, ComponentFormat, Int16))
.value("UInt32", ComponentFormat::UInt32, D(Texture, ComponentFormat, UInt32))
.value("Int32", ComponentFormat::Int32, D(Texture, ComponentFormat, Int32))
.value("Float16", ComponentFormat::Float16, D(Texture, ComponentFormat, Float16))
.value("Float32", ComponentFormat::Float32, D(Texture, ComponentFormat, Float32));
py::enum_<InterpolationMode>(texture, "InterpolationMode", D(Texture, InterpolationMode))
.value("Nearest", InterpolationMode::Nearest, D(Texture, InterpolationMode, Nearest))
.value("Bilinear", InterpolationMode::Bilinear, D(Texture, InterpolationMode, Bilinear))
.value("Trilinear", InterpolationMode::Trilinear, D(Texture, InterpolationMode, Trilinear));
py::enum_<WrapMode>(texture, "WrapMode", D(Texture, WrapMode))
.value("ClampToEdge", WrapMode::ClampToEdge, D(Texture, WrapMode, ClampToEdge))
.value("Repeat", WrapMode::Repeat, D(Texture, WrapMode, Repeat))
.value("MirrorRepeat", WrapMode::MirrorRepeat, D(Texture, WrapMode, MirrorRepeat));
py::enum_<TextureFlags>(texture, "TextureFlags", D(Texture, TextureFlags), py::arithmetic())
.value("ShaderRead", TextureFlags::ShaderRead, D(Texture, TextureFlags, ShaderRead))
.value("RenderTarget", TextureFlags::RenderTarget, D(Texture, TextureFlags, RenderTarget));
texture
.def(py::init<PixelFormat, ComponentFormat, const Vector2i &,
InterpolationMode, InterpolationMode, WrapMode, uint8_t, uint8_t>(),
D(Texture, Texture), "pixel_format"_a, "component_format"_a, "size"_a,
"min_interpolation_mode"_a = InterpolationMode::Bilinear,
"mag_interpolation_mode"_a = InterpolationMode::Bilinear,
"wrap_mode"_a = WrapMode::ClampToEdge, "samples"_a = 1,
"flags"_a = (uint8_t) TextureFlags::ShaderRead)
.def(py::init<const std::string &, InterpolationMode, InterpolationMode, WrapMode>(),
D(Texture, Texture, 2), "filename"_a,
"min_interpolation_mode"_a = InterpolationMode::Bilinear,
"mag_interpolation_mode"_a = InterpolationMode::Bilinear,
"wrap_mode"_a = WrapMode::ClampToEdge)
.def("pixel_format", &Texture::pixel_format, D(Texture, pixel_format))
.def("component_format", &Texture::component_format, D(Texture, component_format))
.def("min_interpolation_mode", &Texture::min_interpolation_mode, D(Texture, min_interpolation_mode))
.def("mag_interpolation_mode", &Texture::mag_interpolation_mode, D(Texture, mag_interpolation_mode))
.def("wrap_mode", &Texture::wrap_mode, D(Texture, wrap_mode))
.def("samples", &Texture::samples, D(Texture, samples))
.def("flags", &Texture::flags, D(Texture, flags))
.def("size", &Texture::size, D(Texture, size))
.def("bytes_per_pixel", &Texture::bytes_per_pixel, D(Texture, bytes_per_pixel))
.def("channels", &Texture::channels, D(Texture, channels))
.def("download", &texture_download, D(Texture, download))
.def("upload", &texture_upload, D(Texture, upload))
.def("resize", &Texture::resize, D(Texture, resize))
#if defined(NANOGUI_USE_OPENGL) || defined(NANOGUI_USE_GLES)
.def("texture_handle", &Texture::texture_handle)
.def("renderbuffer_handle", &Texture::renderbuffer_handle)
#elif defined(NANOGUI_USE_METAL)
.def("texture_handle", &Texture::texture_handle)
.def("sampler_state_handle", &Texture::sampler_state_handle)
#endif
;
auto shader = py::class_<Shader, Object, ref<Shader>>(m, "Shader", D(Shader));
py::enum_<BlendMode>(shader, "BlendMode", D(Shader, BlendMode))
.value("None", BlendMode::None, D(Shader, BlendMode, None))
.value("AlphaBlend", BlendMode::AlphaBlend, D(Shader, BlendMode, AlphaBlend));
shader
.def(py::init<RenderPass *, const std::string &,
const std::string &, const std::string &, Shader::BlendMode>(),
D(Shader, Shader), "render_pass"_a, "name"_a, "vertex_shader"_a,
"fragment_shader"_a, "blend_mode"_a = BlendMode::None)
.def("name", &Shader::name, D(Shader, name))
.def("blend_mode", &Shader::blend_mode, D(Shader, blend_mode))
.def("set_buffer", &shader_set_buffer, D(Shader, set_buffer))
.def("set_texture", &Shader::set_texture, D(Shader, set_texture))
.def("begin", &Shader::begin, D(Shader, begin))
.def("end", &Shader::end, D(Shader, end))
.def("__enter__", &Shader::begin)
.def("__exit__", [](Shader &s, py::handle, py::handle, py::handle) { s.end(); })
.def("draw_array", &Shader::draw_array, D(Shader, draw_array),
"primitive_type"_a, "offset"_a, "count"_a, "indexed"_a = false)
#if defined(NANOGUI_USE_OPENGL) || defined(NANOGUI_USE_GLES)
.def("shader_handle", &Shader::shader_handle)
#elif defined(NANOGUI_USE_METAL)
.def("pipeline_state", &Shader::pipeline_state)
#endif
#if defined(NANOGUI_USE_OPENGL)
.def("vertex_array_handle", &Shader::vertex_array_handle)
#endif
;
py::enum_<PrimitiveType>(shader, "PrimitiveType", D(Shader, PrimitiveType))
.value("Point", PrimitiveType::Point, D(Shader, PrimitiveType, Point))
.value("Line", PrimitiveType::Line, D(Shader, PrimitiveType, Line))
.value("LineStrip", PrimitiveType::LineStrip, D(Shader, PrimitiveType, LineStrip))
.value("Triangle", PrimitiveType::Triangle, D(Shader, PrimitiveType, Triangle))
.value("TriangleStrip", PrimitiveType::TriangleStrip, D(Shader, PrimitiveType, TriangleStrip));
auto renderpass = py::class_<RenderPass, Object, ref<RenderPass>>(m, "RenderPass", D(RenderPass))
.def(py::init<std::vector<Object *>, Object *, Object *, Object *, bool>(),
D(RenderPass, RenderPass), "color_targets"_a, "depth_target"_a = nullptr,
"stencil_target"_a = nullptr, "blit_target"_a = nullptr, "clear"_a = true)
.def("set_clear_color", &RenderPass::set_clear_color, D(RenderPass, set_clear_color))
.def("clear_color", &RenderPass::clear_color, D(RenderPass, clear_color))
.def("set_clear_depth", &RenderPass::set_clear_depth, D(RenderPass, set_clear_depth))
.def("clear_depth", &RenderPass::clear_depth, D(RenderPass, clear_depth))
.def("set_clear_stencil", &RenderPass::set_clear_stencil, D(RenderPass, set_clear_stencil))
.def("clear_stencil", &RenderPass::clear_stencil, D(RenderPass, clear_stencil))
.def("set_viewport", &RenderPass::set_viewport, D(RenderPass, set_viewport), "offset"_a, "size"_a)
.def("viewport", &RenderPass::viewport, D(RenderPass, viewport))
.def("set_depth_test", &RenderPass::set_depth_test, D(RenderPass, set_depth_test), "depth_test"_a, "depth_write"_a)
.def("depth_test", &RenderPass::depth_test, D(RenderPass, depth_test))
.def("set_cull_mode", &RenderPass::set_cull_mode, D(RenderPass, set_cull_mode))
.def("cull_mode", &RenderPass::cull_mode, D(RenderPass, cull_mode))
.def("begin", &RenderPass::begin, D(RenderPass, begin))
.def("end", &RenderPass::end, D(RenderPass, end))
.def("resize", &RenderPass::resize, D(RenderPass, resize))
.def("blit_to", &RenderPass::blit_to, D(RenderPass, blit_to),
"src_offset"_a, "src_size"_a, "dst"_a, "dst_offset"_a)
.def("__enter__", &RenderPass::begin)
.def("__exit__", [](RenderPass &rp, py::handle, py::handle, py::handle) { rp.end(); })
#if defined(NANOGUI_USE_OPENGL) || defined(NANOGUI_USE_GLES)
.def("framebuffer_handle", &RenderPass::framebuffer_handle)
#elif defined(NANOGUI_USE_METAL)
.def("command_encoder", &RenderPass::command_encoder)
#endif
;
py::enum_<CullMode>(renderpass, "CullMode", D(RenderPass, CullMode))
.value("Disabled", CullMode::Disabled, D(RenderPass, CullMode, Disabled))
.value("Front", CullMode::Front, D(RenderPass, CullMode, Front))
.value("Back", CullMode::Back, D(RenderPass, CullMode, Back));
py::enum_<DepthTest>(renderpass, "DepthTest", D(RenderPass, DepthTest))
.value("Never", DepthTest::Never, D(RenderPass, DepthTest, Never))
.value("Less", DepthTest::Less, D(RenderPass, DepthTest, Less))
.value("Equal", DepthTest::Equal, D(RenderPass, DepthTest, Equal))
.value("LessEqual", DepthTest::LessEqual, D(RenderPass, DepthTest, LessEqual))
.value("Greater", DepthTest::Greater, D(RenderPass, DepthTest, Greater))
.value("NotEqual", DepthTest::NotEqual, D(RenderPass, DepthTest, NotEqual))
.value("GreaterEqual", DepthTest::GreaterEqual, D(RenderPass, DepthTest, GreaterEqual))
.value("Always", DepthTest::Always, D(RenderPass, DepthTest, Always));
}
#endif

View File

@@ -0,0 +1,99 @@
# OpenGL/Metal rendering test: render a red triangle to a texture
# and save it to a PNG file
import sys
sys.path.append('python')
import nanogui
from nanogui import Shader, Texture, RenderPass, Screen
import numpy as np
from PIL import Image
nanogui.init()
if nanogui.api == 'opengl':
s = Screen([16, 16], "Unnamed")
vertex_program = '''
#version 330
in vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
'''
fragment_program = '''
#version 330
uniform vec4 color;
out vec4 fragColor;
void main() {
fragColor = color;
}
'''
elif nanogui.api == 'metal':
vertex_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
vertex VertexOut vertex_main(const device packed_float3 *position,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = float4(position[id], 1.f);
return vert;
}
'''
fragment_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
fragment float4 fragment_main(VertexOut vert [[stage_in]],
const constant float4 &color) {
return color;
}
'''
texture = Texture(
pixel_format=Texture.PixelFormat.RGBA,
component_format=Texture.ComponentFormat.UInt8,
size=[512, 512],
flags=Texture.TextureFlags.ShaderRead | Texture.TextureFlags.RenderTarget
)
render_pass = RenderPass([texture])
render_pass.set_viewport(
[10, 10], [512 - 10, 512 - 20]
)
shader = Shader(
render_pass,
"test_shader",
vertex_program,
fragment_program
)
p = np.array([[ 0.0, 0.5, 0],
[-0.5, -0.5, 0],
[ 0.5, -0.5, 0]], dtype=np.float32)
shader.set_buffer("position", p)
shader.set_buffer("color", np.array([1, 0, 0, 1], dtype=np.float32))
shader.set_buffer("indices", np.array([0, 1, 2], dtype=np.uint32))
with render_pass:
with shader:
if False:
shader.draw_array(Shader.PrimitiveType.Triangle, 0, 3)
else:
shader.draw_array(Shader.PrimitiveType.Triangle, 0, 3, indexed=True)
result = texture.download()
Image.fromarray(result).save('test_0_%s.png' % nanogui.api)

View File

@@ -0,0 +1,96 @@
# OpenGL/Metal rendering test: render a green triangle on screen
import sys
sys.path.append('python')
import nanogui
from nanogui import Shader, Texture, RenderPass, Screen
import numpy as np
from PIL import Image
class MyScreen(Screen):
def __init__(self):
Screen.__init__(self, [512, 512], "Unnamed")
if nanogui.api == 'opengl':
vertex_program = '''
#version 330
in vec3 position;
void main() {
gl_Position = vec4(position, 1);
}
'''
fragment_program = '''
#version 330
uniform vec4 color;
out vec4 fragColor;
void main() {
fragColor = color;
}
'''
elif nanogui.api == 'metal':
vertex_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
vertex VertexOut vertex_main(const device packed_float3 *position,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = float4(position[id], 1.f);
return vert;
}
'''
fragment_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
};
fragment float4 fragment_main(VertexOut vert [[stage_in]],
const constant float4 &color) {
return color;
}
'''
self.render_pass = RenderPass([self])
self.render_pass.set_viewport(
[10, 10], self.framebuffer_size() - [10, 20]
)
self.shader = Shader(
self.render_pass,
"test_shader",
vertex_program,
fragment_program
)
p = np.array([[ 0.0, 0.5, 0],
[-0.5, -0.5, 0],
[ 0.5, -0.5, 0]], dtype=np.float32)
self.shader.set_buffer("position", p)
self.shader.set_buffer("color", np.array([0, 1, 0, 1], dtype=np.float32))
self.shader.set_buffer("indices", np.array([0, 1, 2], dtype=np.uint32))
def draw_contents(self):
print('draw_contents()')
with self.render_pass:
with self.shader:
if False:
self.shader.draw_array(Shader.PrimitiveType.Triangle, 0, 3)
else:
self.shader.draw_array(Shader.PrimitiveType.Triangle, 0, 3, indexed=True)
nanogui.init()
s = MyScreen()
s.set_visible(True)
nanogui.mainloop()
nanogui.shutdown()

View File

@@ -0,0 +1,164 @@
# OpenGL/Metal rendering test: render a spinning cube with a perspective
# camera; the window is resizable
import sys
sys.path.append('python')
import nanogui
from nanogui import Shader, Texture, RenderPass, Screen, Matrix4f
from nanogui import glfw
import numpy as np
class MyScreen(Screen):
def __init__(self):
Screen.__init__(self,
size=[512, 512],
caption="Unnamed",
depth_buffer=True
)
if nanogui.api == 'opengl':
vertex_program = '''
#version 330
in vec3 position;
in vec4 color;
out vec4 color_frag;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(position, 1.0);
color_frag = color;
}
'''
fragment_program = '''
#version 330
in vec4 color_frag;
out vec4 fragColor;
void main() {
fragColor = color_frag;
}
'''
elif nanogui.api == 'metal':
vertex_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
float4 color;
};
vertex VertexOut vertex_main(const device packed_float3 *position,
const device float4 *color,
constant float4x4 &mvp,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = mvp * float4(position[id], 1.f);
vert.color = color[id];
return vert;
}
'''
fragment_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
float4 color;
};
fragment float4 fragment_main(VertexOut vert [[stage_in]]) {
return vert.color;
}
'''
self.render_pass = RenderPass(
color_targets=[self],
depth_target=self
)
self.shader = Shader(
self.render_pass,
"test_shader",
vertex_program,
fragment_program
)
p = np.array([
[-1, 1, 1], [-1, -1, 1],
[1, -1, 1], [1, 1, 1],
[-1, 1, -1], [-1, -1, -1],
[1, -1, -1], [1, 1, -1]],
dtype=np.float32
)
color = np.array([
[0, 1, 1, 1], [0, 0, 1, 1],
[1, 0, 1, 1], [1, 1, 1, 1],
[0, 1, 0, 1], [0, 0, 0, 1],
[1, 0, 0, 1], [1, 1, 0, 1]],
dtype=np.float32
)
indices = np.array([
3, 2, 6, 6, 7, 3,
4, 5, 1, 1, 0, 4,
4, 0, 3, 3, 7, 4,
1, 5, 6, 6, 2, 1,
0, 1, 2, 2, 3, 0,
7, 6, 5, 5, 4, 7],
dtype=np.uint32
)
self.shader.set_buffer("position", p)
self.shader.set_buffer("color", color)
self.shader.set_buffer("indices", indices)
def draw_contents(self):
with self.render_pass:
view = Matrix4f.look_at(
origin=[0, -2, -10],
target=[0, 0, 0],
up=[0, 1, 0]
)
model = Matrix4f.rotate(
[0, 1, 0],
glfw.getTime()
)
fbsize = self.framebuffer_size()
proj = Matrix4f.perspective(
fov=25 * np.pi / 180,
near=0.1,
far=20,
aspect=fbsize[0] / float(fbsize[1])
)
mvp = proj @ view @ model
self.shader.set_buffer("mvp", np.float32(mvp).T)
with self.shader:
self.shader.draw_array(Shader.PrimitiveType.Triangle,
0, 36, indexed=True)
def keyboard_event(self, key, scancode, action, modifiers):
if super(MyScreen, self).keyboard_event(key, scancode,
action, modifiers):
return True
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
self.set_visible(False)
return True
return False
def resize_event(self, size):
self.render_pass.resize(self.framebuffer_size())
super(MyScreen, self).resize_event(size)
return True
nanogui.init()
s = MyScreen()
s.set_visible(True)
nanogui.mainloop(1 / 60.0 * 1000)
nanogui.shutdown()

View File

@@ -0,0 +1,169 @@
# OpenGL/Metal rendering test: render a textured spinning cube
import sys
sys.path.append('python')
import nanogui
from nanogui import Shader, Texture, RenderPass, Screen, Matrix4f
from nanogui import glfw
import numpy as np
from PIL import Image
import os
class MyScreen(Screen):
def __init__(self):
Screen.__init__(self,
size=[512, 512],
caption="Unnamed"
)
if nanogui.api == 'opengl':
vertex_program = '''
#version 330
in vec3 position;
in vec2 uv;
out vec2 uv_frag;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(position, 1.0);
uv_frag = uv;
}
'''
fragment_program = '''
#version 330
in vec2 uv_frag;
out vec4 fragColor;
uniform sampler2D albedo_texture;
void main() {
fragColor = texture(albedo_texture, uv_frag);
}
'''
elif nanogui.api == 'metal':
vertex_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
float2 uv;
};
vertex VertexOut vertex_main(const device packed_float3 *position,
const device float2 *uv,
constant float4x4 &mvp,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = mvp * float4(position[id], 1.f);
vert.uv = uv[id];
return vert;
}
'''
fragment_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
float2 uv;
};
fragment float4 fragment_main(VertexOut vert [[stage_in]],
texture2d<float, access::sample> albedo_texture,
sampler albedo_sampler) {
return albedo_texture.sample(albedo_sampler, vert.uv);
}
'''
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
image_fname = os.path.join(base_dir, "resources/icons/icon1.png")
image = np.array(Image.open(image_fname))
self.albedo_texture = Texture(
pixel_format=Texture.PixelFormat.RGBA,
component_format=Texture.ComponentFormat.UInt8,
size=image.shape[:2]
)
self.albedo_texture.upload(image)
self.render_pass = RenderPass(
color_targets=[self]
)
self.shader = Shader(
self.render_pass,
"test_shader",
vertex_program,
fragment_program
)
p = np.array([
[-1, -1, 0], [1, -1, 0],
[1, 1, 0], [-1, 1, 0]],
dtype=np.float32
)
uv = np.array([
[1, 1], [0, 1],
[0, 0], [1, 0]],
dtype=np.float32
)
indices = np.array([
0, 2, 1, 3, 2, 0],
dtype=np.uint32
)
self.shader.set_buffer("position", p)
self.shader.set_buffer("uv", uv)
self.shader.set_buffer("indices", indices)
self.shader.set_texture("albedo_texture", self.albedo_texture)
def draw_contents(self):
with self.render_pass:
view = Matrix4f.look_at(
origin=[0, -2, -10],
target=[0, 0, 0],
up=[0, 1, 0]
)
model = Matrix4f.rotate(
[0, 1, 0],
glfw.getTime() * 0.01
)
fbsize = self.framebuffer_size()
proj = Matrix4f.perspective(
fov=25 * np.pi / 180,
near=0.1,
far=20,
aspect=fbsize[0] / float(fbsize[1])
)
mvp = proj @ view @ model
self.shader.set_buffer("mvp", np.float32(mvp).T)
with self.shader:
self.shader.draw_array(Shader.PrimitiveType.Triangle,
0, 6, indexed=True)
def keyboard_event(self, key, scancode, action, modifiers):
if super(MyScreen, self).keyboard_event(key, scancode,
action, modifiers):
return True
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
self.set_visible(False)
return True
return False
def resize_event(self, size):
self.render_pass.resize(self.framebuffer_size())
super(MyScreen, self).resize_event(size)
return True
nanogui.init()
s = MyScreen()
s.set_visible(True)
nanogui.mainloop(1 / 60.0 * 1000)
nanogui.shutdown()

View File

@@ -0,0 +1,179 @@
# OpenGL/Metal rendering test: render a spinning cube with MSAA
import sys
sys.path.append('python')
import nanogui
from nanogui import Shader, Texture, RenderPass, Screen, Matrix4f
from nanogui import glfw
import numpy as np
class MyScreen(Screen):
def __init__(self):
Screen.__init__(self,
size=[512, 512],
caption="Unnamed"
)
if nanogui.api == 'opengl':
vertex_program = '''
#version 330
in vec3 position;
in vec4 color;
out vec4 color_frag;
uniform mat4 mvp;
void main() {
gl_Position = mvp * vec4(position, 1.0);
color_frag = color;
}
'''
fragment_program = '''
#version 330
in vec4 color_frag;
out vec4 fragColor;
void main() {
fragColor = color_frag;
}
'''
elif nanogui.api == 'metal':
vertex_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
float4 color;
};
vertex VertexOut vertex_main(const device packed_float3 *position,
const device float4 *color,
constant float4x4 &mvp,
uint id [[vertex_id]]) {
VertexOut vert;
vert.position = mvp * float4(position[id], 1.f);
vert.color = color[id];
return vert;
}
'''
fragment_program = '''
using namespace metal;
struct VertexOut {
float4 position [[position]];
float4 color;
};
fragment float4 fragment_main(VertexOut vert [[stage_in]]) {
return vert.color;
}
'''
self.color_target = Texture(
pixel_format=self.pixel_format(),
component_format=self.component_format(),
size=self.framebuffer_size(),
flags=Texture.TextureFlags.RenderTarget,
samples=8
)
self.depth_target = Texture(
pixel_format=Texture.PixelFormat.Depth,
component_format=Texture.ComponentFormat.Float32,
size=self.framebuffer_size(),
flags=Texture.TextureFlags.RenderTarget,
samples=8
)
self.render_pass = RenderPass(
color_targets=[self.color_target],
depth_target=self.depth_target,
blit_target=self
)
self.shader = Shader(
self.render_pass,
"test_shader",
vertex_program,
fragment_program
)
p = np.array([
[-1, 1, 1], [-1, -1, 1],
[1, -1, 1], [1, 1, 1],
[-1, 1, -1], [-1, -1, -1],
[1, -1, -1], [1, 1, -1]],
dtype=np.float32
)
color = np.array([
[0, 1, 1, 1], [0, 0, 1, 1],
[1, 0, 1, 1], [1, 1, 1, 1],
[0, 1, 0, 1], [0, 0, 0, 1],
[1, 0, 0, 1], [1, 1, 0, 1]],
dtype=np.float32
)
indices = np.array([
3, 2, 6, 6, 7, 3,
4, 5, 1, 1, 0, 4,
4, 0, 3, 3, 7, 4,
1, 5, 6, 6, 2, 1,
0, 1, 2, 2, 3, 0,
7, 6, 5, 5, 4, 7],
dtype=np.uint32
)
self.shader.set_buffer("position", p)
self.shader.set_buffer("color", color)
self.shader.set_buffer("indices", indices)
def draw_contents(self):
with self.render_pass:
view = Matrix4f.look_at(
origin=[0, -2, -10],
target=[0, 0, 0],
up=[0, 1, 0]
)
model = Matrix4f.rotate(
[0, 1, 0],
glfw.getTime()
)
fbsize = self.framebuffer_size()
proj = Matrix4f.perspective(
fov=25 * np.pi / 180,
near=0.1,
far=20,
aspect=fbsize[0] / float(fbsize[1])
)
mvp = proj @ view @ model
self.shader.set_buffer("mvp", np.float32(mvp).T)
with self.shader:
self.shader.draw_array(Shader.PrimitiveType.Triangle,
0, 36, indexed=True)
def keyboard_event(self, key, scancode, action, modifiers):
if super(MyScreen, self).keyboard_event(key, scancode,
action, modifiers):
return True
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
self.set_visible(False)
return True
return False
def resize_event(self, size):
self.render_pass.resize(self.framebuffer_size())
super(MyScreen, self).resize_event(size)
return True
nanogui.init()
s = MyScreen()
s.set_visible(True)
nanogui.mainloop(1 / 60.0 * 1000)
nanogui.shutdown()

View File

@@ -0,0 +1,46 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
DECLARE_WIDGET(TabWidgetBase);
DECLARE_WIDGET(TabWidget);
void register_tabs(py::module &m) {
py::class_<TabWidgetBase, Widget, ref<TabWidgetBase>, PyTabWidgetBase>(m, "TabWidgetBase", D(TabWidgetBase))
.def(py::init<Widget *>(), D(TabWidgetBase, TabWidgetBase))
.def("tab_count", &TabWidgetBase::tab_count, D(TabWidgetBase, tab_count))
.def("tab_id", &TabWidgetBase::tab_id, D(TabWidgetBase, tab_id))
.def("tab_index", &TabWidgetBase::tab_index, D(TabWidgetBase, tab_index))
.def("insert_tab", &TabWidgetBase::insert_tab, D(TabWidgetBase, insert_tab), "index"_a, "caption"_a)
.def("append_tab", &TabWidgetBase::append_tab, D(TabWidgetBase, append_tab), "caption"_a)
.def("remove_tab", &TabWidgetBase::remove_tab, D(TabWidgetBase, remove_tab), "id"_a)
.def("selected_index", &TabWidgetBase::selected_index, D(TabWidgetBase, selected_index))
.def("set_selected_index", &TabWidgetBase::set_selected_index, D(TabWidgetBase, set_selected_index), "id"_a)
.def("selected_id", &TabWidgetBase::selected_id, D(TabWidgetBase, selected_id))
.def("set_selected_id", &TabWidgetBase::set_selected_id, D(TabWidgetBase, set_selected_id), "id"_a)
.def("tab_caption", &TabWidgetBase::tab_caption, D(TabWidgetBase, tab_caption), "id"_a)
.def("set_tab_caption", &TabWidgetBase::set_tab_caption, D(TabWidgetBase, set_tab_caption), "id"_a, "caption"_a)
.def("tabs_draggable", &TabWidgetBase::tabs_draggable, D(TabWidgetBase, tabs_draggable))
.def("set_tabs_draggable", &TabWidgetBase::set_tabs_draggable, D(TabWidgetBase, set_tabs_draggable))
.def("tabs_closeable", &TabWidgetBase::tabs_closeable, D(TabWidgetBase, tabs_closeable))
.def("set_tabs_closeable", &TabWidgetBase::set_tabs_closeable, D(TabWidgetBase, set_tabs_closeable))
.def("padding", &TabWidgetBase::padding, D(TabWidgetBase, padding))
.def("set_padding", &TabWidgetBase::set_padding, D(TabWidgetBase, set_padding))
.def("set_background_color", &TabWidgetBase::set_background_color, D(TabWidgetBase, set_background_color))
.def("background_color", &TabWidgetBase::background_color, D(TabWidgetBase, background_color))
.def("set_callback", &TabWidgetBase::set_callback, D(TabWidgetBase, set_callback))
.def("callback", &TabWidgetBase::callback, D(TabWidgetBase, callback))
.def("close_callback", &TabWidgetBase::close_callback, D(TabWidgetBase, close_callback))
.def("set_close_callback", &TabWidgetBase::set_close_callback, D(TabWidgetBase, set_close_callback))
.def("popup_callback", &TabWidgetBase::popup_callback, D(TabWidgetBase, popup_callback))
.def("set_popup_callback", &TabWidgetBase::set_popup_callback, D(TabWidgetBase, set_popup_callback));
py::class_<TabWidget, TabWidgetBase, ref<TabWidget>, PyTabWidget>(m, "TabWidget", D(TabWidget))
.def(py::init<Widget *>(), D(TabWidget, TabWidget))
.def("insert_tab", &TabWidget::insert_tab, D(TabWidget, insert_tab), "index"_a, "caption"_a, "widget"_a)
.def("append_tab", &TabWidget::append_tab, D(TabWidget, append_tab), "caption"_a, "widget"_a)
.def("remove_children", &TabWidget::remove_children, D(TabWidget, remove_children))
.def("set_remove_children", &TabWidget::set_remove_children, D(TabWidget, set_remove_children), "id"_a);
}
#endif

View File

@@ -0,0 +1,27 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
DECLARE_WIDGET(TextArea);
void register_textarea(py::module &m) {
py::class_<TextArea, Widget, ref<TextArea>, PyTextArea>(m, "TextArea", D(TextArea))
.def(py::init<Widget *>(), D(TextArea, TextArea))
.def("set_font", &TextArea::set_font, D(TextArea, set_font))
.def("font", &TextArea::font, D(TextArea, font))
.def("set_foreground_color", &TextArea::set_foreground_color, D(TextArea, set_foreground_color))
.def("foreground_color", &TextArea::foreground_color, D(TextArea, foreground_color))
.def("set_background_color", &TextArea::set_background_color, D(TextArea, set_background_color))
.def("background_color", &TextArea::background_color, D(TextArea, background_color))
.def("set_selection_color", &TextArea::set_selection_color, D(TextArea, set_selection_color))
.def("selection_color", &TextArea::selection_color, D(TextArea, selection_color))
.def("set_padding", &TextArea::set_padding, D(TextArea, set_padding))
.def("padding", &TextArea::padding, D(TextArea, padding))
.def("set_selectable", &TextArea::set_selectable, D(TextArea, set_selectable))
.def("is_selectable", &TextArea::is_selectable, D(TextArea, is_selectable))
.def("append", &TextArea::append, D(TextArea, append))
.def("append_line", &TextArea::append_line, D(TextArea, append_line))
.def("clear", &TextArea::clear, D(TextArea, clear));
}
#endif

View File

@@ -0,0 +1,66 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
typedef FloatBox<double> DoubleBox;
typedef IntBox<int64_t> Int64Box;
DECLARE_WIDGET(TextBox);
DECLARE_WIDGET(DoubleBox);
DECLARE_WIDGET(Int64Box);
void register_textbox(py::module &m) {
py::class_<TextBox, Widget, ref<TextBox>, PyTextBox> tbox(m, "TextBox", D(TextBox));
tbox
.def(py::init<Widget *, const std::string &>(), "parent"_a,
"value"_a = std::string("Untitled"), D(TextBox, TextBox))
.def("editable", &TextBox::editable, D(TextBox, editable))
.def("set_editable", &TextBox::set_editable, D(TextBox, set_editable))
.def("spinnable", &TextBox::spinnable, D(TextBox, spinnable))
.def("set_spinnable", &TextBox::set_spinnable, D(TextBox, set_spinnable))
.def("value", &TextBox::value, D(TextBox, value))
.def("set_value", &TextBox::set_value, D(TextBox, set_value))
.def("default_value", &TextBox::default_value, D(TextBox, default_value))
.def("set_default_value", &TextBox::set_default_value, D(TextBox, set_default_value))
.def("alignment", &TextBox::alignment, D(TextBox, alignment))
.def("set_alignment", &TextBox::set_alignment, D(TextBox, set_alignment))
.def("units", &TextBox::units, D(TextBox, units))
.def("set_units", &TextBox::set_units, D(TextBox, set_units))
.def("units_image", &TextBox::units_image, D(TextBox, units_image))
.def("set_units_image", &TextBox::set_units_image, D(TextBox, set_units_image))
.def("format", &TextBox::format, D(TextBox, format))
.def("set_format", &TextBox::set_format, D(TextBox, set_format))
.def("placeholder", &TextBox::placeholder, D(TextBox, placeholder))
.def("set_placeholder", &TextBox::set_placeholder, D(TextBox, set_placeholder))
.def("callback", &TextBox::callback, D(TextBox, callback))
.def("set_callback", &TextBox::set_callback, D(TextBox, set_callback));
py::enum_<TextBox::Alignment>(tbox, "Alignment", D(TextBox, Alignment))
.value("Left", TextBox::Alignment::Left)
.value("Center", TextBox::Alignment::Center)
.value("Right", TextBox::Alignment::Right);
py::class_<Int64Box, TextBox, ref<Int64Box>, PyInt64Box>(m, "IntBox", D(IntBox))
.def(py::init<Widget *, int64_t>(), "parent"_a, "value"_a = (int64_t) 0, D(IntBox, IntBox))
.def("value", &Int64Box::value, D(IntBox, value))
.def("set_value", (void (Int64Box::*)(int64_t)) &Int64Box::set_value, D(IntBox, set_value))
.def("set_callback", (void (Int64Box::*)(const std::function<void(int64_t)>&))
&Int64Box::set_callback, D(IntBox, set_callback))
.def("set_value_increment", &Int64Box::set_value_increment, D(IntBox, set_value_increment))
.def("set_min_value", &Int64Box::set_min_value, D(IntBox, set_min_value))
.def("set_max_value", &Int64Box::set_max_value, D(IntBox, set_max_value))
.def("set_min_value", &Int64Box::set_min_max_values, D(IntBox, set_min_max_values));
py::class_<DoubleBox, TextBox, ref<DoubleBox>, PyDoubleBox>(m, "FloatBox", D(FloatBox))
.def(py::init<Widget *, double>(), "parent"_a, "value"_a = 0.0)
.def("value", &DoubleBox::value, D(FloatBox, value))
.def("set_value", (void (DoubleBox::*)(double)) &DoubleBox::set_value, D(FloatBox, set_value))
.def("set_callback", (void (DoubleBox::*)(const std::function<void(double)>&))
&DoubleBox::set_callback, D(FloatBox, set_callback))
.def("set_value_increment", &DoubleBox::set_value_increment, D(FloatBox, set_value_increment))
.def("set_min_value", &DoubleBox::set_min_value, D(FloatBox, set_min_value))
.def("set_max_value", &DoubleBox::set_max_value, D(FloatBox, set_max_value))
.def("set_min_value", &DoubleBox::set_min_max_values, D(FloatBox, set_min_max_values));
}
#endif

View File

@@ -0,0 +1,65 @@
#include "python.h"
class PyTheme : public Theme {
public:
using Theme::Theme;
};
void register_theme(py::module &m) {
py::class_<Theme, ref<Theme>, PyTheme> theme(m, "Theme", D(Theme));
theme.def(py::init<NVGcontext *>(), D(Theme, Theme))
.def_readwrite("m_font_sans_regular", &Theme::m_font_sans_regular, D(Theme, m_font_sans_regular))
.def_readwrite("m_font_sans_bold", &Theme::m_font_sans_bold, D(Theme, m_font_sans_bold))
.def_readwrite("m_font_icons", &Theme::m_font_icons, D(Theme, m_font_icons))
.def_readwrite("m_font_mono_regular", &Theme::m_font_mono_regular, D(Theme, m_font_mono_regular))
.def_readwrite("m_icon_scale", &Theme::m_icon_scale, D(Theme, m_icon_scale))
.def_readwrite("m_standard_font_size", &Theme::m_standard_font_size, D(Theme, m_standard_font_size))
.def_readwrite("m_button_font_size", &Theme::m_button_font_size, D(Theme, m_button_font_size))
.def_readwrite("m_text_box_font_size", &Theme::m_text_box_font_size, D(Theme, m_text_box_font_size))
.def_readwrite("m_window_corner_radius", &Theme::m_window_corner_radius, D(Theme, m_window_corner_radius))
.def_readwrite("m_window_header_height", &Theme::m_window_header_height, D(Theme, m_window_header_height))
.def_readwrite("m_window_drop_shadow_size", &Theme::m_window_drop_shadow_size, D(Theme, m_window_drop_shadow_size))
.def_readwrite("m_button_corner_radius", &Theme::m_button_corner_radius, D(Theme, m_button_corner_radius))
.def_readwrite("m_tab_border_width", &Theme::m_tab_border_width, D(Theme, m_tab_border_width))
.def_readwrite("m_tab_inner_margin", &Theme::m_tab_inner_margin, D(Theme, m_tab_inner_margin))
.def_readwrite("m_tab_min_button_width", &Theme::m_tab_min_button_width, D(Theme, m_tab_min_button_width))
.def_readwrite("m_tab_max_button_width", &Theme::m_tab_max_button_width, D(Theme, m_tab_max_button_width))
.def_readwrite("m_tab_control_width", &Theme::m_tab_control_width, D(Theme, m_tab_control_width))
.def_readwrite("m_tab_button_horizontal_padding", &Theme::m_tab_button_horizontal_padding, D(Theme, m_tab_button_horizontal_padding))
.def_readwrite("m_tab_button_vertical_padding", &Theme::m_tab_button_vertical_padding, D(Theme, m_tab_button_vertical_padding))
.def_readwrite("m_drop_shadow", &Theme::m_drop_shadow, D(Theme, m_drop_shadow))
.def_readwrite("m_transparent", &Theme::m_transparent, D(Theme, m_transparent))
.def_readwrite("m_border_dark", &Theme::m_border_dark, D(Theme, m_border_dark))
.def_readwrite("m_border_light", &Theme::m_border_light, D(Theme, m_border_light))
.def_readwrite("m_border_medium", &Theme::m_border_medium, D(Theme, m_border_medium))
.def_readwrite("m_text_color", &Theme::m_text_color, D(Theme, m_text_color))
.def_readwrite("m_disabled_text_color", &Theme::m_disabled_text_color, D(Theme, m_disabled_text_color))
.def_readwrite("m_text_color_shadow", &Theme::m_text_color_shadow, D(Theme, m_text_color_shadow))
.def_readwrite("m_icon_color", &Theme::m_icon_color, D(Theme, m_icon_color))
.def_readwrite("m_button_gradient_top_focused", &Theme::m_button_gradient_top_focused, D(Theme, m_button_gradient_top_focused))
.def_readwrite("m_button_gradient_bot_focused", &Theme::m_button_gradient_bot_focused, D(Theme, m_button_gradient_bot_focused))
.def_readwrite("m_button_gradient_top_unfocused", &Theme::m_button_gradient_top_unfocused, D(Theme, m_button_gradient_top_unfocused))
.def_readwrite("m_button_gradient_bot_unfocused", &Theme::m_button_gradient_bot_unfocused, D(Theme, m_button_gradient_bot_unfocused))
.def_readwrite("m_button_gradient_top_pushed", &Theme::m_button_gradient_top_pushed, D(Theme, m_button_gradient_top_pushed))
.def_readwrite("m_button_gradient_bot_pushed", &Theme::m_button_gradient_bot_pushed, D(Theme, m_button_gradient_bot_pushed))
.def_readwrite("m_window_fill_unfocused", &Theme::m_window_fill_unfocused, D(Theme, m_window_fill_unfocused))
.def_readwrite("m_window_fill_focused", &Theme::m_window_fill_focused, D(Theme, m_window_fill_focused))
.def_readwrite("m_window_title_unfocused", &Theme::m_window_title_unfocused, D(Theme, m_window_title_unfocused))
.def_readwrite("m_window_title_focused", &Theme::m_window_title_focused, D(Theme, m_window_title_focused))
.def_readwrite("m_window_header_gradient_top", &Theme::m_window_header_gradient_top, D(Theme, m_window_header_gradient_top))
.def_readwrite("m_window_header_gradient_bot", &Theme::m_window_header_gradient_bot, D(Theme, m_window_header_gradient_bot))
.def_readwrite("m_window_header_sep_top", &Theme::m_window_header_sep_top, D(Theme, m_window_header_sep_top))
.def_readwrite("m_window_header_sep_bot", &Theme::m_window_header_sep_bot, D(Theme, m_window_header_sep_bot))
.def_readwrite("m_window_popup", &Theme::m_window_popup, D(Theme, m_window_popup))
.def_readwrite("m_window_popup_transparent", &Theme::m_window_popup_transparent, D(Theme, m_window_popup_transparent))
.def_readwrite("m_check_box_icon", &Theme::m_check_box_icon, D(Theme, m_check_box_icon))
.def_readwrite("m_message_information_icon", &Theme::m_message_information_icon, D(Theme, m_message_information_icon))
.def_readwrite("m_message_question_icon", &Theme::m_message_question_icon, D(Theme, m_message_question_icon))
.def_readwrite("m_message_warning_icon", &Theme::m_message_warning_icon, D(Theme, m_message_warning_icon))
.def_readwrite("m_message_alt_button_icon", &Theme::m_message_alt_button_icon, D(Theme, m_message_alt_button_icon))
.def_readwrite("m_message_primary_button_icon", &Theme::m_message_primary_button_icon, D(Theme, m_message_primary_button_icon))
.def_readwrite("m_popup_chevron_right_icon", &Theme::m_popup_chevron_right_icon, D(Theme, m_popup_chevron_right_icon))
.def_readwrite("m_popup_chevron_left_icon", &Theme::m_popup_chevron_left_icon, D(Theme, m_popup_chevron_left_icon))
.def_readwrite("m_text_box_up_icon", &Theme::m_text_box_up_icon, D(Theme, m_text_box_up_icon))
.def_readwrite("m_text_box_down_icon", &Theme::m_text_box_down_icon, D(Theme, m_text_box_down_icon));
}

View File

@@ -0,0 +1,162 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
#include <pybind11/operators.h>
#if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wself-assign-overloaded"
# pragma clang diagnostic ignored "-Wunused-lambda-capture"
#endif
template <typename Array>
auto register_vector_type(py::module &m, const char *name) {
constexpr size_t Size = Array::Size;
using Value = typename Array::Value;
auto array = py::class_<Array>(m, name, py::buffer_protocol());
array.def(py::init<Value>())
.def(py::init<const Array &>())
.def(py::init([Size](const std::array<Value, Size> &arr) {
Array a;
for (size_t i = 0; i < Size; ++i)
a[i] = arr[i];
return a;
}))
.def(py::self == py::self)
.def(py::self != py::self)
.def(py::self + py::self)
.def(py::self - py::self)
.def(py::self * py::self)
.def(Value() + py::self)
.def(Value() - py::self)
.def(Value() * py::self)
.def(Value() / py::self)
.def(py::self / py::self)
.def(py::self += py::self)
.def(py::self -= py::self)
.def(py::self *= py::self)
.def(py::self /= py::self)
.def("__getitem__", [Size](const Array &a, size_t index) -> Value {
if (index >= Size)
throw py::index_error();
return a[index];
}, "index"_a)
.def("__setitem__", [Size](Array &a, size_t index, Value value) {
if (index >= Size)
throw py::index_error();
a[index] = value;
}, "index"_a, "value"_a)
.def_property("x", [](const Array &a) { return a.x(); },
[](Array &a, const Value &v) { a.x() = v; })
.def_property("y", [](const Array &a) { return a.y(); },
[](Array &a, const Value &v) { a.y() = v; })
.def_buffer([Size](Array &m) -> py::buffer_info {
return py::buffer_info(
m.v, // Pointer to buffer
sizeof(Value), // Size of one scalar
py::format_descriptor<Value>::format(), // Python struct-style format descriptor
1, // Number of dimensions
{ Size }, // Buffer dimensions
{ sizeof(Value) }
);
})
.def("__repr__", [](const Array &a) {
std::ostringstream oss;
oss << a;
return oss.str();
});
if constexpr (Size == 2)
array.def(py::init<Value, Value>());
if constexpr (Size == 3) {
array.def(py::init<Value, Value, Value>());
array.def_property("z", [](const Array &a) { return a.z(); },
[](Array &a, const Value &v) { a.z() = v; });
}
py::implicitly_convertible<py::sequence, Array>();
py::implicitly_convertible<Value, Array>();
return array;
}
#if defined(__clang__)
# pragma clang diagnostic pop
#endif
void register_vector(py::module &m) {
register_vector_type<Vector2i>(m, "Vector2i");
register_vector_type<Vector2f>(m, "Vector2f");
register_vector_type<Vector3f>(m, "Vector3f");
py::class_<Matrix4f>(m, "Matrix4f", py::buffer_protocol())
.def(py::init<>())
.def(py::init<float>())
.def("__matmul__", [](const Matrix4f &a, const Matrix4f &b) { return a * b; }, py::is_operator())
.def("__getitem__",
[](const Matrix4f &m, std::pair<size_t, size_t> index) -> float {
if (index.first >= 4 || index.second >= 4)
throw py::index_error();
return m.m[index.second][index.first];
},
"index"_a)
.def("__setitem__",
[](Matrix4f &m, std::pair<size_t, size_t> index, float value) {
if (index.first >= 4 || index.second >= 4)
throw py::index_error();
m.m[index.second][index.first] = value;
},
"index"_a, "value"_a)
.def_static(
"translate",
[](const Vector3f &amount) { return Matrix4f::translate(amount); },
"amount"_a)
.def_static(
"scale",
[](const Vector3f &amount) { return Matrix4f::scale(amount); },
"amount"_a)
.def_static(
"rotate",
[](const Vector3f &axis, float angle) {
return Matrix4f::rotate(axis, angle);
},
"axis"_a, "angle"_a)
.def_static(
"perspective",
[](float fov, float near_, float far_, float aspect) {
return Matrix4f::perspective(fov, near_, far_, aspect);
},
"fov"_a, "near"_a, "far"_a, "aspect"_a = 1.f)
.def_static(
"ortho",
[](float left, float right, float bottom, float top, float near_, float far_) {
return Matrix4f::ortho(left, right, bottom, top, near_, far_);
},
"left"_a, "right"_a, "bottom"_a, "top"_a, "near"_a, "far"_a)
.def_static(
"look_at",
[](const Vector3f &origin, const Vector3f &target, const Vector3f &up) {
return Matrix4f::look_at(origin, target, up);
},
"origin"_a, "target"_a, "up"_a)
.def_buffer([](Matrix4f &m) -> py::buffer_info {
return py::buffer_info(
m.m, // Pointer to buffer
sizeof(float), // Size of one scalar
py::format_descriptor<float>::format(), // Python struct-style
// format descriptor
2, // Number of dimensions
{ 4, 4 }, // Buffer dimensions
{ sizeof(float), sizeof(float) * 4 });
})
.def("__repr__", [](const Matrix4f &m) {
std::ostringstream oss;
oss << m;
return oss.str();
});
}
#endif

View File

@@ -0,0 +1,139 @@
#ifdef NANOGUI_PYTHON
#include "python.h"
DECLARE_WIDGET(Widget);
DECLARE_SCREEN(Screen);
DECLARE_WIDGET(Window);
void register_widget(py::module &m) {
py::class_<Object, ref<Object>>(m, "Object", D(Object));
py::class_<Widget, Object, ref<Widget>, PyWidget>(m, "Widget", D(Widget))
.def(py::init<Widget *>(), D(Widget, Widget))
.def("parent", (Widget *(Widget::*)(void)) &Widget::parent, D(Widget, parent))
.def("set_parent", &Widget::set_parent, D(Widget, set_parent))
.def("layout", (Layout *(Widget::*)(void)) &Widget::layout, D(Widget, layout))
.def("set_layout", &Widget::set_layout, D(Widget, set_layout))
.def("theme", (Theme *(Widget::*)(void)) &Widget::theme, D(Widget, theme))
.def("set_theme", &Widget::set_theme, D(Widget, set_theme))
.def("position", &Widget::position, D(Widget, position))
.def("set_position", &Widget::set_position, D(Widget, set_position))
.def("absolute_position", &Widget::absolute_position, D(Widget, absolute_position))
.def("size", &Widget::size, D(Widget, size))
.def("set_size", &Widget::set_size, D(Widget, set_size))
.def("width", &Widget::width, D(Widget, width))
.def("set_width", &Widget::set_width, D(Widget, set_width))
.def("height", &Widget::height, D(Widget, height))
.def("set_height", &Widget::set_height, D(Widget, set_height))
.def("fixed_size", &Widget::fixed_size, D(Widget, fixed_size))
.def("set_fixed_size", &Widget::set_fixed_size, D(Widget, set_fixed_size))
.def("fixed_width", &Widget::fixed_width, D(Widget, fixed_width))
.def("set_fixed_width", &Widget::set_fixed_width, D(Widget, set_fixed_width))
.def("fixed_height", &Widget::fixed_height, D(Widget, fixed_height))
.def("set_fixed_height", &Widget::set_fixed_height, D(Widget, set_fixed_height))
.def("visible", &Widget::visible, D(Widget, visible))
.def("set_visible", &Widget::set_visible, D(Widget, set_visible))
.def("visible_recursive", &Widget::visible_recursive, D(Widget, visible_recursive))
.def("children", (const std::vector<Widget *>&(Widget::*)(void)) &Widget::children,
D(Widget, children), py::return_value_policy::reference)
.def("add_child", (void (Widget::*) (int, Widget *)) &Widget::add_child, D(Widget, add_child))
.def("add_child", (void (Widget::*) (Widget *)) &Widget::add_child, D(Widget, add_child, 2))
.def("child_count", &Widget::child_count, D(Widget, child_count))
.def("__len__", &Widget::child_count, D(Widget, child_count))
.def("__iter__", [](const Widget &w) {
return py::make_iterator(w.children().begin(), w.children().end());
}, py::keep_alive<0, 1>())
.def("child_index", &Widget::child_index, D(Widget, child_index))
.def("__getitem__", (Widget* (Widget::*)(int)) &Widget::child_at, D(Widget, child_at))
.def("remove_child_at", &Widget::remove_child_at, D(Widget, remove_child_at))
.def("remove_child", &Widget::remove_child, D(Widget, remove_child))
.def("__delitem__", &Widget::remove_child_at, D(Widget, remove_child_at))
.def("enabled", &Widget::enabled, D(Widget, enabled))
.def("set_enabled", &Widget::set_enabled, D(Widget, set_enabled))
.def("focused", &Widget::focused, D(Widget, focused))
.def("set_focused", &Widget::set_focused, D(Widget, set_focused))
.def("request_focus", &Widget::request_focus, D(Widget, request_focus))
.def("tooltip", &Widget::tooltip, D(Widget, tooltip))
.def("set_tooltip", &Widget::set_tooltip, D(Widget, set_tooltip))
.def("font_size", &Widget::font_size, D(Widget, font_size))
.def("set_font_size", &Widget::set_font_size, D(Widget, set_font_size))
.def("has_font_size", &Widget::has_font_size, D(Widget, has_font_size))
.def("cursor", &Widget::cursor, D(Widget, cursor))
.def("set_cursor", &Widget::set_cursor, D(Widget, set_cursor))
.def("find_widget", (Widget *(Widget::*)(const Vector2i &)) &Widget::find_widget, D(Widget, find_widget))
.def("contains", &Widget::contains, D(Widget, contains))
.def("mouse_button_event", &Widget::mouse_button_event, "p"_a, "button"_a,
"down"_a, "modifiers"_a, D(Widget, mouse_button_event))
.def("mouse_motion_event", &Widget::mouse_motion_event, "p"_a, "rel"_a,
"button"_a, "modifiers"_a, D(Widget, mouse_motion_event))
.def("mouse_drag_event", &Widget::mouse_drag_event, "p"_a, "rel"_a,
"button"_a, "modifiers"_a, D(Widget, mouse_drag_event))
.def("mouse_enter_event", &Widget::mouse_enter_event, "p"_a, "enter"_a,
D(Widget, mouse_enter_event))
.def("scroll_event", &Widget::scroll_event, "p"_a, "rel"_a,
D(Widget, scroll_event))
.def("focus_event", &Widget::focus_event, "focused"_a, D(Widget, focus_event))
.def("keyboard_event", &Widget::keyboard_event, "key"_a, "scancode"_a,
"action"_a, "modifiers"_a, D(Widget, keyboard_event))
.def("keyboard_character_event", &Widget::keyboard_character_event,
D(Widget, keyboard_character_event))
.def("preferred_size", &Widget::preferred_size, D(Widget, preferred_size))
.def("perform_layout", &Widget::perform_layout, D(Widget, perform_layout))
.def("screen", py::overload_cast<>(&Widget::screen, py::const_), D(Widget, screen))
.def("window", py::overload_cast<>(&Widget::window, py::const_), D(Widget, window))
.def("draw", &Widget::draw, D(Widget, draw));
py::class_<Window, Widget, ref<Window>, PyWindow>(m, "Window", D(Window))
.def(py::init<Widget *, const std::string>(), "parent"_a,
"title"_a = std::string("Untitled"), D(Window, Window))
.def("title", &Window::title, D(Window, title))
.def("set_title", &Window::set_title, D(Window, set_title))
.def("modal", &Window::modal, D(Window, modal))
.def("set_modal", &Window::set_modal, D(Window, set_modal))
.def("dispose", &Window::dispose, D(Window, dispose))
.def("button_panel", &Window::button_panel, D(Window, button_panel))
.def("center", &Window::center, D(Window, center));
py::class_<Screen, Widget, ref<Screen>, PyScreen>(m, "Screen", D(Screen))
.def(py::init<const Vector2i &, const std::string &, bool, bool, bool,
bool, bool, unsigned int, unsigned int>(),
"size"_a, "caption"_a = "Unnamed", "resizable"_a = true, "fullscreen"_a = false,
"depth_buffer"_a = true, "stencil_buffer"_a = true,
"float_buffer"_a = false, "gl_major"_a = 3, "gl_minor"_a = 2, D(Screen, Screen))
.def("caption", &Screen::caption, D(Screen, caption))
.def("set_caption", &Screen::set_caption, D(Screen, set_caption))
.def("background", &Screen::background, D(Screen, background))
.def("set_background", &Screen::set_background, D(Screen, set_background))
.def("set_visible", &Screen::set_visible, D(Screen, set_visible))
.def("set_size", &Screen::set_size, D(Screen, set_size))
.def("framebuffer_size", &Screen::framebuffer_size, D(Screen, framebuffer_size))
.def("perform_layout", (void(Screen::*)(void)) &Screen::perform_layout, D(Screen, perform_layout))
.def("redraw", &Screen::redraw, D(Screen, redraw))
.def("clear", &Screen::clear, D(Screen, clear))
.def("draw_all", &Screen::draw_all, D(Screen, draw_all))
.def("draw_contents", &Screen::draw_contents, D(Screen, draw_contents))
.def("resize_event", &Screen::resize_event, "size"_a, D(Screen, resize_event))
.def("resize_callback", &Screen::resize_callback)
.def("set_resize_callback", &Screen::set_resize_callback)
.def("drop_event", &Screen::drop_event, D(Screen, drop_event))
.def("mouse_pos", &Screen::mouse_pos, D(Screen, mouse_pos))
.def("pixel_ratio", &Screen::pixel_ratio, D(Screen, pixel_ratio))
.def("has_depth_buffer", &Screen::has_depth_buffer, D(Screen, has_depth_buffer))
.def("has_stencil_buffer", &Screen::has_stencil_buffer, D(Screen, has_stencil_buffer))
.def("has_float_buffer", &Screen::has_float_buffer, D(Screen, has_float_buffer))
.def("glfw_window", &Screen::glfw_window, D(Screen, glfw_window),
py::return_value_policy::reference)
.def("nvg_context", &Screen::nvg_context, D(Screen, nvg_context),
py::return_value_policy::reference)
.def("pixel_format", &Screen::pixel_format, D(Screen, pixel_format))
.def("component_format", &Screen::component_format, D(Screen, component_format))
.def("nvg_flush", &Screen::nvg_flush, D(Screen, nvg_flush))
#if defined(NANOGUI_USE_METAL)
.def("metal_layer", &Screen::metal_layer)
.def("metal_texture", &Screen::metal_texture)
.def("depth_stencil_texture", &Screen::depth_stencil_texture)
#endif
;
}
#endif