cv
This commit is contained in:
@@ -11,6 +11,7 @@ endif
|
|||||||
|
|
||||||
add_project_arguments('-Wno-incompatible-pointer-types', language: 'c')
|
add_project_arguments('-Wno-incompatible-pointer-types', language: 'c')
|
||||||
add_project_arguments('-Wno-narrowing', language: 'cpp')
|
add_project_arguments('-Wno-narrowing', language: 'cpp')
|
||||||
|
add_project_arguments('-Wno-missing-braces', language:'c')
|
||||||
|
|
||||||
deps = []
|
deps = []
|
||||||
|
|
||||||
@@ -73,6 +74,8 @@ deps += dependency('qjs-soloud',static:true)
|
|||||||
deps += dependency('sdl3')
|
deps += dependency('sdl3')
|
||||||
deps += dependency('physfs',static:true)
|
deps += dependency('physfs',static:true)
|
||||||
|
|
||||||
|
deps += dependency('opencv')
|
||||||
|
|
||||||
deps += dependency('threads')
|
deps += dependency('threads')
|
||||||
|
|
||||||
if get_option('chipmunk')
|
if get_option('chipmunk')
|
||||||
@@ -84,7 +87,7 @@ if get_option('enet')
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
sources = []
|
sources = []
|
||||||
src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c','texture.c', 'timer.c', 'transform.c','warp.c','yugine.c', 'wildmatch.c']
|
src += ['anim.c', 'config.c', 'datastream.c','font.c','gameobject.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c','texture.c', 'timer.c', 'transform.c','warp.c','yugine.c', 'wildmatch.c', 'cv.cpp']
|
||||||
|
|
||||||
imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp']
|
imsrc = ['GraphEditor.cpp','ImCurveEdit.cpp','ImGradient.cpp','imgui_draw.cpp','imgui_tables.cpp','imgui_widgets.cpp','imgui.cpp','ImGuizmo.cpp','imnodes.cpp','implot_items.cpp','implot.cpp']
|
||||||
|
|
||||||
@@ -132,4 +135,4 @@ prosperon_dep = declare_dependency(
|
|||||||
link_with:prosperon
|
link_with:prosperon
|
||||||
)
|
)
|
||||||
|
|
||||||
test('sanity', prosperon)
|
test('sanity', prosperon)
|
||||||
|
|||||||
@@ -192,8 +192,8 @@ clay.image = function image(path, ...configs)
|
|||||||
clay.text = function text(str, ...configs)
|
clay.text = function text(str, ...configs)
|
||||||
{
|
{
|
||||||
var config = rectify_configs(configs);
|
var config = rectify_configs(configs);
|
||||||
var tsize = render.text_size(str, config.font);
|
|
||||||
config.size ??= [0,0];
|
config.size ??= [0,0];
|
||||||
|
var tsize = render.text_size(str, config.font, 0, 0, config.size.x);
|
||||||
config.size = config.size.map((x,i) => Math.max(x, tsize[i]));
|
config.size = config.size.map((x,i) => Math.max(x, tsize[i]));
|
||||||
config.text = str;
|
config.text = str;
|
||||||
add_item(config);
|
add_item(config);
|
||||||
@@ -245,7 +245,7 @@ layout.draw_commands = function draw_commands(cmds, pos = [0,0], mousepos)
|
|||||||
render.rectangle(boundingbox, config.background_color);
|
render.rectangle(boundingbox, config.background_color);
|
||||||
|
|
||||||
if (config.text)
|
if (config.text)
|
||||||
render.text(config.text, content, config.font, config.font_size, config.color);
|
render.text(config.text, content, config.font, config.font_size, config.color, config.size.x);
|
||||||
if (config.image)
|
if (config.image)
|
||||||
render.image(config.image, content, 0, config.color);
|
render.image(config.image, content, 0, config.color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ prosperon.init = function () {
|
|||||||
prosperon.camera.mode = "keep";
|
prosperon.camera.mode = "keep";
|
||||||
prosperon.camera.break = "fit";
|
prosperon.camera.break = "fit";
|
||||||
prosperon.camera.size = game.size;
|
prosperon.camera.size = game.size;
|
||||||
shape.quad = {
|
/* shape.quad = {
|
||||||
pos: os.make_buffer([
|
pos: os.make_buffer([
|
||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
0, 1, 0,
|
0, 1, 0,
|
||||||
@@ -111,7 +111,7 @@ prosperon.init = function () {
|
|||||||
verts: 3,
|
verts: 3,
|
||||||
count: 3,
|
count: 3,
|
||||||
index: os.make_buffer([0, 1, 2], 1),
|
index: os.make_buffer([0, 1, 2], 1),
|
||||||
};
|
};*/
|
||||||
if (io.exists("game.js")) global.app = actor.spawn("game.js");
|
if (io.exists("game.js")) global.app = actor.spawn("game.js");
|
||||||
else global.app = actor.spawn("nogame.js");
|
else global.app = actor.spawn("nogame.js");
|
||||||
};
|
};
|
||||||
@@ -299,7 +299,10 @@ game.is_image = function(obj)
|
|||||||
|
|
||||||
// Any request to it returns an image, which is a texture and rect. But they can
|
// Any request to it returns an image, which is a texture and rect. But they can
|
||||||
game.texture = function texture(path) {
|
game.texture = function texture(path) {
|
||||||
if (typeof path !== 'string') throw new Error('need a string for game.texture')
|
if (typeof path !== 'string') {
|
||||||
|
return path;
|
||||||
|
throw new Error('need a string for game.texture')
|
||||||
|
}
|
||||||
var parts = path.split(':');
|
var parts = path.split(':');
|
||||||
path = Resources.find_image(parts[0]);
|
path = Resources.find_image(parts[0]);
|
||||||
|
|
||||||
|
|||||||
@@ -864,7 +864,7 @@ render.rectangle = function render_rectangle(rect, color = Color.white, shader =
|
|||||||
render._main.fillrect(rect,color);
|
render._main.fillrect(rect,color);
|
||||||
};
|
};
|
||||||
|
|
||||||
render.text = function text(str, rect, font = cur_font, size = 0, color = Color.white, wrap = -1, ) {
|
render.text = function text(str, rect, font = cur_font, size = 0, color = Color.white, wrap = 0) {
|
||||||
if (typeof font === 'string')
|
if (typeof font === 'string')
|
||||||
font = render.get_font(font)
|
font = render.get_font(font)
|
||||||
var mesh = os.make_text_buffer(str, rect, 0, color, wrap, font);
|
var mesh = os.make_text_buffer(str, rect, 0, color, wrap, font);
|
||||||
@@ -885,11 +885,11 @@ render.text = function text(str, rect, font = cur_font, size = 0, color = Color.
|
|||||||
};
|
};
|
||||||
|
|
||||||
var tttsize = render.text_size;
|
var tttsize = render.text_size;
|
||||||
render.text_size = function(str, font)
|
render.text_size = function(str, font, ...args)
|
||||||
{
|
{
|
||||||
if (typeof font === 'string')
|
if (typeof font === 'string')
|
||||||
font = render.get_font(font);
|
font = render.get_font(font);
|
||||||
return tttsize(str,font);
|
return tttsize(str,font, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
var lasttex = undefined;
|
var lasttex = undefined;
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ Cmdline.register_order(
|
|||||||
if (io.exists("config.js")) global.mixin("config.js");
|
if (io.exists("config.js")) global.mixin("config.js");
|
||||||
else console.warn("No config.js file found. Starting with default parameters.");
|
else console.warn("No config.js file found. Starting with default parameters.");
|
||||||
var window = game.engine_start(prosperon);
|
var window = game.engine_start(prosperon);
|
||||||
var renderer = window.make_renderer("gpu");
|
var renderer = window.make_renderer("vulkan");
|
||||||
render._main = renderer;
|
render._main = renderer;
|
||||||
|
|
||||||
prosperon.init();
|
prosperon.init();
|
||||||
|
|||||||
151
source/cv.cpp
Normal file
151
source/cv.cpp
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
#include "cv.hpp"
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
cv::Mat SDL_SurfaceToMat(SDL_Surface* surface) {
|
||||||
|
if (!surface) {
|
||||||
|
throw std::invalid_argument("SDL_Surface pointer is null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the surface to a known pixel format (e.g., RGBA32)
|
||||||
|
// SDL_Surface* convertedSurface = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32);
|
||||||
|
// if (!convertedSurface) {
|
||||||
|
// throw std::runtime_error("Failed to convert SDL_Surface to RGBA32 format.");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Create a cv::Mat with the same size and type
|
||||||
|
cv::Mat mat(surface->h, surface->w, CV_8UC4, surface->pixels, surface->pitch);
|
||||||
|
|
||||||
|
// Convert RGBA to BGR
|
||||||
|
cv::Mat matBGR;
|
||||||
|
cv::cvtColor(mat, matBGR, cv::COLOR_RGBA2BGR);
|
||||||
|
|
||||||
|
// Free the converted surface
|
||||||
|
// SDL_DestroySurface(convertedSurface);
|
||||||
|
|
||||||
|
return matBGR;
|
||||||
|
}
|
||||||
|
|
||||||
|
cv::Mat SDL_SurfaceToMat_YUY2(SDL_Surface* surface) {
|
||||||
|
if (!surface) {
|
||||||
|
throw std::invalid_argument("SDL_Surface pointer is null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure the surface format is YUY2
|
||||||
|
if (surface->format!= SDL_PIXELFORMAT_YUY2) {
|
||||||
|
throw std::runtime_error("SDL_Surface is not in YUY2 format.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a cv::Mat with the raw data from the SDL_Surface
|
||||||
|
// YUY2 format has 2 bytes per pixel
|
||||||
|
cv::Mat yuy2Mat(surface->h, surface->w, CV_8UC2, surface->pixels, surface->pitch);
|
||||||
|
|
||||||
|
// Convert YUY2 to BGR format
|
||||||
|
cv::Mat bgrMat;
|
||||||
|
cv::cvtColor(yuy2Mat, bgrMat, cv::COLOR_YUV2BGR_YUY2);
|
||||||
|
|
||||||
|
return bgrMat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Function to perform feature matching
|
||||||
|
|
||||||
|
extern "C" {bool detectImageInWebcam(SDL_Surface* webcamSurface, SDL_Surface* targetSurface, double matchThreshold = 10.0) {
|
||||||
|
// Convert SDL_Surface to cv::Mat
|
||||||
|
cv::Mat webcamMat = SDL_SurfaceToMat(webcamSurface);
|
||||||
|
cv::Mat targetMat = SDL_SurfaceToMat(targetSurface);
|
||||||
|
// cv::imshow("Webcam Image", webcamMat); // uncomment when testing image appearance
|
||||||
|
//cv::waitKey(0);
|
||||||
|
|
||||||
|
|
||||||
|
// Initialize ORB detector
|
||||||
|
cv::Ptr<cv::ORB> orb = cv::ORB::create();
|
||||||
|
/* 1500, // nfeatures
|
||||||
|
1.2f, // scaleFactor
|
||||||
|
8, // nlevels
|
||||||
|
31, // edgeThreshold
|
||||||
|
0, // firstLevel
|
||||||
|
2, // WTA_K
|
||||||
|
cv::ORB::HARRIS_SCORE, // scoreType
|
||||||
|
31, // patchSize
|
||||||
|
20 // fastThreshold
|
||||||
|
);*/
|
||||||
|
|
||||||
|
|
||||||
|
// Detect keypoints and compute descriptors
|
||||||
|
std::vector<cv::KeyPoint> keypointsWebcam, keypointsTarget;
|
||||||
|
cv::Mat descriptorsWebcam, descriptorsTarget;
|
||||||
|
|
||||||
|
orb->detectAndCompute(webcamMat, cv::noArray(), keypointsWebcam, descriptorsWebcam);
|
||||||
|
orb->detectAndCompute(targetMat, cv::noArray(), keypointsTarget, descriptorsTarget);
|
||||||
|
|
||||||
|
if (descriptorsWebcam.empty() || descriptorsTarget.empty()) {
|
||||||
|
fprintf(stderr, "No descriptors found. On webcam? %d. On input image? %d.\n", !descriptorsWebcam.empty(), !descriptorsTarget.empty());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match descriptors using Brute-Force matcher with Hamming distance
|
||||||
|
/* cv::BFMatcher matcher(cv::NORM_HAMMING, true); // crossCheck=true
|
||||||
|
std::vector<cv::DMatch> matches;
|
||||||
|
matcher.match(descriptorsTarget, descriptorsWebcam, matches);
|
||||||
|
*/
|
||||||
|
// Initialize BFMatcher without crossCheck
|
||||||
|
cv::BFMatcher matcher(cv::NORM_HAMMING);
|
||||||
|
|
||||||
|
// Perform k-NN matching with k=2
|
||||||
|
std::vector<std::vector<cv::DMatch>> matches;
|
||||||
|
matcher.knnMatch(descriptorsTarget, descriptorsWebcam, matches, 2);
|
||||||
|
|
||||||
|
if (matches.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
// Filter good matches based on distance
|
||||||
|
double max_dist = 0; double min_dist = 100;
|
||||||
|
|
||||||
|
// Find min and max distances
|
||||||
|
for (const auto& match : matches) {
|
||||||
|
double dist = match.distance;
|
||||||
|
if (dist < min_dist) min_dist = dist;
|
||||||
|
if (dist > max_dist) max_dist = dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define a threshold to identify good matches
|
||||||
|
std::vector<cv::DMatch> goodMatches;
|
||||||
|
for (const auto& match : matches) {
|
||||||
|
if (match.distance <= std::max(2 * min_dist, 30.0)) {
|
||||||
|
goodMatches.push_back(match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// Apply Lowe's ratio test
|
||||||
|
const float ratioThresh = 0.75f;
|
||||||
|
std::vector<cv::DMatch> goodMatches;
|
||||||
|
for (size_t i = 0; i < matches.size(); i++) {
|
||||||
|
if (matches[i].size() < 2)
|
||||||
|
continue; // Not enough matches
|
||||||
|
const cv::DMatch& bestMatch = matches[i][0];
|
||||||
|
const cv::DMatch& betterMatch = matches[i][1];
|
||||||
|
|
||||||
|
float ratio = bestMatch.distance / betterMatch.distance;
|
||||||
|
if (ratio < ratioThresh) {
|
||||||
|
goodMatches.push_back(bestMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug: Print number of good matches
|
||||||
|
// std::cout << "Good Matches: " << goodMatches.size() << std::endl;
|
||||||
|
|
||||||
|
// Optionally, visualize matches
|
||||||
|
/*
|
||||||
|
cv::Mat imgMatches;
|
||||||
|
cv::drawMatches(targetMat, keypointsTarget, webcamMat, keypointsWebcam, goodMatches, imgMatches);
|
||||||
|
cv::imshow("Good Matches", imgMatches);
|
||||||
|
cv::waitKey(30);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Determine if enough good matches are found
|
||||||
|
return (goodMatches.size() >= matchThreshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
source/cv.hpp
Normal file
15
source/cv.hpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef CV_H
|
||||||
|
#define CV_H
|
||||||
|
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
bool detectImageInWebcam(SDL_Surface *webcam, SDL_Surface *img, double threshold);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
152
source/font.c
152
source/font.c
@@ -211,35 +211,79 @@ const char *esc_color(const char *c, struct rgba *color, struct rgba defc)
|
|||||||
// text is a string, font f, size is height in pixels, wrap is how long a line is before wrapping. -1to not wrap
|
// text is a string, font f, size is height in pixels, wrap is how long a line is before wrapping. -1to not wrap
|
||||||
HMM_Vec2 measure_text(const char *text, font *f, float size, float letterSpacing, float wrap)
|
HMM_Vec2 measure_text(const char *text, font *f, float size, float letterSpacing, float wrap)
|
||||||
{
|
{
|
||||||
HMM_Vec2 dim = {0};
|
int breakAtWord = 0;
|
||||||
float maxWidth = 0; // max width of any line
|
HMM_Vec2 dim = {0};
|
||||||
float lineWidth = 0; // current line width
|
float maxWidth = 0; // Maximum width of any line
|
||||||
float scale = size/f->height;
|
float lineWidth = 0; // Current line width
|
||||||
scale = 1;
|
float scale = size / f->height;
|
||||||
float lineHeight = f->ascent - f->descent;
|
float lineHeight = (f->ascent - f->descent) * scale;
|
||||||
lineHeight *= scale;
|
letterSpacing *= scale;
|
||||||
letterSpacing *= scale;
|
|
||||||
|
|
||||||
float height = lineHeight; // total height
|
float height = lineHeight; // Total height
|
||||||
|
const char *wordStart = text; // Start of the current word for word wrapping
|
||||||
|
float wordWidth = 0; // Width of the current word
|
||||||
|
float spaceWidth = f->Characters[' '].advance + letterSpacing; // Space character width
|
||||||
|
|
||||||
for (char *c = text; *c != 0; c++) {
|
for (const char *c = text; *c != '\0'; c++) {
|
||||||
if (*c == '\n') {
|
if (*c == '\n') {
|
||||||
maxWidth = fmaxf(maxWidth, lineWidth);
|
// Handle explicit line breaks
|
||||||
lineWidth = 0;
|
maxWidth = fmaxf(maxWidth, lineWidth);
|
||||||
height += lineHeight + f->linegap;
|
lineWidth = 0;
|
||||||
continue;
|
height += lineHeight + f->linegap;
|
||||||
|
wordStart = c + 1;
|
||||||
|
wordWidth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float charWidth = f->Characters[*c].advance + letterSpacing;
|
||||||
|
|
||||||
|
// Handle wrapping
|
||||||
|
if (wrap > 0 && lineWidth + charWidth > wrap) {
|
||||||
|
if (breakAtWord && *c != ' ') {
|
||||||
|
// Roll back to the last word if breaking at word boundaries
|
||||||
|
if (wordWidth > 0) {
|
||||||
|
lineWidth -= wordWidth + spaceWidth;
|
||||||
|
c = wordStart - 1; // Reset to start of the word
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finish the current line and reset
|
||||||
|
maxWidth = fmaxf(maxWidth, lineWidth);
|
||||||
|
lineWidth = 0;
|
||||||
|
height += lineHeight + f->linegap;
|
||||||
|
wordStart = c + 1; // Start a new word
|
||||||
|
wordWidth = 0;
|
||||||
|
|
||||||
|
// Skip to next character if wrapping on letters
|
||||||
|
if (!breakAtWord) {
|
||||||
|
lineWidth += charWidth;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lineWidth += charWidth;
|
||||||
|
|
||||||
|
// Update word width if breaking at word boundaries
|
||||||
|
if (breakAtWord) {
|
||||||
|
if (*c == ' ') {
|
||||||
|
wordWidth = 0;
|
||||||
|
wordStart = c + 1;
|
||||||
|
} else {
|
||||||
|
wordWidth += charWidth;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lineWidth += f->Characters[*c].advance + letterSpacing;
|
|
||||||
}
|
|
||||||
|
|
||||||
maxWidth = fmaxf(maxWidth, lineWidth);
|
// Finalize dimensions
|
||||||
dim.x = maxWidth;
|
maxWidth = fmaxf(maxWidth, lineWidth);
|
||||||
dim.y = height;
|
dim.x = maxWidth;
|
||||||
return dim;
|
dim.y = height;
|
||||||
|
|
||||||
|
return dim;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pos given in screen coordinates */
|
/* pos given in screen coordinates */
|
||||||
struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, float scale, struct rgba color, float wrap) {
|
struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, float scale, struct rgba color, float wrap) {
|
||||||
|
int wrapAtWord = 1;
|
||||||
text_vert *buffer = NULL;
|
text_vert *buffer = NULL;
|
||||||
int len = strlen(text);
|
int len = strlen(text);
|
||||||
|
|
||||||
@@ -250,57 +294,23 @@ struct text_vert *renderText(const char *text, HMM_Vec2 pos, font *f, float scal
|
|||||||
for (char *c = text; *c != 0; c++) {
|
for (char *c = text; *c != 0; c++) {
|
||||||
if (*c == '\n') {
|
if (*c == '\n') {
|
||||||
cursor.x = pos.x;
|
cursor.x = pos.x;
|
||||||
cursor.y += lineHeight + f->linegap;
|
cursor.y -= lineHeight + f->linegap;
|
||||||
|
lineWidth = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_char_verts(&buffer, f->Characters[*c], cursor, scale, color);
|
struct character chara = f->Characters[*c];
|
||||||
cursor.x += f->Characters[*c].advance;
|
|
||||||
}
|
if (wrap > 0 && lineWidth + chara.advance > wrap) {
|
||||||
return buffer;
|
cursor.x = pos.x;
|
||||||
/*
|
cursor.y -= lineHeight + f->linegap;
|
||||||
const char *line, *wordstart, *drawstart;
|
lineWidth = 0;
|
||||||
line = drawstart = text;
|
|
||||||
|
|
||||||
struct rgba usecolor = color;
|
|
||||||
|
|
||||||
while (*line != '\0') {
|
|
||||||
if (isblank(*line)) {
|
|
||||||
sdrawCharacter(f->Characters[*line], cursor, scale, usecolor);
|
|
||||||
cursor.X += f->Characters[*line].advance * scale;
|
|
||||||
line++;
|
|
||||||
} else if (isspace(*line)) {
|
|
||||||
sdrawCharacter(f->Characters[*line], cursor, scale, usecolor);
|
|
||||||
cursor.Y -= scale * f->linegap;
|
|
||||||
cursor.X = pos.X;
|
|
||||||
line++;
|
|
||||||
} else {
|
|
||||||
if (*line == '\e')
|
|
||||||
line = esc_color(line, &usecolor, color);
|
|
||||||
|
|
||||||
wordstart = line;
|
|
||||||
int wordWidth = 0;
|
|
||||||
|
|
||||||
while (!isspace(*line) && *line != '\0') {
|
|
||||||
|
|
||||||
wordWidth += f->Characters[*line].advance * scale;
|
|
||||||
line++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wrap > 0 && (cursor.X + wordWidth - pos.X) >= wrap) {
|
|
||||||
cursor.X = pos.X;
|
|
||||||
cursor.Y -= scale * f->linegap;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (wordstart < line) {
|
|
||||||
if (*wordstart == '\e')
|
|
||||||
wordstart = esc_color(wordstart, &usecolor, color);
|
|
||||||
|
|
||||||
sdrawCharacter(f->Characters[*wordstart], cursor, scale, usecolor);
|
|
||||||
|
|
||||||
cursor.X += f->Characters[*wordstart].advance * scale;
|
|
||||||
wordstart++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}*/
|
|
||||||
|
draw_char_verts(&buffer, chara, cursor, scale, color);
|
||||||
|
lineWidth += chara.advance;
|
||||||
|
cursor.x += chara.advance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
155
source/jsffi.c
155
source/jsffi.c
@@ -32,6 +32,8 @@
|
|||||||
#include <SDL3/SDL_gpu.h>
|
#include <SDL3/SDL_gpu.h>
|
||||||
#include <SDL3/SDL_error.h>
|
#include <SDL3/SDL_error.h>
|
||||||
|
|
||||||
|
#include <cv.hpp>
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <Accelerate/Accelerate.h>
|
#include <Accelerate/Accelerate.h>
|
||||||
#else
|
#else
|
||||||
@@ -256,6 +258,11 @@ void SDL_Surface_free(JSRuntime *rt, SDL_Surface *s) {
|
|||||||
SDL_DestroySurface(s);
|
SDL_DestroySurface(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDL_Camera_free(JSRuntime *rt, SDL_Camera *cam)
|
||||||
|
{
|
||||||
|
SDL_CloseCamera(cam);
|
||||||
|
}
|
||||||
|
|
||||||
QJSCLASS(transform)
|
QJSCLASS(transform)
|
||||||
QJSCLASS(font)
|
QJSCLASS(font)
|
||||||
//QJSCLASS(warp_gravity)
|
//QJSCLASS(warp_gravity)
|
||||||
@@ -265,8 +272,18 @@ QJSCLASS(timer)
|
|||||||
QJSCLASS(skin)
|
QJSCLASS(skin)
|
||||||
QJSCLASS(SDL_Window)
|
QJSCLASS(SDL_Window)
|
||||||
QJSCLASS(SDL_Renderer)
|
QJSCLASS(SDL_Renderer)
|
||||||
QJSCLASS(SDL_Texture, TracyCAllocN(n, n->w*n->h*4, "vram");)
|
|
||||||
QJSCLASS(SDL_Surface, TracyCAllocN(n, n->pitch*n->h, "texture memory");)
|
QJSCLASS(SDL_Camera)
|
||||||
|
QJSCLASS(SDL_Texture,
|
||||||
|
TracyCAllocN(n, n->w*n->h*4, "vram");
|
||||||
|
JS_SetProperty(js, j, width_atom, number2js(js,n->w));
|
||||||
|
JS_SetProperty(js,j,height_atom,number2js(js,n->h));
|
||||||
|
)
|
||||||
|
QJSCLASS(SDL_Surface,
|
||||||
|
TracyCAllocN(n, n->pitch*n->h, "texture memory");
|
||||||
|
JS_SetProperty(js, j, width_atom, number2js(js,n->w));
|
||||||
|
JS_SetProperty(js,j,height_atom,number2js(js,n->h));
|
||||||
|
)
|
||||||
|
|
||||||
static inline HMM_Mat4 js2transform_mat(JSContext *js, JSValue v)
|
static inline HMM_Mat4 js2transform_mat(JSContext *js, JSValue v)
|
||||||
{
|
{
|
||||||
@@ -672,6 +689,15 @@ JSC_SCALL(render_text_size,
|
|||||||
ret = vec22js(js,measure_text(str, f, size, letterSpacing, wrap));
|
ret = vec22js(js,measure_text(str, f, size, letterSpacing, wrap));
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_SCALL(render_text_rect,
|
||||||
|
rect r = {0};
|
||||||
|
font *f = js2font(js,argv[1]);
|
||||||
|
float wrap = js2number(js,argv[2]);
|
||||||
|
HMM_Vec2 dim = measure_text(str, f, 0, 0, wrap);
|
||||||
|
r.w = dim.x;
|
||||||
|
r.h = dim.y;
|
||||||
|
)
|
||||||
|
|
||||||
JSC_CCALL(render_draw_color,
|
JSC_CCALL(render_draw_color,
|
||||||
SDL_Renderer *renderer = js2SDL_Renderer(js,self);
|
SDL_Renderer *renderer = js2SDL_Renderer(js,self);
|
||||||
struct rgba rgba = js2color(js,argv[0]);
|
struct rgba rgba = js2color(js,argv[0]);
|
||||||
@@ -683,6 +709,7 @@ static const JSCFunctionListEntry js_render_funcs[] = {
|
|||||||
MIST_FUNC_DEF(render, set_projection_ortho, 3),
|
MIST_FUNC_DEF(render, set_projection_ortho, 3),
|
||||||
MIST_FUNC_DEF(render, set_projection_perspective, 4),
|
MIST_FUNC_DEF(render, set_projection_perspective, 4),
|
||||||
MIST_FUNC_DEF(render, set_view, 1),
|
MIST_FUNC_DEF(render, set_view, 1),
|
||||||
|
MIST_FUNC_DEF(render, draw_color, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static JSValue idx_buffer = JS_UNDEFINED;
|
static JSValue idx_buffer = JS_UNDEFINED;
|
||||||
@@ -1372,6 +1399,9 @@ static JSValue event2js(JSContext *js, SDL_Event event)
|
|||||||
JS_SetPropertyStr(js,e,"window", number2js(js,event.text.windowID));
|
JS_SetPropertyStr(js,e,"window", number2js(js,event.text.windowID));
|
||||||
JS_SetPropertyStr(js,e,"text", JS_NewString(js,event.text.text));
|
JS_SetPropertyStr(js,e,"text", JS_NewString(js,event.text.text));
|
||||||
break;
|
break;
|
||||||
|
case SDL_EVENT_CAMERA_DEVICE_APPROVED:
|
||||||
|
JS_SetPropertyStr(js,e,"type", JS_NewString(js, "camera approved"));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@@ -1399,23 +1429,23 @@ JSC_CCALL(game_renderers,
|
|||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(game_cameras,
|
JSC_CCALL(game_cameras,
|
||||||
SDL_CameraID *ids = SDL_GetCameras(NULL);
|
int num;
|
||||||
|
SDL_CameraID *ids = SDL_GetCameras(&num);
|
||||||
JSValue jsids = JS_NewArray(js);
|
JSValue jsids = JS_NewArray(js);
|
||||||
|
for (int i = 0; i < num; i++)
|
||||||
SDL_CameraID *id = ids;
|
|
||||||
while (*id) {
|
|
||||||
printf("camera %d\n", *id);
|
|
||||||
id++;
|
|
||||||
}
|
|
||||||
/* for (int i = 0; i < num; i++) {
|
|
||||||
JS_SetPropertyUint32(js,jsids, i, number2js(js,ids[i]));
|
JS_SetPropertyUint32(js,jsids, i, number2js(js,ids[i]));
|
||||||
}
|
|
||||||
|
|
||||||
SDL_OpenCamera(ids[0], NULL);*/
|
|
||||||
|
|
||||||
return jsids;
|
return jsids;
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(game_open_camera,
|
||||||
|
int id = js2number(js,argv[0]);
|
||||||
|
SDL_Camera *cam = SDL_OpenCamera(id, NULL);
|
||||||
|
if (!cam) ret = JS_ThrowReferenceError(js, "Could not open camera %d: %s\n", id, SDL_GetError());
|
||||||
|
else
|
||||||
|
ret = SDL_Camera2js(js,cam);
|
||||||
|
)
|
||||||
|
|
||||||
#include "wildmatch.h"
|
#include "wildmatch.h"
|
||||||
JSC_SSCALL(game_glob,
|
JSC_SSCALL(game_glob,
|
||||||
if (wildmatch(str, str2, WM_PATHNAME | WM_PERIOD | WM_WILDSTAR) == WM_MATCH)
|
if (wildmatch(str, str2, WM_PATHNAME | WM_PERIOD | WM_WILDSTAR) == WM_MATCH)
|
||||||
@@ -1430,6 +1460,7 @@ static const JSCFunctionListEntry js_game_funcs[] = {
|
|||||||
MIST_FUNC_DEF(game, engine_delay, 1),
|
MIST_FUNC_DEF(game, engine_delay, 1),
|
||||||
MIST_FUNC_DEF(game, renderers, 0),
|
MIST_FUNC_DEF(game, renderers, 0),
|
||||||
MIST_FUNC_DEF(game, cameras, 0),
|
MIST_FUNC_DEF(game, cameras, 0),
|
||||||
|
MIST_FUNC_DEF(game, open_camera, 1),
|
||||||
MIST_FUNC_DEF(game, glob, 2),
|
MIST_FUNC_DEF(game, glob, 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1510,7 +1541,9 @@ JSC_CCALL(SDL_Renderer_rect,
|
|||||||
JSC_CCALL(renderer_load_texture,
|
JSC_CCALL(renderer_load_texture,
|
||||||
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
SDL_Renderer *r = js2SDL_Renderer(js,self);
|
||||||
SDL_Surface *surf = js2SDL_Surface(js,argv[0]);
|
SDL_Surface *surf = js2SDL_Surface(js,argv[0]);
|
||||||
|
if (!surf) return JS_ThrowReferenceError(js, "Surface was not a surface.");
|
||||||
SDL_Texture *tex = SDL_CreateTextureFromSurface(r,surf);
|
SDL_Texture *tex = SDL_CreateTextureFromSurface(r,surf);
|
||||||
|
if (!tex) return JS_ThrowReferenceError(js, "Could not create texture from surface: %s", SDL_GetError());
|
||||||
ret = SDL_Texture2js(js,tex);
|
ret = SDL_Texture2js(js,tex);
|
||||||
JS_SetProperty(js,ret,width_atom, number2js(js,tex->w));
|
JS_SetProperty(js,ret,width_atom, number2js(js,tex->w));
|
||||||
JS_SetProperty(js,ret,height_atom, number2js(js,tex->h));
|
JS_SetProperty(js,ret,height_atom, number2js(js,tex->h));
|
||||||
@@ -1587,7 +1620,7 @@ JSC_CCALL(renderer_9slice,
|
|||||||
SDL_Texture *tex = js2SDL_Texture(js,argv[0]);
|
SDL_Texture *tex = js2SDL_Texture(js,argv[0]);
|
||||||
rect *dst, *src = NULL;
|
rect *dst, *src = NULL;
|
||||||
lrtb bounds = js2lrtb(js,argv[2]);
|
lrtb bounds = js2lrtb(js,argv[2]);
|
||||||
|
SDL_RenderTexture9Grid(renderer, tex, src, bounds.l, bounds.r, bounds.t, bounds.b, 0.0, dst);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(renderer_get_image,
|
JSC_CCALL(renderer_get_image,
|
||||||
@@ -1665,10 +1698,6 @@ void Translate2DPoints(HMM_Vec2 *points, int count, HMM_Vec3 position, HMM_Quat
|
|||||||
float yy = rotation.y * rotation.y;
|
float yy = rotation.y * rotation.y;
|
||||||
float zz = rotation.z * rotation.z;
|
float zz = rotation.z * rotation.z;
|
||||||
float xy = rotation.x * rotation.y;
|
float xy = rotation.x * rotation.y;
|
||||||
float xz = rotation.x * rotation.z;
|
|
||||||
float yz = rotation.y * rotation.z;
|
|
||||||
float xw = rotation.x * rotation.w;
|
|
||||||
float yw = rotation.y * rotation.w;
|
|
||||||
float zw = rotation.z * rotation.w;
|
float zw = rotation.z * rotation.w;
|
||||||
|
|
||||||
// Extract 2D affine rotation and scaling
|
// Extract 2D affine rotation and scaling
|
||||||
@@ -1854,11 +1883,57 @@ JSC_CCALL(surface_rect,
|
|||||||
SDL_FillSurfaceRect(dst,&r,SDL_MapRGBA(&pdetails,NULL,color.r,color.g,color.b,color.a));
|
SDL_FillSurfaceRect(dst,&r,SDL_MapRGBA(&pdetails,NULL,color.r,color.g,color.b,color.a));
|
||||||
)
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(surface_dup,
|
||||||
|
SDL_Surface *surf = js2SDL_Surface(js,self);
|
||||||
|
SDL_Surface *conv = SDL_ConvertSurface(surf, SDL_PIXELFORMAT_RGBA8888);
|
||||||
|
if (!conv)
|
||||||
|
return JS_ThrowReferenceError(js, "could not blit to dup'd surface: %s", SDL_GetError());
|
||||||
|
|
||||||
|
return SDL_Surface2js(js,conv);
|
||||||
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_SDL_Surface_funcs[] = {
|
static const JSCFunctionListEntry js_SDL_Surface_funcs[] = {
|
||||||
MIST_FUNC_DEF(surface, blit, 3),
|
MIST_FUNC_DEF(surface, blit, 3),
|
||||||
MIST_FUNC_DEF(surface, scale, 1),
|
MIST_FUNC_DEF(surface, scale, 1),
|
||||||
MIST_FUNC_DEF(surface,fill,1),
|
MIST_FUNC_DEF(surface,fill,1),
|
||||||
MIST_FUNC_DEF(surface,rect,2),
|
MIST_FUNC_DEF(surface,rect,2),
|
||||||
|
MIST_FUNC_DEF(surface, dup, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
JSC_CCALL(camera_frame,
|
||||||
|
SDL_ClearError();
|
||||||
|
SDL_Camera *cam = js2SDL_Camera(js,self);
|
||||||
|
if (!cam) return JS_ThrowReferenceError(js,"Self was not a camera: %s", SDL_GetError());
|
||||||
|
SDL_Surface *surf = SDL_AcquireCameraFrame(cam, NULL);
|
||||||
|
if (!surf) {
|
||||||
|
const char *msg = SDL_GetError();
|
||||||
|
if (msg[0] != 0)
|
||||||
|
return JS_ThrowReferenceError(js,"Could not get camera frame: %s", SDL_GetError());
|
||||||
|
else return JS_UNDEFINED;
|
||||||
|
}
|
||||||
|
return SDL_Surface2js(js,surf);
|
||||||
|
SDL_Surface *newsurf = SDL_CreateSurface(surf->w, surf->h, surf->format);
|
||||||
|
SDL_ReleaseCameraFrame(cam,surf);
|
||||||
|
|
||||||
|
int didit = SDL_BlitSurface(surf, NULL, newsurf, NULL);
|
||||||
|
if (!didit) {
|
||||||
|
SDL_DestroySurface(newsurf);
|
||||||
|
return JS_ThrowReferenceError(js, "Could not blit: %s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
return SDL_Surface2js(js,newsurf);
|
||||||
|
)
|
||||||
|
|
||||||
|
JSC_CCALL(camera_release_frame,
|
||||||
|
SDL_Camera *cam = js2SDL_Camera(js,self);
|
||||||
|
SDL_Surface *surf = js2SDL_Surface(js,argv[0]);
|
||||||
|
SDL_ReleaseCameraFrame(cam,surf);
|
||||||
|
)
|
||||||
|
|
||||||
|
static const JSCFunctionListEntry js_SDL_Camera_funcs[] =
|
||||||
|
{
|
||||||
|
MIST_FUNC_DEF(camera, frame, 0),
|
||||||
|
MIST_FUNC_DEF(camera, release_frame, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
JSC_CCALL(texture_mode,
|
JSC_CCALL(texture_mode,
|
||||||
@@ -1941,7 +2016,6 @@ int iiihandle(JSRuntime *rt, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSC_CCALL(profile_gather,
|
JSC_CCALL(profile_gather,
|
||||||
int count = js2number(js,argv[0]);
|
|
||||||
instr_v = JS_DupValue(js, argv[1]);
|
instr_v = JS_DupValue(js, argv[1]);
|
||||||
JS_SetInterruptHandler(JS_GetRuntime(js), iiihandle, NULL);
|
JS_SetInterruptHandler(JS_GetRuntime(js), iiihandle, NULL);
|
||||||
)
|
)
|
||||||
@@ -2604,7 +2678,7 @@ JSC_CCALL(os_make_texture,
|
|||||||
FMT = SDL_PIXELFORMAT_RGB24;
|
FMT = SDL_PIXELFORMAT_RGB24;
|
||||||
else {
|
else {
|
||||||
free(data);
|
free(data);
|
||||||
return JS_ThrowReferenceError(js, "unknown pixel format");
|
return JS_ThrowReferenceError(js, "unknown pixel format. got %d channels", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *surf = SDL_CreateSurfaceFrom(width,height,FMT, data, width*n);
|
SDL_Surface *surf = SDL_CreateSurfaceFrom(width,height,FMT, data, width*n);
|
||||||
@@ -2614,8 +2688,6 @@ JSC_CCALL(os_make_texture,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = SDL_Surface2js(js,surf);
|
ret = SDL_Surface2js(js,surf);
|
||||||
JS_SetProperty(js,ret,width_atom,number2js(js,surf->w));
|
|
||||||
JS_SetProperty(js,ret,height_atom,number2js(js,surf->h));
|
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_make_gif,
|
JSC_CCALL(os_make_gif,
|
||||||
@@ -2777,33 +2849,6 @@ JSC_SCALL(os_gltf_skin,
|
|||||||
cgltf_free(data);
|
cgltf_free(data);
|
||||||
)
|
)
|
||||||
|
|
||||||
JSC_CCALL(os_make_buffer,
|
|
||||||
int type = js2number(js,argv[1]);
|
|
||||||
float *b = malloc(sizeof(float)*js_arrlen(js,argv[0]));
|
|
||||||
for (int i = 0; i < js_arrlen(js,argv[0]); i++)
|
|
||||||
b[i] = js_getnum_uint32(js, argv[0],i);
|
|
||||||
/*
|
|
||||||
sg_buffer *p = malloc(sizeof(sg_buffer));
|
|
||||||
|
|
||||||
switch(type) {
|
|
||||||
case 0:
|
|
||||||
*p = sg_make_buffer(&(sg_buffer_desc){
|
|
||||||
.size = sizeof(float)*js_arrlen(js,argv[0]),
|
|
||||||
.data = b
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
*p = index_buffer(b, js_arrlen(js,argv[0]));
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
*p = texcoord_floats(b, js_arrlen(js,argv[0]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(b);
|
|
||||||
return sg_buffer2js(js,p);*/
|
|
||||||
)
|
|
||||||
|
|
||||||
JSC_CCALL(os_make_color_buffer,
|
JSC_CCALL(os_make_color_buffer,
|
||||||
int count = js2number(js,argv[1]);
|
int count = js2number(js,argv[1]);
|
||||||
HMM_Vec4 color = js2vec4(js,argv[0]);
|
HMM_Vec4 color = js2vec4(js,argv[0]);
|
||||||
@@ -3074,6 +3119,14 @@ JSC_CCALL(os_make_sprite_mesh,
|
|||||||
JS_SetProperty(js, ret, count_atom, number2js(js, count));
|
JS_SetProperty(js, ret, count_atom, number2js(js, count));
|
||||||
)
|
)
|
||||||
|
|
||||||
|
bool detectImageInWebcam(SDL_Surface *a, SDL_Surface *b, double t);
|
||||||
|
JSC_CCALL(os_match_img,
|
||||||
|
SDL_Surface *img1 = js2SDL_Surface(js,argv[0]);
|
||||||
|
SDL_Surface *img2 = js2SDL_Surface(js,argv[1]);
|
||||||
|
double threshold = js2number(js,argv[2]);
|
||||||
|
return JS_NewBool(js, detectImageInWebcam(img1,img2,threshold));
|
||||||
|
)
|
||||||
|
|
||||||
static const JSCFunctionListEntry js_os_funcs[] = {
|
static const JSCFunctionListEntry js_os_funcs[] = {
|
||||||
MIST_FUNC_DEF(os, turbulence, 4),
|
MIST_FUNC_DEF(os, turbulence, 4),
|
||||||
MIST_FUNC_DEF(os, fbm, 4),
|
MIST_FUNC_DEF(os, fbm, 4),
|
||||||
@@ -3097,7 +3150,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||||||
MIST_FUNC_DEF(os, make_surface, 1),
|
MIST_FUNC_DEF(os, make_surface, 1),
|
||||||
MIST_FUNC_DEF(os, make_font, 2),
|
MIST_FUNC_DEF(os, make_font, 2),
|
||||||
MIST_FUNC_DEF(os, make_transform, 0),
|
MIST_FUNC_DEF(os, make_transform, 0),
|
||||||
MIST_FUNC_DEF(os, make_buffer, 1),
|
|
||||||
MIST_FUNC_DEF(os, make_line_prim, 4),
|
MIST_FUNC_DEF(os, make_line_prim, 4),
|
||||||
MIST_FUNC_DEF(os, make_cylinder, 2),
|
MIST_FUNC_DEF(os, make_cylinder, 2),
|
||||||
MIST_FUNC_DEF(os, make_cone, 2),
|
MIST_FUNC_DEF(os, make_cone, 2),
|
||||||
@@ -3130,6 +3182,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
|||||||
MIST_FUNC_DEF(os, gltf_skin, 1),
|
MIST_FUNC_DEF(os, gltf_skin, 1),
|
||||||
MIST_FUNC_DEF(os, skin_calculate, 1),
|
MIST_FUNC_DEF(os, skin_calculate, 1),
|
||||||
MIST_FUNC_DEF(os, kill, 1),
|
MIST_FUNC_DEF(os, kill, 1),
|
||||||
|
MIST_FUNC_DEF(os, match_img, 3),
|
||||||
};
|
};
|
||||||
|
|
||||||
#define JSSTATIC(NAME, PARENT) \
|
#define JSSTATIC(NAME, PARENT) \
|
||||||
@@ -3193,6 +3246,7 @@ void ffi_load(JSContext *js) {
|
|||||||
QJSCLASSPREP_FUNCS(SDL_Surface)
|
QJSCLASSPREP_FUNCS(SDL_Surface)
|
||||||
QJSCLASSPREP_FUNCS(SDL_Texture)
|
QJSCLASSPREP_FUNCS(SDL_Texture)
|
||||||
QJSCLASSPREP_FUNCS(SDL_Renderer)
|
QJSCLASSPREP_FUNCS(SDL_Renderer)
|
||||||
|
QJSCLASSPREP_FUNCS(SDL_Camera)
|
||||||
|
|
||||||
QJSGLOBALCLASS(os);
|
QJSGLOBALCLASS(os);
|
||||||
|
|
||||||
@@ -3204,6 +3258,7 @@ void ffi_load(JSContext *js) {
|
|||||||
QJSCLASSPREP_FUNCS(timer);
|
QJSCLASSPREP_FUNCS(timer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
QJSGLOBALCLASS(input);
|
QJSGLOBALCLASS(input);
|
||||||
QJSGLOBALCLASS(io);
|
QJSGLOBALCLASS(io);
|
||||||
QJSGLOBALCLASS(prosperon);
|
QJSGLOBALCLASS(prosperon);
|
||||||
|
|||||||
@@ -96,9 +96,9 @@ static inline TYPE *js2##TYPE (JSContext *js, JSValue val) { \
|
|||||||
return JS_GetOpaque(val,js_##TYPE##_id); \
|
return JS_GetOpaque(val,js_##TYPE##_id); \
|
||||||
}\
|
}\
|
||||||
static inline JSValue TYPE##2js(JSContext *js, TYPE *n) { \
|
static inline JSValue TYPE##2js(JSContext *js, TYPE *n) { \
|
||||||
__VA_ARGS__ \
|
|
||||||
JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\
|
JSValue j = JS_NewObjectClass(js,js_##TYPE##_id);\
|
||||||
JS_SetOpaque(j,n);\
|
JS_SetOpaque(j,n);\
|
||||||
|
__VA_ARGS__ \
|
||||||
return j; }\
|
return j; }\
|
||||||
\
|
\
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user