Commit 1f9ff630 authored by Freddy's avatar Freddy

Initial python support

parent e8acb480
[submodule "libs/crunch"]
path = libs/crunch
url = https://github.com/DaemonEngine/crunch.git
[submodule "libs/pybind11"]
path = libs/pybind11
url = https://github.com/pybind/pybind11
......@@ -4,6 +4,7 @@ project(NetRadiant C CXX)
option(BUILD_RADIANT "Build the GUI" ON)
option(BUILD_CRUNCH "Build Crunch image support" OFF)
option(EMBED_PYTHON "Embed python" ON)
option(USE_WERROR "Build with -Werror -pedantic-errors" OFF)
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
......@@ -65,7 +66,8 @@ endif ()
# Flags
#-----------------------------------------------------------------------
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
# TODO: check why these CXX flags were set
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
macro(addflags_c args)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${args}")
endmacro()
......@@ -145,6 +147,9 @@ else ()
-DPOSIX=1
)
endif ()
if (EMBED_PYTHON)
add_definitions(-D_EMBED_PYTHON)
endif ()
if (XWINDOWS)
find_package(X11 REQUIRED)
......
......@@ -19,6 +19,9 @@ add_subdirectory(modulesystem)
add_subdirectory(os)
add_subdirectory(picomodel)
add_subdirectory(profile)
if (EMBED_PYTHON)
add_subdirectory(pybind11)
endif ()
add_subdirectory(script)
add_subdirectory(signal)
add_subdirectory(splines)
......
Subproject commit e2b884c33bcde70b2ea562ffa52dd7ebee276d50
......@@ -93,6 +93,11 @@ set(RADIANTLIST
if (WIN32)
list(APPEND RADIANTLIST multimon.cpp multimon.h)
endif ()
if (EMBED_PYTHON)
list(APPEND RADIANTLIST
pybindconnector.cpp pybindconnector.h
pythonconsole.cpp pythonconsole.h)
endif ()
radiant_tool(radiant WIN32 radiant.rc ${RADIANTLIST})
add_dependencies(radiant modules)
......@@ -129,5 +134,8 @@ target_link_libraries(radiant
if (X11_LIBRARIES)
target_link_libraries(radiant ${X11_LIBRARIES})
endif ()
if (EMBED_PYTHON)
target_link_libraries(radiant pybind11::embed)
endif ()
copy_dlls(radiant)
......@@ -94,6 +94,10 @@
#include <windows.h>
#endif
#ifdef _EMBED_PYTHON
#include "pybindconnector.h"
#endif // _EMBED_PYTHON
void show_splash();
void hide_splash();
......@@ -645,6 +649,9 @@ int main(int argc, char *argv[])
g_GamesDialog.m_bForceLogConsole = false;
}
#ifdef _EMBED_PYTHON
PYBIND_initializeInterpreter();
#endif // _EMBED_PYTHON
Radiant_Initialise();
......@@ -690,6 +697,10 @@ int main(int argc, char *argv[])
Radiant_Shutdown();
#ifdef _EMBED_PYTHON
PYBIND_finalizeInterpreter();
#endif // _EMBED_PYTHON
// close the log file if any
Sys_LogFile(false);
......
......@@ -86,6 +86,9 @@
#include "pluginmenu.h"
#include "plugintoolbar.h"
#include "preferences.h"
#ifdef _EMBED_PYTHON
#include "pythonconsole.h"
#endif // _EMBED_PYTHON
#include "qe3.h"
#include "qgl.h"
#include "select.h"
......@@ -1210,6 +1213,15 @@ void Console_ToggleShow()
GroupDialog_showPage(g_page_console);
}
#ifdef _EMBED_PYTHON
ui::Widget g_page_pythonconsole{ui::null};
void PythonConsole_ToggleShow()
{
GroupDialog_showPage(g_page_pythonconsole);
}
#endif // _EMBED_PYTHON
ui::Widget g_page_entity{ui::null};
void EntityInspector_ToggleShow()
......@@ -3115,6 +3127,13 @@ void MainFrame::Create()
RawStringExportCaller("Console"));
}
#ifdef _EMBED_PYTHON
if (FloatingGroupDialog()) {
g_page_pythonconsole = GroupDialog_addPage("Python", PythonConsole_constructWindow(GroupDialog_getWindow()),
RawStringExportCaller("Python"));
}
#endif // _EMBED_PYTHON
#if GDEF_OS_WINDOWS
if ( g_multimon_globals.m_bStartOnPrimMon ) {
PositionWindowOnPrimaryScreen( g_layout_globals.m_position );
......
/*
Copyright (C) 2018, Sebastian Schmidt
All Rights Reserved.
This file is part of NetRadiant.
NetRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
NetRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with NetRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <cstdlib>
#include <string>
#include "pybindconnector.h"
#include "../libs/pybind11/include/pybind11/embed.h"
#include <../libs/pybind11/include/pybind11/eval.h>
namespace py = pybind11;
static py::dict scope;
// // TODO: embedded modules
// PYBIND11_EMBEDDED_MODULE(radiant, m) {
// m.def("TODO", [](){});
// }
void PYBIND_initializeInterpreter() {
py::initialize_interpreter();
scope = py::module::import("__main__").attr("__dict__");
}
std::string PYBIND_callfunction(std::string modulename,std::string functionname) {
py::object module = py::module::import(modulename.c_str());
py::object f = module.attr(functionname.c_str());
py::str result = f();
return result.cast<std::string>();
}
void PYBIND_exec(std::string code)
{
py::exec(code.c_str(), scope);
}
std::string PYBIND_scope_as_string()
{
return py::str(scope).cast<std::string>();
}
void PYBIND_finalizeInterpreter() {
scope.release();
py::finalize_interpreter();
}
/*
Copyright (C) 2018, Sebastian Schmidt
All Rights Reserved.
This file is part of NetRadiant.
NetRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
NetRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with NetRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined(PYBIND_CONNECTOR_H)
#define PYBIND_CONNECTOR_H
void PYBIND_initializeInterpreter();
std::string PYBIND_callfunction(std::string modulename, std::string functionname); // TODO: support for arguments
void PYBIND_exec(std::string code);
std::string PYBIND_scope_as_string();
void PYBIND_finalizeInterpreter();
#endif // PYBIND_CONNECTOR_H
/*
Copyright (C) 2018, Sebastian Schmidt
All Rights Reserved.
This file is part of NetRadiant.
NetRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
NetRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with NetRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "pythonconsole.h"
#include <uilib/uilib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "gtkutil/accelerator.h"
#include "gtkutil/messagebox.h"
#include "gtkutil/container.h"
#include "gtkutil/menu.h"
#include "gtkutil/nonmodal.h"
#include "pybindconnector.h"
ui::TextView g_pythonconsole_output{ui::null};
static gint Input_keypress(ui::Entry widget, GdkEventKey *event, gpointer data)
{
if (event->keyval == GDK_KEY_Return) {
try
{
// auto result = PYBIND_callfunction("os", std::string(widget.text()));
PYBIND_exec(std::string(widget.text()));
std::string result = PYBIND_scope_as_string();
g_pythonconsole_output.text(result.c_str());
}
catch (const std::exception& e)
{
g_pythonconsole_output.text(e.what());
}
widget.text("");
return TRUE;
}
if (event->keyval == GDK_KEY_Escape) {
gtk_window_set_focus(widget.window(), NULL);
return TRUE;
}
return FALSE;
}
ui::Widget PythonConsole_constructWindow(ui::Window toplevel)
{
auto vBox = ui::VBox(FALSE, 2);
vBox.show();
gtk_container_set_border_width(GTK_CONTAINER(vBox), 2);
auto scr = ui::ScrolledWindow(ui::New);
scr.overflow(ui::Policy::AUTOMATIC, ui::Policy::AUTOMATIC);
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scr), GTK_SHADOW_IN);
scr.show();
{
auto text = ui::TextView(ui::New);
text.dimensions(0, -1); // allow shrinking
gtk_text_view_set_wrap_mode(text, GTK_WRAP_WORD);
gtk_text_view_set_editable(text, FALSE);
scr.add(text);
text.show();
g_pythonconsole_output = text;
}
auto input = ui::Entry(ui::New);
input.show();
gtk_widget_set_events(input, GDK_KEY_PRESS_MASK);
input.connect("key_press_event", G_CALLBACK(Input_keypress), 0);
vBox.pack_start(scr, TRUE, TRUE, 0);
vBox.pack_end(input, FALSE, FALSE, 0);
gtk_container_set_focus_chain(GTK_CONTAINER(vBox), NULL);
return vBox;
}
/*
Copyright (C) 2018, Sebastian Schmidt
All Rights Reserved.
This file is part of NetRadiant.
NetRadiant is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
NetRadiant is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with NetRadiant; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#if !defined( INCLUDED_PYTHONCONSOLE_H )
#define INCLUDED_PYTHONCONSOLE_H
#include <uilib/uilib.h>
ui::Widget PythonConsole_constructWindow(ui::Window toplevel);
#endif // INCLUDED_PYTHONCONSOLE_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment