4004 lines
178 KiB
C++
4004 lines
178 KiB
C++
#include <map>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <kinc/log.h>
|
|
#include <kinc/io/filereader.h>
|
|
#include <kinc/io/filewriter.h>
|
|
#ifdef WITH_AUDIO
|
|
#include <kinc/audio1/audio.h>
|
|
#include <kinc/audio1/sound.h>
|
|
#include <kinc/audio2/audio.h>
|
|
#endif
|
|
#include <kinc/system.h>
|
|
#include <kinc/window.h>
|
|
#include <kinc/display.h>
|
|
#include <kinc/input/mouse.h>
|
|
#include <kinc/input/surface.h>
|
|
#include <kinc/input/keyboard.h>
|
|
#include <kinc/input/pen.h>
|
|
#include <kinc/input/gamepad.h>
|
|
#include <kinc/math/random.h>
|
|
#include <kinc/math/core.h>
|
|
#include <kinc/threads/thread.h>
|
|
#include <kinc/threads/mutex.h>
|
|
#ifdef WITH_NETWORKING
|
|
#include <kinc/network/http.h>
|
|
#include "httprequest.h"
|
|
#include "websocket_config.h"
|
|
|
|
#include "socket_bridge.h"
|
|
#include "socket_v8_bindings.h"
|
|
|
|
#ifdef WITH_UWS
|
|
#include "uws_websocket_bridge.h"
|
|
#include "uws_websocket_v8_bindings.h"
|
|
#else
|
|
#include "websocket_bridge.h"
|
|
#include "websocket_v8_bindings.h"
|
|
#include "websocket.h"
|
|
#endif
|
|
|
|
#ifdef WITH_BENCHMARK
|
|
#include "BENCHMARK/websocket_benchmark.h"
|
|
extern "C" void websocket_run_benchmark();
|
|
extern "C" void websocket_run_groupchat_test(int rate, int duration);
|
|
#endif
|
|
|
|
#endif
|
|
|
|
//#include "socket_connection_test.cpp"
|
|
#include <kinc/graphics4/shader.h>
|
|
#include <kinc/graphics4/vertexbuffer.h>
|
|
#include <kinc/graphics4/indexbuffer.h>
|
|
#include <kinc/graphics4/graphics.h>
|
|
#include <kinc/graphics4/pipeline.h>
|
|
#include <kinc/graphics4/rendertarget.h>
|
|
#include <kinc/graphics4/texture.h>
|
|
#ifdef WITH_COMPUTE
|
|
#include <kinc/graphics4/compute.h>
|
|
#endif
|
|
#include <kinc/io/lz4/lz4.h>
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
#include <kinc/libs/stb_image.h>
|
|
#ifdef KORE_DIRECT3D11
|
|
#include <d3d11.h>
|
|
#endif
|
|
|
|
#include <libplatform/libplatform.h>
|
|
#ifdef KORE_LINUX // xlib defines conflicting with v8
|
|
#undef True
|
|
#undef False
|
|
#undef None
|
|
#undef Status
|
|
#endif
|
|
#include <v8.h>
|
|
#include <v8-fast-api-calls.h>
|
|
|
|
#ifdef KORE_WINDOWS
|
|
#include <Windows.h> // AttachConsole
|
|
#include <dwmapi.h>
|
|
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
|
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
|
#endif
|
|
extern "C" struct HWND__ *kinc_windows_window_handle(int window_index); // Kore/Windows.h
|
|
bool show_window = false;
|
|
// Enable visual styles for ui controls
|
|
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
|
#endif
|
|
|
|
#ifdef WITH_WORKER
|
|
#include "worker.h"
|
|
#endif
|
|
|
|
#ifdef WITH_VIEWPORT
|
|
#include "viewport_server.h"
|
|
#endif
|
|
|
|
// TODO
|
|
//#ifdef KINC_KONG
|
|
//#include <kong.h>
|
|
//#endif
|
|
|
|
#include <chrono>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
using namespace v8;
|
|
|
|
#ifdef KORE_MACOS
|
|
extern "C" const char *macgetresourcepath();
|
|
#endif
|
|
|
|
namespace {
|
|
int _argc;
|
|
char **_argv;
|
|
bool enable_window = true;
|
|
#ifdef WITH_AUDIO
|
|
bool enable_audio = true;
|
|
#endif
|
|
bool snapshot = false;
|
|
bool stderr_created = false;
|
|
bool in_background = false;
|
|
int paused_frames = 0;
|
|
|
|
#ifdef WITH_VIEWPORT
|
|
bool viewport_server_mode = false;
|
|
char viewport_shmem_name[256] = VIEWPORT_SHMEM_NAME;
|
|
int viewport_width = 1920;
|
|
int viewport_height = 1080;
|
|
#endif
|
|
|
|
Isolate *isolate;
|
|
std::unique_ptr<Platform> plat;
|
|
Global<Context> global_context;
|
|
Global<Function> update_func;
|
|
Global<Function> drop_files_func;
|
|
Global<Function> cut_func;
|
|
Global<Function> copy_func;
|
|
Global<Function> paste_func;
|
|
Global<Function> foreground_func;
|
|
Global<Function> resume_func;
|
|
Global<Function> pause_func;
|
|
Global<Function> background_func;
|
|
Global<Function> shutdown_func;
|
|
Global<Function> keyboard_down_func;
|
|
Global<Function> keyboard_up_func;
|
|
Global<Function> keyboard_press_func;
|
|
Global<Function> mouse_down_func;
|
|
Global<Function> mouse_up_func;
|
|
Global<Function> mouse_move_func;
|
|
Global<Function> touch_down_func;
|
|
Global<Function> touch_up_func;
|
|
Global<Function> touch_move_func;
|
|
Global<Function> mouse_wheel_func;
|
|
Global<Function> pen_down_func;
|
|
Global<Function> pen_up_func;
|
|
Global<Function> pen_move_func;
|
|
Global<Function> gamepad_axis_func;
|
|
Global<Function> gamepad_button_func;
|
|
Global<Function> save_and_quit_func;
|
|
|
|
#ifdef WITH_AUDIO
|
|
Global<Function> audio_func;
|
|
kinc_mutex_t mutex;
|
|
kinc_a2_buffer_t audio_buffer;
|
|
int audio_read_location = 0;
|
|
void update_audio(kinc_a2_buffer_t *buffer, int samples);
|
|
#endif
|
|
|
|
bool save_and_quit_func_set = false;
|
|
void update(void *data);
|
|
void drop_files(wchar_t *file_path, void *data);
|
|
char *cut(void *data);
|
|
char *copy(void *data);
|
|
void paste(char *text, void *data);
|
|
void foreground(void *data);
|
|
void resume(void *data);
|
|
void pause(void *data);
|
|
void background(void *data);
|
|
void shutdown(void *data);
|
|
void key_down(int code, void *data);
|
|
void key_up(int code, void *data);
|
|
void key_press(unsigned int character, void *data);
|
|
void mouse_move(int window, int x, int y, int mx, int my, void *data);
|
|
void mouse_down(int window, int button, int x, int y, void *data);
|
|
void mouse_up(int window, int button, int x, int y, void *data);
|
|
void mouse_wheel(int window, int delta, void *data);
|
|
void touch_move(int index, int x, int y);
|
|
void touch_down(int index, int x, int y);
|
|
void touch_up(int index, int x, int y);
|
|
void pen_down(int window, int x, int y, float pressure);
|
|
void pen_up(int window, int x, int y, float pressure);
|
|
void pen_move(int window, int x, int y, float pressure);
|
|
void gamepad_axis(int gamepad, int axis, float value);
|
|
void gamepad_button(int gamepad, int button, float value);
|
|
|
|
char temp_string[4096];
|
|
char temp_string_vs[1024 * 1024];
|
|
char temp_string_fs[1024 * 1024];
|
|
char temp_string_vstruct[4][32][32];
|
|
std::string assetsdir;
|
|
#ifdef KORE_WINDOWS
|
|
wchar_t temp_wstring[1024];
|
|
wchar_t temp_wstring1[1024];
|
|
#endif
|
|
|
|
class RunTCallbackdata {
|
|
public:
|
|
int32_t size;
|
|
Global<Function> func;
|
|
};
|
|
|
|
void write_stack_trace(const char *stack_trace) {
|
|
kinc_log(KINC_LOG_LEVEL_INFO, "Trace: %s", stack_trace);
|
|
|
|
#ifdef KORE_WINDOWS
|
|
FILE *file = fopen("stderr.txt", stderr_created ? "a" : "w");
|
|
if (file == nullptr) { // Running from protected path
|
|
strcpy(temp_string, kinc_internal_save_path());
|
|
strcat(temp_string, "\\stderr.txt");
|
|
file = fopen(temp_string, stderr_created ? "a" : "w");
|
|
}
|
|
if (file != nullptr) {
|
|
stderr_created = true;
|
|
fwrite(stack_trace, 1, strlen(stack_trace), file);
|
|
fwrite("\n", 1, 1, file);
|
|
fclose(file);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void handle_exception(TryCatch *try_catch) {
|
|
MaybeLocal<Value> trace = try_catch->StackTrace(isolate->GetCurrentContext());
|
|
if (trace.IsEmpty()) {
|
|
String::Utf8Value stack_trace(isolate, try_catch->Message()->Get());
|
|
write_stack_trace(*stack_trace);
|
|
}
|
|
else {
|
|
String::Utf8Value stack_trace(isolate, trace.ToLocalChecked());
|
|
write_stack_trace(*stack_trace);
|
|
}
|
|
}
|
|
|
|
void runt_log(const FunctionCallbackInfo<Value> &args);
|
|
void runt_set_timeout(const FunctionCallbackInfo<Value> &args);
|
|
void runt_set_interval(const FunctionCallbackInfo<Value> &args);
|
|
void runt_clear_timeout(const FunctionCallbackInfo<Value> &args);
|
|
void runt_clear_interval(const FunctionCallbackInfo<Value> &args);
|
|
void execute_timers();
|
|
|
|
void runt_init(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
String::Utf8Value title(isolate, arg);
|
|
int width = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int height = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int samples_per_pixel = args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
bool vertical_sync = args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int window_mode = args[5]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int window_features = args[6]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
// int api_version = args[7]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int x = -1;
|
|
int y = -1;
|
|
int frequency = 60;
|
|
|
|
kinc_window_options_t win;
|
|
win.title = *title;
|
|
win.x = x;
|
|
win.y = y;
|
|
win.width = width;
|
|
win.height = height;
|
|
win.display_index = -1;
|
|
#ifdef KORE_WINDOWS
|
|
win.visible = false; // Prevent white flicker when opening the window
|
|
#else
|
|
win.visible = enable_window;
|
|
#endif
|
|
win.window_features = window_features;
|
|
win.mode = (kinc_window_mode_t)window_mode;
|
|
kinc_framebuffer_options_t frame;
|
|
frame.frequency = frequency;
|
|
frame.vertical_sync = vertical_sync;
|
|
frame.color_bits = 32;
|
|
frame.depth_bits = 0;
|
|
frame.stencil_bits = 0;
|
|
frame.samples_per_pixel = samples_per_pixel;
|
|
kinc_init(*title, width, height, &win, &frame);
|
|
kinc_random_init((int)(kinc_time() * 1000));
|
|
|
|
#ifdef KORE_WINDOWS
|
|
// Maximized window has x < -1, prevent window centering done by kinc
|
|
if (x < -1 && y < -1) {
|
|
kinc_window_move(0, x, y);
|
|
}
|
|
|
|
char vdata[4];
|
|
DWORD cbdata = 4 * sizeof(char);
|
|
RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", L"AppsUseLightTheme", RRF_RT_REG_DWORD, nullptr, vdata, &cbdata);
|
|
BOOL use_dark_mode = int(vdata[3] << 24 | vdata[2] << 16 | vdata[1] << 8 | vdata[0]) != 1;
|
|
DwmSetWindowAttribute(kinc_windows_window_handle(0), DWMWA_USE_IMMERSIVE_DARK_MODE, &use_dark_mode, sizeof(use_dark_mode));
|
|
|
|
show_window = true;
|
|
#endif
|
|
|
|
#ifdef WITH_AUDIO
|
|
if (enable_audio) {
|
|
kinc_mutex_init(&mutex);
|
|
kinc_a1_init();
|
|
kinc_a2_init();
|
|
kinc_a2_set_callback(update_audio);
|
|
audio_buffer.read_location = 0;
|
|
audio_buffer.write_location = 0;
|
|
audio_buffer.data_size = 128 * 1024;
|
|
audio_buffer.data = new uint8_t[audio_buffer.data_size];
|
|
}
|
|
#endif
|
|
|
|
kinc_set_update_callback(update, NULL);
|
|
kinc_set_drop_files_callback(drop_files, NULL);
|
|
kinc_set_copy_callback(copy, NULL);
|
|
kinc_set_cut_callback(cut, NULL);
|
|
kinc_set_paste_callback(paste, NULL);
|
|
kinc_set_foreground_callback(foreground, NULL);
|
|
kinc_set_resume_callback(resume, NULL);
|
|
kinc_set_pause_callback(pause, NULL);
|
|
kinc_set_background_callback(background, NULL);
|
|
kinc_set_shutdown_callback(shutdown, NULL);
|
|
|
|
kinc_keyboard_set_key_down_callback(key_down, NULL);
|
|
kinc_keyboard_set_key_up_callback(key_up, NULL);
|
|
kinc_keyboard_set_key_press_callback(key_press, NULL);
|
|
kinc_mouse_set_move_callback(mouse_move, NULL);
|
|
kinc_mouse_set_press_callback(mouse_down, NULL);
|
|
kinc_mouse_set_release_callback(mouse_up, NULL);
|
|
kinc_mouse_set_scroll_callback(mouse_wheel, NULL);
|
|
kinc_surface_set_move_callback(touch_move);
|
|
kinc_surface_set_touch_start_callback(touch_down);
|
|
kinc_surface_set_touch_end_callback(touch_up);
|
|
kinc_pen_set_press_callback(pen_down);
|
|
kinc_pen_set_move_callback(pen_move);
|
|
kinc_pen_set_release_callback(pen_up);
|
|
kinc_gamepad_set_axis_callback(gamepad_axis);
|
|
kinc_gamepad_set_button_callback(gamepad_button);
|
|
}
|
|
|
|
void runt_set_application_name(const FunctionCallbackInfo<Value> &args) {
|
|
// Name used by kinc_internal_save_path()
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value name(isolate, args[0]);
|
|
kinc_set_application_name(*name);
|
|
}
|
|
|
|
void runt_log(const FunctionCallbackInfo<Value> &args) {
|
|
Isolate* current_isolate = args.GetIsolate();
|
|
HandleScope scope(current_isolate);
|
|
if (args.Length() == 0) {
|
|
return;
|
|
}
|
|
Local<Value> arg = args[0];
|
|
String::Utf8Value value(current_isolate, arg);
|
|
size_t len = strlen(*value);
|
|
if (len < 2048) {
|
|
kinc_log(KINC_LOG_LEVEL_INFO, *value);
|
|
}
|
|
else {
|
|
int pos = 0;
|
|
while (pos < len) {
|
|
strncpy(temp_string, *value + pos, 2047);
|
|
temp_string[2047] = 0;
|
|
kinc_log(KINC_LOG_LEVEL_INFO, temp_string);
|
|
pos += 2047;
|
|
}
|
|
}
|
|
}
|
|
|
|
void runt_clear_fast(Local<Object> receiver, int flags, int color, float depth, int stencil) {
|
|
kinc_g4_clear(flags, color, depth, stencil);
|
|
}
|
|
|
|
void runt_clear(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int flags = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int color = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float depth = (float)args[2]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int stencil = args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
runt_clear_fast(args.This(), flags, color, depth, stencil);
|
|
}
|
|
|
|
void runt_set_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
update_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_drop_files_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
drop_files_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_cut_copy_paste_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> cutArg = args[0];
|
|
Local<Function> cutFunc = Local<Function>::Cast(cutArg);
|
|
cut_func.Reset(isolate, cutFunc);
|
|
Local<Value> copyArg = args[1];
|
|
Local<Function> copyFunc = Local<Function>::Cast(copyArg);
|
|
copy_func.Reset(isolate, copyFunc);
|
|
Local<Value> pasteArg = args[2];
|
|
Local<Function> pasteFunc = Local<Function>::Cast(pasteArg);
|
|
paste_func.Reset(isolate, pasteFunc);
|
|
}
|
|
|
|
void runt_set_application_state_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> foregroundArg = args[0];
|
|
Local<Function> foregroundFunc = Local<Function>::Cast(foregroundArg);
|
|
foreground_func.Reset(isolate, foregroundFunc);
|
|
Local<Value> resumeArg = args[1];
|
|
Local<Function> resumeFunc = Local<Function>::Cast(resumeArg);
|
|
resume_func.Reset(isolate, resumeFunc);
|
|
Local<Value> pauseArg = args[2];
|
|
Local<Function> pauseFunc = Local<Function>::Cast(pauseArg);
|
|
pause_func.Reset(isolate, pauseFunc);
|
|
Local<Value> backgroundArg = args[3];
|
|
Local<Function> backgroundFunc = Local<Function>::Cast(backgroundArg);
|
|
background_func.Reset(isolate, backgroundFunc);
|
|
Local<Value> shutdownArg = args[4];
|
|
Local<Function> shutdownFunc = Local<Function>::Cast(shutdownArg);
|
|
shutdown_func.Reset(isolate, shutdownFunc);
|
|
}
|
|
|
|
void runt_set_keyboard_down_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
keyboard_down_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_keyboard_up_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
keyboard_up_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_keyboard_press_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
keyboard_press_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_mouse_down_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
mouse_down_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_mouse_up_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
mouse_up_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_mouse_move_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
mouse_move_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_touch_down_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
touch_down_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_touch_up_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
touch_up_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_touch_move_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
touch_move_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_mouse_wheel_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
mouse_wheel_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_pen_down_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
pen_down_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_pen_up_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
pen_up_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_pen_move_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
pen_move_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_gamepad_axis_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
gamepad_axis_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_set_gamepad_button_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
gamepad_button_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_lock_mouse_fast(Local<Object> receiver) {
|
|
kinc_mouse_lock(0);
|
|
}
|
|
|
|
void runt_lock_mouse(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
runt_lock_mouse_fast(args.This());
|
|
}
|
|
|
|
void runt_unlock_mouse_fast(Local<Object> receiver) {
|
|
kinc_mouse_unlock();
|
|
}
|
|
|
|
void runt_unlock_mouse(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
runt_unlock_mouse_fast(args.This());
|
|
}
|
|
|
|
int runt_can_lock_mouse_fast(Local<Object> receiver) {
|
|
return kinc_mouse_can_lock();
|
|
}
|
|
|
|
void runt_can_lock_mouse(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(Int32::New(isolate, runt_can_lock_mouse_fast(args.This())));
|
|
}
|
|
|
|
int runt_is_mouse_locked_fast(Local<Object> receiver) {
|
|
return kinc_mouse_is_locked();
|
|
}
|
|
|
|
void runt_is_mouse_locked(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(Int32::New(isolate, runt_is_mouse_locked_fast(args.This())));
|
|
}
|
|
|
|
void runt_set_mouse_position_fast(Local<Object> receiver, int windowId, int x, int y) {
|
|
kinc_mouse_set_position(windowId, x, y);
|
|
}
|
|
|
|
void runt_set_mouse_position(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int x = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int y = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
runt_set_mouse_position_fast(args.This(), windowId, x, y);
|
|
}
|
|
|
|
void runt_show_mouse_fast(Local<Object> receiver, int show) {
|
|
show ? kinc_mouse_show() : kinc_mouse_hide();
|
|
}
|
|
|
|
void runt_show_mouse(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int show = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
runt_show_mouse_fast(args.This(), show);
|
|
}
|
|
|
|
void runt_show_keyboard_fast(Local<Object> receiver, int show) {
|
|
show ? kinc_keyboard_show() : kinc_keyboard_hide();
|
|
}
|
|
|
|
void runt_show_keyboard(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int show = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
runt_show_keyboard_fast(args.This(), show);
|
|
}
|
|
|
|
void runt_create_indexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
kinc_g4_index_buffer_t *buffer = (kinc_g4_index_buffer_t *)malloc(sizeof(kinc_g4_index_buffer_t));
|
|
kinc_g4_index_buffer_init(buffer, args[0]->Int32Value(isolate->GetCurrentContext()).FromJust(), KINC_G4_INDEX_BUFFER_FORMAT_32BIT, KINC_G4_USAGE_STATIC);
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, buffer));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_delete_indexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_index_buffer_t *buffer = (kinc_g4_index_buffer_t *)field->Value();
|
|
kinc_g4_index_buffer_destroy(buffer);
|
|
free(buffer);
|
|
}
|
|
|
|
void runt_lock_indexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_index_buffer_t *buffer = (kinc_g4_index_buffer_t *)field->Value();
|
|
int *vertices = (int *)kinc_g4_index_buffer_lock_all(buffer);
|
|
std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore((void *)vertices, kinc_g4_index_buffer_count(buffer) * sizeof(int), [](void *, size_t, void *) {}, nullptr);
|
|
Local<ArrayBuffer> abuffer = ArrayBuffer::New(isolate, std::move(backing));
|
|
args.GetReturnValue().Set(Uint32Array::New(abuffer, 0, kinc_g4_index_buffer_count(buffer)));
|
|
}
|
|
|
|
void runt_unlock_indexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_index_buffer_t *buffer = (kinc_g4_index_buffer_t *)field->Value();
|
|
kinc_g4_index_buffer_unlock_all(buffer);
|
|
}
|
|
|
|
void runt_set_indexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_index_buffer_t *buffer = (kinc_g4_index_buffer_t *)field->Value();
|
|
kinc_g4_set_index_buffer(buffer);
|
|
}
|
|
|
|
kinc_g4_vertex_data_t convert_vertex_data(int num) {
|
|
switch (num) {
|
|
case 0: // Float32_1X
|
|
return KINC_G4_VERTEX_DATA_F32_1X;
|
|
case 1: // Float32_2X
|
|
return KINC_G4_VERTEX_DATA_F32_2X;
|
|
case 2: // Float32_3X
|
|
return KINC_G4_VERTEX_DATA_F32_3X;
|
|
case 3: // Float32_4X
|
|
return KINC_G4_VERTEX_DATA_F32_4X;
|
|
case 4: // Float32_4X4
|
|
return KINC_G4_VERTEX_DATA_F32_4X4;
|
|
case 5: // Int8_1X
|
|
return KINC_G4_VERTEX_DATA_I8_1X;
|
|
case 6: // UInt8_1X
|
|
return KINC_G4_VERTEX_DATA_U8_1X;
|
|
case 7: // Int8_1X_Normalized
|
|
return KINC_G4_VERTEX_DATA_I8_1X_NORMALIZED;
|
|
case 8: // UInt8_1X_Normalized
|
|
return KINC_G4_VERTEX_DATA_U8_1X_NORMALIZED;
|
|
case 9: // Int8_2X
|
|
return KINC_G4_VERTEX_DATA_I8_2X;
|
|
case 10: // UInt8_2X
|
|
return KINC_G4_VERTEX_DATA_U8_2X;
|
|
case 11: // Int8_2X_Normalized
|
|
return KINC_G4_VERTEX_DATA_I8_2X_NORMALIZED;
|
|
case 12: // UInt8_2X_Normalized
|
|
return KINC_G4_VERTEX_DATA_U8_2X_NORMALIZED;
|
|
case 13: // Int8_4X
|
|
return KINC_G4_VERTEX_DATA_I8_4X;
|
|
case 14: // UInt8_4X
|
|
return KINC_G4_VERTEX_DATA_U8_4X;
|
|
case 15: // Int8_4X_Normalized
|
|
return KINC_G4_VERTEX_DATA_I8_4X_NORMALIZED;
|
|
case 16: // UInt8_4X_Normalized
|
|
return KINC_G4_VERTEX_DATA_U8_4X_NORMALIZED;
|
|
case 17: // Int16_1X
|
|
return KINC_G4_VERTEX_DATA_I16_1X;
|
|
case 18: // UInt16_1X
|
|
return KINC_G4_VERTEX_DATA_U16_1X;
|
|
case 19: // Int16_1X_Normalized
|
|
return KINC_G4_VERTEX_DATA_I16_1X_NORMALIZED;
|
|
case 20: // UInt16_1X_Normalized
|
|
return KINC_G4_VERTEX_DATA_U16_1X_NORMALIZED;
|
|
case 21: // Int16_2X
|
|
return KINC_G4_VERTEX_DATA_I16_2X;
|
|
case 22: // UInt16_2X
|
|
return KINC_G4_VERTEX_DATA_U16_2X;
|
|
case 23: // Int16_2X_Normalized
|
|
return KINC_G4_VERTEX_DATA_I16_2X_NORMALIZED;
|
|
case 24: // UInt16_2X_Normalized
|
|
return KINC_G4_VERTEX_DATA_U16_2X_NORMALIZED;
|
|
case 25: // Int16_4X
|
|
return KINC_G4_VERTEX_DATA_I16_4X;
|
|
case 26: // UInt16_4X
|
|
return KINC_G4_VERTEX_DATA_U16_4X;
|
|
case 27: // Int16_4X_Normalized
|
|
return KINC_G4_VERTEX_DATA_I16_4X_NORMALIZED;
|
|
case 28: // UInt16_4X_Normalized
|
|
return KINC_G4_VERTEX_DATA_U16_4X_NORMALIZED;
|
|
case 29: // Int32_1X
|
|
return KINC_G4_VERTEX_DATA_I32_1X;
|
|
case 30: // UInt32_1X
|
|
return KINC_G4_VERTEX_DATA_U32_1X;
|
|
case 31: // Int32_2X
|
|
return KINC_G4_VERTEX_DATA_I32_2X;
|
|
case 32: // UInt32_2X
|
|
return KINC_G4_VERTEX_DATA_U32_2X;
|
|
case 33: // Int32_3X
|
|
return KINC_G4_VERTEX_DATA_I32_3X;
|
|
case 34: // UInt32_3X
|
|
return KINC_G4_VERTEX_DATA_U32_3X;
|
|
case 35: // Int32_4X
|
|
return KINC_G4_VERTEX_DATA_I32_4X;
|
|
case 36: // UInt32_4X
|
|
return KINC_G4_VERTEX_DATA_U32_4X;
|
|
}
|
|
return KINC_G4_VERTEX_DATA_NONE;
|
|
}
|
|
|
|
void runt_create_vertexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<Object> jsstructure = args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
int32_t length = jsstructure->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "length").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_vertex_structure_t structure;
|
|
kinc_g4_vertex_structure_init(&structure);
|
|
for (int32_t i = 0; i < length; ++i) {
|
|
Local<Object> element = jsstructure->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<Value> str = element->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked()).ToLocalChecked();
|
|
String::Utf8Value utf8_value(isolate, str);
|
|
int32_t data = element->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "data").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
strcpy(temp_string_vstruct[0][i], *utf8_value);
|
|
kinc_g4_vertex_structure_add(&structure, temp_string_vstruct[0][i], convert_vertex_data(data));
|
|
}
|
|
kinc_g4_vertex_buffer_t *buffer = (kinc_g4_vertex_buffer_t *)malloc(sizeof(kinc_g4_vertex_buffer_t));
|
|
kinc_g4_vertex_buffer_init(buffer, args[0]->Int32Value(isolate->GetCurrentContext()).FromJust(), &structure, (kinc_g4_usage_t)args[2]->Int32Value(isolate->GetCurrentContext()).FromJust(), args[3]->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
obj->SetInternalField(0, External::New(isolate, buffer));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_delete_vertexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_vertex_buffer_t *buffer = (kinc_g4_vertex_buffer_t *)field->Value();
|
|
kinc_g4_vertex_buffer_destroy(buffer);
|
|
free(buffer);
|
|
}
|
|
|
|
void runt_lock_vertex_buffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_vertex_buffer_t *buffer = (kinc_g4_vertex_buffer_t *)field->Value();
|
|
int start = args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int count = args[2]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
float *vertices = kinc_g4_vertex_buffer_lock(buffer, start, count);
|
|
std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore((void *)vertices, (uint32_t)(count * kinc_g4_vertex_buffer_stride(buffer)), [](void *, size_t, void *) {}, nullptr);
|
|
Local<ArrayBuffer> abuffer = ArrayBuffer::New(isolate, std::move(backing));
|
|
args.GetReturnValue().Set(abuffer);
|
|
}
|
|
|
|
void runt_unlock_vertex_buffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_vertex_buffer_t *buffer = (kinc_g4_vertex_buffer_t *)field->Value();
|
|
int count = args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
kinc_g4_vertex_buffer_unlock(buffer, count);
|
|
}
|
|
|
|
void runt_set_vertexbuffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_vertex_buffer_t *buffer = (kinc_g4_vertex_buffer_t *)field->Value();
|
|
kinc_g4_set_vertex_buffer(buffer);
|
|
}
|
|
|
|
void runt_set_vertexbuffers(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
kinc_g4_vertex_buffer_t *vertex_buffers[8] = { nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
|
Local<Object> jsarray = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
int32_t length = jsarray->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "length").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
for (int32_t i = 0; i < length; ++i) {
|
|
Local<Object> bufferobj = jsarray->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "buffer").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> bufferfield = Local<External>::Cast(bufferobj->GetInternalField(0));
|
|
kinc_g4_vertex_buffer_t *buffer = (kinc_g4_vertex_buffer_t *)bufferfield->Value();
|
|
vertex_buffers[i] = buffer;
|
|
}
|
|
kinc_g4_set_vertex_buffers(vertex_buffers, length);
|
|
}
|
|
|
|
void runt_draw_indexed_vertices_fast(Local<Object> receiver, int start, int count) {
|
|
if (count < 0) kinc_g4_draw_indexed_vertices();
|
|
else kinc_g4_draw_indexed_vertices_from_to(start, count);
|
|
}
|
|
|
|
void runt_draw_indexed_vertices(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int start = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int count = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
runt_draw_indexed_vertices_fast(args.This(), start, count);
|
|
}
|
|
|
|
void runt_draw_indexed_vertices_instanced_fast(Local<Object> receiver, int instance_count, int start, int count) {
|
|
if (count < 0) kinc_g4_draw_indexed_vertices_instanced(instance_count);
|
|
else kinc_g4_draw_indexed_vertices_instanced_from_to(instance_count, start, count);
|
|
}
|
|
|
|
void runt_draw_indexed_vertices_instanced(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int instance_count = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int start = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int count = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
runt_draw_indexed_vertices_instanced_fast(args.This(), instance_count, start, count);
|
|
}
|
|
|
|
void runt_create_vertex_shader(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
|
kinc_g4_shader_init(shader, content->Data(), (int)content->ByteLength(), KINC_G4_SHADER_TYPE_VERTEX);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked(), args[1]);
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_vertex_shader_from_source(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
|
|
char *source = new char[strlen(*utf8_value) + 1];
|
|
strcpy(source, *utf8_value);
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
|
kinc_g4_shader_init(shader, source, strlen(source), KINC_G4_SHADER_TYPE_VERTEX);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
Local<String> name = String::NewFromUtf8(isolate, "").ToLocalChecked();
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked(), name);
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_fragment_shader(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
|
kinc_g4_shader_init(shader, content->Data(), (int)content->ByteLength(), KINC_G4_SHADER_TYPE_FRAGMENT);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked(), args[1]);
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_fragment_shader_from_source(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
|
|
char *source = new char[strlen(*utf8_value) + 1];
|
|
strcpy(source, *utf8_value);
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
|
kinc_g4_shader_init(shader, source, strlen(source), KINC_G4_SHADER_TYPE_FRAGMENT);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
Local<String> name = String::NewFromUtf8(isolate, "").ToLocalChecked();
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked(), name);
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_geometry_shader(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
|
kinc_g4_shader_init(shader, content->Data(), (int)content->ByteLength(), KINC_G4_SHADER_TYPE_GEOMETRY);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked(), args[1]);
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_tessellation_control_shader(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
|
kinc_g4_shader_init(shader, content->Data(), (int)content->ByteLength(), KINC_G4_SHADER_TYPE_TESSELLATION_CONTROL);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked(), args[1]);
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_tessellation_evaluation_shader(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)malloc(sizeof(kinc_g4_shader_t));
|
|
kinc_g4_shader_init(shader, content->Data(), (int)content->ByteLength(), KINC_G4_SHADER_TYPE_TESSELLATION_EVALUATION);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked(), args[1]);
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_delete_shader(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_shader_t *shader = (kinc_g4_shader_t *)field->Value();
|
|
kinc_g4_shader_destroy(shader);
|
|
free(shader);
|
|
}
|
|
|
|
void runt_create_pipeline(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)malloc(sizeof(kinc_g4_pipeline_t));
|
|
kinc_g4_pipeline_init(pipeline);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(8);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, pipeline));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_delete_pipeline(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Object> pipeobj = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> pipefield = Local<External>::Cast(pipeobj->GetInternalField(0));
|
|
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)pipefield->Value();
|
|
kinc_g4_pipeline_destroy(pipeline);
|
|
free(pipeline);
|
|
}
|
|
|
|
void runt_compile_pipeline(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
|
|
Local<Object> pipeobj = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
|
|
Local<External> pipefield = Local<External>::Cast(pipeobj->GetInternalField(0));
|
|
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)pipefield->Value();
|
|
|
|
kinc_g4_vertex_structure_t s0, s1, s2, s3;
|
|
kinc_g4_vertex_structure_init(&s0);
|
|
kinc_g4_vertex_structure_init(&s1);
|
|
kinc_g4_vertex_structure_init(&s2);
|
|
kinc_g4_vertex_structure_init(&s3);
|
|
kinc_g4_vertex_structure_t *structures[4] = { &s0, &s1, &s2, &s3 };
|
|
|
|
int32_t size = args[5]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
for (int32_t i1 = 0; i1 < size; ++i1) {
|
|
Local<Object> jsstructure = args[i1 + 1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
structures[i1]->instanced = jsstructure->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "instanced").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
Local<Object> elements = jsstructure->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "elements").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
int32_t length = elements->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "length").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
for (int32_t i2 = 0; i2 < length; ++i2) {
|
|
Local<Object> element = elements->Get(isolate->GetCurrentContext(), i2).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<Value> str = element->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "name").ToLocalChecked()).ToLocalChecked();
|
|
String::Utf8Value utf8_value(isolate, str);
|
|
int32_t data = element->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "data").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
|
|
strcpy(temp_string_vstruct[i1][i2], *utf8_value);
|
|
kinc_g4_vertex_structure_add(structures[i1], temp_string_vstruct[i1][i2], convert_vertex_data(data));
|
|
}
|
|
}
|
|
|
|
pipeobj->SetInternalField(1, External::New(isolate, structures));
|
|
pipeobj->SetInternalField(2, External::New(isolate, &size));
|
|
|
|
Local<External> vsfield = Local<External>::Cast(args[6]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_shader_t *vertexShader = (kinc_g4_shader_t *)vsfield->Value();
|
|
pipeobj->SetInternalField(3, External::New(isolate, vertexShader));
|
|
|
|
Local<External> fsfield = Local<External>::Cast(args[7]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_shader_t *fragmentShader = (kinc_g4_shader_t *)fsfield->Value();
|
|
pipeobj->SetInternalField(4, External::New(isolate, fragmentShader));
|
|
|
|
pipeline->vertex_shader = vertexShader;
|
|
pipeline->fragment_shader = fragmentShader;
|
|
|
|
if (!args[8]->IsNullOrUndefined()) {
|
|
Local<External> gsfield = Local<External>::Cast(args[8]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_shader_t *geometryShader = (kinc_g4_shader_t *)gsfield->Value();
|
|
pipeobj->SetInternalField(5, External::New(isolate, geometryShader));
|
|
pipeline->geometry_shader = geometryShader;
|
|
}
|
|
|
|
if (!args[9]->IsNullOrUndefined()) {
|
|
Local<External> tcsfield = Local<External>::Cast(args[9]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_shader_t *tessellationControlShader = (kinc_g4_shader_t *)tcsfield->Value();
|
|
pipeobj->SetInternalField(6, External::New(isolate, tessellationControlShader));
|
|
pipeline->tessellation_control_shader = tessellationControlShader;
|
|
}
|
|
|
|
if (!args[10]->IsNullOrUndefined()) {
|
|
Local<External> tesfield = Local<External>::Cast(args[10]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_shader_t *tessellationEvaluationShader = (kinc_g4_shader_t *)tesfield->Value();
|
|
pipeobj->SetInternalField(7, External::New(isolate, tessellationEvaluationShader));
|
|
pipeline->tessellation_evaluation_shader = tessellationEvaluationShader;
|
|
}
|
|
|
|
for (int i = 0; i < size; ++i) {
|
|
pipeline->input_layout[i] = structures[i];
|
|
}
|
|
pipeline->input_layout[size] = nullptr;
|
|
|
|
Local<Object> args11 = args[11]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
pipeline->cull_mode = (kinc_g4_cull_mode_t)args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "cullMode").ToLocalChecked()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
pipeline->depth_write = args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "depthWrite").ToLocalChecked()).ToLocalChecked()->BooleanValue(isolate);
|
|
pipeline->depth_mode = (kinc_g4_compare_mode_t)args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "depthMode").ToLocalChecked()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
pipeline->blend_source = (kinc_g4_blending_factor_t)args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "blendSource").ToLocalChecked()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
pipeline->blend_destination = (kinc_g4_blending_factor_t)args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "blendDestination").ToLocalChecked()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
pipeline->alpha_blend_source = (kinc_g4_blending_factor_t)args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "alphaBlendSource").ToLocalChecked()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
pipeline->alpha_blend_destination = (kinc_g4_blending_factor_t)args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "alphaBlendDestination").ToLocalChecked()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
Local<Object> maskRedArray = args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "colorWriteMaskRed").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<Object> maskGreenArray = args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "colorWriteMaskGreen").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<Object> maskBlueArray = args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "colorWriteMaskBlue").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<Object> maskAlphaArray = args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "colorWriteMaskAlpha").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
|
|
for (int i = 0; i < 8; ++i) {
|
|
pipeline->color_write_mask_red[i] = maskRedArray->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->BooleanValue(isolate);
|
|
pipeline->color_write_mask_green[i] = maskGreenArray->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->BooleanValue(isolate);
|
|
pipeline->color_write_mask_blue[i] = maskBlueArray->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->BooleanValue(isolate);
|
|
pipeline->color_write_mask_alpha[i] = maskAlphaArray->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->BooleanValue(isolate);
|
|
}
|
|
|
|
pipeline->conservative_rasterization = args11->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "conservativeRasterization").ToLocalChecked()).ToLocalChecked()->BooleanValue(isolate);
|
|
|
|
kinc_g4_pipeline_compile(pipeline);
|
|
}
|
|
|
|
void runt_set_pipeline(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Object> pipeobj = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> pipefield = Local<External>::Cast(pipeobj->GetInternalField(0));
|
|
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)pipefield->Value();
|
|
kinc_g4_set_pipeline(pipeline);
|
|
}
|
|
|
|
bool ends_with(const char *str, const char *suffix) {
|
|
if (!str || !suffix) return 0;
|
|
size_t lenstr = strlen(str);
|
|
size_t lensuffix = strlen(suffix);
|
|
if (lensuffix > lenstr) return 0;
|
|
return strncmp(str + lenstr - lensuffix, suffix, lensuffix) == 0;
|
|
}
|
|
|
|
bool load_image(kinc_file_reader_t &reader, const char *filename, unsigned char *&output, int &width, int &height, kinc_image_format_t &format) {
|
|
format = KINC_IMAGE_FORMAT_RGBA32;
|
|
int size = (int)kinc_file_reader_size(&reader);
|
|
int comp;
|
|
bool success = true;
|
|
unsigned char *data = (unsigned char *)malloc(size);
|
|
kinc_file_reader_read(&reader, data, size);
|
|
kinc_file_reader_close(&reader);
|
|
|
|
if (ends_with(filename, "k")) {
|
|
width = kinc_read_s32le(data);
|
|
height = kinc_read_s32le(data + 4);
|
|
char fourcc[5];
|
|
fourcc[0] = data[8];
|
|
fourcc[1] = data[9];
|
|
fourcc[2] = data[10];
|
|
fourcc[3] = data[11];
|
|
fourcc[4] = 0;
|
|
int compressedSize = size - 12;
|
|
if (strcmp(fourcc, "LZ4 ") == 0) {
|
|
int outputSize = width * height * 4;
|
|
output = (unsigned char *)malloc(outputSize);
|
|
LZ4_decompress_safe((char *)(data + 12), (char *)output, compressedSize, outputSize);
|
|
}
|
|
else if (strcmp(fourcc, "LZ4F") == 0) {
|
|
int outputSize = width * height * 16;
|
|
output = (unsigned char *)malloc(outputSize);
|
|
LZ4_decompress_safe((char *)(data + 12), (char *)output, compressedSize, outputSize);
|
|
format = KINC_IMAGE_FORMAT_RGBA128;
|
|
}
|
|
else {
|
|
success = false;
|
|
}
|
|
}
|
|
else if (ends_with(filename, "hdr")) {
|
|
output = (unsigned char *)stbi_loadf_from_memory(data, size, &width, &height, &comp, 4);
|
|
if (output == nullptr) {
|
|
kinc_log(KINC_LOG_LEVEL_ERROR, stbi_failure_reason());
|
|
success = false;
|
|
}
|
|
format = KINC_IMAGE_FORMAT_RGBA128;
|
|
}
|
|
else { // jpg, png, ..
|
|
output = stbi_load_from_memory(data, size, &width, &height, &comp, 4);
|
|
if (output == nullptr) {
|
|
kinc_log(KINC_LOG_LEVEL_ERROR, stbi_failure_reason());
|
|
success = false;
|
|
}
|
|
}
|
|
free(data);
|
|
return success;
|
|
}
|
|
|
|
void runt_load_image(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
bool readable = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
bool success = true;
|
|
|
|
kinc_image_t *image = (kinc_image_t *)malloc(sizeof(kinc_image_t));
|
|
|
|
// if (armorcore) {
|
|
kinc_file_reader_t reader;
|
|
if (kinc_file_reader_open(&reader, *utf8_value, KINC_FILE_TYPE_ASSET)) {
|
|
unsigned char *image_data;
|
|
int image_width;
|
|
int image_height;
|
|
kinc_image_format_t image_format;
|
|
success = load_image(reader, *utf8_value, image_data, image_width, image_height, image_format);
|
|
if (success) {
|
|
kinc_image_init(image, image_data, image_width, image_height, image_format);
|
|
}
|
|
}
|
|
else {
|
|
success = false;
|
|
}
|
|
// }
|
|
// else {
|
|
// // TODO: make kinc_image load faster
|
|
// size_t byte_size = kinc_image_size_from_file(*utf8_value);
|
|
// if (byte_size == 0) {
|
|
// success = false;
|
|
// }
|
|
// else {
|
|
// void *memory = malloc(byte_size);
|
|
// kinc_image_init_from_file(image, memory, *utf8_value);
|
|
// }
|
|
// }
|
|
|
|
if (!success) {
|
|
free(image);
|
|
return;
|
|
}
|
|
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)malloc(sizeof(kinc_g4_texture_t));
|
|
kinc_g4_texture_init_from_image(texture, image);
|
|
if (!readable) {
|
|
free(image->data);
|
|
kinc_image_destroy(image);
|
|
free(image);
|
|
// free(memory);
|
|
}
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(readable ? 2 : 1);
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, texture));
|
|
if (readable) obj->SetInternalField(1, External::New(isolate, image));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "realWidth").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "realHeight").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_unload_image(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
if (args[0]->IsNullOrUndefined()) return;
|
|
Local<Object> image = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<Value> tex = image->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "texture_").ToLocalChecked()).ToLocalChecked();
|
|
Local<Value> rt = image->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "renderTarget_").ToLocalChecked()).ToLocalChecked();
|
|
|
|
if (tex->IsObject()) {
|
|
Local<External> texfield = Local<External>::Cast(tex->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)texfield->Value();
|
|
kinc_g4_texture_destroy(texture);
|
|
free(texture);
|
|
}
|
|
else if (rt->IsObject()) {
|
|
Local<External> rtfield = Local<External>::Cast(rt->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
kinc_g4_render_target_destroy(render_target);
|
|
free(render_target);
|
|
}
|
|
}
|
|
|
|
#ifdef WITH_AUDIO
|
|
void runt_set_audio_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
audio_func.Reset(isolate, func);
|
|
}
|
|
|
|
void runt_audio_thread(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
bool lock = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
if (lock) kinc_mutex_lock(&mutex); //Locker::Locker(isolate);
|
|
else kinc_mutex_unlock(&mutex); //Unlocker(args.GetIsolate());
|
|
}
|
|
|
|
void runt_load_sound(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
kinc_a1_sound_t *sound = kinc_a1_sound_create(*utf8_value);
|
|
|
|
if (sound == nullptr) {
|
|
return;
|
|
}
|
|
|
|
Local<ArrayBuffer> buffer = ArrayBuffer::New(isolate, sound->size * 2 * sizeof(float));
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
float *to = (float *)content->Data();
|
|
|
|
int16_t *left = (int16_t *)&sound->left[0];
|
|
int16_t *right = (int16_t *)&sound->right[0];
|
|
for (int i = 0; i < sound->size; i += 1) {
|
|
to[i * 2 ] = (float)(left [i] / 32767.0);
|
|
to[i * 2 + 1] = (float)(right[i] / 32767.0);
|
|
}
|
|
args.GetReturnValue().Set(buffer);
|
|
kinc_a1_sound_destroy(sound);
|
|
}
|
|
|
|
void runt_write_audio_buffer(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
int samples = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
|
|
for (int i = 0; i < samples; ++i) {
|
|
float *values = (float *)content->Data();
|
|
float value = values[audio_read_location / 4];
|
|
audio_read_location += 4;
|
|
if (audio_read_location >= content->ByteLength()) audio_read_location = 0;
|
|
*(float *)&audio_buffer.data[audio_buffer.write_location] = value;
|
|
audio_buffer.write_location += 4;
|
|
if (audio_buffer.write_location >= audio_buffer.data_size) audio_buffer.write_location = 0;
|
|
}
|
|
}
|
|
|
|
int runt_get_samples_per_second_fast(Local<Object> receiver) {
|
|
kinc_log(KINC_LOG_LEVEL_INFO, "Samples per second: %d Hz.", kinc_a2_samples_per_second);
|
|
return kinc_a2_samples_per_second;
|
|
}
|
|
|
|
void runt_get_samples_per_second(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(Int32::New(isolate, runt_get_samples_per_second_fast(args.This())));
|
|
}
|
|
|
|
|
|
void update_audio(kinc_a2_buffer_t *buffer, int samples) {
|
|
if (!isolate || isolate->IsExecutionTerminating()) {
|
|
// TODO: Re-investigate fill buffer with silence during shutdown
|
|
for (int i = 0; i < samples; ++i) {
|
|
*(float *)&buffer->data[buffer->write_location] = 0.0f;
|
|
buffer->write_location += 4;
|
|
if (buffer->write_location >= buffer->data_size) {
|
|
buffer->write_location = 0;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
kinc_mutex_lock(&mutex);
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
MicrotasksScope microtasks_scope(isolate, MicrotasksScope::kRunMicrotasks);
|
|
HandleScope handle_scope(isolate);
|
|
|
|
if (global_context.IsEmpty()) {
|
|
kinc_mutex_unlock(&mutex);
|
|
// TODO: re-investigate
|
|
for (int i = 0; i < samples; ++i) {
|
|
*(float *)&buffer->data[buffer->write_location] = 0.0f;
|
|
buffer->write_location += 4;
|
|
if (buffer->write_location >= buffer->data_size) {
|
|
buffer->write_location = 0;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, audio_func);
|
|
Local<Value> result;
|
|
const int argc = 1;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, samples)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
|
|
for (int i = 0; i < samples; ++i) {
|
|
float sample = *(float *)&audio_buffer.data[audio_buffer.read_location];
|
|
audio_buffer.read_location += 4;
|
|
if (audio_buffer.read_location >= audio_buffer.data_size) {
|
|
audio_buffer.read_location = 0;
|
|
}
|
|
|
|
*(float *)&buffer->data[buffer->write_location] = sample;
|
|
buffer->write_location += 4;
|
|
if (buffer->write_location >= buffer->data_size) {
|
|
buffer->write_location = 0;
|
|
}
|
|
}
|
|
|
|
kinc_mutex_unlock(&mutex);
|
|
}
|
|
|
|
#else
|
|
|
|
void runt_set_audio_callback(const FunctionCallbackInfo<Value> &args) {
|
|
}
|
|
|
|
void runt_audio_thread(const FunctionCallbackInfo<Value> &args) {
|
|
}
|
|
|
|
void runt_load_sound(const FunctionCallbackInfo<Value> &args) {
|
|
}
|
|
|
|
void runt_write_audio_buffer(const FunctionCallbackInfo<Value> &args) {
|
|
}
|
|
|
|
void runt_get_samples_per_second(const FunctionCallbackInfo<Value> &args) {
|
|
}
|
|
|
|
#endif
|
|
|
|
void runt_load_blob(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
|
|
kinc_file_reader_t reader;
|
|
if (!kinc_file_reader_open(&reader, *utf8_value, KINC_FILE_TYPE_ASSET)) return;
|
|
uint32_t reader_size = (uint32_t)kinc_file_reader_size(&reader);
|
|
|
|
Local<ArrayBuffer> buffer = ArrayBuffer::New(isolate, reader_size);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_file_reader_read(&reader, content->Data(), reader_size);
|
|
kinc_file_reader_close(&reader);
|
|
|
|
args.GetReturnValue().Set(buffer);
|
|
}
|
|
|
|
void runt_load_url(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
kinc_load_url(*utf8_value);
|
|
}
|
|
|
|
void runt_copy_to_clipboard(const FunctionCallbackInfo<Value>& args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
kinc_copy_to_clipboard(*utf8_value);
|
|
}
|
|
|
|
void runt_get_constant_location(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> pipefield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)pipefield->Value();
|
|
|
|
String::Utf8Value utf8_value(isolate, args[1]);
|
|
kinc_g4_constant_location_t location = kinc_g4_pipeline_get_constant_location(pipeline, *utf8_value);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
kinc_g4_constant_location_t *location_copy = (kinc_g4_constant_location_t *)malloc(sizeof(kinc_g4_constant_location_t));
|
|
memcpy(location_copy, &location, sizeof(kinc_g4_constant_location_t)); // TODO
|
|
obj->SetInternalField(0, External::New(isolate, location_copy));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_get_texture_unit(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> pipefield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_pipeline_t *pipeline = (kinc_g4_pipeline_t *)pipefield->Value();
|
|
|
|
String::Utf8Value utf8_value(isolate, args[1]);
|
|
kinc_g4_texture_unit_t unit = kinc_g4_pipeline_get_texture_unit(pipeline, *utf8_value);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
kinc_g4_texture_unit_t *unit_copy = (kinc_g4_texture_unit_t *)malloc(sizeof(kinc_g4_texture_unit_t));
|
|
memcpy(unit_copy, &unit, sizeof(kinc_g4_texture_unit_t)); // TODO
|
|
obj->SetInternalField(0, External::New(isolate, unit_copy));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_set_texture(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
Local<External> texfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)texfield->Value();
|
|
kinc_g4_set_texture(*unit, texture);
|
|
}
|
|
|
|
void runt_set_render_target(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
Local<External> rtfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
kinc_g4_render_target_use_color_as_texture(render_target, *unit);
|
|
}
|
|
|
|
void runt_set_texture_depth(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
Local<External> rtfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
kinc_g4_render_target_use_depth_as_texture(render_target, *unit);
|
|
}
|
|
|
|
void runt_set_image_texture(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
Local<External> texfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)texfield->Value();
|
|
kinc_g4_set_image_texture(*unit, texture);
|
|
}
|
|
|
|
void runt_set_texture_parameters(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
kinc_g4_set_texture_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture_minification_filter(*unit, (kinc_g4_texture_filter_t)args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture_magnification_filter(*unit, (kinc_g4_texture_filter_t)args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture_mipmap_filter(*unit, (kinc_g4_mipmap_filter_t)args[5]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
}
|
|
|
|
void runt_set_texture3d_parameters(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
kinc_g4_set_texture3d_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture3d_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture3d_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_W, (kinc_g4_texture_addressing_t)args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture3d_minification_filter(*unit, (kinc_g4_texture_filter_t)args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture3d_magnification_filter(*unit, (kinc_g4_texture_filter_t)args[5]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_g4_set_texture3d_mipmap_filter(*unit, (kinc_g4_mipmap_filter_t)args[6]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
}
|
|
|
|
void runt_set_texture_compare_mode(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
kinc_g4_set_texture_compare_mode(*unit, args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
}
|
|
|
|
void runt_set_cube_map_compare_mode(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_unit_t *unit = (kinc_g4_texture_unit_t *)unitfield->Value();
|
|
kinc_g4_set_cubemap_compare_mode(*unit, args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
}
|
|
|
|
void runt_set_bool(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
int32_t value = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_set_bool(*location, value != 0);
|
|
}
|
|
|
|
void runt_set_int(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
int32_t value = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_set_int(*location, value);
|
|
}
|
|
|
|
void runt_set_float(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
float value = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_set_float(*location, value);
|
|
}
|
|
|
|
void runt_set_float2(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
float value1 = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value2 = (float)args[2]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_set_float2(*location, value1, value2);
|
|
}
|
|
|
|
void runt_set_float3(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
float value1 = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value2 = (float)args[2]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value3 = (float)args[3]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_set_float3(*location, value1, value2, value3);
|
|
}
|
|
|
|
void runt_set_float4(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
float value1 = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value2 = (float)args[2]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value3 = (float)args[3]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value4 = (float)args[4]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_set_float4(*location, value1, value2, value3, value4);
|
|
}
|
|
|
|
void runt_set_floats(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
|
|
float *from = (float *)content->Data();
|
|
kinc_g4_set_floats(*location, from, int(content->ByteLength() / 4));
|
|
}
|
|
|
|
void runt_set_matrix(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
float *from = (float *)content->Data();
|
|
kinc_g4_set_matrix4(*location, (kinc_matrix4x4_t *)from);
|
|
}
|
|
|
|
void runt_set_matrix3(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_constant_location_t *location = (kinc_g4_constant_location_t *)locationfield->Value();
|
|
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
float *from = (float *)content->Data();
|
|
kinc_g4_set_matrix3(*location, (kinc_matrix3x3_t *)from);
|
|
}
|
|
|
|
double runt_get_time_fast(Local<Object> receiver) {
|
|
return kinc_time();
|
|
}
|
|
|
|
void runt_get_time(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(Number::New(isolate, runt_get_time_fast(args.This())));
|
|
}
|
|
|
|
int runt_window_width_fast(Local<Object> receiver, int windowId) {
|
|
return kinc_window_width(windowId);
|
|
}
|
|
|
|
void runt_window_width(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, runt_window_width_fast(args.This(), windowId)));
|
|
}
|
|
|
|
int runt_window_height_fast(Local<Object> receiver, int windowId) {
|
|
return kinc_window_height(windowId);
|
|
}
|
|
|
|
void runt_window_height(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, runt_window_height_fast(args.This(), windowId)));
|
|
}
|
|
|
|
void runt_set_window_title(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
String::Utf8Value title(isolate, args[1]);
|
|
kinc_window_set_title(windowId, *title);
|
|
}
|
|
|
|
void runt_get_window_mode(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_window_get_mode(windowId)));
|
|
}
|
|
|
|
void runt_set_window_mode(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_window_mode_t windowMode = (kinc_window_mode_t)args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_window_change_mode(windowId, windowMode);
|
|
}
|
|
|
|
void runt_resize_window(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int width = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int height = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_window_resize(windowId, width, height);
|
|
}
|
|
|
|
void runt_move_window(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int x = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int y = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_window_move(windowId, x, y);
|
|
}
|
|
|
|
void runt_screen_dpi(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int ppi = kinc_display_current_mode(kinc_primary_display()).pixels_per_inch;
|
|
args.GetReturnValue().Set(Int32::New(isolate, ppi));
|
|
}
|
|
|
|
void runt_system_id(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(String::NewFromUtf8(isolate, kinc_system_id()).ToLocalChecked());
|
|
}
|
|
|
|
void runt_request_shutdown(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
kinc_stop();
|
|
}
|
|
|
|
void runt_display_count(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_count_displays()));
|
|
}
|
|
|
|
void runt_display_width(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int index = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_display_current_mode(index).width));
|
|
}
|
|
|
|
void runt_display_height(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int index = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_display_current_mode(index).height));
|
|
}
|
|
|
|
void runt_display_x(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int index = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_display_current_mode(index).x));
|
|
}
|
|
|
|
void runt_display_y(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int index = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_display_current_mode(index).y));
|
|
}
|
|
|
|
void runt_display_frequency(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int index = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_display_current_mode(index).frequency));
|
|
}
|
|
|
|
void runt_display_is_primary(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int index = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
#ifdef KORE_LINUX // TODO: Primary display detection broken in Kinc
|
|
args.GetReturnValue().Set(Int32::New(isolate, true));
|
|
#else
|
|
args.GetReturnValue().Set(Int32::New(isolate, index == kinc_primary_display()));
|
|
#endif
|
|
}
|
|
|
|
void runt_write_storage(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_name(isolate, args[0]);
|
|
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
|
|
kinc_file_writer_t writer;
|
|
kinc_file_writer_open(&writer, *utf8_name);
|
|
kinc_file_writer_write(&writer, content->Data(), (int)content->ByteLength());
|
|
kinc_file_writer_close(&writer);
|
|
}
|
|
|
|
void runt_read_storage(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_name(isolate, args[0]);
|
|
|
|
kinc_file_reader_t reader;
|
|
if (!kinc_file_reader_open(&reader, *utf8_name, KINC_FILE_TYPE_SAVE)) return;
|
|
int reader_size = (int)kinc_file_reader_size(&reader);
|
|
|
|
Local<ArrayBuffer> buffer = ArrayBuffer::New(isolate, reader_size);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_file_reader_read(&reader, content->Data(), reader_size);
|
|
kinc_file_reader_close(&reader);
|
|
|
|
args.GetReturnValue().Set(buffer);
|
|
}
|
|
|
|
void runt_create_render_target(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)malloc(sizeof(kinc_g4_render_target_t));
|
|
kinc_g4_render_target_init(render_target, args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), (kinc_g4_render_target_format_t)args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, render_target));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, render_target->width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, render_target->height));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_render_target_cube_map(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)malloc(sizeof(kinc_g4_render_target_t));
|
|
kinc_g4_render_target_init_cube(render_target, args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), (kinc_g4_render_target_format_t)args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, render_target));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, render_target->width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, render_target->height));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_texture(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)malloc(sizeof(kinc_g4_texture_t));
|
|
kinc_g4_texture_init(texture, args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), (kinc_image_format_t)args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, texture));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "realWidth").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "realHeight").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_texture3d(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)malloc(sizeof(kinc_g4_texture_t));
|
|
kinc_g4_texture_init3d(texture, args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), (kinc_image_format_t)args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, texture));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "depth").ToLocalChecked(), Int32::New(isolate, texture->tex_depth));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_texture_from_bytes(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)malloc(sizeof(kinc_g4_texture_t));
|
|
kinc_image_t *image = (kinc_image_t *)malloc(sizeof(kinc_image_t));
|
|
|
|
bool readable = args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
void *image_data;
|
|
if (readable) {
|
|
image_data = malloc(content->ByteLength());
|
|
memcpy(image_data, content->Data(), content->ByteLength());
|
|
}
|
|
else {
|
|
image_data = content->Data();
|
|
}
|
|
|
|
kinc_image_init(image, image_data, args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), (kinc_image_format_t)args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
kinc_g4_texture_init_from_image(texture, image);
|
|
|
|
if (!readable) {
|
|
kinc_image_destroy(image);
|
|
free(image);
|
|
}
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(readable ? 2 : 1);
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, texture));
|
|
if (readable) obj->SetInternalField(1, External::New(isolate, image));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "realWidth").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "realHeight").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_texture_from_bytes3d(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)malloc(sizeof(kinc_g4_texture_t));
|
|
kinc_image_t *image = (kinc_image_t*)malloc(sizeof(kinc_image_t));
|
|
|
|
bool readable = args[5]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
void *image_data;
|
|
if (readable) {
|
|
image_data = malloc(content->ByteLength());
|
|
memcpy(image_data, content->Data(), content->ByteLength());
|
|
}
|
|
else {
|
|
image_data = content->Data();
|
|
}
|
|
|
|
kinc_image_init3d(image, image_data, args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value(), (kinc_image_format_t)args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
kinc_g4_texture_init_from_image3d(texture, image);
|
|
|
|
if (!readable) {
|
|
kinc_image_destroy(image);
|
|
free(image);
|
|
}
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(readable ? 2 : 1);
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, texture));
|
|
if (readable) obj->SetInternalField(1, External::New(isolate, image));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "depth").ToLocalChecked(), Int32::New(isolate, texture->tex_depth));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_create_texture_from_encoded_bytes(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
String::Utf8Value format(isolate, args[1]);
|
|
bool readable = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)malloc(sizeof(kinc_g4_texture_t));
|
|
kinc_image_t *image = (kinc_image_t *)malloc(sizeof(kinc_image_t));
|
|
|
|
unsigned char *content_data = (unsigned char *)content->Data();
|
|
int content_length = (int)content->ByteLength();
|
|
unsigned char *image_data;
|
|
kinc_image_format_t image_format;
|
|
int image_width;
|
|
int image_height;
|
|
|
|
if (ends_with(*format, "k")) {
|
|
image_width = kinc_read_s32le(content_data);
|
|
image_height = kinc_read_s32le(content_data + 4);
|
|
char fourcc[5];
|
|
fourcc[0] = content_data[8];
|
|
fourcc[1] = content_data[9];
|
|
fourcc[2] = content_data[10];
|
|
fourcc[3] = content_data[11];
|
|
fourcc[4] = 0;
|
|
int compressedSize = (int)content->ByteLength() - 12;
|
|
if (strcmp(fourcc, "LZ4 ") == 0) {
|
|
int outputSize = image_width * image_height * 4;
|
|
image_data = (unsigned char *)malloc(outputSize);
|
|
LZ4_decompress_safe((char *)content_data + 12, (char *)image_data, compressedSize, outputSize);
|
|
image_format = KINC_IMAGE_FORMAT_RGBA32;
|
|
}
|
|
else if (strcmp(fourcc, "LZ4F") == 0) {
|
|
int outputSize = image_width * image_height * 16;
|
|
image_data = (unsigned char *)malloc(outputSize);
|
|
LZ4_decompress_safe((char *)content_data + 12, (char *)image_data, compressedSize, outputSize);
|
|
image_format = KINC_IMAGE_FORMAT_RGBA128;
|
|
}
|
|
}
|
|
else if (ends_with(*format, "hdr")) {
|
|
int comp;
|
|
image_data = (unsigned char *)stbi_loadf_from_memory(content_data, content_length, &image_width, &image_height, &comp, 4);
|
|
image_format = KINC_IMAGE_FORMAT_RGBA128;
|
|
}
|
|
else { // jpg, png, ..
|
|
int comp;
|
|
image_data = stbi_load_from_memory(content_data, content_length, &image_width, &image_height, &comp, 4);
|
|
image_format = KINC_IMAGE_FORMAT_RGBA32;
|
|
}
|
|
|
|
kinc_image_init(image, image_data, image_width, image_height, image_format);
|
|
kinc_g4_texture_init_from_image(texture, image);
|
|
if (!readable) {
|
|
free(image->data);
|
|
kinc_image_destroy(image);
|
|
free(image);
|
|
}
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(readable ? 2 : 1);
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, texture));
|
|
if (readable) obj->SetInternalField(1, External::New(isolate, image));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "width").ToLocalChecked(), Int32::New(isolate, texture->tex_width));
|
|
(void) obj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "height").ToLocalChecked(), Int32::New(isolate, texture->tex_height));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
int format_byte_size(kinc_image_format_t format) {
|
|
switch (format) {
|
|
case KINC_IMAGE_FORMAT_RGBA128:
|
|
return 16;
|
|
case KINC_IMAGE_FORMAT_RGBA64:
|
|
return 8;
|
|
case KINC_IMAGE_FORMAT_RGB24:
|
|
return 4;
|
|
case KINC_IMAGE_FORMAT_A32:
|
|
return 4;
|
|
case KINC_IMAGE_FORMAT_A16:
|
|
return 2;
|
|
case KINC_IMAGE_FORMAT_GREY8:
|
|
return 1;
|
|
case KINC_IMAGE_FORMAT_BGRA32:
|
|
case KINC_IMAGE_FORMAT_RGBA32:
|
|
default:
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
void runt_get_texture_pixels(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(1));
|
|
kinc_image_t *image = (kinc_image_t *)field->Value();
|
|
|
|
uint8_t *data = kinc_image_get_pixels(image);
|
|
int byteLength = format_byte_size(image->format) * image->width * image->height * image->depth;
|
|
std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore((void *)data, byteLength, [](void *, size_t, void *) {}, nullptr);
|
|
Local<ArrayBuffer> buffer = ArrayBuffer::New(isolate, std::move(backing));
|
|
args.GetReturnValue().Set(buffer);
|
|
}
|
|
|
|
void runt_get_render_target_pixels(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)field->Value();
|
|
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
|
|
uint8_t *b = (uint8_t *)content->Data();
|
|
kinc_g4_render_target_get_pixels(rt, b);
|
|
}
|
|
|
|
void runt_lock_texture(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Object> textureobj = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> field = Local<External>::Cast(textureobj->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)field->Value();
|
|
uint8_t *tex = kinc_g4_texture_lock(texture);
|
|
|
|
int stride = kinc_g4_texture_stride(texture);
|
|
(void) textureobj->Set(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "stride").ToLocalChecked(), Int32::New(isolate, stride));
|
|
|
|
int byteLength = stride * texture->tex_height * texture->tex_depth;
|
|
std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore((void *)tex, byteLength, [](void *, size_t, void *) {}, nullptr);
|
|
Local<ArrayBuffer> abuffer = ArrayBuffer::New(isolate, std::move(backing));
|
|
args.GetReturnValue().Set(abuffer);
|
|
}
|
|
|
|
void runt_unlock_texture(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)field->Value();
|
|
kinc_g4_texture_unlock(texture);
|
|
}
|
|
|
|
void runt_clear_texture(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)field->Value();
|
|
int x = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int y = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int z = args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int width = args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int height = args[5]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int depth = args[6]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int color = args[7]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_g4_texture_clear(texture, x, y, z, width, height, depth, color);
|
|
}
|
|
|
|
void runt_generate_texture_mipmaps(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)field->Value();
|
|
kinc_g4_texture_generate_mipmaps(texture, args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
}
|
|
|
|
void runt_generate_render_target_mipmaps(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *rt = (kinc_g4_render_target_t *)field->Value();
|
|
kinc_g4_render_target_generate_mipmaps(rt, args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value());
|
|
}
|
|
|
|
void runt_set_mipmaps(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> field = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)field->Value();
|
|
|
|
Local<Object> jsarray = args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
int32_t length = jsarray->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "length").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
for (int32_t i = 0; i < length; ++i) {
|
|
Local<Object> mipmapobj = jsarray->Get(isolate->GetCurrentContext(), i).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "texture_").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> mipmapfield = Local<External>::Cast(mipmapobj->GetInternalField(1));
|
|
kinc_image_t *mipmap = (kinc_image_t *)mipmapfield->Value();
|
|
kinc_g4_texture_set_mipmap(texture, mipmap, i + 1);
|
|
}
|
|
}
|
|
|
|
void runt_set_depth_stencil_from(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> targetfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)targetfield->Value();
|
|
Local<External> sourcefield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *source_target = (kinc_g4_render_target_t *)sourcefield->Value();
|
|
kinc_g4_render_target_set_depth_stencil_from(render_target, source_target);
|
|
}
|
|
|
|
void runt_viewport_fast(Local<Object> receiver, int x, int y, int w, int h) {
|
|
kinc_g4_viewport(x, y, w, h);
|
|
}
|
|
|
|
void runt_viewport(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int x = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int y = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int w = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int h = args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
runt_viewport_fast(args.This(), x, y, w, h);
|
|
}
|
|
|
|
void runt_scissor_fast(Local<Object> receiver, int x, int y, int w, int h) {
|
|
kinc_g4_scissor(x, y, w, h);
|
|
}
|
|
|
|
void runt_scissor(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int x = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int y = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int w = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
int h = args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
runt_scissor_fast(args.This(), x, y, w, h);
|
|
}
|
|
|
|
void runt_disable_scissor_fast(Local<Object> receiver) {
|
|
kinc_g4_disable_scissor();
|
|
}
|
|
|
|
void runt_disable_scissor(const FunctionCallbackInfo<Value> &args) {
|
|
runt_disable_scissor_fast(args.This());
|
|
}
|
|
|
|
int runt_render_targets_inverted_y_fast(Local<Object> receiver) {
|
|
return kinc_g4_render_targets_inverted_y();
|
|
}
|
|
|
|
void runt_render_targets_inverted_y(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(Int32::New(isolate, runt_render_targets_inverted_y_fast(args.This())));
|
|
}
|
|
|
|
void runt_begin(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
if (args[0]->IsNullOrUndefined()) {
|
|
kinc_g4_restore_render_target();
|
|
}
|
|
else {
|
|
Local<Object> obj = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "renderTarget_").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> rtfield = Local<External>::Cast(obj->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
|
|
int32_t length = 1;
|
|
kinc_g4_render_target_t *render_targets[8] = { render_target, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr };
|
|
if (!args[1]->IsNullOrUndefined()) {
|
|
Local<Object> jsarray = args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
length = jsarray->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "length").ToLocalChecked()).ToLocalChecked()->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value() + 1;
|
|
if (length > 8) length = 8;
|
|
for (int32_t i = 1; i < length; ++i) {
|
|
Local<Object> artobj = jsarray->Get(isolate->GetCurrentContext(), i - 1).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "renderTarget_").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> artfield = Local<External>::Cast(artobj->GetInternalField(0));
|
|
kinc_g4_render_target_t *art = (kinc_g4_render_target_t *)artfield->Value();
|
|
render_targets[i] = art;
|
|
}
|
|
}
|
|
kinc_g4_set_render_targets(render_targets, length);
|
|
}
|
|
}
|
|
|
|
void runt_begin_face(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Object> obj = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "renderTarget_").ToLocalChecked()).ToLocalChecked()->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> rtfield = Local<External>::Cast(obj->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
int face = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
kinc_g4_set_render_target_face(render_target, face);
|
|
}
|
|
|
|
void runt_end(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
}
|
|
|
|
void runt_file_save_bytes(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_path(isolate, args[0]);
|
|
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
|
|
bool hasLengthArg = args.Length() > 2 && !args[2]->IsNullOrUndefined();
|
|
int byteLength = hasLengthArg ? args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value() : (int)content->ByteLength();
|
|
if (byteLength > (int)content->ByteLength()) byteLength = (int)content->ByteLength();
|
|
|
|
#ifdef KORE_WINDOWS
|
|
MultiByteToWideChar(CP_UTF8, 0, *utf8_path, -1, temp_wstring, 1024);
|
|
FILE *file = _wfopen(temp_wstring, L"wb");
|
|
#else
|
|
FILE *file = fopen(*utf8_path, "wb");
|
|
#endif
|
|
if (file == nullptr) return;
|
|
fwrite(content->Data(), 1, byteLength, file);
|
|
fclose(file);
|
|
}
|
|
|
|
int sys_command(const char *cmd) {
|
|
#ifdef KORE_WINDOWS
|
|
int wlen = MultiByteToWideChar(CP_UTF8, 0, cmd, -1, NULL, 0);
|
|
wchar_t *wstr = new wchar_t[wlen];
|
|
MultiByteToWideChar(CP_UTF8, 0, cmd, -1, wstr, wlen);
|
|
int result = _wsystem(wstr);
|
|
delete[] wstr;
|
|
#else
|
|
int result = system(cmd);
|
|
#endif
|
|
return result;
|
|
}
|
|
|
|
void runt_sys_command(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_cmd(isolate, args[0]);
|
|
int result = sys_command(*utf8_cmd);
|
|
args.GetReturnValue().Set(Int32::New(isolate, result));
|
|
}
|
|
|
|
void runt_save_path(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(String::NewFromUtf8(isolate, kinc_internal_save_path()).ToLocalChecked());
|
|
}
|
|
|
|
void runt_get_arg_count(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(Int32::New(isolate, _argc));
|
|
}
|
|
|
|
void runt_get_arg(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int index = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(String::NewFromUtf8(isolate, _argv[index]).ToLocalChecked());
|
|
}
|
|
|
|
void runt_get_files_location(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
#ifdef KORE_MACOS
|
|
char path[1024];
|
|
strcpy(path, macgetresourcepath());
|
|
strcat(path, "/");
|
|
strcat(path, KORE_DEBUGDIR);
|
|
strcat(path, "/");
|
|
args.GetReturnValue().Set(String::NewFromUtf8(isolate, path).ToLocalChecked());
|
|
#else
|
|
args.GetReturnValue().Set(String::NewFromUtf8(isolate, kinc_internal_get_files_location()).ToLocalChecked());
|
|
#endif
|
|
}
|
|
|
|
void runt_http_callback(int error, int response, const char *body, void *callbackdata) {
|
|
#if defined(KORE_MACOS)
|
|
Locker locker{isolate};
|
|
#endif
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Value> result;
|
|
Local<Value> argv[1];
|
|
RunTCallbackdata *cbd = (RunTCallbackdata *)callbackdata;
|
|
if (body != NULL) {
|
|
std::unique_ptr<v8::BackingStore> backing = v8::ArrayBuffer::NewBackingStore((void *)body, cbd->size > 0 ? cbd->size : strlen(body), [](void *, size_t, void *) {}, nullptr);
|
|
argv[0] = ArrayBuffer::New(isolate, std::move(backing));
|
|
}
|
|
Local<Function> func = Local<Function>::New(isolate, cbd->func);
|
|
if (!func->Call(context, context->Global(), body != NULL ? 1 : 0, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
delete cbd;
|
|
}
|
|
|
|
void runt_http_request(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value url(isolate, args[0]);
|
|
|
|
RunTCallbackdata *cbd = new RunTCallbackdata();
|
|
cbd->size = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
Local<Function> func = Local<Function>::Cast(args[2]);
|
|
cbd->func.Reset(isolate, func);
|
|
|
|
char url_base[512];
|
|
char url_path[512];
|
|
const char *curl = *url;
|
|
int i = 0;
|
|
for (; i < strlen(curl) - 8; ++i) {
|
|
if (curl[i + 8] == '/') break;
|
|
url_base[i] = curl[i + 8]; // Strip https://
|
|
}
|
|
url_base[i] = 0;
|
|
int j = 0;
|
|
if (strlen(url_base) < strlen(curl) - 8) ++i; // Skip /
|
|
for (; j < strlen(curl) - 8 - i; ++j) {
|
|
if (curl[i + 8 + j] == 0) break;
|
|
url_path[j] = curl[i + 8 + j];
|
|
}
|
|
url_path[j] = 0;
|
|
kinc_http_request(url_base, url_path, NULL, 443, true, 0, NULL, &runt_http_callback, cbd);
|
|
}
|
|
|
|
#ifdef WITH_COMPUTE
|
|
void runt_set_bool_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
int32_t value = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_compute_set_bool(*location, value != 0);
|
|
}
|
|
|
|
void runt_set_int_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
int32_t value = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_compute_set_int(*location, value);
|
|
}
|
|
|
|
void runt_set_float_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
float value = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_compute_set_float(*location, value);
|
|
}
|
|
|
|
void runt_set_float2_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
float value1 = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value2 = (float)args[2]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_compute_set_float2(*location, value1, value2);
|
|
}
|
|
|
|
void runt_set_float3_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
float value1 = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value2 = (float)args[2]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value3 = (float)args[3]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_compute_set_float3(*location, value1, value2, value3);
|
|
}
|
|
|
|
void runt_set_float4_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
float value1 = (float)args[1]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value2 = (float)args[2]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value3 = (float)args[3]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
float value4 = (float)args[4]->ToNumber(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_compute_set_float4(*location, value1, value2, value3, value4);
|
|
}
|
|
|
|
void runt_set_floats_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
float *from = (float *)content->Data();
|
|
kinc_compute_set_floats(*location, from, int(content->ByteLength() / 4));
|
|
}
|
|
|
|
void runt_set_matrix_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
float *from = (float *)content->Data();
|
|
kinc_compute_set_matrix4(*location, (kinc_matrix4x4_t *)from);
|
|
}
|
|
|
|
void runt_set_matrix3_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> locationfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_constant_location_t *location = (kinc_compute_constant_location_t *)locationfield->Value();
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[1]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
float *from = (float *)content->Data();
|
|
kinc_compute_set_matrix3(*location, (kinc_matrix3x3_t *)from);
|
|
}
|
|
|
|
void runt_set_texture_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)unitfield->Value();
|
|
Local<External> texfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)texfield->Value();
|
|
int access = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
kinc_compute_set_texture(*unit, texture, (kinc_compute_access_t)access);
|
|
}
|
|
|
|
void runt_set_render_target_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)unitfield->Value();
|
|
Local<External> rtfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
int access = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
kinc_compute_set_render_target(*unit, render_target, (kinc_compute_access_t)access);
|
|
}
|
|
|
|
void runt_set_sampled_texture_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)unitfield->Value();
|
|
Local<External> texfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_texture_t *texture = (kinc_g4_texture_t *)texfield->Value();
|
|
kinc_compute_set_sampled_texture(*unit, texture);
|
|
}
|
|
|
|
void runt_set_sampled_render_target_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)unitfield->Value();
|
|
Local<External> rtfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
kinc_compute_set_sampled_render_target(*unit, render_target);
|
|
}
|
|
|
|
void runt_set_sampled_depth_texture_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)unitfield->Value();
|
|
Local<External> rtfield = Local<External>::Cast(args[1]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_g4_render_target_t *render_target = (kinc_g4_render_target_t *)rtfield->Value();
|
|
kinc_compute_set_sampled_depth_from_render_target(*unit, render_target);
|
|
}
|
|
|
|
void runt_set_texture_parameters_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)unitfield->Value();
|
|
kinc_compute_set_texture_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture_minification_filter(*unit, (kinc_g4_texture_filter_t)args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture_magnification_filter(*unit, (kinc_g4_texture_filter_t)args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture_mipmap_filter(*unit, (kinc_g4_mipmap_filter_t)args[5]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
}
|
|
|
|
void runt_set_texture3d_parameters_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> unitfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_texture_unit_t *unit = (kinc_compute_texture_unit_t *)unitfield->Value();
|
|
kinc_compute_set_texture3d_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_U, (kinc_g4_texture_addressing_t)args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture3d_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_V, (kinc_g4_texture_addressing_t)args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture3d_addressing(*unit, KINC_G4_TEXTURE_DIRECTION_W, (kinc_g4_texture_addressing_t)args[3]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture3d_minification_filter(*unit, (kinc_g4_texture_filter_t)args[4]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture3d_magnification_filter(*unit, (kinc_g4_texture_filter_t)args[5]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
kinc_compute_set_texture3d_mipmap_filter(*unit, (kinc_g4_mipmap_filter_t)args[6]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Int32Value(isolate->GetCurrentContext()).FromJust());
|
|
}
|
|
|
|
void runt_set_shader_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> shaderfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_shader *shader = (kinc_compute_shader *)shaderfield->Value();
|
|
kinc_compute_set_shader(shader);
|
|
}
|
|
|
|
void runt_create_shader_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<ArrayBuffer> buffer = Local<ArrayBuffer>::Cast(args[0]);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_compute_shader *shader = (kinc_compute_shader *)malloc(sizeof(kinc_compute_shader));
|
|
kinc_compute_shader_init(shader, content->Data(), (int)content->ByteLength());
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
obj->SetInternalField(0, External::New(isolate, shader));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_delete_shader_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Object> shaderobj = args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked();
|
|
Local<External> shaderfield = Local<External>::Cast(shaderobj->GetInternalField(0));
|
|
kinc_compute_shader *shader = (kinc_compute_shader *)shaderfield->Value();
|
|
kinc_compute_shader_destroy(shader);
|
|
free(shader);
|
|
}
|
|
|
|
void runt_get_constant_location_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> shaderfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_shader *shader = (kinc_compute_shader *)shaderfield->Value();
|
|
|
|
String::Utf8Value utf8_value(isolate, args[1]);
|
|
kinc_compute_constant_location_t location = kinc_compute_shader_get_constant_location(shader, *utf8_value);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
kinc_compute_constant_location_t *location_copy = (kinc_compute_constant_location_t *)malloc(sizeof(kinc_compute_constant_location_t)); // TODO
|
|
memcpy(location_copy, &location, sizeof(kinc_compute_constant_location_t));
|
|
obj->SetInternalField(0, External::New(isolate, location_copy));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_get_texture_unit_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<External> shaderfield = Local<External>::Cast(args[0]->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->GetInternalField(0));
|
|
kinc_compute_shader *shader = (kinc_compute_shader *)shaderfield->Value();
|
|
|
|
String::Utf8Value utf8_value(isolate, args[1]);
|
|
kinc_compute_texture_unit_t unit = kinc_compute_shader_get_texture_unit(shader, *utf8_value);
|
|
|
|
Local<ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
|
templ->SetInternalFieldCount(1);
|
|
|
|
Local<Object> obj = templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked();
|
|
kinc_compute_texture_unit_t *unit_copy = (kinc_compute_texture_unit_t *)malloc(sizeof(kinc_compute_texture_unit_t)); // TODO
|
|
memcpy(unit_copy, &unit, sizeof(kinc_compute_texture_unit_t));
|
|
obj->SetInternalField(0, External::New(isolate, unit_copy));
|
|
args.GetReturnValue().Set(obj);
|
|
}
|
|
|
|
void runt_compute(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int x = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int y = args[1]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
int z = args[2]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_compute(x, y, z);
|
|
}
|
|
#endif
|
|
|
|
bool window_close_callback(void *data) {
|
|
return true;
|
|
}
|
|
|
|
void runt_set_save_and_quit_callback(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
Local<Value> arg = args[0];
|
|
Local<Function> func = Local<Function>::Cast(arg);
|
|
save_and_quit_func.Reset(isolate, func);
|
|
save_and_quit_func_set = true;
|
|
kinc_window_set_close_callback(0, window_close_callback, NULL);
|
|
}
|
|
|
|
void runt_set_mouse_cursor(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int id = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_mouse_set_cursor(id);
|
|
#ifdef KORE_WINDOWS
|
|
// Set hand icon for drag even when mouse button is pressed
|
|
if (id == 1) SetCursor(LoadCursor(NULL, IDC_HAND));
|
|
#endif
|
|
}
|
|
|
|
void runt_delay_idle_sleep_fast(Local<Object> receiver) {
|
|
paused_frames = 0;
|
|
}
|
|
|
|
void runt_delay_idle_sleep(const FunctionCallbackInfo<Value> &args) {
|
|
runt_delay_idle_sleep_fast(args.This());
|
|
}
|
|
|
|
void runt_file_exists(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
bool exists = false;
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
|
|
kinc_file_reader_t reader;
|
|
if (kinc_file_reader_open(&reader, *utf8_value, KINC_FILE_TYPE_ASSET)) {
|
|
exists = true;
|
|
kinc_file_reader_close(&reader);
|
|
}
|
|
|
|
args.GetReturnValue().Set(Int32::New(isolate, exists));
|
|
}
|
|
|
|
void runt_delete_file(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
String::Utf8Value utf8_value(isolate, args[0]);
|
|
#if defined(KORE_WINDOWS)
|
|
char path[1024];
|
|
strcpy(path, "del /f \"");
|
|
strcat(path, *utf8_value);
|
|
strcat(path, "\"");
|
|
sys_command(path);
|
|
#else
|
|
char path[1024];
|
|
strcpy(path, "rm \"");
|
|
strcat(path, *utf8_value);
|
|
strcat(path, "\"");
|
|
sys_command(path);
|
|
#endif
|
|
}
|
|
|
|
void runt_window_x(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_window_x(windowId)));
|
|
}
|
|
|
|
void runt_window_y(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
args.GetReturnValue().Set(Int32::New(isolate, kinc_window_y(windowId)));
|
|
}
|
|
|
|
void runt_language(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
args.GetReturnValue().Set(String::NewFromUtf8(isolate, kinc_language()).ToLocalChecked());
|
|
}
|
|
|
|
void runt_viewport_set_camera(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
float pos_x = (float)args[0]->NumberValue(isolate->GetCurrentContext()).FromMaybe(0.0);
|
|
float pos_y = (float)args[1]->NumberValue(isolate->GetCurrentContext()).FromMaybe(0.0);
|
|
float pos_z = (float)args[2]->NumberValue(isolate->GetCurrentContext()).FromMaybe(0.0);
|
|
float rot_x = (float)args[3]->NumberValue(isolate->GetCurrentContext()).FromMaybe(0.0);
|
|
float rot_y = (float)args[4]->NumberValue(isolate->GetCurrentContext()).FromMaybe(0.0);
|
|
float rot_z = (float)args[5]->NumberValue(isolate->GetCurrentContext()).FromMaybe(0.0);
|
|
float rot_w = (float)args[6]->NumberValue(isolate->GetCurrentContext()).FromMaybe(1.0);
|
|
viewport_server_set_camera(pos_x, pos_y, pos_z, rot_x, rot_y, rot_z, rot_w);
|
|
}
|
|
|
|
void runt_window_set_foreground(const FunctionCallbackInfo<Value> &args) {
|
|
HandleScope scope(args.GetIsolate());
|
|
int windowId = args[0]->ToInt32(isolate->GetCurrentContext()).ToLocalChecked()->Value();
|
|
kinc_window_set_foreground(windowId);
|
|
}
|
|
|
|
#define SET_FUNCTION_FAST(object, name, fn)\
|
|
CFunction fn ## _ = CFunction::Make(fn ## _fast);\
|
|
object->Set(String::NewFromUtf8(isolate, name).ToLocalChecked(),\
|
|
FunctionTemplate::New(isolate, fn, Local<v8::Value>(), Local<v8::Signature>(), 0,\
|
|
v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasNoSideEffect, &fn ## _))
|
|
|
|
#define SET_FUNCTION(object, name, fn)\
|
|
object->Set(String::NewFromUtf8(isolate, name).ToLocalChecked(),\
|
|
FunctionTemplate::New(isolate, fn, Local<v8::Value>(), Local<v8::Signature>(), 0,\
|
|
v8::ConstructorBehavior::kThrow, v8::SideEffectType::kHasNoSideEffect, nullptr))
|
|
|
|
void start_v8(char *runt_bin, int runt_bin_size) {
|
|
plat = platform::NewDefaultPlatform();
|
|
V8::InitializePlatform(plat.get());
|
|
|
|
// std::string flags = "";
|
|
std::string flags = "--max-old-space-size=1024 --initial-old-space-size=128 --max-semi-space-size=64 "
|
|
"--gc-interval=100 --optimize-for-size --turbo-fast-api-calls --concurrent-marking "
|
|
"--parallel-scavenge --use-idle-notification --incremental-marking";
|
|
V8::SetFlagsFromString(flags.c_str(), (int)flags.size());
|
|
|
|
V8::Initialize();
|
|
|
|
Isolate::CreateParams create_params;
|
|
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
|
|
StartupData blob;
|
|
if (runt_bin_size > 0) {
|
|
blob.data = runt_bin;
|
|
blob.raw_size = runt_bin_size;
|
|
create_params.snapshot_blob = &blob;
|
|
}
|
|
isolate = Isolate::New(create_params);
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
|
|
Local<ObjectTemplate> runt = ObjectTemplate::New(isolate);
|
|
SET_FUNCTION(runt, "init", runt_init);
|
|
SET_FUNCTION(runt, "setApplicationName", runt_set_application_name);
|
|
SET_FUNCTION(runt, "log", runt_log);
|
|
SET_FUNCTION_FAST(runt, "clear", runt_clear);
|
|
SET_FUNCTION(runt, "setCallback", runt_set_callback);
|
|
SET_FUNCTION(runt, "setDropFilesCallback", runt_set_drop_files_callback);
|
|
SET_FUNCTION(runt, "setCutCopyPasteCallback", runt_set_cut_copy_paste_callback); ////
|
|
SET_FUNCTION(runt, "setApplicationStateCallback", runt_set_application_state_callback);
|
|
SET_FUNCTION(runt, "setKeyboardDownCallback", runt_set_keyboard_down_callback);
|
|
SET_FUNCTION(runt, "setKeyboardUpCallback", runt_set_keyboard_up_callback);
|
|
SET_FUNCTION(runt, "setKeyboardPressCallback", runt_set_keyboard_press_callback);
|
|
SET_FUNCTION(runt, "setMouseDownCallback", runt_set_mouse_down_callback);
|
|
SET_FUNCTION(runt, "setMouseUpCallback", runt_set_mouse_up_callback);
|
|
SET_FUNCTION(runt, "setMouseMoveCallback", runt_set_mouse_move_callback);
|
|
SET_FUNCTION(runt, "setTouchDownCallback", runt_set_touch_down_callback);
|
|
SET_FUNCTION(runt, "setTouchUpCallback", runt_set_touch_up_callback);
|
|
SET_FUNCTION(runt, "setTouchMoveCallback", runt_set_touch_move_callback);
|
|
SET_FUNCTION(runt, "setMouseWheelCallback", runt_set_mouse_wheel_callback);
|
|
SET_FUNCTION(runt, "setPenDownCallback", runt_set_pen_down_callback);
|
|
SET_FUNCTION(runt, "setPenUpCallback", runt_set_pen_up_callback);
|
|
SET_FUNCTION(runt, "setPenMoveCallback", runt_set_pen_move_callback);
|
|
SET_FUNCTION(runt, "setGamepadAxisCallback", runt_set_gamepad_axis_callback);
|
|
SET_FUNCTION(runt, "setGamepadButtonCallback", runt_set_gamepad_button_callback);
|
|
SET_FUNCTION_FAST(runt, "lockMouse", runt_lock_mouse);
|
|
SET_FUNCTION_FAST(runt, "unlockMouse", runt_unlock_mouse);
|
|
SET_FUNCTION_FAST(runt, "canLockMouse", runt_can_lock_mouse);
|
|
SET_FUNCTION_FAST(runt, "isMouseLocked", runt_is_mouse_locked);
|
|
SET_FUNCTION_FAST(runt, "setMousePosition", runt_set_mouse_position);
|
|
SET_FUNCTION_FAST(runt, "showMouse", runt_show_mouse);
|
|
SET_FUNCTION_FAST(runt, "showKeyboard", runt_show_keyboard);
|
|
SET_FUNCTION(runt, "createIndexBuffer", runt_create_indexbuffer);
|
|
SET_FUNCTION(runt, "deleteIndexBuffer", runt_delete_indexbuffer);
|
|
SET_FUNCTION(runt, "lockIndexBuffer", runt_lock_indexbuffer);
|
|
SET_FUNCTION(runt, "unlockIndexBuffer", runt_unlock_indexbuffer);
|
|
SET_FUNCTION(runt, "setIndexBuffer", runt_set_indexbuffer);
|
|
SET_FUNCTION(runt, "createVertexBuffer", runt_create_vertexbuffer);
|
|
SET_FUNCTION(runt, "deleteVertexBuffer", runt_delete_vertexbuffer);
|
|
SET_FUNCTION(runt, "lockVertexBuffer", runt_lock_vertex_buffer);
|
|
SET_FUNCTION(runt, "unlockVertexBuffer", runt_unlock_vertex_buffer);
|
|
SET_FUNCTION(runt, "setVertexBuffer", runt_set_vertexbuffer);
|
|
SET_FUNCTION(runt, "setVertexBuffers", runt_set_vertexbuffers);
|
|
SET_FUNCTION_FAST(runt, "drawIndexedVertices", runt_draw_indexed_vertices);
|
|
SET_FUNCTION_FAST(runt, "drawIndexedVerticesInstanced", runt_draw_indexed_vertices_instanced);
|
|
SET_FUNCTION(runt, "createVertexShader", runt_create_vertex_shader);
|
|
SET_FUNCTION(runt, "createVertexShaderFromSource", runt_create_vertex_shader_from_source);
|
|
SET_FUNCTION(runt, "createFragmentShader", runt_create_fragment_shader);
|
|
SET_FUNCTION(runt, "createFragmentShaderFromSource", runt_create_fragment_shader_from_source);
|
|
SET_FUNCTION(runt, "createGeometryShader", runt_create_geometry_shader);
|
|
SET_FUNCTION(runt, "createTessellationControlShader", runt_create_tessellation_control_shader);
|
|
SET_FUNCTION(runt, "createTessellationEvaluationShader", runt_create_tessellation_evaluation_shader);
|
|
SET_FUNCTION(runt, "deleteShader", runt_delete_shader);
|
|
SET_FUNCTION(runt, "createPipeline", runt_create_pipeline);
|
|
SET_FUNCTION(runt, "deletePipeline", runt_delete_pipeline);
|
|
SET_FUNCTION(runt, "compilePipeline", runt_compile_pipeline);
|
|
SET_FUNCTION(runt, "setPipeline", runt_set_pipeline);
|
|
SET_FUNCTION(runt, "loadImage", runt_load_image);
|
|
SET_FUNCTION(runt, "unloadImage", runt_unload_image);
|
|
#ifdef WITH_AUDIO
|
|
SET_FUNCTION(runt, "loadSound", runt_load_sound);
|
|
SET_FUNCTION(runt, "setAudioCallback", runt_set_audio_callback);
|
|
SET_FUNCTION(runt, "audioThread", runt_audio_thread);
|
|
SET_FUNCTION(runt, "writeAudioBuffer", runt_write_audio_buffer);
|
|
SET_FUNCTION(runt, "getSamplesPerSecond", runt_get_samples_per_second);
|
|
#endif
|
|
SET_FUNCTION(runt, "loadBlob", runt_load_blob);
|
|
SET_FUNCTION(runt, "loadUrl", runt_load_url);
|
|
SET_FUNCTION(runt, "copyToClipboard", runt_copy_to_clipboard);
|
|
SET_FUNCTION(runt, "getConstantLocation", runt_get_constant_location);
|
|
SET_FUNCTION(runt, "getTextureUnit", runt_get_texture_unit);
|
|
SET_FUNCTION(runt, "setTexture", runt_set_texture);
|
|
SET_FUNCTION(runt, "setRenderTarget", runt_set_render_target);
|
|
SET_FUNCTION(runt, "setTextureDepth", runt_set_texture_depth);
|
|
SET_FUNCTION(runt, "setImageTexture", runt_set_image_texture);
|
|
SET_FUNCTION(runt, "setTextureParameters", runt_set_texture_parameters);
|
|
SET_FUNCTION(runt, "setTexture3DParameters", runt_set_texture3d_parameters);
|
|
SET_FUNCTION(runt, "setTextureCompareMode", runt_set_texture_compare_mode);
|
|
SET_FUNCTION(runt, "setCubeMapCompareMode", runt_set_cube_map_compare_mode);
|
|
SET_FUNCTION(runt, "setBool", runt_set_bool);
|
|
SET_FUNCTION(runt, "setInt", runt_set_int);
|
|
SET_FUNCTION(runt, "setFloat", runt_set_float);
|
|
SET_FUNCTION(runt, "setFloat2", runt_set_float2);
|
|
SET_FUNCTION(runt, "setFloat3", runt_set_float3);
|
|
SET_FUNCTION(runt, "setFloat4", runt_set_float4);
|
|
SET_FUNCTION(runt, "setFloats", runt_set_floats);
|
|
SET_FUNCTION(runt, "setMatrix", runt_set_matrix);
|
|
SET_FUNCTION(runt, "setMatrix3", runt_set_matrix3);
|
|
SET_FUNCTION_FAST(runt, "getTime", runt_get_time);
|
|
SET_FUNCTION_FAST(runt, "windowWidth", runt_window_width);
|
|
SET_FUNCTION_FAST(runt, "windowHeight", runt_window_height);
|
|
SET_FUNCTION(runt, "setWindowTitle", runt_set_window_title);
|
|
SET_FUNCTION(runt, "getWindowMode", runt_get_window_mode);
|
|
SET_FUNCTION(runt, "setWindowMode", runt_set_window_mode);
|
|
SET_FUNCTION(runt, "resizeWindow", runt_resize_window);
|
|
SET_FUNCTION(runt, "moveWindow", runt_move_window);
|
|
SET_FUNCTION(runt, "screenDpi", runt_screen_dpi);
|
|
SET_FUNCTION(runt, "systemId", runt_system_id);
|
|
SET_FUNCTION(runt, "requestShutdown", runt_request_shutdown);
|
|
SET_FUNCTION(runt, "displayCount", runt_display_count);
|
|
SET_FUNCTION(runt, "displayWidth", runt_display_width);
|
|
SET_FUNCTION(runt, "displayHeight", runt_display_height);
|
|
SET_FUNCTION(runt, "displayX", runt_display_x);
|
|
SET_FUNCTION(runt, "displayY", runt_display_y);
|
|
SET_FUNCTION(runt, "displayFrequency", runt_display_frequency);
|
|
SET_FUNCTION(runt, "displayIsPrimary", runt_display_is_primary);
|
|
SET_FUNCTION(runt, "writeStorage", runt_write_storage);
|
|
SET_FUNCTION(runt, "readStorage", runt_read_storage);
|
|
SET_FUNCTION(runt, "createRenderTarget", runt_create_render_target);
|
|
SET_FUNCTION(runt, "createRenderTargetCubeMap", runt_create_render_target_cube_map);
|
|
SET_FUNCTION(runt, "createTexture", runt_create_texture);
|
|
SET_FUNCTION(runt, "createTexture3D", runt_create_texture3d);
|
|
SET_FUNCTION(runt, "createTextureFromBytes", runt_create_texture_from_bytes);
|
|
SET_FUNCTION(runt, "createTextureFromBytes3D", runt_create_texture_from_bytes3d);
|
|
SET_FUNCTION(runt, "createTextureFromEncodedBytes", runt_create_texture_from_encoded_bytes);
|
|
SET_FUNCTION(runt, "getTexturePixels", runt_get_texture_pixels);
|
|
SET_FUNCTION(runt, "getRenderTargetPixels", runt_get_render_target_pixels);
|
|
SET_FUNCTION(runt, "lockTexture", runt_lock_texture);
|
|
SET_FUNCTION(runt, "unlockTexture", runt_unlock_texture);
|
|
SET_FUNCTION(runt, "clearTexture", runt_clear_texture);
|
|
SET_FUNCTION(runt, "generateTextureMipmaps", runt_generate_texture_mipmaps);
|
|
SET_FUNCTION(runt, "generateRenderTargetMipmaps", runt_generate_render_target_mipmaps);
|
|
SET_FUNCTION(runt, "setMipmaps", runt_set_mipmaps);
|
|
SET_FUNCTION(runt, "setDepthStencilFrom", runt_set_depth_stencil_from);
|
|
SET_FUNCTION_FAST(runt, "viewport", runt_viewport);
|
|
SET_FUNCTION_FAST(runt, "scissor", runt_scissor);
|
|
SET_FUNCTION_FAST(runt, "disableScissor", runt_disable_scissor);
|
|
SET_FUNCTION_FAST(runt, "renderTargetsInvertedY", runt_render_targets_inverted_y);
|
|
SET_FUNCTION(runt, "begin", runt_begin);
|
|
SET_FUNCTION(runt, "beginFace", runt_begin_face);
|
|
SET_FUNCTION(runt, "end", runt_end);
|
|
SET_FUNCTION(runt, "fileSaveBytes", runt_file_save_bytes);
|
|
SET_FUNCTION(runt, "sysCommand", runt_sys_command);
|
|
SET_FUNCTION(runt, "savePath", runt_save_path);
|
|
SET_FUNCTION(runt, "getArgCount", runt_get_arg_count);
|
|
SET_FUNCTION(runt, "getArg", runt_get_arg);
|
|
SET_FUNCTION(runt, "getFilesLocation", runt_get_files_location);
|
|
SET_FUNCTION(runt, "httpRequest", runt_http_request);
|
|
SET_FUNCTION(runt, "viewportSetCamera", runt_viewport_set_camera);
|
|
SET_FUNCTION(runt, "windowSetForeground", runt_window_set_foreground);
|
|
|
|
#ifdef WITH_NETWORKING
|
|
SET_FUNCTION(runt, "socketCreate", v8_runt_socket_create);
|
|
SET_FUNCTION(runt, "socketBind", v8_runt_socket_bind);
|
|
SET_FUNCTION(runt, "socketListen", v8_runt_socket_listen);
|
|
SET_FUNCTION(runt, "socketAccept", v8_runt_socket_accept);
|
|
SET_FUNCTION(runt, "socketConnect", v8_runt_socket_connect);
|
|
SET_FUNCTION(runt, "socketSend", v8_runt_socket_send);
|
|
SET_FUNCTION(runt, "socketRecv", v8_runt_socket_recv);
|
|
SET_FUNCTION(runt, "socketClose", v8_runt_socket_close);
|
|
SET_FUNCTION(runt, "socketSetBlocking", v8_runt_socket_set_blocking);
|
|
SET_FUNCTION(runt, "socketSelect", v8_runt_socket_select);
|
|
SET_FUNCTION(runt, "socketIsConnected", v8_runt_socket_is_connected);
|
|
#ifdef WITH_SSL
|
|
SET_FUNCTION(runt, "socketEnableSsl", v8_runt_socket_enable_ssl);
|
|
#endif
|
|
|
|
SET_FUNCTION(runt, "websocketCreate", runt_websocket_create);
|
|
SET_FUNCTION(runt, "websocketSend", runt_websocket_send);
|
|
SET_FUNCTION(runt, "websocketSendBinary", runt_websocket_send_binary);
|
|
SET_FUNCTION(runt, "websocketClose", runt_websocket_close);
|
|
SET_FUNCTION(runt, "websocketGetReadyState", runt_websocket_get_ready_state);
|
|
SET_FUNCTION(runt, "websocketGetUrl", runt_websocket_get_url);
|
|
SET_FUNCTION(runt, "websocketGetBufferedAmount", runt_websocket_get_buffered_amount);
|
|
SET_FUNCTION(runt, "websocketSetOnOpen", runt_websocket_set_onopen);
|
|
SET_FUNCTION(runt, "websocketSetOnMessage", runt_websocket_set_onmessage);
|
|
SET_FUNCTION(runt, "websocketSetOnError", runt_websocket_set_onerror);
|
|
SET_FUNCTION(runt, "websocketSetOnClose", runt_websocket_set_onclose);
|
|
SET_FUNCTION(runt, "websocketServerCreate", v8_runt_websocket_server_create);
|
|
SET_FUNCTION(runt, "websocketServerStart", v8_runt_websocket_server_start);
|
|
SET_FUNCTION(runt, "websocketServerStop", v8_runt_websocket_server_stop);
|
|
SET_FUNCTION(runt, "websocketServerTick", v8_runt_websocket_server_tick);
|
|
SET_FUNCTION(runt, "websocketServerSendAll", v8_runt_websocket_server_send_all);
|
|
SET_FUNCTION(runt, "websocketServerSendClient", v8_runt_websocket_server_send_client);
|
|
|
|
SET_FUNCTION(runt, "httpRequestCreate", runt_httprequest_create);
|
|
SET_FUNCTION(runt, "httpRequestOpen", runt_httprequest_open);
|
|
SET_FUNCTION(runt, "httpRequestSend", runt_httprequest_send);
|
|
SET_FUNCTION(runt, "httpRequestAbort", runt_httprequest_abort);
|
|
SET_FUNCTION(runt, "httpRequestSetRequestHeader", runt_httprequest_set_request_header);
|
|
SET_FUNCTION(runt, "httpRequestGetAllResponseHeaders", runt_httprequest_get_all_response_headers);
|
|
SET_FUNCTION(runt, "httpRequestGetResponseHeader", runt_httprequest_get_response_header);
|
|
SET_FUNCTION(runt, "httpRequestGetReadyState", runt_httprequest_get_ready_state);
|
|
SET_FUNCTION(runt, "httpRequestGetStatus", runt_httprequest_get_status);
|
|
SET_FUNCTION(runt, "httpRequestGetStatusText", runt_httprequest_get_status_text);
|
|
SET_FUNCTION(runt, "httpRequestGetResponseText", runt_httprequest_get_response_text);
|
|
SET_FUNCTION(runt, "httpRequestGetResponseURL", runt_httprequest_get_response_url);
|
|
SET_FUNCTION(runt, "httpRequestSetTimeout", runt_httprequest_set_timeout);
|
|
SET_FUNCTION(runt, "httpRequestSetResponseType", runt_httprequest_set_response_type);
|
|
SET_FUNCTION(runt, "httpRequestSetWithCredentials", runt_httprequest_set_with_credentials);
|
|
SET_FUNCTION(runt, "httpRequestSetOnReadyStateChange", runt_httprequest_set_onreadystatechange);
|
|
SET_FUNCTION(runt, "httpRequestSetOnLoad", runt_httprequest_set_onload);
|
|
SET_FUNCTION(runt, "httpRequestSetOnError", runt_httprequest_set_onerror);
|
|
SET_FUNCTION(runt, "httpRequestSetOnTimeout", runt_httprequest_set_ontimeout);
|
|
SET_FUNCTION(runt, "httpRequestSetOnAbort", runt_httprequest_set_onabort);
|
|
SET_FUNCTION(runt, "httpRequestSetOnProgress", runt_httprequest_set_onprogress);
|
|
SET_FUNCTION(runt, "httpRequestSetOnLoadStart", runt_httprequest_set_onloadstart);
|
|
SET_FUNCTION(runt, "httpRequestSetOnLoadEnd", runt_httprequest_set_onloadend);
|
|
#endif
|
|
|
|
#ifdef WITH_COMPUTE
|
|
SET_FUNCTION(runt, "setBoolCompute", runt_set_bool_compute);
|
|
SET_FUNCTION(runt, "setIntCompute", runt_set_int_compute);
|
|
SET_FUNCTION(runt, "setFloatCompute", runt_set_float_compute);
|
|
SET_FUNCTION(runt, "setFloat2Compute", runt_set_float2_compute);
|
|
SET_FUNCTION(runt, "setFloat3Compute", runt_set_float3_compute);
|
|
SET_FUNCTION(runt, "setFloat4Compute", runt_set_float4_compute);
|
|
SET_FUNCTION(runt, "setFloatsCompute", runt_set_floats_compute);
|
|
SET_FUNCTION(runt, "setMatrixCompute", runt_set_matrix_compute);
|
|
SET_FUNCTION(runt, "setMatrix3Compute", runt_set_matrix3_compute);
|
|
SET_FUNCTION(runt, "setTextureCompute", runt_set_texture_compute);
|
|
SET_FUNCTION(runt, "setRenderTargetCompute", runt_set_render_target_compute);
|
|
SET_FUNCTION(runt, "setSampledTextureCompute", runt_set_sampled_texture_compute);
|
|
SET_FUNCTION(runt, "setSampledRenderTargetCompute", runt_set_sampled_render_target_compute);
|
|
SET_FUNCTION(runt, "setSampledDepthTextureCompute", runt_set_sampled_depth_texture_compute);
|
|
SET_FUNCTION(runt, "setTextureParametersCompute", runt_set_texture_parameters_compute);
|
|
SET_FUNCTION(runt, "setTexture3DParametersCompute", runt_set_texture3d_parameters_compute);
|
|
SET_FUNCTION(runt, "setShaderCompute", runt_set_shader_compute);
|
|
SET_FUNCTION(runt, "deleteShaderCompute", runt_delete_shader_compute);
|
|
SET_FUNCTION(runt, "createShaderCompute", runt_create_shader_compute);
|
|
SET_FUNCTION(runt, "getConstantLocationCompute", runt_get_constant_location_compute);
|
|
SET_FUNCTION(runt, "getTextureUnitCompute", runt_get_texture_unit_compute);
|
|
SET_FUNCTION(runt, "compute", runt_compute);
|
|
#endif
|
|
SET_FUNCTION(runt, "setSaveAndQuitCallback", runt_set_save_and_quit_callback);
|
|
SET_FUNCTION(runt, "setMouseCursor", runt_set_mouse_cursor);
|
|
SET_FUNCTION_FAST(runt, "delayIdleSleep", runt_delay_idle_sleep);
|
|
SET_FUNCTION(runt, "fileExists", runt_file_exists);
|
|
SET_FUNCTION(runt, "deleteFile", runt_delete_file);
|
|
SET_FUNCTION(runt, "windowX", runt_window_x);
|
|
SET_FUNCTION(runt, "windowY", runt_window_y);
|
|
SET_FUNCTION(runt, "language", runt_language);
|
|
|
|
Local<ObjectTemplate> global = ObjectTemplate::New(isolate);
|
|
global->Set(String::NewFromUtf8(isolate, "RunT").ToLocalChecked(), runt);
|
|
global->Set(String::NewFromUtf8(isolate, "runt").ToLocalChecked(), runt); // lowercase alias for JavaScript compatibility
|
|
|
|
// additional common APIs
|
|
Local<ObjectTemplate> window_template = ObjectTemplate::New(isolate);
|
|
window_template->Set(String::NewFromUtf8(isolate, "innerWidth").ToLocalChecked(), Integer::New(isolate, kinc_window_width(0)));
|
|
window_template->Set(String::NewFromUtf8(isolate, "innerHeight").ToLocalChecked(), Integer::New(isolate, kinc_window_height(0)));
|
|
window_template->Set(String::NewFromUtf8(isolate, "devicePixelRatio").ToLocalChecked(), Number::New(isolate, 1.0));
|
|
global->Set(String::NewFromUtf8(isolate, "window").ToLocalChecked(), window_template);
|
|
global->Set(String::NewFromUtf8(isolate, "global").ToLocalChecked(), window_template);
|
|
global->Set(String::NewFromUtf8(isolate, "globalThis").ToLocalChecked(), window_template);
|
|
Local<ObjectTemplate> console_template = ObjectTemplate::New(isolate);
|
|
console_template->Set(String::NewFromUtf8(isolate, "log").ToLocalChecked(), FunctionTemplate::New(isolate, runt_log));
|
|
console_template->Set(String::NewFromUtf8(isolate, "warn").ToLocalChecked(), FunctionTemplate::New(isolate, runt_log));
|
|
console_template->Set(String::NewFromUtf8(isolate, "error").ToLocalChecked(), FunctionTemplate::New(isolate, runt_log));
|
|
console_template->Set(String::NewFromUtf8(isolate, "info").ToLocalChecked(), FunctionTemplate::New(isolate, runt_log));
|
|
console_template->Set(String::NewFromUtf8(isolate, "debug").ToLocalChecked(), FunctionTemplate::New(isolate, runt_log));
|
|
|
|
global->Set(String::NewFromUtf8(isolate, "console").ToLocalChecked(), console_template);
|
|
window_template->Set(String::NewFromUtf8(isolate, "console").ToLocalChecked(), console_template);
|
|
|
|
#ifdef WITH_NETWORKING
|
|
setupNativeWebSocketClass(isolate, global);
|
|
setupNativeEventClasses(isolate, global);
|
|
setupNativeXMLHttpRequestClass(isolate, global);
|
|
#endif
|
|
|
|
Local<Context> context = Context::New(isolate, NULL, global);
|
|
global_context.Reset(isolate, context);
|
|
|
|
// needs self scope to add more browser APIs
|
|
{
|
|
Context::Scope context_scope(context);
|
|
Local<Object> global_obj = context->Global();
|
|
Local<Value> window_obj = global_obj->Get(context, String::NewFromUtf8(isolate, "window").ToLocalChecked()).ToLocalChecked();
|
|
|
|
if (window_obj->IsObject()) {
|
|
Local<Object> window = window_obj->ToObject(context).ToLocalChecked();
|
|
|
|
window->Set(context, String::NewFromUtf8(isolate, "window").ToLocalChecked(), window);
|
|
window->Set(context, String::NewFromUtf8(isolate, "self").ToLocalChecked(), window);
|
|
window->Set(context, String::NewFromUtf8(isolate, "top").ToLocalChecked(), window);
|
|
window->Set(context, String::NewFromUtf8(isolate, "parent").ToLocalChecked(), window);
|
|
|
|
Local<Object> location = Object::New(isolate);
|
|
location->Set(context, String::NewFromUtf8(isolate, "href").ToLocalChecked(), String::NewFromUtf8(isolate, "runt://localhost/").ToLocalChecked());
|
|
location->Set(context, String::NewFromUtf8(isolate, "origin").ToLocalChecked(), String::NewFromUtf8(isolate, "runt://localhost").ToLocalChecked());
|
|
location->Set(context, String::NewFromUtf8(isolate, "protocol").ToLocalChecked(), String::NewFromUtf8(isolate, "runt:").ToLocalChecked());
|
|
location->Set(context, String::NewFromUtf8(isolate, "host").ToLocalChecked(), String::NewFromUtf8(isolate, "localhost").ToLocalChecked());
|
|
location->Set(context, String::NewFromUtf8(isolate, "hostname").ToLocalChecked(), String::NewFromUtf8(isolate, "localhost").ToLocalChecked());
|
|
window->Set(context, String::NewFromUtf8(isolate, "location").ToLocalChecked(), location);
|
|
|
|
Local<Object> navigator = Object::New(isolate);
|
|
navigator->Set(context, String::NewFromUtf8(isolate, "userAgent").ToLocalChecked(), String::NewFromUtf8(isolate, "RunT/1.0").ToLocalChecked());
|
|
navigator->Set(context, String::NewFromUtf8(isolate, "platform").ToLocalChecked(), String::NewFromUtf8(isolate, "RunT").ToLocalChecked());
|
|
window->Set(context, String::NewFromUtf8(isolate, "navigator").ToLocalChecked(), navigator);
|
|
|
|
Local<Object> document = Object::New(isolate);
|
|
document->Set(context, String::NewFromUtf8(isolate, "title").ToLocalChecked(), String::NewFromUtf8(isolate, "Leenkx Application").ToLocalChecked());
|
|
window->Set(context, String::NewFromUtf8(isolate, "document").ToLocalChecked(), document);
|
|
|
|
window->Set(context, String::NewFromUtf8(isolate, "localStorage").ToLocalChecked(), Null(isolate));
|
|
window->Set(context, String::NewFromUtf8(isolate, "sessionStorage").ToLocalChecked(), Null(isolate));
|
|
window->Set(context, String::NewFromUtf8(isolate, "indexedDB").ToLocalChecked(), Null(isolate));
|
|
window->Set(context, String::NewFromUtf8(isolate, "setTimeout").ToLocalChecked(), Function::New(context, runt_set_timeout).ToLocalChecked()).Check();
|
|
window->Set(context, String::NewFromUtf8(isolate, "clearTimeout").ToLocalChecked(), Function::New(context, runt_clear_timeout).ToLocalChecked()).Check();
|
|
window->Set(context, String::NewFromUtf8(isolate, "setInterval").ToLocalChecked(), Function::New(context, runt_set_interval).ToLocalChecked()).Check();
|
|
window->Set(context, String::NewFromUtf8(isolate, "clearInterval").ToLocalChecked(), Function::New(context, runt_clear_interval).ToLocalChecked()).Check();
|
|
|
|
global_obj->Set(context, String::NewFromUtf8(isolate, "location").ToLocalChecked(), location);
|
|
global_obj->Set(context, String::NewFromUtf8(isolate, "navigator").ToLocalChecked(), navigator);
|
|
global_obj->Set(context, String::NewFromUtf8(isolate, "document").ToLocalChecked(), document);
|
|
global_obj->Set(context, String::NewFromUtf8(isolate, "setTimeout").ToLocalChecked(), Function::New(context, runt_set_timeout).ToLocalChecked()).Check();
|
|
global_obj->Set(context, String::NewFromUtf8(isolate, "clearTimeout").ToLocalChecked(), Function::New(context, runt_clear_timeout).ToLocalChecked()).Check();
|
|
global_obj->Set(context, String::NewFromUtf8(isolate, "setInterval").ToLocalChecked(), Function::New(context, runt_set_interval).ToLocalChecked()).Check();
|
|
global_obj->Set(context, String::NewFromUtf8(isolate, "clearInterval").ToLocalChecked(), Function::New(context, runt_clear_interval).ToLocalChecked()).Check();
|
|
}
|
|
}
|
|
|
|
#ifdef WITH_NETWORKING
|
|
WebSocketWrapper::initialize();
|
|
//kinc_log(KINC_LOG_LEVEL_INFO, "WebSocket client support initialized successfully");
|
|
HttpRequestWrapper::initialize();
|
|
//kinc_log(KINC_LOG_LEVEL_INFO, "Initializing native HTTP request support");
|
|
#endif
|
|
|
|
}
|
|
|
|
void start_runt(char *scriptfile) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
if (scriptfile != NULL) {
|
|
Local<String> source = String::NewFromUtf8(isolate, scriptfile, NewStringType::kNormal).ToLocalChecked();
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Script> compiled_script = Script::Compile(isolate->GetCurrentContext(), source).ToLocalChecked();
|
|
|
|
Local<Value> result;
|
|
if (!compiled_script->Run(context).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
else {
|
|
TryCatch try_catch(isolate);
|
|
Local<Value> js_kickstart = context->Global()->Get(isolate->GetCurrentContext(), String::NewFromUtf8(isolate, "kickstart").ToLocalChecked()).ToLocalChecked();
|
|
if (!js_kickstart->IsNullOrUndefined()) {
|
|
Local<Value> result;
|
|
if (!js_kickstart->ToObject(isolate->GetCurrentContext()).ToLocalChecked()->CallAsFunction(context, context->Global(), 0, nullptr).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void run_v8() {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
MicrotasksScope microtasks_scope(isolate, MicrotasksScope::kRunMicrotasks);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, update_func);
|
|
Local<Value> result;
|
|
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void update(void *data) {
|
|
#ifdef KORE_WINDOWS
|
|
if (show_window && enable_window) {
|
|
show_window = false;
|
|
|
|
#ifdef WITH_VIEWPORT
|
|
if (!viewport_server_mode) {
|
|
kinc_window_show(0);
|
|
}
|
|
#else
|
|
kinc_window_show(0);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#ifdef WITH_AUDIO
|
|
if (enable_audio) {
|
|
kinc_a2_update();
|
|
}
|
|
#endif
|
|
|
|
#ifdef WITH_WORKER
|
|
handle_worker_messages(isolate, global_context);
|
|
#endif
|
|
|
|
#ifdef WITH_NETWORKING
|
|
WebSocketWrapper::processEvents();
|
|
HttpRequestWrapper::processEvents();
|
|
#endif
|
|
|
|
execute_timers();
|
|
|
|
#ifdef WITH_VIEWPORT
|
|
if (viewport_server_mode && viewport_server_is_enabled()) {
|
|
if (viewport_server_check_shutdown()) {
|
|
kinc_stop();
|
|
return;
|
|
}
|
|
|
|
int new_width, new_height;
|
|
if (viewport_server_check_resize(&new_width, &new_height)) {
|
|
viewport_server_resize(new_width, new_height);
|
|
}
|
|
|
|
InputEvent input_event;
|
|
while (viewport_server_read_input(&input_event)) {
|
|
switch (input_event.type) {
|
|
case INPUT_EVENT_MOUSE_MOVE:
|
|
kinc_internal_mouse_trigger_move(0, input_event.x, input_event.y);
|
|
break;
|
|
case INPUT_EVENT_MOUSE_DOWN:
|
|
kinc_internal_mouse_trigger_press(0, input_event.button, input_event.x, input_event.y);
|
|
break;
|
|
case INPUT_EVENT_MOUSE_UP:
|
|
kinc_internal_mouse_trigger_release(0, input_event.button, input_event.x, input_event.y);
|
|
break;
|
|
case INPUT_EVENT_MOUSE_WHEEL:
|
|
kinc_internal_mouse_trigger_scroll(0, input_event.delta);
|
|
break;
|
|
case INPUT_EVENT_KEY_DOWN:
|
|
kinc_internal_keyboard_trigger_key_down(input_event.button);
|
|
break;
|
|
case INPUT_EVENT_KEY_UP:
|
|
kinc_internal_keyboard_trigger_key_up(input_event.button);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
kinc_g4_begin(0);
|
|
#ifdef WITH_VIEWPORT
|
|
if (viewport_server_mode && viewport_server_is_enabled()) {
|
|
viewport_server_begin_frame();
|
|
}
|
|
#endif
|
|
run_v8();
|
|
|
|
kinc_g4_end(0);
|
|
|
|
#ifdef WITH_VIEWPORT
|
|
// before the swap
|
|
if (viewport_server_mode && viewport_server_is_enabled()) {
|
|
viewport_server_end_frame();
|
|
}
|
|
#endif
|
|
kinc_g4_swap_buffers();
|
|
}
|
|
|
|
void drop_files(wchar_t *file_path, void *data) {
|
|
// Update mouse position
|
|
#ifdef KORE_WINDOWS
|
|
POINT p;
|
|
GetCursorPos(&p);
|
|
ScreenToClient(kinc_windows_window_handle(0), &p);
|
|
mouse_move(0, p.x, p.y, 0, 0, NULL);
|
|
#endif
|
|
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, drop_files_func);
|
|
Local<Value> result;
|
|
const int argc = 1;
|
|
Local<Value> argv[argc];
|
|
if (sizeof(wchar_t) == 2) {
|
|
argv[0] = {String::NewFromTwoByte(isolate, (const uint16_t *)file_path).ToLocalChecked()};
|
|
}
|
|
else {
|
|
size_t len = wcslen(file_path);
|
|
uint16_t *str = new uint16_t[len + 1];
|
|
for (int i = 0; i < len; i++) str[i] = file_path[i];
|
|
str[len] = 0;
|
|
argv[0] = {String::NewFromTwoByte(isolate, str).ToLocalChecked()};
|
|
delete[] str;
|
|
}
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
|
|
in_background = false;
|
|
}
|
|
|
|
char *copy(void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, copy_func);
|
|
Local<Value> result;
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
String::Utf8Value cutCopyString(isolate, result);
|
|
strcpy(temp_string, *cutCopyString);
|
|
|
|
return temp_string;
|
|
}
|
|
|
|
char *cut(void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, cut_func);
|
|
Local<Value> result;
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
String::Utf8Value cutCopyString(isolate, result);
|
|
strcpy(temp_string, *cutCopyString);
|
|
|
|
return temp_string;
|
|
}
|
|
|
|
void paste(char *text, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, paste_func);
|
|
Local<Value> result;
|
|
const int argc = 1;
|
|
Local<Value> argv[argc] = {String::NewFromUtf8(isolate, text).ToLocalChecked()};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void foreground(void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, foreground_func);
|
|
Local<Value> result;
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
|
|
in_background = false;
|
|
}
|
|
|
|
void resume(void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, resume_func);
|
|
Local<Value> result;
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void pause(void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, pause_func);
|
|
Local<Value> result;
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void background(void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, background_func);
|
|
Local<Value> result;
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
|
|
in_background = true;
|
|
paused_frames = 0;
|
|
}
|
|
|
|
void shutdown(void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, shutdown_func);
|
|
Local<Value> result;
|
|
if (!func->Call(context, context->Global(), 0, NULL).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
|
|
#ifdef WITH_NETWORKING
|
|
WebSocketWrapper::cleanup();
|
|
HttpRequestWrapper::cleanup();
|
|
#endif
|
|
#ifdef WITH_VIEWPORT
|
|
if (viewport_server_mode) {
|
|
viewport_server_shutdown();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void key_down(int code, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, keyboard_down_func);
|
|
Local<Value> result;
|
|
const int argc = 1;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, code)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void key_up(int code, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, keyboard_up_func);
|
|
Local<Value> result;
|
|
const int argc = 1;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, code)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void key_press(unsigned int character, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, keyboard_press_func);
|
|
Local<Value> result;
|
|
const int argc = 1;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, character)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void mouse_move(int window, int x, int y, int mx, int my, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, mouse_move_func);
|
|
Local<Value> result;
|
|
const int argc = 4;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, x), Int32::New(isolate, y), Int32::New(isolate, mx), Int32::New(isolate, my)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void mouse_down(int window, int button, int x, int y, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, mouse_down_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, button), Int32::New(isolate, x), Int32::New(isolate, y)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void mouse_up(int window, int button, int x, int y, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, mouse_up_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, button), Int32::New(isolate, x), Int32::New(isolate, y)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void mouse_wheel(int window, int delta, void *data) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, mouse_wheel_func);
|
|
Local<Value> result;
|
|
const int argc = 1;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, delta)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void touch_move(int index, int x, int y) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, touch_move_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, index), Int32::New(isolate, x), Int32::New(isolate, y)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void touch_down(int index, int x, int y) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, touch_down_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, index), Int32::New(isolate, x), Int32::New(isolate, y)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void touch_up(int index, int x, int y) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, touch_up_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, index), Int32::New(isolate, x), Int32::New(isolate, y)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void pen_down(int window, int x, int y, float pressure) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, pen_down_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, x), Int32::New(isolate, y), Number::New(isolate, pressure)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void pen_up(int window, int x, int y, float pressure) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, pen_up_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, x), Int32::New(isolate, y), Number::New(isolate, pressure)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void pen_move(int window, int x, int y, float pressure) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, pen_move_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, x), Int32::New(isolate, y), Number::New(isolate, pressure)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void gamepad_axis(int gamepad, int axis, float value) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, gamepad_axis_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, gamepad), Int32::New(isolate, axis), Number::New(isolate, value)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
void gamepad_button(int gamepad, int button, float value) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
Local<Function> func = Local<Function>::New(isolate, gamepad_button_func);
|
|
Local<Value> result;
|
|
const int argc = 3;
|
|
Local<Value> argv[argc] = {Int32::New(isolate, gamepad), Int32::New(isolate, button), Number::New(isolate, value)};
|
|
if (!func->Call(context, context->Global(), argc, argv).ToLocal(&result)) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
}
|
|
|
|
// timer system for setTimeout and setInterval
|
|
struct Timer {
|
|
Global<Function> callback;
|
|
std::chrono::steady_clock::time_point executionTime;
|
|
int id;
|
|
bool isInterval;
|
|
int intervalMs;
|
|
};
|
|
|
|
std::map<int, Timer> timers;
|
|
int nextTimerId = 1;
|
|
|
|
void runt_set_timeout(const FunctionCallbackInfo<Value> &args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
if (args.Length() < 2 || !args[0]->IsFunction()) {
|
|
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "setTimeout requires a function and delay").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
Local<Function> callback = Local<Function>::Cast(args[0]);
|
|
int delay = args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
Timer timer;
|
|
timer.callback.Reset(isolate, callback);
|
|
timer.executionTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(delay);
|
|
timer.id = nextTimerId++;
|
|
timer.isInterval = false;
|
|
timer.intervalMs = 0;
|
|
|
|
timers[timer.id] = std::move(timer);
|
|
|
|
args.GetReturnValue().Set(Integer::New(isolate, timer.id));
|
|
}
|
|
|
|
void runt_set_interval(const FunctionCallbackInfo<Value> &args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
if (args.Length() < 2 || !args[0]->IsFunction()) {
|
|
isolate->ThrowException(Exception::TypeError(String::NewFromUtf8(isolate, "setInterval requires a function and delay").ToLocalChecked()));
|
|
return;
|
|
}
|
|
|
|
Local<Function> callback = Local<Function>::Cast(args[0]);
|
|
int delay = args[1]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
|
|
Timer timer;
|
|
timer.callback.Reset(isolate, callback);
|
|
timer.executionTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(delay);
|
|
timer.id = nextTimerId++;
|
|
timer.isInterval = true;
|
|
timer.intervalMs = delay;
|
|
|
|
timers[timer.id] = std::move(timer);
|
|
|
|
args.GetReturnValue().Set(Integer::New(isolate, timer.id));
|
|
}
|
|
|
|
void runt_clear_timeout(const FunctionCallbackInfo<Value> &args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
if (args.Length() < 1) {
|
|
return;
|
|
}
|
|
|
|
int id = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
timers.erase(id);
|
|
}
|
|
|
|
void runt_clear_interval(const FunctionCallbackInfo<Value> &args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
if (args.Length() < 1) {
|
|
return;
|
|
}
|
|
|
|
int id = args[0]->Int32Value(isolate->GetCurrentContext()).FromJust();
|
|
timers.erase(id);
|
|
}
|
|
|
|
void execute_timers() {
|
|
if (timers.empty()) return;
|
|
|
|
auto now = std::chrono::steady_clock::now();
|
|
std::vector<int> toRemove;
|
|
|
|
for (auto& [id, timer] : timers) {
|
|
if (now >= timer.executionTime) {
|
|
Locker locker{isolate};
|
|
|
|
Isolate::Scope isolate_scope(isolate);
|
|
HandleScope handle_scope(isolate);
|
|
Local<Context> context = Local<Context>::New(isolate, global_context);
|
|
Context::Scope context_scope(context);
|
|
|
|
TryCatch try_catch(isolate);
|
|
|
|
Local<Function> callback = Local<Function>::New(isolate, timer.callback);
|
|
Local<Value> args[1] = {};
|
|
callback->Call(context, context->Global(), 0, args);
|
|
|
|
if (try_catch.HasCaught()) {
|
|
handle_exception(&try_catch);
|
|
}
|
|
|
|
// reschedule interval
|
|
if (timer.isInterval) {
|
|
timer.executionTime = std::chrono::steady_clock::now() + std::chrono::milliseconds(timer.intervalMs);
|
|
} else {
|
|
toRemove.push_back(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (int id : toRemove) {
|
|
timers.erase(id);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WITH_NETWORKING
|
|
v8::Global<v8::Context>* WebSocketWrapper::getGlobalContext() {
|
|
return &global_context;
|
|
}
|
|
|
|
v8::Global<v8::Context>* HttpRequestWrapper::getGlobalContext() {
|
|
return &global_context;
|
|
}
|
|
#endif
|
|
|
|
int kickstart(int argc, char **argv) {
|
|
_argc = argc;
|
|
_argv = argv;
|
|
std::string bindir(argv[0]);
|
|
|
|
#ifdef KORE_WINDOWS // Handle non-ascii path
|
|
HMODULE hModule = GetModuleHandleW(NULL);
|
|
GetModuleFileNameW(hModule, temp_wstring, 1024);
|
|
WideCharToMultiByte(CP_UTF8, 0, temp_wstring, -1, temp_string, 4096, nullptr, nullptr);
|
|
bindir = temp_string;
|
|
#endif
|
|
|
|
#ifdef KORE_WINDOWS
|
|
bindir = bindir.substr(0, bindir.find_last_of("\\"));
|
|
#else
|
|
bindir = bindir.substr(0, bindir.find_last_of("/"));
|
|
#endif
|
|
|
|
//#if defined(WITH_NETWORKING) && defined(WITH_BENCHMARK)
|
|
// for (int i = 1; i < argc; ++i) {
|
|
// if (strcmp(argv[i], "--websocket-benchmark") == 0) {
|
|
// WSADATA wsaData;
|
|
// WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
// websocket_run_benchmark();
|
|
// WSACleanup();
|
|
// return 0;
|
|
// }
|
|
// else if (strcmp(argv[i], "--websocket-test") == 0) {
|
|
// WSADATA wsaData;
|
|
// WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
// websocket_run_groupchat_test(60, 5);
|
|
// WSACleanup();
|
|
// return 0;
|
|
// }
|
|
// }
|
|
//#endif
|
|
|
|
assetsdir = argc > 1 ? argv[1] : bindir;
|
|
|
|
// Opening a file
|
|
int l = (int)assetsdir.length();
|
|
if ((l > 6 && assetsdir[l - 6] == '.') ||
|
|
(l > 5 && assetsdir[l - 5] == '.') ||
|
|
(l > 4 && assetsdir[l - 4] == '.')) {
|
|
assetsdir = bindir;
|
|
}
|
|
|
|
bool read_console_pid = false;
|
|
bool read_shmem_name = false;
|
|
bool read_viewport_width = false;
|
|
bool read_viewport_height = false;
|
|
|
|
for (int i = 2; i < argc; ++i) {
|
|
if (strcmp(argv[i], "--nowindow") == 0) {
|
|
enable_window = false;
|
|
}
|
|
#ifdef WITH_AUDIO
|
|
else if (strcmp(argv[i], "--nosound") == 0) {
|
|
enable_audio = false;
|
|
}
|
|
#endif
|
|
else if (strcmp(argv[i], "--snapshot") == 0) {
|
|
snapshot = true;
|
|
}
|
|
else if (read_console_pid) {
|
|
#ifdef KORE_WINDOWS
|
|
AttachConsole(atoi(argv[i]));
|
|
#endif
|
|
read_console_pid = false;
|
|
}
|
|
else if (strcmp(argv[i], "--consolepid") == 0) {
|
|
read_console_pid = true;
|
|
}
|
|
else if (strcmp(argv[i], "--viewport-server") == 0) {
|
|
viewport_server_mode = true;
|
|
}
|
|
else if (strcmp(argv[i], "--shmem") == 0) {
|
|
read_shmem_name = true;
|
|
}
|
|
else if (read_shmem_name) {
|
|
strncpy(viewport_shmem_name, argv[i], sizeof(viewport_shmem_name) - 1);
|
|
read_shmem_name = false;
|
|
}
|
|
else if (strcmp(argv[i], "--viewport-width") == 0) {
|
|
read_viewport_width = true;
|
|
}
|
|
else if (read_viewport_width) {
|
|
viewport_width = atoi(argv[i]);
|
|
read_viewport_width = false;
|
|
}
|
|
else if (strcmp(argv[i], "--viewport-height") == 0) {
|
|
read_viewport_height = true;
|
|
}
|
|
else if (read_viewport_height) {
|
|
viewport_height = atoi(argv[i]);
|
|
read_viewport_height = false;
|
|
}
|
|
//#if defined(WITH_NETWORKING) && defined(WITH_BENCHMARK)
|
|
// else if (strcmp(argv[i], "--websocket-benchmark") == 0) {
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "Running WebSocket benchmark...");
|
|
// websocket_run_benchmark();
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "Benchmark complete.");
|
|
// return 0;
|
|
// }
|
|
// else if (strcmp(argv[i], "--websocket-test") == 0) {
|
|
// websocket_run_groupchat_test(1008, 30);
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "Test complete.");
|
|
// return 0;
|
|
// }
|
|
//#endif
|
|
}
|
|
|
|
#if !defined(KORE_MACOS)
|
|
kinc_internal_set_files_location(&assetsdir[0u]);
|
|
#endif
|
|
|
|
#ifdef KORE_MACOS
|
|
// Handle loading assets located outside of '.app/Contents/Resources/Deployment' folder
|
|
// when assets and shaders dir is passed as an argument
|
|
if (argc > 2) {
|
|
kinc_internal_set_files_location(&assetsdir[0u]);
|
|
}
|
|
#endif
|
|
|
|
bool snapshot_found = true;
|
|
kinc_file_reader_t reader;
|
|
if (snapshot || !kinc_file_reader_open(&reader, "runt.bin", KINC_FILE_TYPE_ASSET)) {
|
|
if (!kinc_file_reader_open(&reader, "runt.js", KINC_FILE_TYPE_ASSET)) {
|
|
kinc_log(KINC_LOG_LEVEL_ERROR, "Could not load runt.js, aborting.");
|
|
exit(1);
|
|
}
|
|
snapshot_found = false;
|
|
}
|
|
|
|
int reader_size = (int)kinc_file_reader_size(&reader);
|
|
char *code = (char *)malloc(reader_size + 1);
|
|
kinc_file_reader_read(&reader, code, reader_size);
|
|
code[reader_size] = 0;
|
|
kinc_file_reader_close(&reader);
|
|
|
|
if (snapshot) {
|
|
plat = platform::NewDefaultPlatform();
|
|
V8::InitializePlatform(plat.get());
|
|
|
|
std::string flags = "--nolazy";
|
|
V8::SetFlagsFromString(flags.c_str(), (int)flags.size());
|
|
V8::Initialize();
|
|
|
|
ScriptCompiler::CachedData *cache;
|
|
Isolate::CreateParams create_params;
|
|
create_params.array_buffer_allocator = ArrayBuffer::Allocator::NewDefaultAllocator();
|
|
Isolate *isolate_cache = Isolate::New(create_params);
|
|
{
|
|
HandleScope handle_scope(isolate_cache);
|
|
{
|
|
Local<Context> context = Context::New(isolate_cache);
|
|
Context::Scope context_scope(context);
|
|
|
|
ScriptOrigin origin(isolate_cache, String::NewFromUtf8(isolate_cache, "runt_cache").ToLocalChecked());
|
|
ScriptCompiler::Source source(String::NewFromUtf8(isolate_cache, code).ToLocalChecked(), origin);
|
|
|
|
Local<Script> compiled_script = ScriptCompiler::Compile(context, &source, ScriptCompiler::kEagerCompile).ToLocalChecked();
|
|
cache = ScriptCompiler::CreateCodeCache(compiled_script->GetUnboundScript());
|
|
}
|
|
}
|
|
|
|
SnapshotCreator creator_cold;
|
|
Isolate *isolate_cold = creator_cold.GetIsolate();
|
|
{
|
|
HandleScope handle_scope(isolate_cold);
|
|
{
|
|
Local<Context> context = Context::New(isolate_cold);
|
|
Context::Scope context_scope(context);
|
|
|
|
const size_t line_size = 512;
|
|
char line[line_size];
|
|
strcpy(line, assetsdir.c_str());
|
|
strcat(line, "/data/embed.txt");
|
|
FILE *fp = fopen (line, "r");
|
|
if (fp != NULL) {
|
|
while (fgets(line, line_size, fp) != NULL) {
|
|
line[strlen(line) - 1] = 0; // Trim \n
|
|
kinc_file_reader_t reader;
|
|
if (!kinc_file_reader_open(&reader, line, KINC_FILE_TYPE_ASSET)) continue;
|
|
int reader_size = (int)kinc_file_reader_size(&reader);
|
|
|
|
Local<ArrayBuffer> buffer = ArrayBuffer::New(isolate_cold, reader_size);
|
|
std::shared_ptr<BackingStore> content = buffer->GetBackingStore();
|
|
kinc_file_reader_read(&reader, content->Data(), reader_size);
|
|
kinc_file_reader_close(&reader);
|
|
|
|
(void) context->Global()->Set(context, String::NewFromUtf8(isolate_cold, line).ToLocalChecked(), buffer);
|
|
}
|
|
fclose (fp);
|
|
}
|
|
|
|
ScriptOrigin origin(isolate_cache, String::NewFromUtf8(isolate_cold, "runt_cold").ToLocalChecked());
|
|
ScriptCompiler::Source source(String::NewFromUtf8(isolate_cold, code).ToLocalChecked(), origin, cache);
|
|
|
|
Local<Script> compiled_script = ScriptCompiler::Compile(context, &source, ScriptCompiler::kConsumeCodeCache).ToLocalChecked();
|
|
(void) compiled_script->Run(context);
|
|
|
|
creator_cold.SetDefaultContext(context);
|
|
}
|
|
}
|
|
StartupData coldData = creator_cold.CreateBlob(SnapshotCreator::FunctionCodeHandling::kKeep);
|
|
|
|
// SnapshotCreator creator_warm(nullptr, &coldData);
|
|
// Isolate *isolate_warm = creator_warm.GetIsolate();
|
|
// {
|
|
// HandleScope handle_scope(isolate_warm);
|
|
// {
|
|
// Local<Context> context = Context::New(isolate_warm);
|
|
// Context::Scope context_scope(context);
|
|
|
|
// // std::string code_warm("Main.main();");
|
|
// ScriptOrigin origin(String::NewFromUtf8(isolate_warm, "runt_warm").ToLocalChecked());
|
|
// ScriptCompiler::Source source(String::NewFromUtf8(isolate_warm, code).ToLocalChecked(), origin);
|
|
|
|
// Local<Script> compiled_script = ScriptCompiler::Compile(context, &source, ScriptCompiler::kEagerCompile).ToLocalChecked();
|
|
// compiled_script->Run(context);
|
|
// }
|
|
// }
|
|
// {
|
|
// HandleScope handle_scope(isolate_warm);
|
|
// isolate_warm->ContextDisposedNotification(false);
|
|
// Local<Context> context = Context::New(isolate_warm);
|
|
// creator_warm.SetDefaultContext(context);
|
|
// }
|
|
// StartupData warmData = creator_warm.CreateBlob(SnapshotCreator::FunctionCodeHandling::kKeep);
|
|
|
|
std::string runtbin = assetsdir + "/runt.bin";
|
|
FILE *file = fopen(&runtbin[0u], "wb");
|
|
if (file != nullptr) {
|
|
// fwrite(warmData.data, 1, warmData.raw_size, file);
|
|
fwrite(coldData.data, 1, coldData.raw_size, file);
|
|
fclose(file);
|
|
}
|
|
exit(0);
|
|
}
|
|
|
|
kinc_threads_init();
|
|
kinc_display_init();
|
|
|
|
start_v8(snapshot_found ? code : NULL, snapshot_found ? reader_size : 0);
|
|
#ifdef WITH_WORKER
|
|
bind_worker_class(isolate, global_context);
|
|
#endif
|
|
|
|
#ifdef WITH_NETWORKING
|
|
//#ifndef WITH_UWS
|
|
//bind_socket_bridge(isolate, global_context);
|
|
//#endif
|
|
WEBSOCKET_BIND_V8(isolate, global_context);
|
|
#endif
|
|
|
|
start_runt(snapshot_found ? NULL : code);
|
|
|
|
#ifdef WITH_NETWORKING
|
|
if (viewport_server_mode) {
|
|
kinc_log(KINC_LOG_LEVEL_INFO, "Initializing viewport server: %dx%d, shmem=%s",
|
|
viewport_width, viewport_height, viewport_shmem_name);
|
|
if (!viewport_server_init(viewport_shmem_name, viewport_width, viewport_height)) {
|
|
kinc_log(KINC_LOG_LEVEL_ERROR, "Failed to initialize viewport server");
|
|
exit(1);
|
|
}
|
|
kinc_window_resize(0, viewport_width, viewport_height);
|
|
}
|
|
#endif
|
|
|
|
kinc_start();
|
|
|
|
// NOTE: WebSocket benchmark disabled for faster bootup
|
|
// #ifdef WITH_NETWORKING
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "=== WEBSOCKET BOOTUP BENCHMARK ===");
|
|
// {
|
|
// WebSocketBenchmark benchmark;
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "Running quick WebSocket performance check...");
|
|
// auto result = benchmark.runCollaborative3DTest(5, 10);
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "Benchmark Results:");
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "- Messages/sec: %llu", result.messagesPerSecond);
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "- Avg Latency: %.1f μs", result.averageLatency);
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "- CPU Usage: %.1f%%", result.avgCpuPercent);
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "- Memory: %zu MB", result.peakMemoryMB);
|
|
// if (result.messagesPerSecond > 100) {
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "✓ WebSocket performance: GOOD");
|
|
// } else {
|
|
// kinc_log(KINC_LOG_LEVEL_WARNING, "⚠ WebSocket performance: LOW - check system load");
|
|
// }
|
|
// }
|
|
// kinc_log(KINC_LOG_LEVEL_INFO, "=== BENCHMARK COMPLETE ===");
|
|
// #endif
|
|
|
|
#ifdef WITH_AUDIO
|
|
if (enable_audio) {
|
|
kinc_a2_shutdown();
|
|
}
|
|
#endif
|
|
|
|
free(code);
|
|
|
|
return 0;
|
|
}
|