Begin experimental guile support

This commit is contained in:
Dane Johnson 2021-05-06 16:24:51 -05:00
parent 44e8f784f5
commit f79b33e8dc
7 changed files with 225 additions and 12 deletions

View File

@ -12,11 +12,25 @@ if (LUA_ENABLED)
find_package(Lua REQUIRED)
include_directories(${LUA_INCLUDE_DIR})
endif ()
option(GUILE_ENABLED "Guile 2.0 scripting support" OFF)
if (GUILE_ENABLED)
add_compile_definitions(GUILE_SCRIPTING)
## Find pkg-config
find_package(PkgConfig REQUIRED)
## Use pkg-config to find Guile 2.0
pkg_check_modules(GUILE REQUIRED guile-2.0)
include_directories(${GUILE_INCLUDE_DIRS})
endif ()
add_executable(couch core/couch.cpp)
add_subdirectory(core)
target_link_libraries(couch couchlib)
target_link_libraries(couch couchlib_luascripting)
target_link_libraries(couch couchlib_guilescripting)
add_subdirectory(scripting)
if (LUA_ENABLED)

View File

@ -65,12 +65,16 @@ target_sources(couchlib PUBLIC
add_library(couchlib_luascripting STATIC)
target_sources(couchlib_luascripting PUBLIC
Scripting/Lua.h
Scripting/Lua.cpp)
target_link_libraries(couchlib_luascripting couchlua)
add_library(couchlib_guilescripting STATIC)
target_sources(couchlib_guilescripting PUBLIC
Scripting/Guile.h
Scripting/Guile.cpp)
target_link_libraries(couchlib_guilescripting couchguile)
target_include_directories(couchlib
PUBLIC
@ -89,7 +93,10 @@ target_link_libraries(couchlib OpenGL::GL)
target_link_libraries(couchlib GLEW::GLEW)
if (LUA_ENABLED)
target_link_libraries(couchlib_luascripting ${LUA_LIBRARIES})
endif ()
endif ()
if (GUILE_ENABLED)
target_link_libraries(couchlib_guilescripting ${GUILE_LIBRARIES})
endif ()
target_link_libraries(couchlib ${BULLET_LIBRARIES})
target_link_libraries(couchlib ${ASSIMP_LIBRARY})

103
core/Scripting/Guile.cpp Normal file
View File

@ -0,0 +1,103 @@
#include "Guile.h"
#include "../Util.h"
void Guile::Initialize() {
#ifdef GUILE_SCRIPTING
language = this;
// Initialize Guile
scm_with_guile(Guile::inner_init, NULL);
// Bind input functions
Input *input = Input::GetInstance();
if (HasHook("onkey")) {
input->keyHandlers.push_back(GuileKeyHandler);
}
if (HasHook("onmousemotion")) {
input->mousePositionHandlers.push_back(GuileMousePositionHandler);
}
#else // GUILE_SCRIPTING
Util::Die("Guile is selected as the scripting language, but this binary was built without Guile support.");
#endif // GUILE_SCRIPTING
}
void Guile::Update(double delta) {
#ifdef GUILE_SCRIPTING
if (HasHook("update")) {
scm_with_guile(Guile::inner_update, &delta);
}
#endif // GUILE_SCRIPTING
}
void Guile::Close() {
// Nothing to do
}
bool Guile::HasHook(const char *name) {
bool exists = false;
#ifdef GUILE_SCRIPTING
exists = scm_with_guile(Guile::inner_has_hook, (void *) name);
#endif // GUILE_SCRIPTING
return exists;
}
#ifdef GUILE_SCRIPTING
void Guile::GuileKeyHandler(int key, int code, int action, int mods) {
Guile::key_event ev {key, code, action, mods};
scm_with_guile(Guile::inner_key_handler, &ev);
}
void Guile::GuileMousePositionHandler(double xpos, double ypos, double relx, double rely) {
Guile::mouse_position_event ev {xpos, ypos, relx, rely};
scm_with_guile(Guile::inner_mouse_position_handler, &ev);
}
void *Guile::inner_init(void* empty) {
// Init swig
SWIG_init();
// Load main file
scm_c_primitive_load("main.scm");
// Execute the init function if it exists
if (ScriptingLanguage::language->HasHook("init")) {
scm_call_0(scm_c_eval_string("init"));
}
}
void *Guile::inner_update(void *data) {
double delta = *(double*) data;
if (ScriptingLanguage::language->HasHook("update")) {
scm_call_1(scm_c_eval_string("update"), scm_from_double(delta));
}
}
void *Guile::inner_has_hook(void *data) {
const char *name = (const char *) data;
return (void *) scm_to_bool(scm_defined_p(scm_from_locale_symbol(name), SCM_UNDEFINED));
}
void *Guile::inner_key_handler(void *data) {
Guile::key_event *ev = (Guile::key_event*) data;
if (ScriptingLanguage::language->HasHook("onkey")) {
scm_call_4(scm_c_eval_string("onkey"),
scm_from_int(ev->key),
scm_from_int(ev->code),
scm_from_int(ev->action),
scm_from_int(ev->mods));
}
}
void *Guile::inner_mouse_position_handler(void *data) {
Guile::mouse_position_event *ev = (Guile::mouse_position_event *) data;
if (ScriptingLanguage::language->HasHook("onmousemotion")) {
scm_call_4(scm_c_eval_string("onmousemotion"),
scm_from_double(ev->xpos),
scm_from_double(ev->ypos),
scm_from_double(ev->relx),
scm_from_double(ev->rely));
}
}
#endif // GUILE_SCRIPTING

46
core/Scripting/Guile.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef GUILE_H
#define GUILE_H
#include "../Input.h"
#ifdef GUILE_SCRIPTING
#include <libguile.h>
extern "C" void SWIG_init();
#endif // GUILE_SCRIPTING
#include "ScriptingLanguage.h"
class Guile : public ScriptingLanguage {
public:
void Initialize();
void Update(double delta);
void Close();
bool HasHook(const char *name);
private:
#ifdef GUILE_SCRIPTING
struct key_event {
int key;
int code;
int action;
int mods;
};
struct mouse_position_event {
double xpos;
double ypos;
double relx;
double rely;
};
static void *inner_init(void *empty);
static void *inner_update(void *delta);
static void *inner_has_hook(void *name);
static void *inner_key_handler(void *ev);
static void *inner_mouse_position_handler(void *ev);
static void GuileKeyHandler(int key, int code, int action, int mods);
static void GuileMousePositionHandler(double xpos, double ypos, double relx, double rely);
#endif // GUILE_SCRIPTING
};
#endif /* GUILE_H */

View File

@ -30,11 +30,14 @@
#include "Rigidbody.h"
#include "World.h"
#include "Scripting/Lua.h"
#include "Scripting/Guile.h"
Node *root;
char script_type = 'l';
ScriptingLanguage *sl;
void render(Node *curr, Shader *shader, Matrix model) {
Spatial *spatial = dynamic_cast<Spatial*>(curr);
if (spatial) {
@ -57,11 +60,27 @@ void render(Node *curr, Shader *shader, Matrix model) {
}
}
void parse_args(int argc, char* argv[]) {
int curr = 1;
while (curr < argc) {
if (argv[curr][0] == '-') {
switch(argv[curr][1]) {
case 'l':
++curr;
script_type = argv[curr][0];
++curr;
break;
}
} else {
chdir(argv[curr]);
++curr;
}
}
}
int main(int argc, char *argv[]) {
if (argc == 2) {
chdir(argv[1]);
}
parse_args(argc, argv);
Window window;
window.Init();
@ -84,9 +103,15 @@ int main(int argc, char *argv[]) {
Matrix projection = glm::perspective(glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.0f);
// TODO Allow multiple scripting languages
Lua *lua = new Lua();
lua->Initialize();
switch(script_type) {
case 'l':
sl = new Lua();
break;
case 'g':
sl = new Guile();
break;
}
sl->Initialize();
double lastTime = glfwGetTime();
@ -97,7 +122,7 @@ int main(int argc, char *argv[]) {
world->Step(delta);
// Script update
lua->Update(delta);
ScriptingLanguage::GetCurrentLanguage()->Update(delta);
// Delete freed nodes
root->DoFree();
@ -158,7 +183,7 @@ int main(int argc, char *argv[]) {
lastTime = curTime;
}
lua->Close();
ScriptingLanguage::GetCurrentLanguage()->Close();
window.Close();
return 0;
}

View File

@ -0,0 +1,5 @@
(define (init)
(display "Hello from init!")
(newline))
(display "Hello from main.scm!")
(newline)

View File

@ -4,7 +4,6 @@ set_property(SOURCE couch.i PROPERTY CPLUSPLUS ON)
set_property(SOURCE couch.i PROPERTY USE_TARGET_INCLUDE_DIRECTORIES ON)
if (LUA_ENABLED)
## Find Lua
swig_add_library(couchlua
TYPE STATIC
LANGUAGE lua
@ -17,3 +16,17 @@ if (LUA_ENABLED)
couchlib
${LUA_LIBRARIES})
endif ()
if (GUILE_ENABLED)
swig_add_library(couchguile
TYPE STATIC
LANGUAGE guile
SOURCES couch.i)
target_include_directories(couchguile PRIVATE "${PROJECT_SOURCE_DIR}/core")
swig_link_libraries(couchguile
PRIVATE
couchlib
${GUILE_LIBRARIES})
endif ()