PeriDyno 1.2.1
Loading...
Searching...
No Matches
WPythonWidget.cpp
Go to the documentation of this file.
1#include "WPythonWidget.h"
2
3#include <Wt/WJavaScript.h>
4#include <Wt/WMessageBox.h>
5#include <Wt/WPushButton.h>
6#include <Wt/WVBoxLayout.h>
7
8#include <SceneGraph.h>
9
10// python
11#include <pybind11/embed.h>
12namespace py = pybind11;
13
15{
16 this->setLayoutSizeAware(true);
17 this->setOverflow(Wt::Overflow::Auto);
18 //this->setHeight(Wt::WLength("100%"));
19 this->setMargin(0);
20
21 auto layout = this->setLayout(std::make_unique<Wt::WVBoxLayout>());
22 layout->setContentsMargins(0, 0, 0, 0);
23
24 mCodeEditor = layout->addWidget(std::make_unique<Wt::WText>(), 1);
25 mCodeEditor->setInline(false);
26 //mCodeEditor->setWidth(Wt::WLength("100%"));
27
28 // ACE editor
29 std::string ref = mCodeEditor->jsRef(); // is a text string that will be the element when executed in JS
30
31 std::string command =
32 ref + ".editor = ace.edit(" + ref + ");" +
33 ref + ".editor.setTheme(\"ace/theme/monokai\");" +
34 ref + ".editor.getSession().setMode(\"ace/mode/python\");" +
35 ref + ".editor.setFontSize(14);" +
36 "ace.require(\"ace/ext/language_tools\");" +
37 ref + ".editor.setOptions({enableBasicAutocompletion: true,enableSnippets : true,enableLiveAutocompletion : true});" +
38 ref + ".editor.setOption(\"wrap\",\"free\")";
39 mCodeEditor->doJavaScript(command);
40
41 // create signal
42 auto jsignal = new Wt::JSignal<std::string>(mCodeEditor, "update");
43 jsignal->connect(this, &WPythonWidget::execute);
44
45 auto str = jsignal->createCall({ ref + ".editor.getValue()" });
46 command = "function(object, event) {" + str + ";}";
47 auto btn = layout->addWidget(std::make_unique<Wt::WPushButton>("Update"), 0);
48 btn->clicked().connect(command);
49
50 // some default code here...
51 std::string source = R"====(# dyno sample
52import PyPeridyno as dyno
53
54class VolumeTest(dyno.Node):
55
56 def __init__(self):
57 dyno = __import__('PyPeridyno')
58 super().__init__()
59 self.state_LevelSet = dyno.FInstanceLevelSet3f("LevelSet", "", dyno.FieldTypeEnum.State, self)
60
61 self.set_auto_hidden(True)
62 mapper = dyno.VolumeToTriangleSet3f()
63 self.state_level_set().connect(mapper.io_volume())
64 self.graphics_pipeline().push_module(mapper)
65
66 renderer = dyno.GLSurfaceVisualModule()
67 mapper.out_triangle_set().connect(renderer.in_triangle_set())
68 self.graphics_pipeline().push_module(renderer)
69
70 def get_node_type(self):
71 return "Volume"
72
73 def state_level_set(self):
74 return self.state_LevelSet
75
76
77scn = dyno.SceneGraph()
78
79test = VolumeTest()
80scn.add_node(test)
81)====";
82
83 setText(source);
84}
85
87{
88 Wt::log("warning") << "WPythonWidget destory";
89}
90
91void WPythonWidget::setText(const std::string& text)
92{
93 // update code editor content
94 std::string ref = mCodeEditor->jsRef();
95 std::string command = ref + ".editor.setValue(`" + text + "`, 1);";
96 mCodeEditor->doJavaScript(command);
97 //mCodeEditor->refresh();
98}
99
100void WPythonWidget::execute(const std::string& src)
101{
102 bool flag = true;
103 py::scoped_interpreter guard{};
104
105 try {
106 auto locals = py::dict();
107 py::exec(src, py::globals(), locals);
108
109 if (locals.contains("scn"))
110 {
111 auto scene = locals["scn"].cast<std::shared_ptr<dyno::SceneGraph>>();
112 if (scene) mSignal.emit(scene);
113 }
114 else
115 {
116 Wt::WMessageBox::show("Error", "Please define 'scn = dyno.SceneGraph()'", Wt::StandardButton::Ok);
117 }
118 }
119 catch (const std::exception& e) {
120 Wt::WMessageBox::show("Error", e.what(), Wt::StandardButton::Ok);
121 flag = false;
122 }
123}
Wt::WText * mCodeEditor
Wt::Signal< std::shared_ptr< dyno::SceneGraph > > mSignal
void execute(const std::string &src)
void setText(const std::string &text)